120 lines
3.3 KiB
TypeScript
120 lines
3.3 KiB
TypeScript
import { Ionicons } from "@expo/vector-icons";
|
|
import { router } from "expo-router";
|
|
import { Pressable, StyleSheet, Text, View } from "react-native";
|
|
|
|
import { AppBackground } from "@/components/AppBackground";
|
|
import { PageHeader } from "@/components/PageHeader";
|
|
import { TabPage } from "@/components/TabPage";
|
|
import { TabScrollView } from "@/components/TabScrollView";
|
|
import { fonts, radii, spacing } from "@/constants/theme";
|
|
import { useAppTheme } from "@/contexts/ThemeContext";
|
|
import type { ThemeColors } from "@/lib/theme-palette";
|
|
import { useThemedStyles } from "@/lib/use-themed-styles";
|
|
|
|
type HubItem = {
|
|
title: string;
|
|
subtitle: string;
|
|
href: string;
|
|
icon: keyof typeof Ionicons.glyphMap;
|
|
};
|
|
|
|
const ITEMS: HubItem[] = [
|
|
{
|
|
title: "Expenses",
|
|
subtitle: "Track costs and attach receipts",
|
|
href: "/(app)/more/expenses",
|
|
icon: "receipt-outline",
|
|
},
|
|
{
|
|
title: "Reports",
|
|
subtitle: "Revenue, hours, and tax summaries",
|
|
href: "/(app)/more/reports",
|
|
icon: "bar-chart-outline",
|
|
},
|
|
{
|
|
title: "Recurring invoices",
|
|
subtitle: "Scheduled billing templates",
|
|
href: "/(app)/more/recurring",
|
|
icon: "repeat-outline",
|
|
},
|
|
{
|
|
title: "Time entries",
|
|
subtitle: "Full history with edit and delete",
|
|
href: "/(app)/more/time-entries",
|
|
icon: "time-outline",
|
|
},
|
|
];
|
|
|
|
export default function MoreScreen() {
|
|
const { colors } = useAppTheme();
|
|
const styles = useThemedStyles(createStyles);
|
|
|
|
return (
|
|
<AppBackground>
|
|
<TabPage>
|
|
<TabScrollView header={<PageHeader title="More" subtitle="Additional tools" />}>
|
|
<View style={styles.list}>
|
|
{ITEMS.map((item) => (
|
|
<Pressable
|
|
key={item.href}
|
|
style={({ pressed }) => [styles.row, pressed && styles.rowPressed]}
|
|
onPress={() => router.push(item.href as never)}
|
|
>
|
|
<View style={[styles.iconWrap, { backgroundColor: colors.muted }]}>
|
|
<Ionicons name={item.icon} size={22} color={colors.primary} />
|
|
</View>
|
|
<View style={styles.copy}>
|
|
<Text style={[styles.title, { color: colors.foreground }]}>{item.title}</Text>
|
|
<Text style={[styles.subtitle, { color: colors.mutedForeground }]}>
|
|
{item.subtitle}
|
|
</Text>
|
|
</View>
|
|
<Ionicons name="chevron-forward" size={18} color={colors.mutedForeground} />
|
|
</Pressable>
|
|
))}
|
|
</View>
|
|
</TabScrollView>
|
|
</TabPage>
|
|
</AppBackground>
|
|
);
|
|
}
|
|
|
|
const createStyles = (colors: ThemeColors) =>
|
|
StyleSheet.create({
|
|
list: {
|
|
gap: spacing.sm,
|
|
},
|
|
row: {
|
|
flexDirection: "row",
|
|
alignItems: "center",
|
|
gap: spacing.md,
|
|
padding: spacing.md,
|
|
borderRadius: radii.lg,
|
|
borderWidth: 1,
|
|
borderColor: colors.border,
|
|
backgroundColor: colors.card,
|
|
},
|
|
rowPressed: {
|
|
opacity: 0.85,
|
|
},
|
|
iconWrap: {
|
|
width: 44,
|
|
height: 44,
|
|
borderRadius: radii.md,
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
},
|
|
copy: {
|
|
flex: 1,
|
|
gap: 2,
|
|
},
|
|
title: {
|
|
fontFamily: fonts.bodySemiBold,
|
|
fontSize: 16,
|
|
},
|
|
subtitle: {
|
|
fontFamily: fonts.body,
|
|
fontSize: 13,
|
|
},
|
|
});
|