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>
62 lines
2.1 KiB
TypeScript
62 lines
2.1 KiB
TypeScript
import { router } from "expo-router";
|
|
import { FlatList, useWindowDimensions, View } from "react-native";
|
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
import { useTranslation } from "react-i18next";
|
|
import { EmptyState } from "@/components/ui/EmptyState";
|
|
import { ProductCard, GRID_CARD_GAP } from "@/components/ui/ProductCard";
|
|
import { Screen, TAB_BAR_INSET } from "@/components/ui/Screen";
|
|
import { Text } from "@/components/ui/Text";
|
|
import { products } from "@/lib/data/products";
|
|
import { routes } from "@/lib/routes";
|
|
import { useFavoritesStore } from "@/lib/stores/favoritesStore";
|
|
import { gutter } from "@/lib/theme";
|
|
|
|
export default function FavoritesScreen() {
|
|
const { t } = useTranslation();
|
|
const insets = useSafeAreaInsets();
|
|
const ids = useFavoritesStore((s) => s.ids);
|
|
const items = products.filter((p) => ids.includes(p.id));
|
|
const { width } = useWindowDimensions();
|
|
const cardWidth = (width - gutter * 2 - GRID_CARD_GAP) / 2;
|
|
|
|
return (
|
|
<Screen>
|
|
<View
|
|
style={{
|
|
paddingTop: insets.top + 16,
|
|
paddingHorizontal: gutter,
|
|
paddingBottom: 8,
|
|
}}
|
|
>
|
|
<Text variant="h1">{t("common.favorites")}</Text>
|
|
<Text variant="bodySm" color="#8A9188" style={{ marginTop: 4 }}>
|
|
Saved products for quick reorder
|
|
</Text>
|
|
</View>
|
|
{items.length === 0 ? (
|
|
<EmptyState
|
|
icon="heart-outline"
|
|
title={t("common.emptyFavorites")}
|
|
body="Tap the heart on any product to save it here."
|
|
actionTitle="Browse shop"
|
|
onAction={() => router.push(routes.shop)}
|
|
/>
|
|
) : (
|
|
<FlatList
|
|
data={items}
|
|
numColumns={2}
|
|
keyExtractor={(i) => i.id}
|
|
columnWrapperStyle={{ gap: GRID_CARD_GAP }}
|
|
contentContainerStyle={{
|
|
paddingHorizontal: gutter,
|
|
paddingTop: 12,
|
|
paddingBottom: TAB_BAR_INSET + 24,
|
|
gap: GRID_CARD_GAP,
|
|
}}
|
|
renderItem={({ item }) => <ProductCard product={item} width={cardWidth} />}
|
|
/>
|
|
)}
|
|
</Screen>
|
|
);
|
|
}
|