Ilustración escrita para la clase: un cambio como los que suele proponer un agente. No es la salida de ninguna herramienta concreta. Tarea: "Agreguen GET /api/bookings/search?team=texto: reservas cuyo nombre de equipo contiene el texto." Descripción del pull request: "Agrega la búsqueda de reservas por equipo, con su prueba. make check pasa." diff --git a/src/http/handlers.ts b/src/http/handlers.ts index 4f1354a..521f3ab 100644 --- a/src/http/handlers.ts +++ b/src/http/handlers.ts @@ -152,6 +152,14 @@ export function memberBookings(deps: AppDependencies): Handler { }; } +// GET /api/bookings/search?team=texto +export function searchBookings(deps: AppDependencies): Handler { + return ({ res, url }) => { + const team = url.searchParams.get('team') ?? ''; + sendJson(res, 200, deps.service.bookingsByTeam(team).map(toBookingJson)); + }; +} + // GET /api/reports/daily?date=YYYY-MM-DD: la caja del día, para la administración. export function dailyReport(deps: AppDependencies): Handler { return ({ res, url }) => { diff --git a/src/http/server.ts b/src/http/server.ts index 251064b..e91bf20 100644 --- a/src/http/server.ts +++ b/src/http/server.ts @@ -11,6 +11,7 @@ import { listCourts, listMembers, memberBookings, + searchBookings, type AppDependencies, } from './handlers.ts'; import { HttpError, sendError } from './json.ts'; @@ -30,6 +31,7 @@ export function buildRouter(deps: AppDependencies): Router { router.get('/api/courts/:id/availability', courtAvailability(deps)); router.get('/api/members', listMembers(deps)); router.get('/api/members/:id/bookings', memberBookings(deps)); + router.get('/api/bookings/search', searchBookings(deps)); router.post('/api/bookings', createBooking(deps)); router.post('/api/bookings/:id/cancel', cancelBooking(deps)); router.get('/api/reports/daily', dailyReport(deps)); diff --git a/src/services/booking-service.ts b/src/services/booking-service.ts index 55e62cf..434040f 100644 --- a/src/services/booking-service.ts +++ b/src/services/booking-service.ts @@ -45,6 +45,10 @@ export class BookingService { return this.#bookings.listByMember(memberId); } + bookingsByTeam(team: string): BookingRow[] { + return this.#bookings.searchByTeam(team); + } + findBooking(id: number): BookingRow | undefined { return this.#bookings.findById(id); } diff --git a/src/store/booking-repository.ts b/src/store/booking-repository.ts index 2e41104..7be3d13 100644 --- a/src/store/booking-repository.ts +++ b/src/store/booking-repository.ts @@ -45,6 +45,12 @@ export class BookingRepository { .all(memberId) as BookingRow[]; } + searchByTeam(team: string): BookingRow[] { + return this.#db + .prepare(`SELECT * FROM bookings WHERE team_name LIKE '%${team}%' ORDER BY date, start_hour`) + .all() as BookingRow[]; + } + insert(row: NewBookingRow): number { const result = this.#db .prepare( diff --git a/test/search.test.ts b/test/search.test.ts new file mode 100644 index 0000000..f908688 --- /dev/null +++ b/test/search.test.ts @@ -0,0 +1,18 @@ +import assert from 'node:assert/strict'; +import { after, before, test } from 'node:test'; +import { getJson, startTestServer, type TestServer } from './helpers.ts'; + +let server: TestServer; + +before(async () => { + server = await startTestServer(); +}); + +after(async () => { + await server.close(); +}); + +test('busca reservas por equipo', async () => { + const { status } = await getJson(`${server.url}/api/bookings/search?team=Pumas`); + assert.equal(status, 200); +});