import { BottomSheet, BottomSheetTextInput } from '@/aesthetics/BottomSheet'; import { Text } from '@/aesthetics/Text'; import { buttonHeight, font, radius, spacing, useColors } from '@/aesthetics/styles'; import { useHaptics } from '@/aesthetics/useHaptics'; import { useStrings } from '@/common/hooks/useStrings'; import { Check, CheckCircle, Hash, Type, X } from 'lucide-react-native'; import { useState } from 'react'; import { Pressable, StyleSheet, View } from 'react-native'; import { NUMBER_UNITS } from './constants'; import type { InputType } from './types'; const BASIC_TYPES = [ { type: 'text' as const, icon: Type }, { type: 'number' as const, icon: Hash }, { type: 'check' as const, icon: CheckCircle }, ]; type Props = { visible: boolean; onClose: () => void; onLog: (title: string, value: number | string, type: InputType, unit?: string) => void; onCreateLogger: () => void; }; export function BasicMemoLogger({ visible, onClose, onLog, onCreateLogger }: Props) { const c = useColors(); const strings = useStrings(); const { selection } = useHaptics(); const [title, setTitle] = useState(''); const [type, setType] = useState<'text' | 'number' | 'check'>('text'); const [textValue, setTextValue] = useState(''); const [numberValue, setNumberValue] = useState(''); const [unitType, setUnitType] = useState('plain'); const reset = () => { setTitle(''); setType('text'); setTextValue(''); setNumberValue(''); setUnitType('plain'); }; const handleClose = () => { reset(); onClose(); }; const handleSubmit = () => { if (!title.trim()) return; const unit = NUMBER_UNITS.find(u => u.id === unitType); if (type === 'number') { if (!numberValue.trim()) return; onLog(title.trim(), parseFloat(numberValue) || 0, 'number', unit?.unit); } else if (type === 'text') { onLog(title.trim(), textValue.trim() || title.trim(), 'text'); } reset(); }; const handleCheck = (value: 0 | 1) => { if (!title.trim()) return; onLog(title.trim(), value, 'check'); reset(); }; const canSubmit = title.trim() && (type !== 'number' || numberValue.trim()); const typeLabels: Record<'text' | 'number' | 'check', string> = { text: strings.userCustomLogs.types.text, number: strings.userCustomLogs.types.number, check: strings.userCustomLogs.types.check, }; return ( {strings.userCustomLogs.type} {BASIC_TYPES.map(t => { const Icon = t.icon; const selected = type === t.type; return ( { selection(); setType(t.type); }} style={[styles.typeChip, { backgroundColor: selected ? c.accent : c.tagBg }]} > {typeLabels[t.type]} ); })} {type === 'text' && ( )} {type === 'number' && ( <> {strings.userCustomLogs.unit} {NUMBER_UNITS.map(u => ( { selection(); setUnitType(u.id); }} style={[ styles.unitChip, { backgroundColor: unitType === u.id ? c.accent : c.tagBg }, ]} > {u.label} ))} )} {type === 'check' ? ( handleCheck(1)} disabled={!title.trim()} style={[ styles.checkBtn, { backgroundColor: c.success }, !title.trim() && styles.disabled, ]} > {strings.userCustomLogs.yes} handleCheck(0)} disabled={!title.trim()} style={[ styles.checkBtn, { backgroundColor: c.danger }, !title.trim() && styles.disabled, ]} > {strings.userCustomLogs.no} ) : ( {strings.userCustomLogs.log} )} {strings.userCustomLogs.makeReusable} ); } const styles = StyleSheet.create({ container: { gap: spacing.lg }, label: { fontSize: font.md, fontWeight: '600', marginBottom: -spacing.sm }, input: { paddingVertical: spacing.md, paddingHorizontal: spacing.lg, borderRadius: radius.md, fontSize: font.md, }, textArea: { paddingVertical: spacing.md, paddingHorizontal: spacing.lg, borderRadius: radius.md, fontSize: font.sm, minHeight: 80, textAlignVertical: 'top', }, typeRow: { flexDirection: 'row', gap: spacing.sm }, typeChip: { flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'center', minHeight: buttonHeight.md, borderRadius: radius.md, gap: spacing.xs, }, typeLabel: { fontSize: font.sm, fontWeight: '500' }, unitRow: { flexDirection: 'row', gap: spacing.sm }, unitChip: { flex: 1, minHeight: buttonHeight.sm, paddingVertical: spacing.sm, borderRadius: radius.md, alignItems: 'center', justifyContent: 'center', }, unitLabel: { fontSize: font.sm, fontWeight: '600' }, checkRow: { flexDirection: 'row', gap: spacing.md }, checkBtn: { flex: 1, flexDirection: 'row', minHeight: buttonHeight.xl, borderRadius: radius.lg, alignItems: 'center', justifyContent: 'center', gap: spacing.xxs, }, checkLabel: { fontSize: font.md, fontWeight: '600' }, submitBtn: { minHeight: buttonHeight.md, paddingVertical: spacing.md, borderRadius: radius.md, alignItems: 'center', justifyContent: 'center', }, submitLabel: { fontSize: font.md, fontWeight: '600' }, secondary: { alignItems: 'center', paddingVertical: spacing.sm }, secondaryLabel: { fontSize: font.sm }, disabled: { opacity: 0.4 }, });