177 lines
5.8 KiB
TypeScript
177 lines
5.8 KiB
TypeScript
import { Router } from 'express'
|
|
import { optionalRenterAuth } from '../../middleware/requireRenterAuth'
|
|
import { parseBody, parseParams, parseQuery } from '../../http/validate'
|
|
import { ok, created } from '../../http/respond'
|
|
import { isDatabaseUnavailableError } from '../../lib/isDatabaseUnavailable'
|
|
import * as service from './marketplace.service'
|
|
import {
|
|
paginationSchema, searchSchema, companiesQuerySchema, marketplaceReservationSchema,
|
|
reviewBodySchema, slugParamSchema, vehicleParamSchema, reviewTokenSchema, offerCodeParamSchema,
|
|
vehicleAvailabilityQuerySchema, marketplaceFunnelEventSchema,
|
|
} from './marketplace.schemas'
|
|
|
|
const router = Router()
|
|
router.use(optionalRenterAuth)
|
|
|
|
router.get('/offers', async (_req, res, next) => {
|
|
try {
|
|
ok(res, await service.getPublicOffers())
|
|
} catch (err) {
|
|
if (isDatabaseUnavailableError(err)) return res.json({ data: [] })
|
|
next(err)
|
|
}
|
|
})
|
|
|
|
router.get('/cities', async (_req, res, next) => {
|
|
try {
|
|
ok(res, await service.getCities())
|
|
} catch (err) {
|
|
if (isDatabaseUnavailableError(err)) return res.json({ data: [] })
|
|
next(err)
|
|
}
|
|
})
|
|
|
|
router.get('/companies', async (req, res, next) => {
|
|
try {
|
|
const { city, hasOffer } = parseQuery(companiesQuerySchema, req)
|
|
const { page, pageSize } = parseQuery(paginationSchema, req)
|
|
ok(res, await service.getListedCompanies({ city, hasOffer, page, pageSize }))
|
|
} catch (err) {
|
|
if (isDatabaseUnavailableError(err)) return res.json({ data: [] })
|
|
next(err)
|
|
}
|
|
})
|
|
|
|
router.get('/search', async (req, res, next) => {
|
|
try {
|
|
const filters = parseQuery(searchSchema, req)
|
|
const pagination = parseQuery(paginationSchema, req)
|
|
ok(res, await service.searchVehicles({ ...filters, ...pagination }))
|
|
} catch (err) {
|
|
if (isDatabaseUnavailableError(err)) return res.json({ data: [] })
|
|
next(err)
|
|
}
|
|
})
|
|
|
|
router.post('/reservations', async (req, res, next) => {
|
|
try {
|
|
const body = parseBody(marketplaceReservationSchema, req)
|
|
const result = await service.createMarketplaceReservation(body)
|
|
created(res, result)
|
|
} catch (err) {
|
|
if (isDatabaseUnavailableError(err)) {
|
|
return res.status(503).json({ error: 'database_unavailable', message: 'Service temporarily unavailable', statusCode: 503 })
|
|
}
|
|
next(err)
|
|
}
|
|
})
|
|
|
|
router.post('/events', async (req, res, next) => {
|
|
try {
|
|
const body = parseBody(marketplaceFunnelEventSchema, req)
|
|
ok(res, await service.trackMarketplaceFunnelEvent(body, req.renterId))
|
|
} catch (err) {
|
|
if (isDatabaseUnavailableError(err)) {
|
|
return res.status(503).json({ error: 'database_unavailable', message: 'Analytics events are temporarily unavailable', statusCode: 503 })
|
|
}
|
|
next(err)
|
|
}
|
|
})
|
|
|
|
router.get('/review/:token', async (req, res, next) => {
|
|
try {
|
|
const { token } = parseParams(reviewTokenSchema, req)
|
|
ok(res, await service.getReviewContext(token))
|
|
} catch (err) { next(err) }
|
|
})
|
|
|
|
router.post('/review/:token', async (req, res, next) => {
|
|
try {
|
|
const { token } = parseParams(reviewTokenSchema, req)
|
|
const body = parseBody(reviewBodySchema, req)
|
|
const result = await service.submitReview(token, body)
|
|
created(res, result)
|
|
} catch (err) { next(err) }
|
|
})
|
|
|
|
router.post('/offers/:code/validate', async (req, res, next) => {
|
|
try {
|
|
const { code } = parseParams(offerCodeParamSchema, req)
|
|
ok(res, await service.validateOfferCode(code))
|
|
} catch (err) {
|
|
if (isDatabaseUnavailableError(err)) {
|
|
return res.status(503).json({ error: 'database_unavailable', message: 'Offer validation is temporarily unavailable', statusCode: 503 })
|
|
}
|
|
next(err)
|
|
}
|
|
})
|
|
|
|
router.get('/:slug', async (req, res, next) => {
|
|
try {
|
|
const { slug } = parseParams(slugParamSchema, req)
|
|
ok(res, await service.getCompanyPage(slug))
|
|
} catch (err) {
|
|
if (isDatabaseUnavailableError(err)) {
|
|
return res.status(503).json({ error: 'database_unavailable', message: 'Marketplace data is temporarily unavailable', statusCode: 503 })
|
|
}
|
|
next(err)
|
|
}
|
|
})
|
|
|
|
router.get('/:slug/reviews', async (req, res, next) => {
|
|
try {
|
|
const { slug } = parseParams(slugParamSchema, req)
|
|
ok(res, await service.getCompanyReviews(slug))
|
|
} catch (err) {
|
|
if (isDatabaseUnavailableError(err)) return res.json({ data: [] })
|
|
next(err)
|
|
}
|
|
})
|
|
|
|
router.get('/:slug/vehicles', async (req, res, next) => {
|
|
try {
|
|
const { slug } = parseParams(slugParamSchema, req)
|
|
ok(res, await service.getCompanyVehicles(slug))
|
|
} catch (err) {
|
|
if (isDatabaseUnavailableError(err)) return res.json({ data: [] })
|
|
next(err)
|
|
}
|
|
})
|
|
|
|
router.get('/:slug/vehicles/:id', async (req, res, next) => {
|
|
try {
|
|
const { slug, id } = parseParams(vehicleParamSchema, req)
|
|
ok(res, await service.getVehicleDetail(slug, id))
|
|
} catch (err) {
|
|
if (isDatabaseUnavailableError(err)) {
|
|
return res.status(503).json({ error: 'database_unavailable', message: 'Vehicle details are temporarily unavailable', statusCode: 503 })
|
|
}
|
|
next(err)
|
|
}
|
|
})
|
|
|
|
router.get('/:slug/vehicles/:id/availability', async (req, res, next) => {
|
|
try {
|
|
const { slug, id } = parseParams(vehicleParamSchema, req)
|
|
const { startDate, endDate } = parseQuery(vehicleAvailabilityQuerySchema, req)
|
|
ok(res, await service.getMarketplaceVehicleAvailability(slug, id, { startDate, endDate }))
|
|
} catch (err) {
|
|
if (isDatabaseUnavailableError(err)) {
|
|
return res.status(503).json({ error: 'database_unavailable', message: 'Availability checks are temporarily unavailable', statusCode: 503 })
|
|
}
|
|
next(err)
|
|
}
|
|
})
|
|
|
|
router.get('/:slug/offers', async (req, res, next) => {
|
|
try {
|
|
const { slug } = parseParams(slugParamSchema, req)
|
|
ok(res, await service.getCompanyOffers(slug))
|
|
} catch (err) {
|
|
if (isDatabaseUnavailableError(err)) return res.json({ data: [] })
|
|
next(err)
|
|
}
|
|
})
|
|
|
|
export default router
|