Polish mobile app for App Store review and expand CRUD.

Default to beenvoice.soconnor.dev with server settings hidden behind Advanced; add Entities tab with clients/businesses, invoice creation, UI fixes for dashboard layout, date fields, FAB position, and card-matched button radius.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-17 23:14:58 -04:00
parent 14c880123c
commit 6d2711e36e
41 changed files with 2410 additions and 181 deletions
+42 -8
View File
@@ -1,5 +1,6 @@
import { useState } from "react";
import Constants from "expo-constants";
import { Ionicons } from "@expo/vector-icons";
import { router } from "expo-router";
import { Alert, Platform, Pressable, StyleSheet, Switch, Text, View } from "react-native";
import { TabPage } from "@/components/TabPage";
@@ -38,6 +39,11 @@ export default function SettingsScreen() {
clearActiveAccount,
} = useAccounts();
const { colors, colorMode, setColorMode } = useAppTheme();
const switchProps = {
trackColor: { false: colors.switchTrackOff, true: colors.switchTrackOn },
thumbColor: Platform.OS === "android" ? colors.switchThumb : undefined,
ios_backgroundColor: colors.switchIosBackground,
};
const {
enabled: lockEnabled,
biometricEnabled,
@@ -59,6 +65,7 @@ export default function SettingsScreen() {
| null
>(null);
const [pendingPin, setPendingPin] = useState("");
const [showAdvanced, setShowAdvanced] = useState(false);
async function handleSignOut() {
await authClient.signOut();
@@ -268,7 +275,7 @@ export default function SettingsScreen() {
<Switch
value={lockEnabled}
onValueChange={handleLockToggle}
trackColor={{ false: colors.border, true: colors.primary }}
{...switchProps}
/>
</View>
@@ -285,7 +292,7 @@ export default function SettingsScreen() {
<Switch
value={biometricEnabled}
onValueChange={handleBiometricToggle}
trackColor={{ false: colors.border, true: colors.primary }}
{...switchProps}
/>
</View>
) : null}
@@ -329,12 +336,28 @@ export default function SettingsScreen() {
</View>
</Card>
<Card title="Server instance">
<InstanceUrlField onSaved={confirmInstanceChange} />
<Text style={[styles.currentServer, { color: colors.mutedForeground }]}>
Connected to {activeAccount?.instanceUrl ?? apiUrl}
</Text>
</Card>
<Pressable
accessibilityRole="button"
accessibilityState={{ expanded: showAdvanced }}
onPress={() => setShowAdvanced((open) => !open)}
style={styles.advancedToggle}
>
<Text style={[styles.advancedLabel, { color: colors.mutedForeground }]}>Advanced</Text>
<Ionicons
name={showAdvanced ? "chevron-up" : "chevron-down"}
size={16}
color={colors.mutedForeground}
/>
</Pressable>
{showAdvanced ? (
<Card title="Server instance">
<InstanceUrlField onSaved={confirmInstanceChange} />
<Text style={[styles.currentServer, { color: colors.mutedForeground }]}>
Connected to {activeAccount?.instanceUrl ?? apiUrl}
</Text>
</Card>
) : null}
<Card title="App">
<View style={styles.appRow}>
@@ -375,6 +398,17 @@ const styles = StyleSheet.create({
fontSize: 12,
fontFamily: fonts.mono,
},
advancedToggle: {
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
gap: spacing.xs,
minHeight: 36,
},
advancedLabel: {
fontSize: 13,
fontFamily: fonts.bodyMedium,
},
appRow: {
flexDirection: "row",
justifyContent: "space-between",