| 1 | import { CUSTOMIZE_SECTIONS, type CustomizeSection } from "@g1t/contracts/customize"; |
| 2 | import { Redirect, Stack, useLocalSearchParams } from "expo-router"; |
| 3 | import * as WebBrowser from "expo-web-browser"; |
| 4 | import { ExternalLink } from "lucide-react-native"; |
| 5 | import { SectionList, View } from "react-native"; |
| 6 | |
| 7 | import { Badge, Button, Row, Screen, SectionHeader, Text } from "@/components/ui"; |
| 8 | import { CUSTOMIZE, type CustomizeItem, customizeItems, customizePath } from "@/lib/customize"; |
| 9 | import { siteUrl } from "@/lib/server"; |
| 10 | import { useSignedIn } from "@/lib/session"; |
| 11 | import { space } from "@/theme"; |
| 12 | |
| 13 | /** One part of Customize: its listings, grouped, each opening where it is set up. */ |
| 14 | export default function CustomizeSectionScreen() { |
| 15 | const { section } = useLocalSearchParams<{ section: string }>(); |
| 16 | const { workspace, server } = useSignedIn(); |
| 17 | if (!CUSTOMIZE_SECTIONS.includes(section as CustomizeSection)) return <Redirect href="/customize" />; |
| 18 | const id = section as CustomizeSection; |
| 19 | const slug = workspace?.slug ?? ""; |
| 20 | const items = customizeItems(id, slug); |
| 21 | const groups = [...new Set(items.map((item) => item.group))].map((group) => ({ title: group, data: items.filter((item) => item.group === group) })); |
| 22 | const open = (path: string) => WebBrowser.openBrowserAsync(siteUrl(server, path)); |
| 23 | |
| 24 | return ( |
| 25 | <Screen> |
| 26 | <Stack.Screen options={{ title: CUSTOMIZE[id].title }} /> |
| 27 | <SectionList |
| 28 | sections={groups} |
| 29 | keyExtractor={(item) => item.id} |
| 30 | stickySectionHeadersEnabled={false} |
| 31 | ListHeaderComponent={ |
| 32 | <View style={{ padding: space.lg, gap: space.md }}> |
| 33 | <Text tone="muted">{CUSTOMIZE[id].description}</Text> |
| 34 | <Button title={`Manage ${CUSTOMIZE[id].title.toLowerCase()} on g1t`} variant="secondary" icon={ExternalLink} onPress={() => open(customizePath(id, slug))} /> |
| 35 | </View> |
| 36 | } |
| 37 | renderSectionHeader={({ section: group }) => <SectionHeader title={group.title} />} |
| 38 | renderItem={({ item }) => <Item item={item} onPress={() => open(item.sitePath)} />} |
| 39 | /> |
| 40 | </Screen> |
| 41 | ); |
| 42 | } |
| 43 | |
| 44 | function Item({ item, onPress }: { item: CustomizeItem; onPress: () => void }) { |
| 45 | const badge = item.status === "available" ? <Badge label="Available" tone="success" /> : item.status === "soon" ? <Badge label="Soon" /> : <Badge label="Built in" tone="accent" />; |
| 46 | return <Row title={item.name} subtitle={item.description} trailing={badge} onPress={item.status === "soon" ? undefined : onPress} />; |
| 47 | } |