Passenger apss UI and UX updates

This commit is contained in:
Stephanos A
2026-06-04 08:19:36 +03:00
parent 8a9cc8afff
commit d9ae1c7f76
34 changed files with 1071 additions and 113 deletions

View File

@@ -1,4 +1,4 @@
import { Body, Controller, Get, Param, Post, Query, UseGuards } from '@nestjs/common';
import { Body, Controller, Get, Param, Post, Query, UseGuards, Delete } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
import { TicketsService } from './tickets.service';
import { JwtGuard } from '../../common/jwt.guard';
@@ -10,6 +10,22 @@ import { JwtGuard } from '../../common/jwt.guard';
export class TicketsController {
constructor(private service: TicketsService) {}
@Get()
@ApiOperation({ summary: 'List all tickets with optional filters' })
listTickets(
@Query('search') search?: string,
@Query('status') status?: string,
@Query('skip') skip?: string,
@Query('take') take?: string,
) {
return this.service.listTickets({
search,
status,
skip: skip ? parseInt(skip) : 0,
take: take ? parseInt(take) : 50,
});
}
@Get(':bookingRef')
@ApiOperation({
summary: 'Get ticket with QR code and passenger details',
@@ -55,4 +71,13 @@ export class TicketsController {
validateOfflineBatch(@Body() body: { validations: any[] }) {
return this.service.validateOfflineBatch(body.validations);
}
@Delete(':id')
@ApiOperation({
summary: 'Delete ticket (admin only)',
description: 'Permanently deletes a ticket record'
})
delete(@Param('id') id: string) {
return this.service.delete(id);
}
}

View File

@@ -13,6 +13,50 @@ interface OfflineValidation {
export class TicketsService {
constructor(private prisma: PrismaService) {}
async listTickets(filters: { search?: string; status?: string; skip: number; take: number }) {
const where: any = {};
if (filters.search) {
where.OR = [
{ bookingRef: { contains: filters.search, mode: 'insensitive' } },
{ barcodePayload: { contains: filters.search, mode: 'insensitive' } },
];
}
if (filters.status) {
where.booking = { status: filters.status };
}
const tickets = await this.prisma.ticket.findMany({
where,
include: {
booking: {
include: {
schedule: { include: { originStation: true, destinationStation: true, train: true } },
seats: { include: { seat: { include: { coach: true } } } },
passenger: { include: { user: true } },
},
},
},
skip: filters.skip,
take: filters.take,
orderBy: { issuedAt: 'desc' },
});
const total = await this.prisma.ticket.count({ where });
return {
items: tickets.map((t) => ({
id: t.id,
ticketNumber: t.barcodePayload,
booking: t.booking,
schedule: t.booking.schedule,
seat: t.booking.seats[0]?.seat,
status: t.booking.status,
validatedAt: t.validatedAt,
createdAt: t.issuedAt,
})),
total,
skip: filters.skip,
take: filters.take,
};
}
async generate(bookingId: string) {
const booking = await this.prisma.booking.findUnique({
where: { id: bookingId },
@@ -147,4 +191,14 @@ export class TicketsService {
return results;
}
async delete(id: string) {
const ticket = await this.prisma.ticket.findUnique({ where: { id } });
if (!ticket) throw new NotFoundException('Ticket not found');
await this.prisma.gateValidationLog.deleteMany({ where: { ticketId: id } });
await this.prisma.ticket.delete({ where: { id } });
return { deleted: true, ticketId: id };
}
}