general destination and verify
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
interface UpsertProfileInput {
|
||||
bio?: string;
|
||||
city?: string;
|
||||
instagram?: string;
|
||||
interests: string[];
|
||||
}
|
||||
|
||||
export const profileRepo = {
|
||||
async findByUserId(userId: string) {
|
||||
return prisma.userProfile.findUnique({ where: { userId } });
|
||||
},
|
||||
|
||||
async upsertByUserId(userId: string, data: UpsertProfileInput) {
|
||||
return prisma.userProfile.upsert({
|
||||
where: { userId },
|
||||
create: {
|
||||
userId,
|
||||
bio: data.bio,
|
||||
city: data.city,
|
||||
instagram: data.instagram,
|
||||
interests: data.interests,
|
||||
},
|
||||
update: {
|
||||
bio: data.bio,
|
||||
city: data.city,
|
||||
instagram: data.instagram,
|
||||
interests: data.interests,
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -24,6 +24,31 @@ export const userRepo = {
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Profil sosial publik untuk halaman /u/[id]. JANGAN sertakan field sensitif
|
||||
* (email, password, KYC). Hanya yang user pilih untuk dibagikan.
|
||||
*/
|
||||
async findSocialProfileById(id: string) {
|
||||
return prisma.user.findUnique({
|
||||
where: { id },
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
image: true,
|
||||
createdAt: true,
|
||||
profile: {
|
||||
select: {
|
||||
bio: true,
|
||||
city: true,
|
||||
interests: true,
|
||||
instagram: true,
|
||||
},
|
||||
},
|
||||
organizerVerification: { select: { status: true } },
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
async create(data: Prisma.UserCreateInput) {
|
||||
return prisma.user.create({ data });
|
||||
},
|
||||
|
||||
@@ -2,9 +2,53 @@ 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) {
|
||||
|
||||
Reference in New Issue
Block a user