import { router } from "expo-router"; import { useEffect, useMemo, useState } from "react"; import { Alert, Linking, Pressable, ScrollView, View } from "react-native"; import { useTranslation } from "react-i18next"; import { Button } from "@/components/ui/Button"; import { Card, InfoRow } from "@/components/ui/Card"; import { Chip, Segmented } from "@/components/ui/Chip"; import { Field, OptionRow } from "@/components/ui/Field"; import { AppHeader } from "@/components/ui/Header"; import { Screen } from "@/components/ui/Screen"; import { StickyBar } from "@/components/ui/StickyBar"; import { Text } from "@/components/ui/Text"; import { DELIVERY_FEE, generatePickupCode, orderSubtotalTotal, voucherDiscount } from "@/lib/commerce"; import { branches } from "@/lib/data/branches"; import { routes } from "@/lib/routes"; import { useAddressStore } from "@/lib/stores/addressStore"; import { useAuthStore } from "@/lib/stores/authStore"; import { useCartStore } from "@/lib/stores/cartStore"; import { useFamilyStore } from "@/lib/stores/familyStore"; import { useLocationStore, type PaymentMethod } from "@/lib/stores/locationStore"; import { useNotificationStore } from "@/lib/stores/notificationStore"; import { useOrdersStore } from "@/lib/stores/ordersStore"; import { useProfileModeStore } from "@/lib/stores/profileModeStore"; import { colors, gutter } from "@/lib/theme"; import { formatETB, WHATSAPP_NUMBER } from "@/lib/utils"; export default function CheckoutScreen() { const { t } = useTranslation(); const items = useCartStore((s) => s.items); const clear = useCartStore((s) => s.clear); const subtotal = useCartStore((s) => s.subtotal()); const cartVoucher = useCartStore((s) => s.voucherCode); const setCartVoucher = useCartStore((s) => s.setVoucher); const fulfillment = useLocationStore((s) => s.fulfillment); const setFulfillment = useLocationStore((s) => s.setFulfillment); const branchId = useLocationStore((s) => s.branchId); const setBranchId = useLocationStore((s) => s.setBranchId); const areaLabel = useLocationStore((s) => s.areaLabel); const setAreaLabel = useLocationStore((s) => s.setAreaLabel); const payment = useLocationStore((s) => s.paymentPreference); const setPayment = useLocationStore((s) => s.setPaymentPreference); const addresses = useAddressStore((s) => s.addresses); const defaultAddress = useAddressStore((s) => s.defaultAddress()); const addOrder = useOrdersStore((s) => s.addOrder); const pushNotification = useNotificationStore((s) => s.push); const addPoints = useAuthStore((s) => s.addPoints); const user = useAuthStore((s) => s.user); const setActiveVoucher = useAuthStore((s) => s.setActiveVoucher); const quoteSplit = useProfileModeStore((s) => s.quoteSplit); const consumeAllowance = useProfileModeStore((s) => s.consumeAllowance); const mode = useProfileModeStore((s) => s.mode); const membership = useProfileModeStore((s) => s.activeMembership()); const familyMembers = useFamilyStore((s) => s.members); const activeMemberId = useFamilyStore((s) => s.activeMemberId); const setActiveMember = useFamilyStore((s) => s.setActiveMember); const isGuest = !!user?.isGuest; const [name, setName] = useState(user?.name && !user.isGuest ? user.name : ""); const [phone, setPhone] = useState(user?.phone ?? ""); const [notes, setNotes] = useState(""); const [addressId, setAddressId] = useState(defaultAddress?.id ?? ""); const [voucher, setVoucher] = useState( cartVoucher || user?.activeVoucher || "" ); const [forMemberId, setForMemberId] = useState(activeMemberId); /** Guests (and optional pickup) can fulfill at any branch with a quick code */ const [anyBranch, setAnyBranch] = useState(isGuest); useEffect(() => { if (!isGuest) return; if (fulfillment !== "pickup") setFulfillment("pickup"); setAnyBranch(true); if (payment !== "pay_at_branch") setPayment("pay_at_branch"); }, [isGuest, fulfillment, payment, setFulfillment, setPayment]); const selectedAddress = useMemo( () => addresses.find((a) => a.id === addressId) ?? defaultAddress, [addresses, addressId, defaultAddress] ); const effectiveFulfillment = isGuest ? "pickup" : fulfillment; const useAnyBranchPickup = effectiveFulfillment === "pickup" && (anyBranch || isGuest); const allowed = useMemo((): PaymentMethod[] => { const base: PaymentMethod[] = ["chapa", "telebirr", "mpesa"]; return effectiveFulfillment === "pickup" ? [...base, "pay_at_branch"] : base; }, [effectiveFulfillment]); const deliveryFee = effectiveFulfillment === "delivery" && items.length ? DELIVERY_FEE : 0; const discount = voucherDiscount(subtotal, voucher); const afterDiscount = Math.max(0, subtotal - discount); const split = mode === "corporate" && !isGuest ? quoteSplit(afterDiscount) : { covered: 0, selfPay: afterDiscount }; const total = orderSubtotalTotal({ subtotal: split.selfPay, deliveryFee, discount: 0, }); const pay = () => { if (!items.length) return; if (!name.trim() || phone.trim().length < 9) { Alert.alert("Contact details", "Enter your name and a valid phone number."); return; } if (!allowed.includes(payment) && !(useAnyBranchPickup && payment === "pay_at_branch")) { Alert.alert("Payment", "Select a valid payment method."); return; } if (effectiveFulfillment === "pickup" && !useAnyBranchPickup && !branchId) { Alert.alert("Pickup", "Select a branch, or choose any-branch quick code."); return; } if (effectiveFulfillment === "delivery" && !selectedAddress && !areaLabel.trim()) { Alert.alert("Delivery", "Choose a saved address or enter an area."); return; } const branch = branches.find((b) => b.id === branchId); const addressLine = selectedAddress ? `${selectedAddress.street}${selectedAddress.landmark ? ` · ${selectedAddress.landmark}` : ""}` : undefined; const forMember = familyMembers.find((m) => m.id === forMemberId); const orderNotes = [ notes.trim(), forMember ? `For family: ${forMember.name} (${forMember.relationship})` : "", isGuest ? "Pharmacist order code — enter in admin to create the order" : useAnyBranchPickup ? "Quick code — redeemable at any Gishen branch" : "", ] .filter(Boolean) .join(" · "); const pickupCode = isGuest || effectiveFulfillment === "pickup" ? generatePickupCode() : null; const fee = effectiveFulfillment === "pickup" ? 0 : deliveryFee; const order = addOrder({ items, subtotal, deliveryFee: fee, discount, voucherCode: discount ? voucher.trim().toUpperCase() : null, total: afterDiscount + fee, fulfillment: effectiveFulfillment, branchId: useAnyBranchPickup ? null : branchId, areaLabel: useAnyBranchPickup ? "Any Gishen branch" : effectiveFulfillment === "pickup" ? branch?.name ?? areaLabel : selectedAddress?.area ?? areaLabel, addressId: effectiveFulfillment === "delivery" ? selectedAddress?.id ?? null : null, addressLine: useAnyBranchPickup ? undefined : addressLine, paymentMethod: payment, corporateCovered: split.covered, selfPay: split.selfPay + fee, customerName: name.trim(), customerPhone: phone.trim(), notes: orderNotes, riderAssigned: false, pickupCode, anyBranch: useAnyBranchPickup || isGuest, isGuestOrder: isGuest, status: isGuest ? "requested" : useAnyBranchPickup || payment === "pay_at_branch" ? "confirmed" : undefined, }); if (forMemberId) setActiveMember(forMemberId); if (!isGuest && split.covered > 0) consumeAllowance(split.covered); if (!isGuest) addPoints(Math.max(1, Math.floor(afterDiscount / 10)), "Order reward"); if (discount) { setActiveVoucher(null); setCartVoucher(null); } clear(); pushNotification({ kind: "order", title: isGuest ? `Pharmacist code ${pickupCode}` : pickupCode ? `Pickup code ${pickupCode}` : "Order placed", body: isGuest ? `Share ${pickupCode} so a pharmacist can create your order in admin.` : pickupCode ? useAnyBranchPickup ? `Show ${pickupCode} at any Gishen branch counter to collect your order.` : `Show ${pickupCode} at ${branch?.name ?? "your branch"} to collect.` : `Your ${order.fulfillment} order is confirmed.`, href: isGuest && pickupCode ? routes.orderCode(order.id) : routes.orderDetail(order.id), }); if (isGuest && pickupCode) { router.replace(routes.orderCode(order.id) as never); return; } Alert.alert( pickupCode ? "Quick pickup code ready" : "Order placed", pickupCode ? `Your code is ${pickupCode}. ${ useAnyBranchPickup ? "Present it at any Gishen branch for fulfillment." : `Present it at ${branch?.name ?? "the branch"}.` }${ payment === "pay_at_branch" ? ` Pay ${formatETB(order.selfPay ?? order.total)} at the counter.` : "" }` : payment === "pay_at_branch" ? `Pay ${formatETB(order.selfPay ?? order.total)} at ${branch?.name ?? "the branch"}.` : `Mock ${labelPayment(payment, t)} payment of ${formatETB(order.total)} succeeded.`, [ { text: "View order", onPress: () => router.replace(routes.orderDetail(order.id)) }, { text: pickupCode ? "Done" : "Track", onPress: () => pickupCode ? router.replace(routes.orderDetail(order.id)) : router.replace(routes.tracking(order.id)), }, ] ); }; const whatsapp = () => { const lines = items .map((i) => `• ${i.name} x${i.quantity} — ${i.price * i.quantity} ETB`) .join("%0A"); const msg = `Gishen order%0AName: ${name}%0APhone: ${phone}%0A${lines}%0ATotal: ${total} ETB%0A${fulfillment}%0A${notes}`; Linking.openURL(`https://wa.me/${WHATSAPP_NUMBER}?text=${msg}`); }; if (!items.length) { return ( Your cart is empty. Add products before checking out.