import React, { useState, useCallback } from 'react' import { View, Text, FlatList, StyleSheet, RefreshControl, ActivityIndicator } from 'react-native' import { COLORS } from '../../constants/Config' import { getAuditLogs } from '../../services/api' function maskIp(ip: string | undefined) { if (!ip) return '-' const parts = ip.split('.') if (parts.length === 4) return `${parts[0]}.xxx.xxx.xxx` return ip.replace(/[0-9]+/g, 'x') } export default function AuditLogScreen() { const [items, setItems] = useState([]) const [page, setPage] = useState(0) const [loading, setLoading] = useState(false) const [loadingMore, setLoadingMore] = useState(false) const [hasMore, setHasMore] = useState(true) const load = useCallback(async (pg = 0) => { if (pg === 0) setLoading(true) else setLoadingMore(true) try { const r = await getAuditLogs(pg) const data = r.data?.items ?? r.data ?? [] if (pg === 0) setItems(data) else setItems(prev => [...prev, ...data]) setHasMore(data.length >= 30) setPage(pg) } catch {} finally { setLoading(false); setLoadingMore(false) } }, []) React.useEffect(() => { load(0) }, []) const loadMore = () => { if (!loadingMore && hasMore) load(page + 1) } const renderItem = ({ item }: { item: any }) => ( {item.actor} {item.created_at?.slice(0, 16).replace('T', ' ')} {item.action} {item.detail} IP: {maskIp(item.ip_hash ?? item.ip_addr)} ) if (loading) return return ( String(i)} renderItem={renderItem} refreshControl={ load(0)} />} onEndReached={loadMore} onEndReachedThreshold={0.3} ListFooterComponent={loadingMore ? : null} ListEmptyComponent={감사 로그가 없습니다.} contentContainerStyle={{ padding: 12 }} style={{ backgroundColor: COLORS.bg }} /> ) } const s = StyleSheet.create({ card: { backgroundColor: '#fff', borderRadius: 8, padding: 12, marginBottom: 6, elevation: 1 }, row: { flexDirection: 'row', justifyContent: 'space-between', marginBottom: 4 }, actor: { fontSize: 13, fontWeight: '700', color: COLORS.text }, time: { fontSize: 11, color: COLORS.muted }, action: { fontSize: 12, color: COLORS.accent, fontWeight: '600', marginBottom: 2 }, detail: { fontSize: 12, color: COLORS.text }, ip: { fontSize: 11, color: COLORS.muted, marginTop: 4 }, empty: { textAlign: 'center', color: COLORS.muted, marginTop: 40 }, })