diff --git a/pages/user.vue b/pages/user.vue index 83ae3f9..c9304ad 100644 --- a/pages/user.vue +++ b/pages/user.vue @@ -1,9 +1,172 @@ \ No newline at end of file diff --git a/server/api/book.post.ts b/server/api/book.post.ts new file mode 100644 index 0000000..c8330ab --- /dev/null +++ b/server/api/book.post.ts @@ -0,0 +1,55 @@ +import { defineEventHandler, readBody, createError } from 'h3'; +import { db, rooms, reservations } from '~/server/db'; +import { eq, gt, and, sql } from 'drizzle-orm'; + +export default defineEventHandler(async (event) => { + const body = await readBody(event); + const { customerId, roomId, checkInTime, stayDays } = body; + + if (!customerId || !roomId || !checkInTime || !stayDays) { + return createError({ statusCode: 400, statusMessage: '请填写完整信息' }); + } + + try { + const result = await db.transaction(async (tx) => { + // 1. Check for availability and get the room + const room = await tx.query.rooms.findFirst({ + where: and(eq(rooms.id, roomId), gt(rooms.availableCount, 0)), + columns: { + id: true, + } + }); + + if (!room) { + // By throwing an error, we automatically roll back the transaction + throw new Error('Room not available'); + } + + // 2. Decrement available count + await tx.update(rooms) + .set({ availableCount: sql`${rooms.availableCount} - 1` }) + .where(eq(rooms.id, roomId)); + + // 3. Create reservation + const newReservation = await tx.insert(reservations).values({ + customerId: parseInt(customerId, 10), + roomId: parseInt(roomId, 10), + checkInTime: new Date(checkInTime), + stayDays: parseInt(stayDays, 10), + }).returning({ id: reservations.id }); + + return newReservation[0]; + }); + + return { + message: '预订成功!', + reservationId: result.id, + }; + } catch (error: any) { + if (error.message === 'Room not available') { + return createError({ statusCode: 409, statusMessage: '该房间已无可预订数量' }); + } + console.error('Booking error:', error); + return createError({ statusCode: 500, statusMessage: '预订失败,请稍后重试' }); + } +}); \ No newline at end of file diff --git a/server/api/reservations/[customerId].get.ts b/server/api/reservations/[customerId].get.ts new file mode 100644 index 0000000..545a2f6 --- /dev/null +++ b/server/api/reservations/[customerId].get.ts @@ -0,0 +1,35 @@ +import { defineEventHandler, getRouterParam } from 'h3'; +import { db } from '~/server/db'; +import { reservations } from '~/server/db/schema'; +import { eq } from 'drizzle-orm'; + +export default defineEventHandler(async (event) => { + const customerId = getRouterParam(event, 'customerId'); + + if (!customerId) { + return createError({ + statusCode: 400, + statusMessage: 'Customer ID is required', + }); + } + + try { + const userReservations = await db + .select({ + ReservationID: reservations.id, + RoomID: reservations.roomId, + CheckInTime: reservations.checkInTime, + StayDays: reservations.stayDays, + }) + .from(reservations) + .where(eq(reservations.customerId, parseInt(customerId, 10))); + + return userReservations; + } catch (error) { + console.error(`Error fetching reservations for customer ${customerId}:`, error); + return createError({ + statusCode: 500, + statusMessage: 'Failed to fetch reservations', + }); + } +}); \ No newline at end of file diff --git a/server/api/rooms/index.get.ts b/server/api/rooms/index.get.ts new file mode 100644 index 0000000..120b8a0 --- /dev/null +++ b/server/api/rooms/index.get.ts @@ -0,0 +1,28 @@ +import { defineEventHandler } from 'h3'; +import { db } from '~/server/db'; +import { rooms, roomTypes } from '~/server/db/schema'; +import { eq, gt } from 'drizzle-orm'; + +export default defineEventHandler(async () => { + try { + const availableRooms = await db + .select({ + RoomID: rooms.id, + Type: roomTypes.typeName, + Price: rooms.price, + Feature: rooms.feature, + AvailableCount: rooms.availableCount, + }) + .from(rooms) + .leftJoin(roomTypes, eq(rooms.typeId, roomTypes.id)) + .where(gt(rooms.availableCount, 0)); + + return availableRooms; + } catch (error) { + console.error('Error fetching rooms:', error); + return createError({ + statusCode: 500, + statusMessage: 'Failed to fetch rooms', + }); + } +}); \ No newline at end of file