107 lines
2.8 KiB
TypeScript
107 lines
2.8 KiB
TypeScript
import { tripRepo } from "@/server/repositories/trip.repo";
|
|
import { participantRepo } from "@/server/repositories/participant.repo";
|
|
|
|
interface CreateTripInput {
|
|
title: string;
|
|
description?: string;
|
|
mountain: string;
|
|
location: string;
|
|
date: Date;
|
|
maxParticipants: number;
|
|
price: number;
|
|
organizerId: string;
|
|
imageUrls?: string[];
|
|
}
|
|
|
|
export const tripService = {
|
|
async getOpenTrips() {
|
|
return tripRepo.findOpen();
|
|
},
|
|
|
|
async getAllTrips() {
|
|
return tripRepo.findAll();
|
|
},
|
|
|
|
async getTripById(id: string) {
|
|
const trip = await tripRepo.findById(id);
|
|
if (!trip) {
|
|
throw new Error("Trip tidak ditemukan");
|
|
}
|
|
return trip;
|
|
},
|
|
|
|
async createTrip(input: CreateTripInput) {
|
|
const images = input.imageUrls?.length
|
|
? {
|
|
create: input.imageUrls.map((url, i) => ({ url, order: i })),
|
|
}
|
|
: undefined;
|
|
|
|
return tripRepo.create({
|
|
title: input.title,
|
|
description: input.description,
|
|
mountain: input.mountain,
|
|
location: input.location,
|
|
date: input.date,
|
|
maxParticipants: input.maxParticipants,
|
|
price: input.price,
|
|
organizer: { connect: { id: input.organizerId } },
|
|
images,
|
|
});
|
|
},
|
|
|
|
async joinTrip(tripId: string, userId: string) {
|
|
const trip = await tripRepo.findById(tripId);
|
|
if (!trip) {
|
|
throw new Error("Trip tidak ditemukan");
|
|
}
|
|
|
|
if (trip.status !== "OPEN") {
|
|
throw new Error("Trip tidak tersedia untuk pendaftaran");
|
|
}
|
|
|
|
if (trip.organizerId === userId) {
|
|
throw new Error("Organizer tidak bisa join trip sendiri");
|
|
}
|
|
|
|
const existing = await participantRepo.findByTripAndUser(tripId, userId);
|
|
if (existing && existing.status !== "CANCELLED") {
|
|
throw new Error("Kamu sudah terdaftar di trip ini");
|
|
}
|
|
|
|
const participantCount = await participantRepo.countByTrip(tripId);
|
|
if (participantCount >= trip.maxParticipants) {
|
|
await tripRepo.updateStatus(tripId, "FULL");
|
|
throw new Error("Trip sudah penuh");
|
|
}
|
|
|
|
const participant = await participantRepo.create(tripId, userId);
|
|
|
|
const newCount = await participantRepo.countByTrip(tripId);
|
|
if (newCount >= trip.maxParticipants) {
|
|
await tripRepo.updateStatus(tripId, "FULL");
|
|
}
|
|
|
|
return participant;
|
|
},
|
|
|
|
async cancelJoin(tripId: string, userId: string) {
|
|
const existing = await participantRepo.findByTripAndUser(tripId, userId);
|
|
if (!existing || existing.status === "CANCELLED") {
|
|
throw new Error("Kamu tidak terdaftar di trip ini");
|
|
}
|
|
|
|
const result = await participantRepo.cancel(tripId, userId);
|
|
|
|
const trip = await tripRepo.findById(tripId);
|
|
if (trip && trip.status === "FULL") {
|
|
const count = await participantRepo.countByTrip(tripId);
|
|
if (count < trip.maxParticipants) {
|
|
await tripRepo.updateStatus(tripId, "OPEN");
|
|
}
|
|
}
|
|
|
|
return result;
|
|
},
|
|
};
|