import AsyncStorage from "@react-native-async-storage/async-storage"; import { create } from "zustand"; import { createJSONStorage, persist } from "zustand/middleware"; import { seedOrders } from "@/lib/data/seed"; import type { CartItem } from "@/lib/stores/cartStore"; import type { Fulfillment, PaymentMethod } from "@/lib/stores/locationStore"; export type OrderStatus = | "requested" | "confirmed" | "paid" | "dispatched" | "delivered" | "completed" | "cancelled"; export type Order = { id: string; createdAt: string; items: CartItem[]; subtotal: number; deliveryFee: number; discount: number; voucherCode?: string | null; total: number; fulfillment: Fulfillment; branchId?: string | null; areaLabel?: string; addressId?: string | null; addressLine?: string; paymentMethod: PaymentMethod; status: OrderStatus; riderAssigned?: boolean; corporateCovered?: number; selfPay?: number; customerName?: string; customerPhone?: string; notes?: string; /** Guest / pickup QR-style code shown at any branch counter */ pickupCode?: string | null; /** When true, order can be fulfilled at any Gishen branch */ anyBranch?: boolean; isGuestOrder?: boolean; timeline?: { at: string; label: string; status: OrderStatus | "created" }[]; }; type OrdersState = { orders: Order[]; addOrder: ( order: Omit & { discount?: number; status?: OrderStatus; } ) => Order; updateStatus: (id: string, status: OrderStatus) => void; cancelOrder: (id: string) => void; getById: (id: string) => Order | undefined; getByPickupCode: (code: string) => Order | undefined; }; function timelineFor(status: OrderStatus, createdAt: string) { const steps: Order["timeline"] = [ { at: createdAt, label: "Order placed", status: "created" }, ]; const add = (label: string, s: OrderStatus, hours: number) => { const d = new Date(createdAt); d.setHours(d.getHours() + hours); steps!.push({ at: d.toISOString(), label, status: s }); }; if (["confirmed", "paid", "dispatched", "delivered", "completed"].includes(status)) { add("Confirmed by pharmacy", "confirmed", 0.2); } if (["paid", "dispatched", "delivered", "completed"].includes(status) && status !== "confirmed") { add("Payment received", "paid", 0.4); } if (["dispatched", "delivered", "completed"].includes(status)) { add("Out for delivery / ready for pickup", "dispatched", 1); } if (["delivered", "completed"].includes(status)) { add("Delivered / collected", "delivered", 3); } if (status === "cancelled") { steps.push({ at: new Date().toISOString(), label: "Order cancelled", status: "cancelled", }); } return steps; } export const useOrdersStore = create()( persist( (set, get) => ({ orders: seedOrders.map((o) => ({ ...o, discount: o.discount ?? 0, customerName: o.customerName ?? "Kirukib Abebe", customerPhone: o.customerPhone ?? "+251911000000", notes: o.notes ?? "", timeline: o.timeline ?? timelineFor(o.status, o.createdAt), })), addOrder: (payload) => { const createdAt = new Date().toISOString(); const discount = payload.discount ?? 0; const status = payload.status ?? (payload.paymentMethod === "pay_at_branch" ? "confirmed" : "paid"); const order: Order = { ...payload, discount, id: `ord_${Date.now()}`, createdAt, status, riderAssigned: false, timeline: timelineFor(status, createdAt), }; set({ orders: [order, ...get().orders] }); return order; }, updateStatus: (id, status) => set({ orders: get().orders.map((o) => { if (o.id !== id) return o; const next = { ...o, status, riderAssigned: status === "dispatched" || status === "delivered" ? true : o.riderAssigned, }; const stamp = new Date().toISOString(); const label = status === "dispatched" ? "Rider assigned / ready" : status === "delivered" ? "Delivered / collected" : status === "cancelled" ? "Order cancelled" : `Status: ${status}`; return { ...next, timeline: [...(o.timeline ?? []), { at: stamp, label, status }], }; }), }), cancelOrder: (id) => get().updateStatus(id, "cancelled"), getById: (id) => get().orders.find((o) => o.id === id), getByPickupCode: (code) => { const normalized = code.trim().toUpperCase(); if (!normalized) return undefined; return get().orders.find( (o) => (o.pickupCode ?? "").toUpperCase() === normalized ); }, }), { name: "gishen-orders", storage: createJSONStorage(() => AsyncStorage), version: 4, migrate: (persisted: unknown) => { const state = (persisted ?? {}) as Partial; if (!state.orders?.length) { return { ...state, orders: seedOrders.map((o) => ({ ...o, discount: o.discount ?? 0, customerName: o.customerName ?? "Kirukib Abebe", customerPhone: o.customerPhone ?? "+251911000000", timeline: timelineFor(o.status, o.createdAt), })), }; } return { ...state, orders: state.orders.map((o) => ({ ...o, discount: o.discount ?? 0, timeline: o.timeline ?? timelineFor(o.status, o.createdAt), })), }; }, } ) );