8aab968e09
Build & Deploy / Build & Push Docker Image (push) Successful in 1m2s
Test / Type Check (all packages) (push) Failing after 28s
Test / API Unit Tests (push) Has been skipped
Test / Homepage Unit Tests (push) Has been skipped
Test / Storefront Unit Tests (push) Has been skipped
Test / Admin Unit Tests (push) Has been skipped
Test / Dashboard Unit Tests (push) Has been skipped
Test / API Integration Tests (push) Has been skipped
Build & Deploy / Deploy to VPS (push) Successful in 3s
Comprehensive rename of all marketplace references to storefront: - API module: apps/api/src/modules/marketplace/ → storefront/ - Components: MarketplaceHeader → StorefrontHeader, MarketplaceShell → StorefrontShell, MarketplaceFooter → StorefrontFooter - Types: marketplace-homepage.ts → storefront-homepage.ts - Test files: employee-marketplace-* → employee-storefront-* - All source code identifiers, imports, route paths, and strings - Documentation (docs/), CI config (.gitlab-ci.yml), scripts - Dashboard, admin, storefront workspace references - Prisma field names preserved (isListedOnMarketplace, marketplaceRating, marketplaceFunnelEvent) as they map to database schema Validation: - API type-check: 0 errors - Storefront type-check: 0 errors - Dashboard type-check: 0 errors - Full monorepo type-check: only pre-existing admin TS18046
87 lines
3.5 KiB
TypeScript
87 lines
3.5 KiB
TypeScript
import { z } from 'zod'
|
|
|
|
export const paginationSchema = z.object({
|
|
page: z.coerce.number().int().min(1).max(10000).default(1),
|
|
pageSize: z.coerce.number().int().min(1).max(100).default(20),
|
|
})
|
|
|
|
export const searchSchema = z.object({
|
|
city: z.string().trim().max(100).optional(),
|
|
pickupLocation: z.string().trim().max(100).optional(),
|
|
dropoffLocation: z.string().trim().max(100).optional(),
|
|
dropoffMode: z.enum(['same', 'different']).optional(),
|
|
startDate: z.string().datetime().optional(),
|
|
endDate: z.string().datetime().optional(),
|
|
category: z.string().trim().max(50).optional(),
|
|
maxPrice: z.coerce.number().int().min(0).max(1_000_000).optional(),
|
|
transmission: z.string().trim().max(20).optional(),
|
|
make: z.string().trim().max(60).optional(),
|
|
model: z.string().trim().max(60).optional(),
|
|
})
|
|
|
|
export const companiesQuerySchema = z.object({
|
|
city: z.string().trim().max(100).optional(),
|
|
hasOffer: z.string().optional(),
|
|
})
|
|
|
|
export const vehicleAvailabilityQuerySchema = z.object({
|
|
startDate: z.string().datetime(),
|
|
endDate: z.string().datetime(),
|
|
})
|
|
|
|
export const storefrontReservationSchema = z.object({
|
|
vehicleId: z.string().cuid(),
|
|
companySlug: z.string().trim().max(100).optional(),
|
|
firstName: z.string().min(1).max(100),
|
|
lastName: z.string().min(1).max(100),
|
|
email: z.string().email(),
|
|
// Contact info — collected at reservation time
|
|
phone: z.string().min(1).max(30).optional(),
|
|
// Identity & license — optional at reservation, collected at pickup
|
|
dateOfBirth: z.string().datetime().optional(),
|
|
nationality: z.string().min(1).max(100).optional(),
|
|
identityDocumentNumber: z.string().min(1).max(100).optional(),
|
|
fullAddress: z.string().min(1).max(500).optional(),
|
|
driverLicense: z.string().min(1).max(50).optional(),
|
|
licenseExpiry: z.string().datetime().optional(),
|
|
licenseIssuedAt: z.string().datetime().optional(),
|
|
licenseCountry: z.string().min(1).max(100).optional(),
|
|
licenseCategory: z.string().min(1).max(20).optional(),
|
|
internationalLicenseNumber: z.string().trim().max(100).optional(),
|
|
startDate: z.string().datetime(),
|
|
endDate: z.string().datetime(),
|
|
pickupLocation: z.string().trim().max(100).optional(),
|
|
returnLocation: z.string().trim().max(100).optional(),
|
|
notes: z.string().max(500).optional(),
|
|
language: z.enum(['en', 'fr', 'ar']).default('fr'),
|
|
})
|
|
|
|
export const marketplaceFunnelEventSchema = z.object({
|
|
eventName: z.enum([
|
|
'booking_form_viewed',
|
|
'trip_dates_selected',
|
|
'contact_details_started',
|
|
'driver_details_expanded',
|
|
'booking_request_submitted',
|
|
'booking_request_failed',
|
|
'booking_request_success',
|
|
]),
|
|
companySlug: z.string().trim().max(100),
|
|
vehicleId: z.string().cuid(),
|
|
sessionId: z.string().trim().max(100).optional(),
|
|
path: z.string().trim().max(500).optional(),
|
|
metadata: z.record(z.string(), z.union([z.string(), z.number(), z.boolean(), z.null()])).optional(),
|
|
})
|
|
|
|
export const reviewBodySchema = z.object({
|
|
overallRating: z.number().int().min(1).max(5),
|
|
vehicleRating: z.number().int().min(1).max(5).optional(),
|
|
serviceRating: z.number().int().min(1).max(5).optional(),
|
|
comment: z.string().max(2000).optional(),
|
|
})
|
|
|
|
export const slugParamSchema = z.object({ slug: z.string() })
|
|
export const vehicleParamSchema = z.object({ slug: z.string(), id: z.string() })
|
|
export const reviewTokenSchema = z.object({ token: z.string() })
|
|
export const offerCodeParamSchema = z.object({ code: z.string() })
|