import { router, Stack, useLocalSearchParams } from "expo-router";
import { Pressable, ScrollView, StyleSheet, Text, View } from "react-native";
import { AppBackground } from "@/components/AppBackground";
import { LoadingScreen } from "@/components/LoadingScreen";
import { StatusBadge } from "@/components/StatusBadge";
import { Button } from "@/components/ui/Button";
import { Card } from "@/components/ui/Card";
import { fonts, spacing } from "@/constants/theme";
import { useAppTheme } from "@/contexts/ThemeContext";
import { formatCurrency, formatDate } from "@/lib/format";
import { getInvoiceStatus } from "@/lib/invoice-status";
import { useTabBarScrollPadding } from "@/lib/tab-bar-insets";
import type { ThemeColors } from "@/lib/theme-palette";
import { useThemedStyles } from "@/lib/use-themed-styles";
import { api } from "@/lib/trpc";
export default function ClientDetailScreen() {
const { colors } = useAppTheme();
const styles = useThemedStyles(createClientDetailStyles);
const { id } = useLocalSearchParams<{ id: string }>();
const scrollPadding = useTabBarScrollPadding();
const clientQuery = api.clients.getById.useQuery(
{ id: id ?? "" },
{ enabled: Boolean(id) },
);
if (!id) {
return ;
}
if (clientQuery.isLoading) {
return ;
}
const client = clientQuery.data;
if (!client) {
return ;
}
const invoices = client.invoices ?? [];
const totalInvoiced = invoices.reduce((sum, invoice) => sum + invoice.totalAmount, 0);
const currency = client.currency ?? "USD";
return (
{client.name}
{client.email ? {client.email} : null}
{client.phone ? {client.phone} : null}
{client.defaultHourlyRate != null ? (
) : null}
{(client.addressLine1 || client.city || client.state) && (
{client.addressLine1 ? {client.addressLine1} : null}
{client.addressLine2 ? {client.addressLine2} : null}
{(client.city || client.state || client.postalCode) && (
{[client.city, client.state, client.postalCode].filter(Boolean).join(", ")}
)}
{client.country ? {client.country} : null}
)}
{invoices.length === 0 ? (
No invoices for this client yet.
) : (
invoices.map((invoice) => {
const status = getInvoiceStatus(invoice);
return (
router.push(`/(app)/invoices/${invoice.id}`)}
>
{invoice.invoicePrefix}
{invoice.invoiceNumber}
Due {formatDate(invoice.dueDate)}
{formatCurrency(invoice.totalAmount, invoice.currency)}
);
})
)}
);
}
function DetailRow({ label, value }: { label: string; value: string }) {
const { colors } = useAppTheme();
return (
{label}
{value}
);
}
const detailStyles = StyleSheet.create({
row: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingVertical: 4,
},
label: {
fontFamily: fonts.body,
fontSize: 14,
},
value: {
fontFamily: fonts.bodySemiBold,
fontSize: 14,
},
});
const createClientDetailStyles = (colors: ThemeColors, _isDark: boolean) =>
StyleSheet.create({
container: {
padding: spacing.md,
gap: spacing.md,
},
hero: {
gap: 4,
},
name: {
fontSize: 24,
lineHeight: 28,
fontFamily: fonts.heading,
color: colors.foreground,
},
meta: {
fontSize: 14,
fontFamily: fonts.body,
color: colors.mutedForeground,
},
body: {
fontFamily: fonts.body,
fontSize: 14,
color: colors.foreground,
lineHeight: 20,
},
muted: {
fontFamily: fonts.body,
fontSize: 14,
color: colors.mutedForeground,
},
invoiceRow: {
flexDirection: "row",
justifyContent: "space-between",
gap: spacing.md,
paddingVertical: spacing.sm,
borderTopWidth: 1,
borderTopColor: colors.border,
},
invoiceMeta: {
flex: 1,
gap: 2,
},
invoiceTitle: {
fontFamily: fonts.bodySemiBold,
color: colors.foreground,
fontSize: 15,
},
invoiceRight: {
alignItems: "flex-end",
gap: spacing.sm,
},
invoiceAmount: {
fontFamily: fonts.bodySemiBold,
color: colors.foreground,
fontSize: 15,
},
actions: {
gap: spacing.sm,
},
});