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>
144 lines
4.9 KiB
TypeScript
144 lines
4.9 KiB
TypeScript
import { useState } from "react";
|
|
import { Alert, Linking, ScrollView, View } from "react-native";
|
|
import { Button } from "@/components/ui/Button";
|
|
import { Card, InfoRow } from "@/components/ui/Card";
|
|
import { Field } from "@/components/ui/Field";
|
|
import { AppHeader } from "@/components/ui/Header";
|
|
import { Screen } from "@/components/ui/Screen";
|
|
import { Text } from "@/components/ui/Text";
|
|
import { brand } from "@/lib/data/brand";
|
|
import { useAuthStore } from "@/lib/stores/authStore";
|
|
import { colors, gutter } from "@/lib/theme";
|
|
import { CALL_PHONE, CHATWOOT_BASE, WHATSAPP_NUMBER } from "@/lib/utils";
|
|
|
|
type Ticket = {
|
|
id: string;
|
|
at: string;
|
|
subject: string;
|
|
message: string;
|
|
status: "received" | "in_progress" | "resolved";
|
|
};
|
|
|
|
export default function ContactScreen() {
|
|
const user = useAuthStore((s) => s.user);
|
|
const [name, setName] = useState(user?.name ?? "");
|
|
const [subject, setSubject] = useState("Order help");
|
|
const [message, setMessage] = useState("");
|
|
const [tickets, setTickets] = useState<Ticket[]>([
|
|
{
|
|
id: "tkt_demo_1",
|
|
at: new Date(Date.now() - 1000 * 60 * 60 * 26).toISOString(),
|
|
subject: "Refill timing",
|
|
message: "When will my Metformin refill be ready at CMC?",
|
|
status: "resolved",
|
|
},
|
|
]);
|
|
|
|
return (
|
|
<Screen>
|
|
<AppHeader title="Contact" subtitle="Talk to Gishen support" />
|
|
<ScrollView contentContainerStyle={{ paddingHorizontal: gutter, paddingBottom: 40, gap: 14 }}>
|
|
<Card elevated={false}>
|
|
<InfoRow label="Phone" value={brand.phoneDisplay} />
|
|
<InfoRow label="Email" value={brand.email} />
|
|
<InfoRow label="Orders email" value={brand.orderEmail} last />
|
|
<View style={{ flexDirection: "row", gap: 8, marginTop: 12, flexWrap: "wrap" }}>
|
|
<Button
|
|
title="Call"
|
|
size="sm"
|
|
fullWidth={false}
|
|
icon="call-outline"
|
|
onPress={() => Linking.openURL(`tel:${CALL_PHONE}`)}
|
|
/>
|
|
<Button
|
|
title="WhatsApp"
|
|
size="sm"
|
|
variant="outline"
|
|
fullWidth={false}
|
|
icon="logo-whatsapp"
|
|
onPress={() => Linking.openURL(`https://wa.me/${WHATSAPP_NUMBER}`)}
|
|
/>
|
|
<Button
|
|
title="Live chat"
|
|
size="sm"
|
|
variant="soft"
|
|
fullWidth={false}
|
|
icon="chatbubble-ellipses-outline"
|
|
onPress={() => Linking.openURL(CHATWOOT_BASE)}
|
|
/>
|
|
</View>
|
|
</Card>
|
|
|
|
<Card elevated={false}>
|
|
<Text variant="h3" style={{ marginBottom: 12 }}>
|
|
Send a message
|
|
</Text>
|
|
<View style={{ gap: 12 }}>
|
|
<Field label="Your name" value={name} onChangeText={setName} />
|
|
<Field label="Subject" value={subject} onChangeText={setSubject} />
|
|
<Field
|
|
label="Message"
|
|
value={message}
|
|
onChangeText={setMessage}
|
|
placeholder="How can we help?"
|
|
multiline
|
|
style={{ height: 100, textAlignVertical: "top", paddingTop: 12 }}
|
|
/>
|
|
<Button
|
|
title="Send message"
|
|
onPress={() => {
|
|
if (!message.trim()) {
|
|
Alert.alert("Message required", "Tell us how we can help.");
|
|
return;
|
|
}
|
|
const id = `tkt_${Date.now().toString().slice(-6)}`;
|
|
setTickets((prev) => [
|
|
{
|
|
id,
|
|
at: new Date().toISOString(),
|
|
subject: subject.trim() || "General",
|
|
message: message.trim(),
|
|
status: "received",
|
|
},
|
|
...prev,
|
|
]);
|
|
setMessage("");
|
|
Alert.alert(
|
|
"Ticket created",
|
|
`Reference ${id}. We'll reply by phone or WhatsApp (demo — not sent to a server).`
|
|
);
|
|
}}
|
|
/>
|
|
</View>
|
|
</Card>
|
|
|
|
<Card elevated={false}>
|
|
<Text variant="h3" style={{ marginBottom: 10 }}>
|
|
Your tickets
|
|
</Text>
|
|
{tickets.map((t) => (
|
|
<View
|
|
key={t.id}
|
|
style={{
|
|
paddingVertical: 10,
|
|
borderBottomWidth: 1,
|
|
borderBottomColor: colors.line,
|
|
}}
|
|
>
|
|
<Text variant="h3">
|
|
{t.subject} · {t.id}
|
|
</Text>
|
|
<Text variant="caption" color={colors.subtle} style={{ marginTop: 2 }}>
|
|
{new Date(t.at).toLocaleString()} · {t.status}
|
|
</Text>
|
|
<Text variant="bodySm" color={colors.muted} style={{ marginTop: 4 }}>
|
|
{t.message}
|
|
</Text>
|
|
</View>
|
|
))}
|
|
</Card>
|
|
</ScrollView>
|
|
</Screen>
|
|
);
|
|
}
|