diff --git a/src/App.jsx b/src/App.jsx
index 38e7dc2..4c07c34 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,80 +1,27 @@
-import { useCallback } from 'react'
-import {
- Link,
- Navigate,
- NavLink,
- Outlet,
- Route,
- Routes,
- useLocation,
- useNavigate,
-} from 'react-router-dom'
+import { Navigate, Outlet, Route, Routes } from 'react-router-dom'
+import LoginRoute from './routes/Login.jsx'
+import OrdersRoute from './routes/Orders/Index.jsx'
+import ProfileRoute from './routes/Profile.jsx'
import ProtectedRoute from './components/ProtectedRoute.jsx'
-import { useAuth } from './context/AuthContext.jsx'
-import LoginPage from './pages/Login.jsx'
-import SettingsPage from './pages/Settings.jsx'
-import OrdersFeed from './pages/orders/OrdersFeed.jsx'
-import OrderDetails from './pages/orders/OrderDetails.jsx'
-import OrderCamera from './pages/orders/OrderCamera.jsx'
-import OrderSignature from './pages/orders/OrderSignature.jsx'
-import OrderBypass from './pages/orders/OrderBypass.jsx'
-import OrderCancel from './pages/orders/OrderCancel.jsx'
-import './App.css'
+import Header from './components/Header.jsx'
+import BottomNav from './components/BottomNav.jsx'
+import { useAuth } from './hooks/useAuth.jsx'
+import { useLocationTracking } from './hooks/useLocationTracking.ts'
+import { OrdersProvider } from './hooks/useOrders.jsx'
-function AppLayout() {
- const { user, logout } = useAuth()
- const navigate = useNavigate()
- const location = useLocation()
-
- const handleLogout = useCallback(() => {
- logout()
- navigate('/login', { replace: true })
- }, [logout, navigate])
-
- const isSettingsRoute = location.pathname.startsWith('/settings')
-
- const navItems = [
- { to: '/orders', label: 'Orders' },
- { to: '/settings', label: 'Settings' },
- ]
+function AppShell() {
+ const { driver } = useAuth()
+ const trackingActive = useLocationTracking({ isActive: driver?.status !== 'OFFLINE' })
return (
-
-
-
-
- Jason's Liquor Drivers
-
-
-
-
- {isSettingsRoute ? (
-
- {user?.name?.first} {user?.name?.last}
- {user?.email}
-
- ) : null}
-
-
-
-
-
-
+
+
+
+
+
+
+
+
)
}
@@ -82,19 +29,14 @@ function AppLayout() {
export default function App() {
return (
- } />
- }>
- }>
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
-
+ } />
+ }>
+ }>
+ } />
+ } />
+ } />
+
} />
)
diff --git a/src/App.tsx b/src/App.tsx
deleted file mode 100644
index ca5860b..0000000
--- a/src/App.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import { Navigate, Outlet, Route, Routes } from 'react-router-dom'
-import LoginRoute from './routes/Login'
-import OrdersRoute from './routes/Orders/Index'
-import ProfileRoute from './routes/Profile'
-import { ProtectedRoute } from './components/ProtectedRoute'
-import { Header } from './components/Header'
-import { BottomNav } from './components/BottomNav'
-import { useAuth } from './hooks/useAuth'
-import { useLocationTracking } from './hooks/useLocationTracking'
-import { OrdersProvider } from './hooks/useOrders'
-
-function AppShell(): JSX.Element {
- const { driver } = useAuth()
- const trackingActive = useLocationTracking({ isActive: driver?.status !== 'OFFLINE' })
-
- return (
-
-
-
-
-
-
-
-
-
- )
-}
-
-export default function App(): JSX.Element {
- return (
-
- } />
- }>
- }>
- } />
- } />
- } />
-
-
- } />
-
- )
-}
diff --git a/src/api/mockData.ts b/src/api/mockData.ts
index e381c8e..1dd799a 100644
--- a/src/api/mockData.ts
+++ b/src/api/mockData.ts
@@ -1,4 +1,4 @@
-import { AuthResponse, Driver, Message, Order } from '../types'
+import { AuthResponse, Driver, Message } from '../types'
const now = new Date()
@@ -14,71 +14,6 @@ export const mockDriver: Driver = {
status: 'ONLINE',
}
-export const mockOrders: Order[] = [
- {
- id: 'order-1',
- number: 'JL-2847',
- total: 127.5,
- status: 'NEW',
- requiresIdCheck: true,
- requiresPaymentCheck: true,
- createdAt: minutesAgo(35),
- customer: {
- name: 'Michael Rodriguez',
- phone: '(555) 123-4567',
- address: '85 Dolores Street, San Francisco, CA 94110',
- },
- priority: true,
- assignedDriverId: 'driver-1',
- items: [
- { id: 'item-1', name: 'Johnnie Walker Black Label', quantity: 1 },
- { id: 'item-2', name: 'Grey Goose Vodka', quantity: 1 },
- { id: 'item-3', name: 'Corona Extra 6-pack', quantity: 1 },
- ],
- },
- {
- id: 'order-2',
- number: 'JL-2846',
- total: 156,
- status: 'IN_PROGRESS',
- requiresIdCheck: true,
- requiresPaymentCheck: true,
- createdAt: minutesAgo(28),
- customer: {
- name: 'John Doe',
- phone: '(555) 246-8135',
- address: '123 Market Street, San Francisco, CA 94103',
- lat: 37.7937,
- lng: -122.396,
- },
- assignedDriverId: 'driver-1',
- items: [
- { id: 'item-4', name: 'Don Julio Blanco', quantity: 1 },
- { id: 'item-5', name: 'Casamigos Reposado', quantity: 1 },
- { id: 'item-6', name: 'Limes', quantity: 6 },
- ],
- },
- {
- id: 'order-3',
- number: 'JL-2845',
- total: 98.4,
- status: 'COMPLETED',
- requiresIdCheck: true,
- requiresPaymentCheck: true,
- createdAt: minutesAgo(125),
- customer: {
- name: 'Alice Lee',
- phone: '(555) 678-9012',
- address: '678 Mission Street, San Francisco, CA 94105',
- },
- assignedDriverId: 'driver-1',
- items: [
- { id: 'item-7', name: 'Veuve Clicquot Brut', quantity: 2 },
- { id: 'item-8', name: 'San Pellegrino', quantity: 4 },
- ],
- },
-]
-
export const mockAuthResponse: AuthResponse = {
token: 'demo-token',
driver: mockDriver,
diff --git a/src/api/orders.ts b/src/api/orders.ts
deleted file mode 100644
index 6766aca..0000000
--- a/src/api/orders.ts
+++ /dev/null
@@ -1,77 +0,0 @@
-import { apiClient, safeRequest } from './client'
-import { mockOrders } from './mockData'
-import { Order } from '../types'
-
-export async function getOrders(): Promise
{
- return safeRequest(
- async () => {
- const response = await apiClient.get('/orders')
- return response.data
- },
- async () => mockOrders,
- )
-}
-
-export async function acceptOrder(orderId: string): Promise {
- return safeRequest(
- async () => {
- const response = await apiClient.post(`/orders/${orderId}/accept`)
- return response.data
- },
- async () => {
- const existing = mockOrders.find((order) => order.id === orderId)
- if (!existing) {
- throw new Error('Order not found')
- }
- existing.status = 'IN_PROGRESS'
- return existing
- },
- )
-}
-
-export async function arriveOrder(orderId: string): Promise {
- return safeRequest(
- async () => {
- const response = await apiClient.post(`/orders/${orderId}/arrive`)
- return response.data
- },
- async () => {
- const existing = mockOrders.find((order) => order.id === orderId)
- if (!existing) {
- throw new Error('Order not found')
- }
- existing.status = 'ARRIVED'
- return existing
- },
- )
-}
-
-export async function completeOrder(orderId: string, signature?: string): Promise {
- return safeRequest(
- async () => {
- const response = await apiClient.post(`/orders/${orderId}/complete`, { signature })
- return response.data
- },
- async () => {
- const existing = mockOrders.find((order) => order.id === orderId)
- if (!existing) {
- throw new Error('Order not found')
- }
- existing.status = 'COMPLETED'
- return existing
- },
- )
-}
-
-export function getElapsedMinutes(order: Order): number {
- const start = new Date(order.createdAt)
- const now = new Date()
- const diff = (now.getTime() - start.getTime()) / 60000
- return Math.max(0, diff)
-}
-
-export function getEta(order: Order): string {
- const minutes = getElapsedMinutes(order)
- const eta = new Date(new Date(order.createdAt).getTime() + Math.round(minutes) * 60000)
- return eta.toISOString()
-}
diff --git a/src/components/BottomNav.jsx b/src/components/BottomNav.jsx
new file mode 100644
index 0000000..e064d4b
--- /dev/null
+++ b/src/components/BottomNav.jsx
@@ -0,0 +1,35 @@
+import { NavLink } from 'react-router-dom'
+
+export default function BottomNav() {
+ return (
+
+ )
+}
diff --git a/src/components/BottomNav.tsx b/src/components/BottomNav.tsx
deleted file mode 100644
index 5e08fd0..0000000
--- a/src/components/BottomNav.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import { NavLink } from 'react-router-dom'
-
-export function BottomNav(): JSX.Element {
- return (
-
- )
-}
diff --git a/src/components/Header.jsx b/src/components/Header.jsx
new file mode 100644
index 0000000..b326644
--- /dev/null
+++ b/src/components/Header.jsx
@@ -0,0 +1,39 @@
+import { Link } from 'react-router-dom'
+import { useAuth } from '../hooks/useAuth.jsx'
+import { classNames } from '../utils/classNames.ts'
+
+const statusLabels = {
+ ONLINE: 'Online',
+ OFFLINE: 'Offline',
+ ON_DELIVERY: 'On Delivery',
+}
+
+export default function Header({ trackingActive }) {
+ const { driver } = useAuth()
+
+ return (
+
+ )
+}
diff --git a/src/components/Header.tsx b/src/components/Header.tsx
deleted file mode 100644
index e8fdd75..0000000
--- a/src/components/Header.tsx
+++ /dev/null
@@ -1,49 +0,0 @@
-import { Link } from 'react-router-dom'
-import { DriverStatus } from '../types'
-import { useAuth } from '../hooks/useAuth'
-import { classNames } from '../utils/classNames'
-
-interface HeaderProps {
- trackingActive: boolean
-}
-
-const statusLabels: Record = {
- ONLINE: 'Online',
- OFFLINE: 'Offline',
- ON_DELIVERY: 'On Delivery',
-}
-
-export function Header({ trackingActive }: HeaderProps): JSX.Element {
- const { driver } = useAuth()
-
- return (
-
- )
-}
diff --git a/src/components/ProtectedRoute.jsx b/src/components/ProtectedRoute.jsx
index b94e007..d35e1c4 100644
--- a/src/components/ProtectedRoute.jsx
+++ b/src/components/ProtectedRoute.jsx
@@ -1,19 +1,20 @@
-import { Navigate, Outlet } from 'react-router-dom'
-import { useAuth } from '../context/AuthContext'
+import { Navigate, Outlet, useLocation } from 'react-router-dom'
+import { useAuth } from '../hooks/useAuth.jsx'
-export default function ProtectedRoute({ redirectTo = '/login' }) {
- const { token, initialising } = useAuth()
+export default function ProtectedRoute() {
+ const { driver, loading } = useAuth()
+ const location = useLocation()
- if (initialising) {
+ if (loading) {
return (
-
-
+
+ Loading driver session…
)
}
- if (!token) {
- return
+ if (!driver) {
+ return
}
return
diff --git a/src/components/ProtectedRoute.tsx b/src/components/ProtectedRoute.tsx
deleted file mode 100644
index fc1b12e..0000000
--- a/src/components/ProtectedRoute.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import { Navigate, Outlet, useLocation } from 'react-router-dom'
-import { useAuth } from '../hooks/useAuth'
-
-export function ProtectedRoute(): JSX.Element {
- const { driver, loading } = useAuth()
- const location = useLocation()
-
- if (loading) {
- return (
-
- Loading driver session…
-
- )
- }
-
- if (!driver) {
- return
- }
-
- return
-}
diff --git a/src/components/SignaturePad.tsx b/src/components/SignaturePad.jsx
similarity index 87%
rename from src/components/SignaturePad.tsx
rename to src/components/SignaturePad.jsx
index ca7c591..224ebbe 100644
--- a/src/components/SignaturePad.tsx
+++ b/src/components/SignaturePad.jsx
@@ -1,12 +1,7 @@
import { useEffect, useRef } from 'react'
-interface SignaturePadProps {
- value: string | null
- onChange: (value: string | null) => void
-}
-
-export function SignaturePad({ value, onChange }: SignaturePadProps): JSX.Element {
- const canvasRef = useRef
(null)
+export default function SignaturePad({ value, onChange }) {
+ const canvasRef = useRef(null)
const drawing = useRef(false)
const hasSignature = useRef(false)
@@ -49,7 +44,7 @@ export function SignaturePad({ value, onChange }: SignaturePadProps): JSX.Elemen
const ctx = canvas.getContext('2d')
if (!ctx) return
- function getPoint(event: PointerEvent) {
+ function getPoint(event) {
const rect = canvas.getBoundingClientRect()
return {
x: event.clientX - rect.left,
@@ -57,7 +52,7 @@ export function SignaturePad({ value, onChange }: SignaturePadProps): JSX.Elemen
}
}
- function handlePointerDown(event: PointerEvent) {
+ function handlePointerDown(event) {
drawing.current = true
const { x, y } = getPoint(event)
ctx.beginPath()
@@ -65,7 +60,7 @@ export function SignaturePad({ value, onChange }: SignaturePadProps): JSX.Elemen
event.preventDefault()
}
- function handlePointerMove(event: PointerEvent) {
+ function handlePointerMove(event) {
if (!drawing.current) return
const { x, y } = getPoint(event)
ctx.lineTo(x, y)
@@ -74,7 +69,7 @@ export function SignaturePad({ value, onChange }: SignaturePadProps): JSX.Elemen
event.preventDefault()
}
- function handlePointerUp(event: PointerEvent) {
+ function handlePointerUp(event) {
if (!drawing.current) return
handlePointerMove(event)
drawing.current = false
diff --git a/src/components/Tabs.jsx b/src/components/Tabs.jsx
new file mode 100644
index 0000000..709ed7b
--- /dev/null
+++ b/src/components/Tabs.jsx
@@ -0,0 +1,19 @@
+export default function Tabs({ tabs, activeId, onChange }) {
+ return (
+
+ {tabs.map((tab) => (
+
+ ))}
+
+ )
+}
diff --git a/src/components/Tabs.tsx b/src/components/Tabs.tsx
deleted file mode 100644
index f899ab9..0000000
--- a/src/components/Tabs.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-interface TabOption {
- id: string
- label: string
- badge?: number
-}
-
-interface TabsProps {
- tabs: TabOption[]
- activeId: string
- onChange: (id: string) => void
-}
-
-export function Tabs({ tabs, activeId, onChange }: TabsProps): JSX.Element {
- return (
-
- {tabs.map((tab) => (
-
- ))}
-
- )
-}
diff --git a/src/components/TimerChip.tsx b/src/components/TimerChip.jsx
similarity index 57%
rename from src/components/TimerChip.tsx
rename to src/components/TimerChip.jsx
index 889cc6a..fdc6b5e 100644
--- a/src/components/TimerChip.tsx
+++ b/src/components/TimerChip.jsx
@@ -1,17 +1,26 @@
-import { Order } from '../types'
-import { getElapsedMinutes } from '../api/orders'
-
-interface TimerChipProps {
- order: Order
+function getElapsedMinutes(order) {
+ if (!order) {
+ return 0
+ }
+ const timestamp = order.createdAt ?? order.created_at ?? order.updatedAt
+ if (!timestamp) {
+ return 0
+ }
+ const start = new Date(timestamp)
+ if (Number.isNaN(start.getTime())) {
+ return 0
+ }
+ const diff = (Date.now() - start.getTime()) / 60000
+ return diff > 0 ? diff : 0
}
-function formatDuration(minutes: number): string {
+function formatDuration(minutes) {
const wholeMinutes = Math.floor(minutes)
const seconds = Math.floor((minutes - wholeMinutes) * 60)
return `${wholeMinutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`
}
-export function TimerChip({ order }: TimerChipProps): JSX.Element {
+export default function TimerChip({ order }) {
const elapsed = getElapsedMinutes(order)
const variant = elapsed < 20 ? 'normal' : elapsed < 35 ? 'warning' : 'priority'
diff --git a/src/components/ToastContainer.tsx b/src/components/ToastContainer.jsx
similarity index 64%
rename from src/components/ToastContainer.tsx
rename to src/components/ToastContainer.jsx
index a19041b..fffc562 100644
--- a/src/components/ToastContainer.tsx
+++ b/src/components/ToastContainer.jsx
@@ -1,6 +1,6 @@
-import { useToast } from '../hooks/useToast'
+import { useToast } from '../hooks/useToast.jsx'
-export function ToastContainer(): JSX.Element {
+export default function ToastContainer() {
const { toasts, dismiss } = useToast()
return (
@@ -11,7 +11,12 @@ export function ToastContainer(): JSX.Element {
{toast.title}
{toast.description ? {toast.description}
: null}
-
diff --git a/src/components/VerifyChecklist.tsx b/src/components/VerifyChecklist.jsx
similarity index 77%
rename from src/components/VerifyChecklist.tsx
rename to src/components/VerifyChecklist.jsx
index 335518f..c91c920 100644
--- a/src/components/VerifyChecklist.tsx
+++ b/src/components/VerifyChecklist.jsx
@@ -1,10 +1,4 @@
-interface VerifyChecklistProps {
- idChecked: boolean
- paymentChecked: boolean
- onChange: (next: { idChecked: boolean; paymentChecked: boolean }) => void
-}
-
-export function VerifyChecklist({ idChecked, paymentChecked, onChange }: VerifyChecklistProps): JSX.Element {
+export default function VerifyChecklist({ idChecked, paymentChecked, onChange }) {
return (