auth, trips and join trips
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
import bcrypt from "bcryptjs";
|
||||
import { userRepo } from "@/server/repositories/user.repo";
|
||||
|
||||
export const authService = {
|
||||
async register(data: { name: string; email: string; password: string }) {
|
||||
const existing = await userRepo.findByEmail(data.email);
|
||||
if (existing) {
|
||||
throw new Error("Email sudah terdaftar");
|
||||
}
|
||||
|
||||
const hashedPassword = await bcrypt.hash(data.password, 12);
|
||||
|
||||
const user = await userRepo.create({
|
||||
name: data.name,
|
||||
email: data.email,
|
||||
password: hashedPassword,
|
||||
});
|
||||
|
||||
return { id: user.id, name: user.name, email: user.email };
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,102 @@
|
||||
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;
|
||||
image?: string;
|
||||
organizerId: 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) {
|
||||
return tripRepo.create({
|
||||
title: input.title,
|
||||
description: input.description,
|
||||
mountain: input.mountain,
|
||||
location: input.location,
|
||||
date: input.date,
|
||||
maxParticipants: input.maxParticipants,
|
||||
price: input.price,
|
||||
image: input.image,
|
||||
organizer: { connect: { id: input.organizerId } },
|
||||
});
|
||||
},
|
||||
|
||||
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);
|
||||
|
||||
// Auto update status if full after join
|
||||
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);
|
||||
|
||||
// Re-open trip if was full
|
||||
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;
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user