This repository has been archived on 2026-08-11. You can view files and clone it, but cannot push or open issues or pull requests.
Gishen-Mob/app/(root)/(screens)/orders/code/[id].tsx
kirukib 858972b5ca Add multi-provider login and guest pharmacist order codes.
Guests can generate a shareable GSH code for admin fulfillment; sign-in now supports Google, email, phone, and Telegram demos, with the backend spec updated.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-07 16:11:23 +03:00

276 lines
8.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Ionicons } from "@expo/vector-icons";
import * as Clipboard from "expo-clipboard";
import { router, useLocalSearchParams } from "expo-router";
import { useState } from "react";
import {
Alert,
Image,
Linking,
Pressable,
ScrollView,
Share,
View,
} from "react-native";
import { Button } from "@/components/ui/Button";
import { AppHeader } from "@/components/ui/Header";
import { Screen } from "@/components/ui/Screen";
import { Text } from "@/components/ui/Text";
import { buildPharmacistOrderShareText } from "@/lib/commerce";
import { routes } from "@/lib/routes";
import { useOrdersStore } from "@/lib/stores/ordersStore";
import { colors, fonts, gutter, radii, shadows } from "@/lib/theme";
import { formatETB, WHATSAPP_NUMBER } from "@/lib/utils";
/**
* Screenshot-friendly pharmacist order code card.
* Guests copy / share / screenshot this so staff can create the order in admin.
*/
export default function PharmacistOrderCodeScreen() {
const { id } = useLocalSearchParams<{ id: string }>();
const order = useOrdersStore((s) => s.getById(id));
const [copied, setCopied] = useState(false);
if (!order?.pickupCode) {
return (
<Screen>
<AppHeader title="Order code" />
<View style={{ padding: gutter }}>
<Text variant="body" color={colors.muted}>
No pharmacist order code found for this order.
</Text>
<Button
title="Back to orders"
style={{ marginTop: 16 }}
onPress={() => router.replace(routes.orders)}
/>
</View>
</Screen>
);
}
const shareText = buildPharmacistOrderShareText(order);
const due = order.selfPay ?? order.total;
const copyCode = async () => {
await Clipboard.setStringAsync(order.pickupCode!);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};
const copyFull = async () => {
await Clipboard.setStringAsync(shareText);
Alert.alert("Copied", "Order details copied — paste into chat or admin notes.");
};
const share = async () => {
try {
await Share.share({ message: shareText, title: `Gishen code ${order.pickupCode}` });
} catch {
// user dismissed
}
};
const whatsapp = () => {
Linking.openURL(
`https://wa.me/${WHATSAPP_NUMBER}?text=${encodeURIComponent(shareText)}`
);
};
return (
<Screen>
<AppHeader
title="Pharmacist code"
subtitle="Copy, share, or screenshot"
/>
<ScrollView
contentContainerStyle={{
paddingHorizontal: gutter,
paddingBottom: 48,
gap: 16,
}}
>
<Text variant="bodySm" color={colors.muted}>
Share this code with a Gishen pharmacist. They enter it on the admin page
to create your order. Pay when you collect.
</Text>
{/* Clean card — ideal for device screenshots */}
<View
style={{
borderRadius: radii.lg,
overflow: "hidden",
backgroundColor: colors.surface,
borderWidth: 1,
borderColor: colors.brandBorder,
...shadows.md,
}}
>
<View
style={{
backgroundColor: colors.brand,
paddingVertical: 20,
paddingHorizontal: 20,
alignItems: "center",
gap: 10,
}}
>
<Image
source={require("@/assets/logo/gishen-logo.png")}
style={{ width: 48, height: 48, borderRadius: 12 }}
resizeMode="contain"
/>
<Text variant="h3" style={{ textAlign: "center" }}>
Gishen Pharmacy
</Text>
<Text variant="caption" style={{ textAlign: "center", opacity: 0.85 }}>
Pharmacist order code
</Text>
</View>
<View style={{ padding: 22, alignItems: "center" }}>
<Text variant="caption" color={colors.subtle} style={{ letterSpacing: 1 }}>
SHOW OR SHARE THIS CODE
</Text>
<Text
variant="display"
style={{
marginTop: 10,
letterSpacing: 3,
fontFamily: fonts.bold,
fontSize: 36,
lineHeight: 42,
}}
>
{order.pickupCode}
</Text>
<Text
variant="bodySm"
color={colors.muted}
style={{ marginTop: 12, textAlign: "center" }}
>
Enter on admin → create order
</Text>
</View>
<View
style={{
borderTopWidth: 1,
borderTopColor: colors.line,
padding: 18,
gap: 8,
}}
>
<Row label="Customer" value={order.customerName ?? "—"} />
<Row label="Phone" value={order.customerPhone ?? "—"} />
<Row label="Items" value={`${order.items.length}`} />
{order.items.slice(0, 6).map((item) => (
<Text
key={item.productId}
variant="caption"
color={colors.subtle}
style={{ paddingLeft: 2 }}
>
· {item.name} ×{item.quantity}
</Text>
))}
{order.items.length > 6 ? (
<Text variant="caption" color={colors.subtle}>
· +{order.items.length - 6} more
</Text>
) : null}
<View
style={{
marginTop: 8,
paddingTop: 12,
borderTopWidth: 1,
borderTopColor: colors.line,
flexDirection: "row",
justifyContent: "space-between",
alignItems: "baseline",
}}
>
<Text variant="label" color={colors.muted}>
Total due
</Text>
<Text variant="priceLg">{formatETB(due)}</Text>
</View>
<Text variant="caption" color={colors.subtle} style={{ marginTop: 4 }}>
Pay at branch when collecting
</Text>
</View>
</View>
<View
style={{
flexDirection: "row",
alignItems: "center",
gap: 8,
paddingHorizontal: 4,
}}
>
<Ionicons name="camera-outline" size={16} color={colors.subtle} />
<Text variant="caption" color={colors.subtle} style={{ flex: 1 }}>
Tip: screenshot the card above to show in person or send as an image.
</Text>
</View>
<View style={{ gap: 10 }}>
<Button
title={copied ? "Code copied" : "Copy code"}
icon={copied ? "checkmark-circle" : "copy-outline"}
onPress={copyCode}
/>
<View style={{ flexDirection: "row", gap: 10 }}>
<View style={{ flex: 1 }}>
<Button title="Share" icon="share-outline" variant="soft" onPress={share} />
</View>
<View style={{ flex: 1 }}>
<Button
title="WhatsApp"
icon="logo-whatsapp"
variant="outline"
onPress={whatsapp}
/>
</View>
</View>
<Pressable onPress={copyFull} hitSlop={8}>
<Text
variant="label"
color={colors.brandText}
style={{ textAlign: "center", marginTop: 4 }}
>
Copy full order details
</Text>
</Pressable>
</View>
<View style={{ gap: 10, marginTop: 4 }}>
<Button
title="View order"
variant="ghost"
onPress={() => router.replace(routes.orderDetail(order.id))}
/>
<Button
title="Done — back home"
variant="dark"
onPress={() => router.replace(routes.home)}
/>
</View>
</ScrollView>
</Screen>
);
}
function Row({ label, value }: { label: string; value: string }) {
return (
<View style={{ flexDirection: "row", justifyContent: "space-between", gap: 12 }}>
<Text variant="caption" color={colors.subtle}>
{label}
</Text>
<Text variant="label" style={{ flexShrink: 1, textAlign: "right" }}>
{value}
</Text>
</View>
);
}