fix signin signout and apply the new style

This commit is contained in:
root
2026-05-24 23:58:54 -04:00
parent bf97a072dd
commit 9bd0938951
68 changed files with 851 additions and 200 deletions
@@ -4,6 +4,46 @@ import { sendNotification, sendTransactionalEmail } from '../../services/notific
import { marketplaceReservationEmail, type Lang } from '../../lib/emailTranslations'
import * as repo from './marketplace.repo'
function normalizeLocation(value?: string | null) {
const normalized = value?.trim()
return normalized ? normalized : null
}
function normalizeLocationList(values?: string[] | null) {
if (!Array.isArray(values)) return []
return values
.map((value) => normalizeLocation(value))
.filter((value): value is string => Boolean(value))
}
function includesLocation(values: string[], target: string) {
const key = target.toLocaleLowerCase()
return values.some((value) => value.toLocaleLowerCase() === key)
}
function matchesVehicleLocationRules(
vehicle: { pickupLocations?: string[]; dropoffLocations?: string[]; allowDifferentDropoff?: boolean },
params: { pickupLocation?: string; dropoffLocation?: string; dropoffMode?: 'same' | 'different' },
) {
const pickupLocation = normalizeLocation(params.pickupLocation)
const dropoffLocation = normalizeLocation(params.dropoffLocation)
const pickupLocations = normalizeLocationList(vehicle.pickupLocations)
const dropoffLocations = normalizeLocationList(vehicle.dropoffLocations)
if (pickupLocation && pickupLocations.length > 0 && !includesLocation(pickupLocations, pickupLocation)) {
return false
}
if (params.dropoffMode === 'different') {
if (!vehicle.allowDifferentDropoff) return false
if (dropoffLocation && dropoffLocations.length > 0 && !includesLocation(dropoffLocations, dropoffLocation)) {
return false
}
}
return true
}
export async function getPublicOffers() {
return repo.findPublicOffers()
}
@@ -34,7 +74,8 @@ export async function getListedCompanies(params: {
}
export async function searchVehicles(params: {
city?: string; startDate?: string; endDate?: string; category?: string
city?: string; pickupLocation?: string; dropoffLocation?: string; dropoffMode?: 'same' | 'different'
startDate?: string; endDate?: string; category?: string
maxPrice?: number; transmission?: string; make?: string; model?: string
page?: number; pageSize?: number
}) {
@@ -54,10 +95,12 @@ export async function searchVehicles(params: {
where.company = { ...where.company, brand: { isListedOnMarketplace: true, publicCity: { contains: params.city, mode: 'insensitive' } } }
}
const vehicles = await repo.findPublishedVehicles(where, (page - 1) * pageSize, pageSize)
const vehicles = await repo.findPublishedVehicles(where)
const locationFiltered = vehicles.filter((vehicle) => matchesVehicleLocationRules(vehicle, params))
const pagedVehicles = locationFiltered.slice((page - 1) * pageSize, page * pageSize)
const availability = await Promise.all(
vehicles.map(async (v) => {
pagedVehicles.map(async (v) => {
const a = await getVehicleAvailabilitySummary(v.id, {
range: params.startDate && params.endDate
? { startDate: new Date(params.startDate), endDate: new Date(params.endDate) }
@@ -68,7 +111,7 @@ export async function searchVehicles(params: {
)
const availMap = new Map(availability)
return vehicles.map((v) => ({
return pagedVehicles.map((v) => ({
...v,
availability: availMap.get(v.id)?.available ?? null,
availabilityStatus: availMap.get(v.id)?.status ?? 'AVAILABLE',
@@ -79,7 +122,7 @@ export async function searchVehicles(params: {
export async function createMarketplaceReservation(body: {
vehicleId: string; companySlug: string; firstName: string; lastName: string
email: string; phone?: string; startDate: string; endDate: string
notes?: string; language?: string
pickupLocation?: string; returnLocation?: string; notes?: string; language?: string
}) {
const startDate = new Date(body.startDate)
const endDate = new Date(body.endDate)
@@ -91,6 +134,24 @@ export async function createMarketplaceReservation(body: {
const vehicle = await repo.findVehicleForMarketplace(body.vehicleId, body.companySlug)
if (!vehicle) throw new NotFoundError('Vehicle not found')
const pickupLocation = normalizeLocation(body.pickupLocation)
const returnLocation = normalizeLocation(body.returnLocation) ?? pickupLocation
const pickupLocations = normalizeLocationList(vehicle.pickupLocations)
const dropoffLocations = normalizeLocationList(vehicle.dropoffLocations)
if (pickupLocation && pickupLocations.length > 0 && !includesLocation(pickupLocations, pickupLocation)) {
throw new AppError('Selected pickup location is not available for this vehicle', 400, 'invalid_pickup_location')
}
if (pickupLocation && returnLocation && pickupLocation.toLocaleLowerCase() !== returnLocation.toLocaleLowerCase()) {
if (!vehicle.allowDifferentDropoff) {
throw new AppError('This vehicle must be returned to the same pickup location', 400, 'same_dropoff_required')
}
if (dropoffLocations.length > 0 && !includesLocation(dropoffLocations, returnLocation)) {
throw new AppError('Selected return location is not available for this vehicle', 400, 'invalid_return_location')
}
}
const availability = await getVehicleAvailabilitySummary(body.vehicleId, { range: { startDate, endDate } })
if (!availability.available) {
throw new AppError('Vehicle is not available for the selected dates', 409, 'unavailable', {
@@ -107,7 +168,7 @@ export async function createMarketplaceReservation(body: {
const reservation = await repo.createMarketplaceReservation({
companyId: vehicle.companyId, vehicleId: body.vehicleId, customerId: customer.id,
startDate, endDate, dailyRate: vehicle.dailyRate, totalDays, totalAmount, notes: body.notes,
startDate, endDate, pickupLocation, returnLocation, dailyRate: vehicle.dailyRate, totalDays, totalAmount, notes: body.notes,
})
const lang = (body.language ?? 'fr') as Lang