Stabilize mobile auth session handling

This commit is contained in:
2026-06-29 17:58:50 -04:00
parent 477459edd4
commit 57e1aa658a
25 changed files with 1126 additions and 192 deletions
+37 -2
View File
@@ -20,6 +20,7 @@ import { useThemedStyles } from "@/lib/use-themed-styles";
import { getInvoiceStatus } from "@/lib/invoice-status";
import { formatElapsedHoursMinutes, resolveClockDescription } from "@/lib/time-clock";
import { useRunningElapsed } from "@/lib/use-running-elapsed";
import { formatTrpcErrorMessage } from "@/lib/trpc-errors";
import { api } from "@/lib/trpc";
export default function DashboardScreen() {
@@ -41,7 +42,7 @@ export default function DashboardScreen() {
<Screen>
<View style={styles.errorBox}>
<Text style={styles.errorTitle}>Could not load dashboard</Text>
<Text style={styles.errorText}>{statsQuery.error.message}</Text>
<Text style={styles.errorText}>{formatTrpcErrorMessage(statsQuery.error)}</Text>
</View>
</Screen>
</AppBackground>
@@ -62,7 +63,7 @@ export default function DashboardScreen() {
: "No change vs last month";
const maxRevenue = Math.max(...stats.revenueChartData.map((d) => d.revenue), 1);
const sendReminderDue = stats.sendReminderDue ?? [];
const sendReminderDue = stats.recentInvoices.filter((inv) => inv.status === "draft");
return (
<AppBackground>
@@ -146,8 +147,31 @@ export default function DashboardScreen() {
variant="secondary"
onPress={() => router.push("/(app)/invoices")}
/>
<Button
title="Reports"
variant="secondary"
onPress={() => router.push("/(app)/more/reports" as never)}
/>
</View>
{stats.currentDraft ? (
<GlassSurface style={styles.alertGlass}>
<Pressable
style={styles.alertBanner}
onPress={() => router.push(`/(app)/invoices/${stats.currentDraft!.id}`)}
>
<Text style={styles.alertTitle}>
Draft {stats.currentDraft.invoiceNumber}
</Text>
<Text style={styles.alertText}>
{stats.currentDraft.client?.name ?? "Client"} ·{" "}
{formatCurrency(stats.currentDraft.totalAmount)} ·{" "}
{stats.currentDraft.totalHours.toFixed(1)}h logged
</Text>
</Pressable>
</GlassSurface>
) : null}
<View style={styles.statsGrid}>
<View style={styles.statCell}>
<StatCard label="Total revenue" value={formatCurrency(stats.totalRevenue)} />
@@ -190,6 +214,17 @@ export default function DashboardScreen() {
</View>
</Card>
<Card title="Invoice status">
{(stats.statusChartData ?? []).map((item) => (
<View key={item.status} style={styles.invoiceRow}>
<Text style={styles.invoiceClient}>{item.name}</Text>
<Text style={styles.invoiceDate}>
{item.count} · {formatCurrency(item.value)}
</Text>
</View>
))}
</Card>
<Card title="Recent invoices">
{stats.recentInvoices.length === 0 ? (
<Text style={styles.empty}>No invoices yet. Create one from the Invoices tab.</Text>