Ship Expo Router screens, seeded stores, and polished UX so auth, shop, checkout, prescriptions, loyalty, family, and account processes work end-to-end offline. Co-authored-by: Cursor <cursoragent@cursor.com>
123 lines
4.2 KiB
TypeScript
123 lines
4.2 KiB
TypeScript
import { useLocalSearchParams, router } from "expo-router";
|
||
import { useEffect } from "react";
|
||
import { View } from "react-native";
|
||
import MapView, { Marker } from "@/components/maps/AppMap";
|
||
import { Badge } from "@/components/ui/Badge";
|
||
import { Button } from "@/components/ui/Button";
|
||
import { Card, InfoRow } from "@/components/ui/Card";
|
||
import { AppHeader } from "@/components/ui/Header";
|
||
import { Screen } from "@/components/ui/Screen";
|
||
import { Text } from "@/components/ui/Text";
|
||
import { getBranchById } from "@/lib/data/branches";
|
||
import { routes } from "@/lib/routes";
|
||
import { useOrdersStore } from "@/lib/stores/ordersStore";
|
||
import { colors, gutter } from "@/lib/theme";
|
||
import { formatETB } from "@/lib/utils";
|
||
|
||
export default function TrackingScreen() {
|
||
const { id } = useLocalSearchParams<{ id: string }>();
|
||
const order = useOrdersStore((s) => s.orders.find((o) => o.id === id));
|
||
const updateStatus = useOrdersStore((s) => s.updateStatus);
|
||
const branch = order?.branchId ? getBranchById(order.branchId) : undefined;
|
||
|
||
useEffect(() => {
|
||
if (!order) return;
|
||
if (order.fulfillment === "pickup") return;
|
||
if (order.riderAssigned || order.status === "cancelled" || order.status === "delivered") {
|
||
return;
|
||
}
|
||
if (order.status === "paid" || order.status === "confirmed") {
|
||
const t = setTimeout(() => updateStatus(order.id, "dispatched"), 2500);
|
||
return () => clearTimeout(t);
|
||
}
|
||
}, [order?.id, order?.status, order?.fulfillment]);
|
||
|
||
if (!order) {
|
||
return (
|
||
<Screen>
|
||
<AppHeader title="Tracking" />
|
||
<View style={{ padding: gutter }}>
|
||
<Text variant="body" color={colors.muted}>
|
||
Order not found.
|
||
</Text>
|
||
</View>
|
||
</Screen>
|
||
);
|
||
}
|
||
|
||
const lat = branch?.lat ?? 9.03;
|
||
const lng = branch?.lng ?? 38.74;
|
||
const isPickup = order.fulfillment === "pickup";
|
||
|
||
return (
|
||
<Screen>
|
||
<AppHeader
|
||
title={isPickup ? "Pickup status" : "Live tracking"}
|
||
subtitle={order.id}
|
||
right={<Badge label={order.status} tone="brand" />}
|
||
/>
|
||
<MapView
|
||
style={{ flex: 1, marginHorizontal: gutter, borderRadius: 20, overflow: "hidden" }}
|
||
initialRegion={{
|
||
latitude: lat,
|
||
longitude: lng,
|
||
latitudeDelta: 0.06,
|
||
longitudeDelta: 0.06,
|
||
}}
|
||
>
|
||
<Marker
|
||
coordinate={{ latitude: lat, longitude: lng }}
|
||
title={isPickup ? branch?.name ?? "Branch" : "Delivery area"}
|
||
pinColor={colors.brand}
|
||
/>
|
||
{!isPickup && order.riderAssigned ? (
|
||
<Marker
|
||
coordinate={{ latitude: lat - 0.01, longitude: lng + 0.012 }}
|
||
title="Rider"
|
||
description={order.status}
|
||
/>
|
||
) : null}
|
||
</MapView>
|
||
|
||
<View style={{ padding: gutter, gap: 12 }}>
|
||
<Card elevated={false}>
|
||
<Text variant="h3">
|
||
{isPickup
|
||
? order.status === "delivered" || order.status === "completed"
|
||
? "Collected"
|
||
: "Ready for pickup soon"
|
||
: order.riderAssigned
|
||
? "Rider on the way"
|
||
: "Preparing your order"}
|
||
</Text>
|
||
<Text variant="bodySm" color={colors.muted} style={{ marginTop: 6 }}>
|
||
{isPickup
|
||
? `${branch?.name ?? "Branch"} · ${branch?.hours ?? ""} · ${branch?.area ?? order.areaLabel}`
|
||
: `${order.areaLabel ?? "Addis Ababa"} · ETA 25–40 min (mock)`}
|
||
</Text>
|
||
<InfoRow label="Total" value={formatETB(order.total)} />
|
||
<InfoRow label="Payment" value={order.paymentMethod} last />
|
||
</Card>
|
||
|
||
<Button
|
||
title="View full order"
|
||
variant="outline"
|
||
onPress={() => router.push(routes.orderDetail(order.id))}
|
||
/>
|
||
{!isPickup && order.status !== "delivered" && order.status !== "cancelled" ? (
|
||
<Button
|
||
title="Mark delivered (demo)"
|
||
onPress={() => updateStatus(order.id, "delivered")}
|
||
/>
|
||
) : null}
|
||
{isPickup && order.status !== "delivered" && order.status !== "cancelled" ? (
|
||
<Button
|
||
title="Mark collected (demo)"
|
||
onPress={() => updateStatus(order.id, "delivered")}
|
||
/>
|
||
) : null}
|
||
</View>
|
||
</Screen>
|
||
);
|
||
}
|