Add self-hosted auth, admin API, and owner web dashboard
- Replace Clerk with self-hosted JWT auth (register/login/verify, bcrypt passwords, Gmail OTP with console fallback) - Add lib/db.ts pg pool + transaction helpers; seed script migrates legacy Clerk-era schema (drop clerk_id, enforce UUID ids and unique email) - Add owner-gated admin API: stats, users, drivers CRUD, rides - Add dashboard/ Vite React owner dashboard (login, overview, users, fleet, rides) with dev-server proxy to avoid Expo CORS middleware - Add scripts/set-owner.mjs for role management
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
// Fare model tuned to the Lebanese market:
|
||||
// - Distance-based with a base fare (like CTaxi/local taxis), not time-only.
|
||||
// - Typical Beirut rides land in the $3–8 range riders expect.
|
||||
// - Prices are quoted in USD (the de facto ride-hailing currency) with an
|
||||
// L.B.P. equivalent shown for cash settlement.
|
||||
|
||||
export const FARE = {
|
||||
base: 1.5, // USD, flag drop
|
||||
perKm: 0.55, // USD per kilometer of the trip
|
||||
perMin: 0.15, // USD per minute of the trip
|
||||
minimum: 3.0, // USD minimum fare
|
||||
} as const;
|
||||
|
||||
// Parallel market rate used for the L.B.P. cash equivalent shown in-app.
|
||||
export const LBP_RATE = 89500;
|
||||
|
||||
export const calculateFare = ({
|
||||
distanceMeters,
|
||||
durationSeconds,
|
||||
}: {
|
||||
distanceMeters: number;
|
||||
durationSeconds: number;
|
||||
}): string => {
|
||||
const km = distanceMeters / 1000;
|
||||
const minutes = durationSeconds / 60;
|
||||
|
||||
const fare = FARE.base + km * FARE.perKm + minutes * FARE.perMin;
|
||||
|
||||
return Math.max(fare, FARE.minimum).toFixed(2);
|
||||
};
|
||||
|
||||
// Rounds to the nearest 1,000 L.B.P. — the smallest practical cash note.
|
||||
export const formatLBP = (usd: number): string =>
|
||||
`${(Math.round((usd * LBP_RATE) / 1000) * 1000).toLocaleString("en-US")} L.B.P.`;
|
||||
Reference in New Issue
Block a user