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:
Krikorios
2026-08-23 16:38:41 +03:00
parent fbe92c9d16
commit a0b297285a
75 changed files with 5158 additions and 2837 deletions
+34
View File
@@ -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 $38 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.`;