import { Switch, StyleSheet, Text, View } from "react-native"; import { DateTimeField } from "@/components/ui/DateTimeField"; import { Input } from "@/components/ui/Input"; import { SelectField, type SelectOption } from "@/components/ui/SelectField"; import { fonts, spacing } from "@/constants/theme"; import { useAppTheme } from "@/contexts/ThemeContext"; import { EXPENSE_CATEGORIES } from "@/lib/expense-categories"; const NONE = "__none__"; export type ExpenseFormState = { description: string; amountText: string; date: Date; category: string; businessId: string; clientId: string; billable: boolean; reimbursable: boolean; taxDeductible: boolean; notes: string; }; type ExpenseFormFieldsProps = { value: ExpenseFormState; businesses: Array<{ id: string; name: string; isDefault?: boolean | null }>; clients: Array<{ id: string; name: string }>; onChange: (value: ExpenseFormState) => void; notesLabel?: string; notesPlaceholder?: string; }; export function defaultExpenseFormState( defaultBusinessId = "", ): ExpenseFormState { return { description: "", amountText: "", date: new Date(), category: "", businessId: defaultBusinessId, clientId: "", billable: false, reimbursable: false, taxDeductible: false, notes: "", }; } export function ExpenseFormFields({ value, businesses, clients, onChange, notesLabel = "Notes", notesPlaceholder = "Internal details", }: ExpenseFormFieldsProps) { const { colors } = useAppTheme(); const businessOptions: SelectOption[] = [ { label: "Default business", value: NONE }, ...businesses.map((business) => ({ label: business.isDefault ? `${business.name} (default)` : business.name, value: business.id, })), ]; const clientOptions: SelectOption[] = [ { label: "No client", value: NONE }, ...clients.map((client) => ({ label: client.name, value: client.id })), ]; const categoryOptions: SelectOption[] = [ { label: "No category", value: NONE }, ...EXPENSE_CATEGORIES.map((category) => ({ label: category, value: category, })), ]; const setField = ( field: K, nextValue: ExpenseFormState[K], ) => onChange({ ...value, [field]: nextValue }); return ( setField("description", text)} placeholder="e.g. Client lunch" /> setField("amountText", text)} keyboardType="decimal-pad" placeholder="0.00" /> setField("date", date)} mode="date" /> setField("category", next === NONE ? "" : next) } /> setField("businessId", next === NONE ? "" : next) } /> setField("clientId", next === NONE ? "" : next) } /> setField("billable", next)} /> setField("reimbursable", next)} /> setField("taxDeductible", next)} /> setField("notes", text)} placeholder={notesPlaceholder} multiline style={styles.notesInput} /> ); function FlagSwitch({ label, value: checked, onValueChange, }: { label: string; value: boolean; onValueChange: (value: boolean) => void; }) { return ( {label} ); } } const styles = StyleSheet.create({ stack: { gap: spacing.md, }, flags: { gap: spacing.sm, }, flagRow: { minHeight: 48, borderWidth: 1, borderRadius: 12, paddingHorizontal: spacing.md, flexDirection: "row", alignItems: "center", justifyContent: "space-between", }, flagLabel: { fontFamily: fonts.bodyMedium, fontSize: 14, }, notesInput: { minHeight: 96, textAlignVertical: "top", paddingTop: spacing.md, }, });