72 lines
2.9 KiB
TypeScript
72 lines
2.9 KiB
TypeScript
import React, { useState, useCallback } from 'react'
|
||
import { View, Text, FlatList, StyleSheet, TouchableOpacity } from 'react-native'
|
||
import { useFocusEffect, useRouter } from 'expo-router'
|
||
import * as SecureStore from 'expo-secure-store'
|
||
import { COLORS } from '../../constants/Config'
|
||
|
||
const RECENT_KEY = 'guardia_recent_screens'
|
||
const MAX_RECENT = 10
|
||
|
||
export const recordVisit = async (route: string, label: string, icon: string) => {
|
||
const raw = await SecureStore.getItemAsync(RECENT_KEY)
|
||
const existing: any[] = raw ? JSON.parse(raw) : []
|
||
const filtered = existing.filter(r => r.route !== route)
|
||
const updated = [{ route, label, icon, ts: new Date().toISOString() }, ...filtered].slice(0, MAX_RECENT)
|
||
await SecureStore.setItemAsync(RECENT_KEY, JSON.stringify(updated))
|
||
}
|
||
|
||
export default function RecentScreensScreen() {
|
||
const [items, setItems] = useState<any[]>([])
|
||
const router = useRouter()
|
||
|
||
const load = useCallback(async () => {
|
||
const raw = await SecureStore.getItemAsync(RECENT_KEY)
|
||
setItems(raw ? JSON.parse(raw) : [])
|
||
}, [])
|
||
|
||
useFocusEffect(useCallback(() => { load() }, [load]))
|
||
|
||
const clear = async () => {
|
||
await SecureStore.deleteItemAsync(RECENT_KEY)
|
||
setItems([])
|
||
}
|
||
|
||
return (
|
||
<FlatList
|
||
data={items}
|
||
keyExtractor={(_, i) => String(i)}
|
||
ListEmptyComponent={<Text style={s.empty}>최근 방문 기록이 없습니다.</Text>}
|
||
style={{ backgroundColor: COLORS.bg }}
|
||
contentContainerStyle={{ padding: 12 }}
|
||
ListHeaderComponent={
|
||
<View style={s.header}>
|
||
<Text style={s.title}>최근 방문 화면</Text>
|
||
{items.length > 0 && <TouchableOpacity onPress={clear}><Text style={s.clear}>전체 삭제</Text></TouchableOpacity>}
|
||
</View>
|
||
}
|
||
renderItem={({ item }) => (
|
||
<TouchableOpacity style={s.card} onPress={() => router.push(item.route)}>
|
||
<Text style={s.icon}>{item.icon}</Text>
|
||
<View style={{ flex: 1 }}>
|
||
<Text style={s.label}>{item.label}</Text>
|
||
<Text style={s.time}>{item.ts?.slice(0, 16)?.replace('T', ' ') ?? ''}</Text>
|
||
</View>
|
||
<Text style={s.arrow}>›</Text>
|
||
</TouchableOpacity>
|
||
)}
|
||
/>
|
||
)
|
||
}
|
||
|
||
const s = StyleSheet.create({
|
||
header: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 },
|
||
title: { fontSize: 16, fontWeight: '800', color: COLORS.text },
|
||
clear: { fontSize: 12, color: COLORS.danger },
|
||
card: { flexDirection: 'row', alignItems: 'center', gap: 12, backgroundColor: '#fff', borderRadius: 10, padding: 14, marginBottom: 6, elevation: 1 },
|
||
icon: { fontSize: 22, width: 30, textAlign: 'center' },
|
||
label: { fontSize: 14, fontWeight: '700', color: COLORS.text, marginBottom: 2 },
|
||
time: { fontSize: 11, color: COLORS.muted },
|
||
arrow: { fontSize: 20, color: COLORS.muted },
|
||
empty: { textAlign: 'center', color: COLORS.muted, marginTop: 40 },
|
||
})
|