mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
feat(filters): route filter, select-styled trigger, tune default pin set
- New "route" FilterType: RouteBody popover (searchable origin + destination selects, apply once both are picked), wired into ContractRequestsPage and BookingRequestsPage. Bookings already had server-side originYardId/destinationYardId; contracts gets both new (contract_routes is one-to-many, so origin/destination are separate EXISTS subqueries, not a join). - Inactive FilterPill trigger restyled to read like a closed Mantine Select (opaque solid border, trailing chevron) instead of a dashed "+" pill — trigger only, popover body/position unchanged. - Search box text set to regular weight. - A couple more filters (Direction, Freight) pinned by default per page on top of the existing always-pinned ones; the rest stay behind More filters.
This commit is contained in:
@@ -48,6 +48,8 @@ export interface ContractListFilterOptions {
|
||||
hasClearanceDocuments?: boolean;
|
||||
createdFrom?: string;
|
||||
createdTo?: string;
|
||||
originYardId?: string;
|
||||
destinationYardId?: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@@ -489,6 +491,25 @@ export class ContractsRepository extends BaseRepository<Contract> {
|
||||
if (options.createdTo) {
|
||||
qb.andWhere('contract.created_at <= :createdTo', { createdTo: options.createdTo });
|
||||
}
|
||||
// Routes are one-to-many (a contract can list several lanes), so origin
|
||||
// and destination each need their own EXISTS — a plain join would
|
||||
// duplicate the contract row per matching route.
|
||||
if (omit !== 'originYardId' && options.originYardId) {
|
||||
qb.andWhere(
|
||||
'EXISTS (SELECT 1 FROM freight.contract_routes cr_o ' +
|
||||
'WHERE cr_o.contract_id = contract.id AND cr_o.deleted_at IS NULL ' +
|
||||
'AND cr_o.origin_yard_id = :originYardId)',
|
||||
{ originYardId: options.originYardId },
|
||||
);
|
||||
}
|
||||
if (omit !== 'destinationYardId' && options.destinationYardId) {
|
||||
qb.andWhere(
|
||||
'EXISTS (SELECT 1 FROM freight.contract_routes cr_d ' +
|
||||
'WHERE cr_d.contract_id = contract.id AND cr_d.deleted_at IS NULL ' +
|
||||
'AND cr_d.destination_yard_id = :destinationYardId)',
|
||||
{ destinationYardId: options.destinationYardId },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -768,6 +768,8 @@ export class ContractsService {
|
||||
paymentCurrency: filter.paymentCurrency,
|
||||
createdFrom: filter.createdFrom,
|
||||
createdTo: filter.createdTo,
|
||||
originYardId: filter.originYardId,
|
||||
destinationYardId: filter.destinationYardId,
|
||||
search: filter.search,
|
||||
sortBy: filter.sortBy,
|
||||
sortOrder: filter.sortOrder,
|
||||
@@ -789,6 +791,8 @@ export class ContractsService {
|
||||
paymentCurrency: filter.paymentCurrency,
|
||||
createdFrom: filter.createdFrom,
|
||||
createdTo: filter.createdTo,
|
||||
originYardId: filter.originYardId,
|
||||
destinationYardId: filter.destinationYardId,
|
||||
};
|
||||
|
||||
const [facets, metrics] = await Promise.all([
|
||||
|
||||
@@ -61,6 +61,22 @@ export class FilterContractDto {
|
||||
@IsIn([...PAYMENT_CURRENCIES])
|
||||
paymentCurrency?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
format: 'uuid',
|
||||
description: 'Only contracts with a route starting at this yard.',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsUUID()
|
||||
originYardId?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
format: 'uuid',
|
||||
description: 'Only contracts with a route ending at this yard.',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsUUID()
|
||||
destinationYardId?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Filter contracts created on/after this date (ISO)' })
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
|
||||
Reference in New Issue
Block a user