import { Text } from '@/aesthetics/Text'; import { font, radius, spacing, useColors } from '@/aesthetics/styles'; import { useStrings } from '@/common/hooks/useStrings'; import { Pressable, StyleSheet, View } from 'react-native'; import { Card } from '@/see-log/aesthetics/Card'; import { IconPicker, preloadIconData } from '@/aesthetics/IconPicker'; import { useAlert } from '@/aesthetics/Alert'; import { useHaptics } from '@/aesthetics/useHaptics'; import { useEffect, useState, useCallback, useMemo } from 'react'; import { ArrowDown, ArrowUp } from 'lucide-react-native'; import { SelectLogger } from './SelectLogger'; import { CheckLogger } from './CheckLogger'; import { NumberMemoLogger } from './NumberMemoLogger'; import { TextMemoLogger } from './TextMemoLogger'; import { BasicMemoLogger } from './BasicMemoLogger'; import { MemoLoggerEditor } from './MemoLoggerEditor'; import { MemoLogCard } from './MemoLogCard'; import { LoggerTileGrid } from './LoggerTileGrid'; import { useMemoLog } from './useMemoLog'; type Sheet = 'basic' | 'create-logger' | 'edit-logger' | string | null; export function AddLogCard() { const strings = useStrings(); const c = useColors(); const { showConfirm } = useAlert(); const { notification, NotificationType } = useHaptics(); const { entries, loggers, loggerMap, isLoading, createBasicLog, logWithLogger, logWithLoggerOption, logMultiselect, deleteEntry, createLogger, updateLogger, deleteLogger, } = useMemoLog(); const [activeSheet, setActiveSheet] = useState(null); const [isEditMode, setIsEditMode] = useState(false); const [editingLoggerId, setEditingLoggerId] = useState(null); const [iconPicker, setIconPicker] = useState<{ index: number; onSelect: (icon: string) => void; } | null>(null); const [sortOrder, setSortOrder] = useState<'new_to_old' | 'old_to_new'>('new_to_old'); useEffect(() => { preloadIconData(); }, []); const sortedEntries = useMemo( () => (sortOrder === 'new_to_old' ? entries : [...entries].reverse()), [entries, sortOrder] ); const activeLogger = activeSheet && activeSheet !== 'basic' && activeSheet !== 'create-logger' && activeSheet !== 'edit-logger' ? loggerMap.get(activeSheet) : undefined; const editingLogger = editingLoggerId ? loggerMap.get(editingLoggerId) : undefined; const enterEditMode = () => { notification(NotificationType.Warning); setIsEditMode(true); }; const closeSheet = () => { setActiveSheet(null); setEditingLoggerId(null); }; const handleEditLogger = (id: string) => { setEditingLoggerId(id); setActiveSheet('edit-logger'); }; const handleBasicLog = useCallback( async ( title: string, value: number | string, type: 'text' | 'number' | 'check', unit?: string ) => { await createBasicLog(title, value, type, unit); closeSheet(); }, [createBasicLog] ); const handleCreateLogger = useCallback( async (logger: Parameters[0]) => { await createLogger(logger); closeSheet(); }, [createLogger] ); const handleUpdateLogger = useCallback( async (id: string, updates: Parameters[1]) => { await updateLogger(id, updates); closeSheet(); }, [updateLogger] ); const handleOpenIconPicker = useCallback((index: number, onSelect: (icon: string) => void) => { setIconPicker({ index, onSelect }); }, []); const handleSelectIcon = useCallback( (icon: string) => { iconPicker?.onSelect(icon); setIconPicker(null); }, [iconPicker] ); const getLoggerLabel = (l: { id: string; name: string }) => strings.userCustomLogs[l.id] || l.name; return ( <> {strings.userCustomLogs.loggers} setIsEditMode(false)} onSelect={setActiveSheet} onEdit={handleEditLogger} onDelete={id => { const logger = loggerMap.get(id); const name = logger ? getLoggerLabel(logger) : ''; showConfirm( strings.userCustomLogs.deleteLogger, strings.userCustomLogs.deleteConfirm(name), () => deleteLogger(id) ); }} onAddNew={() => setActiveSheet('basic')} getLabel={getLoggerLabel} /> {sortedEntries.length > 0 && ( <> {strings.userCustomLogs.logs} setSortOrder(s => (s === 'new_to_old' ? 'old_to_new' : 'new_to_old')) } style={({ pressed }) => [ styles.sortButton, { backgroundColor: c.tagBg }, pressed && { opacity: 0.7 }, ]} > {sortOrder === 'new_to_old' ? ( ) : ( )} {sortOrder === 'new_to_old' ? strings.userCustomLogs.newToOld : strings.userCustomLogs.oldToNew} {sortedEntries.map((entry, i) => ( {}} onRequestDelete={() => showConfirm( strings.userCustomLogs.deleteEntry, strings.userCustomLogs.deleteConfirm(entry.title), () => deleteEntry(entry.id) ) } /> ))} )} setActiveSheet('create-logger')} /> {activeLogger?.type === 'singleselect' && activeLogger.options && ( { await logWithLoggerOption(activeLogger, i, getLoggerLabel(activeLogger)); closeSheet(); }} onClose={closeSheet} /> )} {activeLogger?.type === 'multiselect' && activeLogger.options && ( { await logMultiselect(activeLogger, indices, getLoggerLabel(activeLogger)); closeSheet(); }} onClose={closeSheet} /> )} {activeLogger?.type === 'check' && ( { await logWithLogger(activeLogger, val, undefined, getLoggerLabel(activeLogger)); closeSheet(); }} onClose={closeSheet} /> )} {activeLogger?.type === 'number' && ( { await logWithLogger(activeLogger, val, undefined, getLoggerLabel(activeLogger)); closeSheet(); }} onClose={closeSheet} /> )} {activeLogger?.type === 'text' && ( { await logWithLogger(activeLogger, val, undefined, getLoggerLabel(activeLogger)); closeSheet(); }} onClose={closeSheet} /> )} setIconPicker(null)} onSelect={handleSelectIcon} /> ); } const styles = StyleSheet.create({ sectionTitle: { fontSize: font.md, fontWeight: '600', marginBottom: spacing.sm }, logsTitle: { marginBottom: 0 }, logsHeader: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginTop: spacing.xl, marginBottom: spacing.sm, }, sortButton: { flexDirection: 'row', alignItems: 'center', gap: spacing.xs, paddingHorizontal: spacing.sm, paddingVertical: spacing.sm, borderRadius: radius.md, }, sortLabel: { fontSize: font.xs, fontWeight: '500' }, entryList: { gap: spacing.sm }, });