Files
territory-log/app/(tabs)/_layout.tsx
Kibin 6fe6ebef13 feat: Sprint 5 — PIN lock, biometric auth, sync screen, QR code, merge logic
- lib/pinService.ts: PIN storage/verification via expo-secure-store
- lib/syncService.ts: sync abstraction with full merge logic (mDNS/TCP stubbed)
- app/lock.tsx: full-screen PIN lock with biometric support
- components/ui/PinPad.tsx: reusable 6-digit PIN pad component
- components/sync/QRScanner.tsx: QR code scanner via expo-camera
- app/(tabs)/sync.tsx: Sync tab with QR display, partner input, history
- app/sync-progress.tsx: animated sync progress screen with summary
- app/(tabs)/settings.tsx: full settings with PIN setup, security, data sections
- app/(tabs)/_layout.tsx: added Sync tab (RefreshCw icon)
- app/_layout.tsx: AppState listener locks app after 60s background
- package.json: added expo-secure-store, react-native-qrcode-svg
2026-02-18 19:57:35 +08:00

69 lines
1.7 KiB
TypeScript

// app/(tabs)/_layout.tsx
import { Tabs, router } from 'expo-router';
import { useEffect } from 'react';
import { Home, Users, Map, Settings, MapPin, RefreshCw } from 'lucide-react-native';
import { useUserStore } from '@/store/useUserStore';
export default function TabLayout() {
const user = useUserStore((s) => s.user);
useEffect(() => {
if (!user) {
router.replace('/onboarding');
}
}, [user]);
return (
<Tabs
screenOptions={{
tabBarActiveTintColor: '#1A6B72',
tabBarInactiveTintColor: '#9CA3AF',
headerShown: false,
}}
>
<Tabs.Screen
name="index"
options={{
title: 'Home',
tabBarIcon: ({ color, size }) => <Home size={size} color={color} />,
}}
/>
<Tabs.Screen
name="contacts"
options={{
title: 'Contacts',
tabBarIcon: ({ color, size }) => <Users size={size} color={color} />,
}}
/>
<Tabs.Screen
name="territories"
options={{
title: 'Territories',
tabBarIcon: ({ color, size }) => <MapPin size={size} color={color} />,
}}
/>
<Tabs.Screen
name="map"
options={{
title: 'Map',
tabBarIcon: ({ color, size }) => <Map size={size} color={color} />,
}}
/>
<Tabs.Screen
name="sync"
options={{
title: 'Sync',
tabBarIcon: ({ color, size }) => <RefreshCw size={size} color={color} />,
}}
/>
<Tabs.Screen
name="settings"
options={{
title: 'Settings',
tabBarIcon: ({ color, size }) => <Settings size={size} color={color} />,
}}
/>
</Tabs>
);
}