Move production to beenvoice.app with migrated accounts, refreshed auth and timer UX, and expanded invoice flows.

Official URL migration preserves sessions, shortcuts prefs, and last clock-in client; auth screens match web with legal links; time clock and invoice editor/send flows are updated for the new domain and UI patterns.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-26 03:40:48 -04:00
co-authored by Cursor
parent e17c4c6854
commit 6762a9bff3
60 changed files with 2544 additions and 1091 deletions
@@ -3,21 +3,34 @@ import { ScrollView, StyleSheet, View } from "react-native";
import { FilterChip } from "@/components/FilterChip";
import { spacing } from "@/constants/theme";
export type InvoiceEditorSection = "edit" | "preview";
export type InvoiceEditorSection = "setup" | "lines" | "preview";
export type InvoiceViewSection = "details" | "preview";
type InvoiceEditorSectionTabsProps = {
value: InvoiceEditorSection;
onChange: (value: InvoiceEditorSection) => void;
editLabel?: string;
previewLabel?: string;
};
type InvoiceEditorSectionTabsProps =
| {
mode?: "edit";
value: InvoiceEditorSection;
onChange: (value: InvoiceEditorSection) => void;
}
| {
mode: "view";
value: InvoiceViewSection;
onChange: (value: InvoiceViewSection) => void;
};
export function InvoiceEditorSectionTabs(props: InvoiceEditorSectionTabsProps) {
const tabs =
props.mode === "view"
? [
{ id: "details" as const, label: "Details" },
{ id: "preview" as const, label: "PDF" },
]
: [
{ id: "setup" as const, label: "Setup" },
{ id: "lines" as const, label: "Line items" },
{ id: "preview" as const, label: "PDF preview" },
];
export function InvoiceEditorSectionTabs({
value,
onChange,
editLabel = "Edit",
previewLabel = "PDF preview",
}: InvoiceEditorSectionTabsProps) {
return (
<View>
<ScrollView
@@ -25,16 +38,14 @@ export function InvoiceEditorSectionTabs({
showsHorizontalScrollIndicator={false}
contentContainerStyle={styles.row}
>
<FilterChip
label={editLabel}
active={value === "edit"}
onPress={() => onChange("edit")}
/>
<FilterChip
label={previewLabel}
active={value === "preview"}
onPress={() => onChange("preview")}
/>
{tabs.map((tab) => (
<FilterChip
key={tab.id}
label={tab.label}
active={props.value === tab.id}
onPress={() => props.onChange(tab.id as never)}
/>
))}
</ScrollView>
</View>
);