import { userRepo } from "@/server/repositories/user.repo"; import { tripRepo } from "@/server/repositories/trip.repo"; import { participantRepo } from "@/server/repositories/participant.repo"; import { organizerRepo } from "@/server/repositories/organizer.repo"; import { profileRepo } from "@/server/repositories/profile.repo"; import { isPastTripLastDayForReview } from "@/lib/trip-dates"; import type { UpdateProfileInput } from "@/features/profile/schemas"; export const profileService = { async getOwnProfile(userId: string) { return profileRepo.findByUserId(userId); }, async updateProfile(userId: string, input: UpdateProfileInput) { return profileRepo.upsertByUserId(userId, { bio: input.bio, city: input.city, instagram: input.instagram, interests: input.interests, }); }, /** * Halaman profil publik /u/[id]. Membaca user + UserProfile + counts trip. * Tidak ekspos email/KYC. */ async getPublicProfile(userId: string) { const user = await userRepo.findSocialProfileById(userId); if (!user) return null; const [organizedTrips, participations] = await Promise.all([ tripRepo.findByOrganizerId(userId), participantRepo.findWithTripForProfile(userId), ]); const joinedTrips = participations .filter((p) => p.status !== "CANCELLED") .map((p) => p.trip) .sort( (a, b) => new Date(b.date).getTime() - new Date(a.date).getTime() ); return { user, isVerifiedOrganizer: user.organizerVerification?.status === "APPROVED", organizedTrips, joinedTrips, }; }, async getProfileDashboard(userId: string) { const user = await userRepo.findPublicProfileById(userId); if (!user) { throw new Error("Pengguna tidak ditemukan"); } const [organizedTrips, participations, verification] = await Promise.all([ tripRepo.findByOrganizerId(userId), participantRepo.findWithTripForProfile(userId), organizerRepo.findByUserId(userId), ]); const isVerifiedOrganizer = verification?.status === "APPROVED"; const activeJoined = participations .filter((p) => p.status !== "CANCELLED") .sort( (a, b) => new Date(b.trip.date).getTime() - new Date(a.trip.date).getTime() ); const cancelledJoined = participations .filter((p) => p.status === "CANCELLED") .sort( (a, b) => new Date(b.trip.date).getTime() - new Date(a.trip.date).getTime() ); const reviewable = activeJoined .filter((p) => { if (p.status !== "CONFIRMED") return false; const t = p.trip; if (t.organizerId === userId) return false; return isPastTripLastDayForReview(t.date, t.endDate); }) .sort( (a, b) => new Date(b.trip.date).getTime() - new Date(a.trip.date).getTime() ); return { user, isVerifiedOrganizer, organizedTrips, activeJoined, cancelledJoined, reviewable, }; }, };