Replace the profile tab with prescription management (inline reminders and family invite), add a shared tab top bar, separate notifications from orders, and support any-branch guest checkout with GSH codes. Co-authored-by: Cursor <cursoragent@cursor.com>
117 lines
2.8 KiB
TypeScript
117 lines
2.8 KiB
TypeScript
import type { ReactNode } from "react";
|
|
import { router } from "expo-router";
|
|
import { View } from "react-native";
|
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
import { IconButton } from "@/components/ui/Button";
|
|
import { Text } from "@/components/ui/Text";
|
|
import { colors, gutter } from "@/lib/theme";
|
|
|
|
type Props = {
|
|
title?: string;
|
|
subtitle?: string;
|
|
/** Large left-aligned title, matching the "Explore Products" reference. */
|
|
large?: boolean;
|
|
back?: boolean;
|
|
onBack?: () => void;
|
|
right?: ReactNode;
|
|
background?: string;
|
|
};
|
|
|
|
/**
|
|
* Shared stack header. Back control and title share one row so they stay
|
|
* vertically centered with each other (subtitle stacks under the title).
|
|
*/
|
|
export function AppHeader({
|
|
title,
|
|
subtitle,
|
|
large,
|
|
back = true,
|
|
onBack,
|
|
right,
|
|
background = "transparent",
|
|
}: Props) {
|
|
const insets = useSafeAreaInsets();
|
|
|
|
return (
|
|
<View
|
|
style={{
|
|
paddingTop: insets.top + 6,
|
|
paddingHorizontal: gutter,
|
|
paddingBottom: large ? 4 : 10,
|
|
backgroundColor: background,
|
|
}}
|
|
>
|
|
<View
|
|
style={{
|
|
flexDirection: "row",
|
|
alignItems: "center",
|
|
gap: 10,
|
|
minHeight: 44,
|
|
}}
|
|
>
|
|
{back ? (
|
|
<IconButton
|
|
icon="arrow-back"
|
|
accessibilityLabel="Go back"
|
|
onPress={onBack ?? (() => router.back())}
|
|
tone="surface"
|
|
/>
|
|
) : null}
|
|
|
|
{!large ? (
|
|
<View
|
|
style={{
|
|
flex: 1,
|
|
justifyContent: "center",
|
|
minHeight: 40,
|
|
paddingRight: right ? 4 : 0,
|
|
}}
|
|
>
|
|
{title ? (
|
|
<Text variant="h2" numberOfLines={1}>
|
|
{title}
|
|
</Text>
|
|
) : null}
|
|
{subtitle ? (
|
|
<Text
|
|
variant="caption"
|
|
color={colors.subtle}
|
|
numberOfLines={2}
|
|
style={{ marginTop: title ? 2 : 0 }}
|
|
>
|
|
{subtitle}
|
|
</Text>
|
|
) : null}
|
|
</View>
|
|
) : (
|
|
<View style={{ flex: 1 }} />
|
|
)}
|
|
|
|
{right ? (
|
|
<View
|
|
style={{
|
|
flexShrink: 0,
|
|
alignItems: "flex-end",
|
|
justifyContent: "center",
|
|
maxWidth: "36%",
|
|
}}
|
|
>
|
|
{right}
|
|
</View>
|
|
) : null}
|
|
</View>
|
|
|
|
{large && title ? (
|
|
<View style={{ marginTop: back || right ? 14 : 8, marginBottom: 4 }}>
|
|
<Text variant="h1">{title}</Text>
|
|
{subtitle ? (
|
|
<Text variant="bodySm" color={colors.subtle} style={{ marginTop: 4 }}>
|
|
{subtitle}
|
|
</Text>
|
|
) : null}
|
|
</View>
|
|
) : null}
|
|
</View>
|
|
);
|
|
}
|