create review and profile
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import { tripRepo } from "@/server/repositories/trip.repo";
|
||||
import { participantRepo } from "@/server/repositories/participant.repo";
|
||||
import { LIMITS } from "@/lib/limits";
|
||||
import { utcStartOfDay, isTripDepartureDayPast } from "@/lib/trip-dates";
|
||||
|
||||
interface CreateTripInput {
|
||||
title: string;
|
||||
@@ -32,6 +34,25 @@ export const tripService = {
|
||||
},
|
||||
|
||||
async createTrip(input: CreateTripInput) {
|
||||
const since = utcStartOfDay(new Date());
|
||||
const todayCount = await tripRepo.countByOrganizerSince(
|
||||
input.organizerId,
|
||||
since
|
||||
);
|
||||
if (todayCount >= LIMITS.MAX_TRIPS_PER_ORGANIZER_PER_DAY) {
|
||||
throw new Error(
|
||||
`Batas harian: maksimal ${LIMITS.MAX_TRIPS_PER_ORGANIZER_PER_DAY} trip per hari (UTC). Coba lagi besok.`
|
||||
);
|
||||
}
|
||||
|
||||
if (isTripDepartureDayPast(input.date)) {
|
||||
throw new Error("Tanggal berangkat tidak boleh di masa lalu");
|
||||
}
|
||||
|
||||
if (input.endDate && input.endDate.getTime() < input.date.getTime()) {
|
||||
throw new Error("Tanggal pulang tidak boleh sebelum tanggal berangkat");
|
||||
}
|
||||
|
||||
const images = input.imageUrls?.length
|
||||
? {
|
||||
create: input.imageUrls.map((url, i) => ({ url, order: i })),
|
||||
@@ -62,6 +83,12 @@ export const tripService = {
|
||||
throw new Error("Trip tidak tersedia untuk pendaftaran");
|
||||
}
|
||||
|
||||
if (isTripDepartureDayPast(trip.date)) {
|
||||
throw new Error(
|
||||
"Trip sudah melewati tanggal berangkat, tidak bisa mendaftar"
|
||||
);
|
||||
}
|
||||
|
||||
if (trip.organizerId === userId) {
|
||||
throw new Error("Organizer tidak bisa join trip sendiri");
|
||||
}
|
||||
@@ -77,7 +104,10 @@ export const tripService = {
|
||||
throw new Error("Trip sudah penuh");
|
||||
}
|
||||
|
||||
const participant = await participantRepo.create(tripId, userId);
|
||||
const participant =
|
||||
existing?.status === "CANCELLED"
|
||||
? await participantRepo.reactivate(tripId, userId)
|
||||
: await participantRepo.create(tripId, userId);
|
||||
|
||||
const newCount = await participantRepo.countByTrip(tripId);
|
||||
if (newCount >= trip.maxParticipants) {
|
||||
@@ -88,6 +118,17 @@ export const tripService = {
|
||||
},
|
||||
|
||||
async cancelJoin(tripId: string, userId: string) {
|
||||
const trip = await tripRepo.findById(tripId);
|
||||
if (!trip) {
|
||||
throw new Error("Trip tidak ditemukan");
|
||||
}
|
||||
|
||||
if (isTripDepartureDayPast(trip.date)) {
|
||||
throw new Error(
|
||||
"Tanggal berangkat trip sudah lewat — pendaftaran tidak bisa dibatalkan. Jika trip sudah selesai, gunakan bagian ulasan."
|
||||
);
|
||||
}
|
||||
|
||||
const existing = await participantRepo.findByTripAndUser(tripId, userId);
|
||||
if (!existing || existing.status === "CANCELLED") {
|
||||
throw new Error("Kamu tidak terdaftar di trip ini");
|
||||
@@ -95,8 +136,7 @@ export const tripService = {
|
||||
|
||||
const result = await participantRepo.cancel(tripId, userId);
|
||||
|
||||
const trip = await tripRepo.findById(tripId);
|
||||
if (trip && trip.status === "FULL") {
|
||||
if (trip.status === "FULL") {
|
||||
const count = await participantRepo.countByTrip(tripId);
|
||||
if (count < trip.maxParticipants) {
|
||||
await tripRepo.updateStatus(tripId, "OPEN");
|
||||
|
||||
Reference in New Issue
Block a user