diff --git a/app/(app)/_layout.tsx b/app/(app)/_layout.tsx
index 5889056..0813a5b 100644
--- a/app/(app)/_layout.tsx
+++ b/app/(app)/_layout.tsx
@@ -1,44 +1,51 @@
import { Tabs } from 'expo-router';
-import { Text } from 'react-native';
+import { Icon } from '../../components/Icon';
export default function AppLayout() {
return (
๐ }}
+ options={{ title: 'Home', tabBarIcon: ({ color }) => }}
/>
๐ฅ }}
+ options={{ title: 'Clients', tabBarIcon: ({ color }) => }}
/>
๐ฐ }}
+ options={{ title: 'Collect', tabBarIcon: ({ color }) => }}
/>
๐ }}
- />
- ๐ซ }}
- />
- ๐ }}
+ name="tasks"
+ options={{ title: 'Tickets', tabBarIcon: ({ color }) => }}
/>
๐ค }}
+ options={{ title: 'Profile', tabBarIcon: ({ color }) => }}
/>
+ {/* Hidden โ accessed programmatically */}
+
+
);
}
diff --git a/app/(app)/clients/[id].tsx b/app/(app)/clients/[id].tsx
index ed1ec4b..75eb29e 100644
--- a/app/(app)/clients/[id].tsx
+++ b/app/(app)/clients/[id].tsx
@@ -1,25 +1,24 @@
import { useState } from 'react';
import { View, Text, ScrollView, TouchableOpacity, ActivityIndicator, Linking } from 'react-native';
+import { SafeAreaView } from 'react-native-safe-area-context';
import { useLocalSearchParams, router } from 'expo-router';
import { useQuery } from '@tanstack/react-query';
import { api } from '../../../services/api';
const TABS = ['Profile', 'Subscription', 'Invoices', 'Payments'];
-const STATUS_COLORS: Record = {
- ACTIVE: '#16A34A', SUSPENDED: '#D97706', CANCELLED: '#DC2626', PENDING: '#6B7280',
+const STATUS_COLOR: Record = {
+ ACTIVE: '#166534', SUSPENDED: '#92400E', CANCELLED: '#991B1B', PENDING: '#475569',
};
-
-const INV_STATUS: Record = {
- PAID: { label: 'Paid', color: '#16A34A' },
- UNPAID: { label: 'Unpaid', color: '#D97706' },
- OVERDUE: { label: 'Overdue', color: '#DC2626' },
- PARTIAL: { label: 'Partial', color: '#2563EB' },
- VOID: { label: 'Void', color: '#6B7280' },
+const STATUS_BG: Record = {
+ ACTIVE: '#DCFCE7', SUSPENDED: '#FEF3C7', CANCELLED: '#FEE2E2', PENDING: '#F1F5F9',
};
-
-const PAYMENT_METHODS: Record = {
- CASH: '๐ต', GCASH: '๐ฑ', MAYA: '๐', BANK: '๐ฆ',
+const INV_STATUS: Record = {
+ PAID: { label: 'Paid', color: '#166534', bg: '#DCFCE7' },
+ UNPAID: { label: 'Unpaid', color: '#92400E', bg: '#FEF3C7' },
+ OVERDUE: { label: 'Overdue', color: '#991B1B', bg: '#FEE2E2' },
+ PARTIAL: { label: 'Partial', color: '#0E7490', bg: '#CFFAFE' },
+ VOID: { label: 'Void', color: '#6B7280', bg: '#F1F5F9' },
};
function InfoRow({ label, value, onPress, isLast }: { label: string; value?: string | null; onPress?: () => void; isLast?: boolean }) {
@@ -27,10 +26,11 @@ function InfoRow({ label, value, onPress, isLast }: { label: string; value?: str
- {label}
- {value ?? 'โ'}
+ {label}
+ {value ?? 'โ'}
);
}
@@ -43,177 +43,180 @@ export default function ClientDetailScreen() {
queryKey: ['client', id],
queryFn: () => api.get(`/api/v1/clients/${id}`).then(r => r.data),
});
-
const { data: subData, isLoading: subLoading } = useQuery({
queryKey: ['client-subscription', id],
queryFn: () => api.get(`/api/v1/subscriptions?clientId=${id}&limit=1`).then(r => r.data?.data?.[0] ?? r.data?.[0] ?? null),
enabled: tab === 'Subscription',
});
-
const { data: invoices, isLoading: invLoading } = useQuery({
queryKey: ['client-invoices', id],
queryFn: () => api.get(`/api/v1/invoices?clientId=${id}&limit=20`).then(r => r.data?.data ?? r.data ?? []),
enabled: tab === 'Invoices',
});
-
const { data: payments, isLoading: payLoading } = useQuery({
queryKey: ['client-payments', id],
queryFn: () => api.get(`/api/v1/payments?clientId=${id}&limit=20`).then(r => r.data?.data ?? r.data ?? []),
enabled: tab === 'Payments',
});
- if (isLoading) return (
-
-
-
- );
+ if (isLoading) {
+ return (
+
+
+
+
+
+ );
+ }
+
+ const statusColor = STATUS_COLOR[client?.status] ?? '#475569';
+ const statusBg = STATUS_BG[client?.status] ?? '#F1F5F9';
return (
-
- {/* Header */}
-
- router.back()} className="mr-3 p-1">
- โ
-
-
- {client?.firstName} {client?.lastName}
- {client?.accountNumber}
-
-
-
- {client?.status}
-
-
-
-
- {/* Tabs */}
-
- {TABS.map(t => (
- setTab(t)}
- className={`flex-1 py-3 items-center border-b-2 ${tab === t ? 'border-primary' : 'border-transparent'}`}
- >
- {t}
+
+
+ {/* Header */}
+
+ router.back()} style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 12 }} activeOpacity={0.7} hitSlop={{ top: 10, bottom: 10, left: 0, right: 20 }}>
+ โ Back
- ))}
-
-
-
- {/* PROFILE TAB */}
- {tab === 'Profile' && (
-
-
-
- client?.phone && Linking.openURL(`tel:${client.phone}`)} />
-
-
-
+
+
+ {client?.firstName} {client?.lastName}
+ {client?.accountNumber}
+
+
+ {client?.status}
+
- )}
+
- {/* SUBSCRIPTION TAB */}
- {tab === 'Subscription' && (
- subLoading ? (
-
- ) : !subData ? (
-
- ๐ก
- No active subscription
+ {/* Tabs */}
+
+ {TABS.map(t => (
+ setTab(t)}
+ style={{ flex: 1, paddingVertical: 14, alignItems: 'center', borderBottomWidth: 2.5, borderBottomColor: tab === t ? '#0891B2' : 'transparent' }}
+ activeOpacity={0.7}
+ >
+ {t}
+
+ ))}
+
+
+
+ {/* PROFILE */}
+ {tab === 'Profile' && (
+
+
+
+ client?.phone && Linking.openURL(`tel:${client.phone}`)} />
+
+
+
- ) : (
-
-
-
-
-
-
-
-
+ )}
+
+ {/* SUBSCRIPTION */}
+ {tab === 'Subscription' && (
+ subLoading ? (
+
+ ) : !subData ? (
+
+ No active subscription
- {subData.nextBillingDate && (
-
-
- ๐
Next billing: {new Date(subData.nextBillingDate).toLocaleDateString()}
-
+ ) : (
+
+
+
+
+
+
+
+
- )}
-
- )
- )}
+ {subData.nextBillingDate && (
+
+ Next billing date
+ {new Date(subData.nextBillingDate).toLocaleDateString('en-PH', { year: 'numeric', month: 'long', day: 'numeric' })}
+
+ )}
+
+ )
+ )}
- {/* INVOICES TAB */}
- {tab === 'Invoices' && (
- invLoading ? (
-
- ) : !invoices?.length ? (
-
- ๐งพ
- No invoices yet
-
- ) : (
- invoices.map((inv: any) => {
- const st = INV_STATUS[inv.status] ?? { label: inv.status, color: '#6B7280' };
- return (
-
-
- {inv.invoiceNumber}
-
- {st.label}
+ {/* INVOICES */}
+ {tab === 'Invoices' && (
+ invLoading ? (
+
+ ) : !invoices?.length ? (
+
+ No invoices yet
+
+ ) : (
+ invoices.map((inv: any) => {
+ const st = INV_STATUS[inv.status] ?? { label: inv.status, color: '#6B7280', bg: '#F1F5F9' };
+ return (
+
+
+ {inv.invoiceNumber}
+
+ {st.label}
+
+
+ Due: {inv.dueDate ? new Date(inv.dueDate).toLocaleDateString() : 'โ'}
+ โฑ{Number(inv.amount ?? inv.totalAmount ?? 0).toLocaleString()}
+
+ {inv.balance > 0 && (
+ Balance: โฑ{Number(inv.balance).toLocaleString()}
+ )}
-
- {inv.dueDate ? new Date(inv.dueDate).toLocaleDateString() : 'โ'}
- โฑ{Number(inv.amount ?? inv.totalAmount).toLocaleString()}
-
- {inv.balance > 0 && (
- Balance: โฑ{Number(inv.balance).toLocaleString()}
- )}
-
- );
- })
- )
- )}
+ );
+ })
+ )
+ )}
- {/* PAYMENTS TAB */}
- {tab === 'Payments' && (
- payLoading ? (
-
- ) : !payments?.length ? (
-
- ๐ณ
- No payments recorded
-
- ) : (
- <>
- router.push({ pathname: '/(app)/payments/record', params: { prefillClientId: id, prefillName: `${client?.firstName} ${client?.lastName}`, prefillAccountNumber: client?.accountNumber } })}
- >
- + Record Payment
-
- {payments.map((p: any) => (
-
-
-
-
- {PAYMENT_METHODS[p.paymentMethod] ?? '๐ณ'} {p.paymentMethod}
-
-
- {p.paymentDate ? new Date(p.paymentDate).toLocaleDateString() : new Date(p.createdAt).toLocaleDateString()}
-
- {p.referenceNumber && (
- Ref: {p.referenceNumber}
- )}
-
- โฑ{Number(p.amount).toLocaleString()}
+ {/* PAYMENTS */}
+ {tab === 'Payments' && (
+ payLoading ? (
+
+ ) : (
+ <>
+ router.push({ pathname: '/(app)/payments/record', params: { prefillClientId: id, prefillName: `${client?.firstName} ${client?.lastName}`, prefillAccountNumber: client?.accountNumber } })}
+ activeOpacity={0.8}
+ >
+ + Record Payment
+
+
+ {!payments?.length ? (
+
+ No payments recorded
-
- ))}
- >
- )
- )}
-
-
+ ) : (
+ payments.map((p: any) => (
+
+
+
+ {p.paymentMethod}
+
+ {p.paymentDate ? new Date(p.paymentDate).toLocaleDateString('en-PH') : new Date(p.createdAt).toLocaleDateString('en-PH')}
+
+ {p.referenceNumber && Ref: {p.referenceNumber}}
+
+ โฑ{Number(p.amount).toLocaleString()}
+
+
+ ))
+ )}
+ >
+ )
+ )}
+
+
+
);
}
diff --git a/app/(app)/clients/_layout.tsx b/app/(app)/clients/_layout.tsx
new file mode 100644
index 0000000..8d87bcb
--- /dev/null
+++ b/app/(app)/clients/_layout.tsx
@@ -0,0 +1,4 @@
+import { Stack } from 'expo-router';
+export default function ClientsLayout() {
+ return ;
+}
diff --git a/app/(app)/clients/index.tsx b/app/(app)/clients/index.tsx
index 31c3838..c81d2f8 100644
--- a/app/(app)/clients/index.tsx
+++ b/app/(app)/clients/index.tsx
@@ -1,11 +1,15 @@
import { useState } from 'react';
import { View, Text, FlatList, TextInput, TouchableOpacity, ActivityIndicator, RefreshControl } from 'react-native';
+import { SafeAreaView } from 'react-native-safe-area-context';
import { useQuery } from '@tanstack/react-query';
import { router } from 'expo-router';
import { api } from '../../../services/api';
-const STATUS_COLORS: Record = {
- ACTIVE: '#16A34A', SUSPENDED: '#D97706', CANCELLED: '#DC2626', PENDING: '#6B7280',
+const STATUS_CONFIG: Record = {
+ ACTIVE: { label: 'Active', color: '#166534', bg: '#DCFCE7' },
+ SUSPENDED: { label: 'Suspended', color: '#92400E', bg: '#FEF3C7' },
+ CANCELLED: { label: 'Cancelled', color: '#991B1B', bg: '#FEE2E2' },
+ PENDING: { label: 'Pending', color: '#475569', bg: '#F1F5F9' },
};
export default function ClientsScreen() {
@@ -20,54 +24,73 @@ export default function ClientsScreen() {
);
return (
-
-
- Clients
-
-
-
-
- {isLoading ? (
-
-
+
+
+ {/* Header */}
+
+ Clients
+ {data?.length ?? 0} subscribers
- ) : (
- item.id}
- refreshControl={}
- contentContainerStyle={{ paddingHorizontal: 16, paddingBottom: 24 }}
- renderItem={({ item }) => (
- router.push(`/(app)/clients/${item.id}`)}
- >
-
-
- {item.firstName} {item.lastName}
- {item.accountNumber}
- {item.phone && {item.phone}}
-
-
-
- {item.status}
-
+
+ {/* Search */}
+
+
+
+ {search.length > 0 && (
+ setSearch('')} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}>
+
+ ร
+
+ )}
+
+
+
+ {isLoading ? (
+
+
+
+ ) : (
+ item.id}
+ refreshControl={}
+ contentContainerStyle={{ padding: 16, paddingBottom: 32 }}
+ renderItem={({ item }) => {
+ const st = STATUS_CONFIG[item.status] ?? { label: item.status, color: '#475569', bg: '#F1F5F9' };
+ return (
+ router.push(`/(app)/clients/${item.id}`)}
+ activeOpacity={0.7}
+ >
+
+
+ {item.firstName} {item.lastName}
+ {item.accountNumber}
+ {item.phone && {item.phone}}
+
+
+ {st.label}
+
+
+
+ );
+ }}
+ ListEmptyComponent={
+
+ No clients found
-
- )}
- ListEmptyComponent={
-
- No clients found
-
- }
- />
- )}
-
+ }
+ />
+ )}
+
+
);
}
diff --git a/app/(app)/dashboard.tsx b/app/(app)/dashboard.tsx
index 37ea1ba..7ed0fae 100644
--- a/app/(app)/dashboard.tsx
+++ b/app/(app)/dashboard.tsx
@@ -1,141 +1,194 @@
import { View, Text, ScrollView, RefreshControl, ActivityIndicator, TouchableOpacity } from 'react-native';
-import { useQuery } from '@tanstack/react-query';
+import { SafeAreaView } from 'react-native-safe-area-context';
+import { useQueries } from '@tanstack/react-query';
import { router } from 'expo-router';
import { api } from '../../services/api';
import { useAuthStore } from '../../stores/authStore';
-const PRIORITY_COLOR: Record = { HIGH: '#DC2626', MEDIUM: '#D97706', LOW: '#6B7280' };
-const TICKET_STATUS_COLOR: Record = { OPEN: '#2563EB', IN_PROGRESS: '#D97706', RESOLVED: '#16A34A', CLOSED: '#6B7280' };
+// โโโ Constants โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+const PRIORITY_COLOR: Record = { HIGH: '#DC2626', NORMAL: '#0891B2' };
+const PRIORITY_BG: Record = { HIGH: '#FEE2E2', NORMAL: '#ECFEFF' };
+const STATUS_COLOR: Record = { OPEN: '#0891B2', IN_PROGRESS: '#D97706', RESOLVED: '#16A34A', CLOSED: '#6B7280' };
+const TYPE_COLOR: Record = { INSTALLATION: '#0891B2', SUPPORT: '#7C3AED', BILLING: '#D97706' };
+
+// โโโ KPI Card โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+function KpiCard({ label, value, color, bg }: { label: string; value: string | number; color: string; bg: string }) {
+ return (
+
+ {label}
+ {value}
+
+ );
+}
+
+// โโโ Ticket Row โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+function TaskRow({ task, onPress }: { task: any; onPress: () => void }) {
+ const typeColor = TYPE_COLOR[task.type] ?? '#6B7280';
+ const isHigh = task.priority === 'HIGH';
-function KpiCard({ label, value, color, onPress }: { label: string; value: string | number; color: string; onPress?: () => void }) {
return (
- {label}
- {value}
-
- );
-}
-
-function QuickAction({ icon, label, onPress }: { icon: string; label: string; onPress: () => void }) {
- return (
-
- {icon}
- {label}
-
- );
-}
-
-export default function DashboardScreen() {
- const { user } = useAuthStore();
- const { data, isLoading, refetch, isRefetching } = useQuery({
- queryKey: ['dashboard'],
- queryFn: () => api.get('/api/v1/dashboard/summary').then(r => r.data),
- });
-
- const greeting = () => {
- const h = new Date().getHours();
- if (h < 12) return 'Good morning';
- if (h < 17) return 'Good afternoon';
- return 'Good evening';
- };
-
- return (
- }
- >
- {/* Header */}
-
- {greeting()},
- {user?.firstName ?? 'Field Staff'} ๐
- {new Date().toLocaleDateString('en-PH', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })}
-
-
- {isLoading ? (
-
-
-
- ) : (
-
- {/* KPIs */}
- Overview
-
- router.push('/(app)/clients')}
- />
-
+
+
+
+ {task.type}
-
- router.push('/(app)/clients')}
- />
- router.push('/(app)/payments')}
- />
-
-
- {/* Quick Actions */}
- Quick Actions
-
- router.push('/(app)/payments/record')} />
- router.push('/(app)/tickets/create')} />
- router.push('/(app)/installations')} />
- router.push('/(app)/remittances/submit')} />
-
-
- {/* Recent Tickets */}
- Recent Tickets
- {(data?.recentTickets ?? []).length === 0 ? (
-
- No recent tickets
- router.push('/(app)/tickets/create')}
- >
- Create Ticket
-
+ {isHigh && (
+
+ HIGH
- ) : (
- (data?.recentTickets ?? []).map((t: any) => (
- router.push(`/(app)/tickets/${t.id}`)}
- >
-
- {t.subject}
-
- {t.priority}
-
-
-
- {t.clientName ?? 'No client'}
-
- {t.status}
-
-
-
- ))
)}
- )}
-
+
+ {task.status?.replace('_', ' ')}
+
+
+ {task.subject}
+
+ {task.client?.firstName} {task.client?.lastName}
+ {task.assignedTo
+ ? ` ยท ${task.assignedTo.firstName} ${task.assignedTo.lastName}`
+ : ' ยท Unassigned'}
+
+
+ );
+}
+
+// โโโ Main Screen โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+export default function DashboardScreen() {
+ const { user } = useAuthStore();
+ const hour = new Date().getHours();
+ const greeting = hour < 12 ? 'Good morning' : hour < 18 ? 'Good afternoon' : 'Good evening';
+
+ const [summaryQ, tasksQ] = useQueries({
+ queries: [
+ {
+ queryKey: ['dashboard'],
+ queryFn: () => api.get('/api/v1/dashboard/summary').then(r => r.data),
+ },
+ {
+ queryKey: ['dashboard-tasks'],
+ queryFn: () =>
+ api.get('/api/v1/tickets?status=OPEN&status=IN_PROGRESS&limit=20')
+ .then(r => r.data?.data ?? r.data ?? []),
+ },
+ ],
+ });
+
+ const isLoading = summaryQ.isLoading || tasksQ.isLoading;
+ const isRefetching = summaryQ.isRefetching || tasksQ.isRefetching;
+ const summary = summaryQ.data;
+
+ // Real dashboard API shape:
+ // { subscribers: { total, active, pending, suspended },
+ // billing: { unpaidInvoices, overdueInvoices },
+ // support: { openTickets, inProgressTickets },
+ // tasks: { pending },
+ // revenue: { thisMonth, lastMonth, growth } }
+ const totalClients = summary?.subscribers?.total ?? 'โ';
+ const activeSubscribers = summary?.subscribers?.active ?? 'โ';
+ const unpaidInvoices = summary?.billing?.unpaidInvoices ?? 'โ';
+ const openTickets = summary?.support?.openTickets ?? 'โ';
+ const thisMonthRevenue = summary?.revenue?.thisMonth ?? null;
+
+ const allTasks: any[] = tasksQ.data ?? [];
+ const unassigned = allTasks.filter((t: any) => !t.assignedToId);
+ const assigned = allTasks.filter((t: any) => !!t.assignedToId);
+ const prioOrder: Record = { HIGH: 0, NORMAL: 1 };
+ const byPrio = (a: any, b: any) => (prioOrder[a.priority] ?? 2) - (prioOrder[b.priority] ?? 2);
+
+ const refetchAll = () => { summaryQ.refetch(); tasksQ.refetch(); };
+
+ return (
+
+ }
+ >
+ {/* Header */}
+
+ {greeting},
+ {user?.firstName ?? 'Field Staff'}
+
+
+ {isLoading ? (
+
+
+
+ ) : (
+
+ {/* KPI Row 1 */}
+
+
+
+
+
+ {/* KPI Row 2 */}
+
+
+
+
+
+ {/* Revenue card */}
+ {thisMonthRevenue !== null && (
+
+
+ This Month's Revenue
+ โฑ{Number(thisMonthRevenue).toLocaleString()}
+
+ {summary?.revenue?.growth !== undefined && (
+
+ +{summary.revenue.growth}%
+
+ )}
+
+ )}
+
+ {/* Unassigned Tasks */}
+
+
+ Unassigned
+ {unassigned.length > 0 && (
+
+ {unassigned.length}
+
+ )}
+
+ router.push('/(app)/tasks')} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}>
+ View all
+
+
+
+ {unassigned.length === 0 ? (
+
+ No unassigned tasks
+
+ ) : (
+
+ {[...unassigned].sort(byPrio).slice(0, 5).map((t: any) => (
+ router.push(`/(app)/tasks/${t.id}`)} />
+ ))}
+
+ )}
+
+ {/* Assigned Tasks */}
+ {assigned.length > 0 && (
+ <>
+ Assigned Tasks
+ {[...assigned].sort(byPrio).slice(0, 5).map((t: any) => (
+ router.push(`/(app)/tasks/${t.id}`)} />
+ ))}
+ >
+ )}
+
+
+
+ )}
+
+
);
}
diff --git a/app/(app)/installations/[id].tsx b/app/(app)/installations/[id].tsx
deleted file mode 100644
index 710ec5c..0000000
--- a/app/(app)/installations/[id].tsx
+++ /dev/null
@@ -1,83 +0,0 @@
-import { useState } from 'react';
-import { View, Text, TouchableOpacity, ScrollView, Alert, Image, ActivityIndicator } from 'react-native';
-import { useLocalSearchParams, router } from 'expo-router';
-import * as ImagePicker from 'expo-image-picker';
-import * as Location from 'expo-location';
-import { api } from '../../../services/api';
-
-export default function InstallationConfirmScreen() {
- const { id } = useLocalSearchParams<{ id: string }>();
- const [photo, setPhoto] = useState(null);
- const [coords, setCoords] = useState<{ lat: number; lng: number } | null>(null);
- const [loading, setLoading] = useState(false);
- const [gpsLoading, setGpsLoading] = useState(false);
-
- const capturePhoto = async () => {
- const { status } = await ImagePicker.requestCameraPermissionsAsync();
- if (status !== 'granted') return Alert.alert('Permission denied', 'Camera access is required.');
- const result = await ImagePicker.launchCameraAsync({ quality: 0.7, base64: false });
- if (!result.canceled) setPhoto(result.assets[0].uri);
- };
-
- const captureGPS = async () => {
- setGpsLoading(true);
- try {
- const { status } = await Location.requestForegroundPermissionsAsync();
- if (status !== 'granted') { Alert.alert('Permission denied', 'Location access is required.'); return; }
- const loc = await Location.getCurrentPositionAsync({ accuracy: Location.Accuracy.High });
- setCoords({ lat: loc.coords.latitude, lng: loc.coords.longitude });
- } catch { Alert.alert('Error', 'Could not get location.'); }
- finally { setGpsLoading(false); }
- };
-
- const confirm = async () => {
- if (!coords) return Alert.alert('Required', 'Capture GPS location first.');
- setLoading(true);
- try {
- await api.patch(`/api/v1/tickets/${id}/confirm-installation`, {
- latitude: coords.lat,
- longitude: coords.lng,
- photoUrl: photo,
- });
- Alert.alert('Done!', 'Installation confirmed.', [{ text: 'OK', onPress: () => router.back() }]);
- } catch (e: any) {
- Alert.alert('Error', e?.response?.data?.message ?? 'Confirmation failed.');
- } finally { setLoading(false); }
- };
-
- return (
-
-
- router.back()} className="mr-3">
- โ
-
- Installation Confirmation
-
-
-
- ๐ GPS Location
- {coords ? (
- โ {coords.lat.toFixed(6)}, {coords.lng.toFixed(6)}
- ) : (
- No location captured yet
- )}
-
- {gpsLoading ? : Capture GPS}
-
-
-
-
- ๐ท Photo Proof
- {photo && }
-
- {photo ? 'Retake Photo' : 'Take Photo'}
-
-
-
-
- {loading ? : โ Confirm Installation}
-
-
-
- );
-}
diff --git a/app/(app)/installations/index.tsx b/app/(app)/installations/index.tsx
deleted file mode 100644
index 95e940f..0000000
--- a/app/(app)/installations/index.tsx
+++ /dev/null
@@ -1,110 +0,0 @@
-import { View, Text, FlatList, TouchableOpacity, ActivityIndicator, RefreshControl } from 'react-native';
-import { useQuery } from '@tanstack/react-query';
-import { router } from 'expo-router';
-import { api } from '../../../services/api';
-
-// Installations are tickets of type INSTALLATION (or filtered by subject prefix)
-// We query tickets with type=INSTALLATION if the API supports it, fallback to all open tickets
-async function fetchInstallations() {
- try {
- const res = await api.get('/api/v1/tickets?type=INSTALLATION&limit=50');
- return res.data?.data ?? res.data ?? [];
- } catch {
- // Fallback: all OPEN tickets
- const res = await api.get('/api/v1/tickets?status=OPEN&limit=50');
- return res.data?.data ?? res.data ?? [];
- }
-}
-
-const STATUS_STYLE: Record = {
- OPEN: { bg: '#EFF6FF', text: '#2563EB' },
- IN_PROGRESS: { bg: '#FFFBEB', text: '#D97706' },
- RESOLVED: { bg: '#F0FDF4', text: '#16A34A' },
- CLOSED: { bg: '#F3F4F6', text: '#6B7280' },
-};
-
-export default function InstallationsScreen() {
- const { data, isLoading, refetch, isRefetching } = useQuery({
- queryKey: ['installations'],
- queryFn: fetchInstallations,
- });
-
- const installations: any[] = data ?? [];
-
- return (
-
- {/* Header */}
-
- Installations
-
- {installations.length} pending
-
-
-
- {isLoading ? (
-
-
-
- ) : (
- item.id}
- refreshControl={}
- contentContainerStyle={{ padding: 16 }}
- renderItem={({ item }) => {
- const statusStyle = STATUS_STYLE[item.status] ?? { bg: '#F3F4F6', text: '#6B7280' };
- return (
- router.push(`/(app)/installations/${item.id}`)}
- >
-
-
- {item.subject}
-
-
-
- {item.status?.replace('_', ' ')}
-
-
-
-
-
-
- {item.client?.firstName} {item.client?.lastName}
-
-
- {item.createdAt ? new Date(item.createdAt).toLocaleDateString() : ''}
-
-
-
- {item.client?.address && (
-
- ๐ {item.client.address}
-
- )}
-
- {/* Confirm button if not yet resolved */}
- {item.status !== 'RESOLVED' && item.status !== 'CLOSED' && (
- router.push(`/(app)/installations/${item.id}`)}
- >
- ๐ท Confirm Installation
-
- )}
-
- );
- }}
- ListEmptyComponent={
-
- ๐
- No installations pending
- All caught up!
-
- }
- />
- )}
-
- );
-}
diff --git a/app/(app)/payments/_layout.tsx b/app/(app)/payments/_layout.tsx
new file mode 100644
index 0000000..483e0bb
--- /dev/null
+++ b/app/(app)/payments/_layout.tsx
@@ -0,0 +1,4 @@
+import { Stack } from 'expo-router';
+export default function PaymentsLayout() {
+ return ;
+}
diff --git a/app/(app)/payments/index.tsx b/app/(app)/payments/index.tsx
index 81d9331..e1f5f71 100644
--- a/app/(app)/payments/index.tsx
+++ b/app/(app)/payments/index.tsx
@@ -1,87 +1,48 @@
-import { useState } from 'react';
-import { View, Text, FlatList, TouchableOpacity, ActivityIndicator, RefreshControl } from 'react-native';
-import { useQuery } from '@tanstack/react-query';
+import { View, Text, TouchableOpacity, ScrollView } from 'react-native';
+import { SafeAreaView } from 'react-native-safe-area-context';
import { router } from 'expo-router';
-import { api } from '../../../services/api';
-
-const METHOD_ICON: Record = { CASH: '๐ต', GCASH: '๐ฑ', MAYA: '๐', BANK: '๐ฆ' };
-
-export default function PaymentsScreen() {
- const { data, isLoading, refetch, isRefetching } = useQuery({
- queryKey: ['payments'],
- queryFn: () => api.get('/api/v1/payments?limit=50').then(r => r.data?.data ?? r.data ?? []),
- });
-
- const payments: any[] = data ?? [];
-
- // Calculate today's total
- const today = new Date().toDateString();
- const todayTotal = payments
- .filter((p: any) => new Date(p.paymentDate ?? p.createdAt).toDateString() === today)
- .reduce((sum: number, p: any) => sum + Number(p.amount), 0);
+export default function CollectScreen() {
return (
-
- {/* Header */}
-
-
- Payments
- Today: โฑ{todayTotal.toLocaleString()}
+
+
+
+ Collect
+ Payments & remittances
- router.push('/(app)/payments/record')}
- >
- + Record
-
-
- {isLoading ? (
-
- ) : (
- item.id}
- refreshControl={}
- contentContainerStyle={{ padding: 16, paddingBottom: 32 }}
- ListEmptyComponent={
-
- ๐ณ
- No payments yet
- router.push('/(app)/payments/record')}
- >
- Record First Payment
-
+
+ router.push('/(app)/payments/record')}
+ activeOpacity={0.7}
+ >
+
+ ๐ณ
- }
- renderItem={({ item }) => (
-
-
-
-
- {METHOD_ICON[item.paymentMethod] ?? '๐ณ'}
-
- {item.client?.firstName} {item.client?.lastName}
-
-
- {item.client?.accountNumber}
-
- {new Date(item.paymentDate ?? item.createdAt).toLocaleDateString()} ยท {item.paymentMethod}
-
- {item.referenceNumber && (
- Ref: {item.referenceNumber}
- )}
-
-
- โฑ{Number(item.amount).toLocaleString()}
-
-
+
+ Record Payment
+ Cash, GCash, Maya, or bank
- )}
- />
- )}
-
+ โบ
+
+
+ router.push('/(app)/remittances')}
+ activeOpacity={0.7}
+ >
+
+ ๐
+
+
+ Remittances
+ Submit & track daily collections
+
+ โบ
+
+
+
+
);
}
diff --git a/app/(app)/payments/record.tsx b/app/(app)/payments/record.tsx
index 6e9bf58..fa07a84 100644
--- a/app/(app)/payments/record.tsx
+++ b/app/(app)/payments/record.tsx
@@ -1,189 +1,211 @@
import { useState, useEffect } from 'react';
-import { View, Text, TextInput, TouchableOpacity, ScrollView, Alert, ActivityIndicator, FlatList, Modal } from 'react-native';
+import { View, Text, TextInput, TouchableOpacity, ScrollView, Alert, ActivityIndicator } from 'react-native';
+import { SafeAreaView } from 'react-native-safe-area-context';
import { router, useLocalSearchParams } from 'expo-router';
-import { useQuery, useQueryClient } from '@tanstack/react-query';
import { api } from '../../../services/api';
-const METHODS = ['CASH', 'GCASH', 'MAYA', 'BANK'];
+const METHODS = [
+ { id: 'CASH', label: 'Cash' },
+ { id: 'GCASH', label: 'GCash' },
+ { id: 'MAYA', label: 'Maya' },
+ { id: 'BANK', label: 'Bank Transfer' },
+];
export default function RecordPaymentScreen() {
- const params = useLocalSearchParams<{ prefillClientId?: string; prefillName?: string; prefillAccountNumber?: string }>();
- const qc = useQueryClient();
+ // Prefill params when navigated from client detail
+ const params = useLocalSearchParams<{
+ prefillClientId?: string;
+ prefillName?: string;
+ prefillAccountNumber?: string;
+ }>();
- const [search, setSearch] = useState('');
- const [showPicker, setShowPicker] = useState(false);
- const [client, setClient] = useState(
- params.prefillClientId
- ? { id: params.prefillClientId, firstName: params.prefillName?.split(' ')[0], lastName: params.prefillName?.split(' ').slice(1).join(' '), accountNumber: params.prefillAccountNumber }
- : null
- );
- const [amount, setAmount] = useState('');
- const [method, setMethod] = useState('CASH');
+ const [search, setSearch] = useState('');
+ const [client, setClient] = useState(null);
+ const [amount, setAmount] = useState('');
+ const [method, setMethod] = useState('CASH');
const [reference, setReference] = useState('');
- const [notes, setNotes] = useState('');
- const [loading, setLoading] = useState(false);
+ const [loading, setLoading] = useState(false);
+ const [searching, setSearching] = useState(false);
- // Debounced client search
- const [debouncedSearch, setDebouncedSearch] = useState('');
+ // Auto-fill client if navigated from client detail
useEffect(() => {
- const t = setTimeout(() => setDebouncedSearch(search), 400);
- return () => clearTimeout(t);
- }, [search]);
+ if (params.prefillClientId && params.prefillName) {
+ setClient({
+ id: params.prefillClientId,
+ firstName: params.prefillName.split(' ')[0] ?? '',
+ lastName: params.prefillName.split(' ').slice(1).join(' ') ?? '',
+ accountNumber: params.prefillAccountNumber ?? '',
+ });
+ }
+ }, []);
- const { data: searchResults, isFetching: searching } = useQuery({
- queryKey: ['client-search', debouncedSearch],
- queryFn: () => api.get(`/api/v1/clients?search=${debouncedSearch}&limit=8`).then(r => r.data?.data ?? r.data ?? []),
- enabled: debouncedSearch.trim().length >= 2,
- });
+ const searchClient = async () => {
+ if (!search.trim()) return;
+ setSearching(true);
+ try {
+ const res = await api.get(`/api/v1/clients?search=${encodeURIComponent(search.trim())}&limit=5`);
+ const found = res.data?.data ?? res.data ?? [];
+ if (Array.isArray(found) && found.length === 1) {
+ setClient(found[0]);
+ } else if (Array.isArray(found) && found.length > 1) {
+ // Show picker if multiple results
+ Alert.alert(
+ 'Multiple clients found',
+ found.map((c: any, i: number) => `${i + 1}. ${c.firstName} ${c.lastName} (${c.accountNumber})`).join('\n'),
+ [
+ ...found.slice(0, 5).map((c: any, i: number) => ({
+ text: `${i + 1}. ${c.firstName} ${c.lastName}`,
+ onPress: () => setClient(c),
+ })),
+ { text: 'Cancel', style: 'cancel' as const },
+ ]
+ );
+ } else {
+ Alert.alert('Not Found', 'No client found. Try account number or full name.');
+ }
+ } catch {
+ Alert.alert('Error', 'Search failed. Please try again.');
+ } finally { setSearching(false); }
+ };
const submit = async () => {
- if (!client) return Alert.alert('Required', 'Select a client first.');
- if (!amount || isNaN(Number(amount)) || Number(amount) <= 0)
- return Alert.alert('Required', 'Enter a valid amount.');
+ if (!client) return Alert.alert('Required', 'Search and select a client first.');
+ const amt = Number(amount);
+ if (!amount || isNaN(amt) || amt <= 0) return Alert.alert('Required', 'Enter a valid amount.');
setLoading(true);
try {
await api.post('/api/v1/payments', {
- clientId: client.id,
- amount: Number(amount),
- paymentMethod: method,
- referenceNumber: reference || undefined,
- notes: notes || undefined,
- paymentDate: new Date().toISOString(),
+ clientId: client.id,
+ amount: amt,
+ channel: method, // API uses `channel` not `paymentMethod`
+ referenceNumber: reference.trim() || undefined,
+ paymentDate: new Date().toISOString(),
});
- // Invalidate relevant queries
- qc.invalidateQueries({ queryKey: ['payments'] });
- qc.invalidateQueries({ queryKey: ['client-payments', client.id] });
- qc.invalidateQueries({ queryKey: ['dashboard'] });
- Alert.alert('โ
Payment Recorded', `โฑ${Number(amount).toLocaleString()} from ${client.firstName} ${client.lastName}`, [
+ Alert.alert('Payment Recorded!', `โฑ${amt.toLocaleString()} from ${client.firstName} ${client.lastName}`, [
+ { text: 'Record Another', onPress: () => { setClient(null); setAmount(''); setSearch(''); setReference(''); } },
{ text: 'Done', onPress: () => router.back() },
- { text: 'Record Another', onPress: () => { setClient(null); setAmount(''); setReference(''); setNotes(''); setSearch(''); } },
]);
} catch (e: any) {
- Alert.alert('Error', e?.response?.data?.message ?? 'Payment failed. Try again.');
- } finally {
- setLoading(false);
- }
+ const msg = e?.response?.data?.message;
+ Alert.alert('Error', Array.isArray(msg) ? msg.join('\n') : msg ?? 'Payment failed.');
+ } finally { setLoading(false); }
};
+ const canSubmit = !!client && !!amount && Number(amount) > 0;
+
return (
-
-
- router.back()} className="mr-3 p-1">
- โ
-
- Record Payment
-
-
-
- {/* Client selector */}
- Client *
- {client ? (
-
-
- {client.firstName} {client.lastName}
- {client.accountNumber}
-
- { setClient(null); setSearch(''); }} className="p-2">
- Change
-
-
- ) : (
-
-
-
- {searching && }
-
- {debouncedSearch.trim().length >= 2 && (
-
- {(searchResults ?? []).length === 0 && !searching && (
- No clients found
- )}
- {(searchResults ?? []).map((c: any) => (
- { setClient(c); setSearch(''); }}
- >
- {c.firstName} {c.lastName}
- {c.accountNumber}
-
- ))}
-
- )}
-
- )}
-
- {/* Amount */}
- Amount (โฑ) *
-
-
- {/* Payment method */}
- Payment Method *
-
- {METHODS.map(m => (
- setMethod(m)}
- className={`rounded-xl px-5 py-2.5 mr-2 mb-2 border ${method === m ? 'bg-primary border-primary' : 'bg-white border-gray-200'}`}
- >
- {m}
-
- ))}
+
+
+ {/* Header */}
+
+ router.back()} style={{ marginBottom: 12 }} activeOpacity={0.7}>
+ โ Back
+
+ Record Payment
+ Field collection
- {/* Reference (for non-cash) */}
- {method !== 'CASH' && (
- <>
- Reference # *
-
- >
- )}
+
+ {/* Client section */}
+ Client
- {/* Notes */}
- Notes (optional)
-
+ {client ? (
+
+ {client.firstName} {client.lastName}
+ {client.accountNumber}
+ { setClient(null); setSearch(''); }} style={{ marginTop: 10 }} hitSlop={{ top: 8, bottom: 8, left: 0, right: 8 }}>
+ ร Change client
+
+
+ ) : (
+
+
+
+
+ {search.length > 0 && (
+ setSearch('')} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}>
+
+ ร
+
+
+ )}
+
+
+ {searching
+ ?
+ : Find
+ }
+
+
+ Search by account number, first name, or last name
+
+ )}
- {/* Submit */}
-
- {loading
- ?
- :
- Submit Payment {amount ? `ยท โฑ${Number(amount || 0).toLocaleString()}` : ''}
-
- }
-
+ {/* Amount */}
+ Amount (โฑ)
+
-
-
-
+ {/* Payment method */}
+ Payment Method
+
+ {METHODS.map(m => (
+ setMethod(m.id)}
+ style={{ flex: 1, borderRadius: 14, paddingVertical: 14, alignItems: 'center', marginHorizontal: 4, backgroundColor: method === m.id ? '#0891B2' : '#FFF', borderWidth: 1.5, borderColor: method === m.id ? '#0891B2' : '#E2E8F0' }}
+ activeOpacity={0.7}
+ >
+ {m.label}
+
+ ))}
+
+
+ {/* Reference */}
+
+ Reference # (optional)
+
+
+
+
+ {loading
+ ?
+ :
+ {canSubmit ? `Record โฑ${Number(amount || 0).toLocaleString()} Payment` : 'Record Payment'}
+
+ }
+
+
+
+
);
}
diff --git a/app/(app)/profile.tsx b/app/(app)/profile.tsx
index a83c9f8..5bf137b 100644
--- a/app/(app)/profile.tsx
+++ b/app/(app)/profile.tsx
@@ -1,57 +1,81 @@
import { View, Text, TouchableOpacity, Alert, ScrollView } from 'react-native';
+import { SafeAreaView } from 'react-native-safe-area-context';
import { useAuthStore } from '../../stores/authStore';
import { router } from 'expo-router';
export default function ProfileScreen() {
const { user, logout, tenantSlug } = useAuthStore();
+ const initials = `${user?.firstName?.[0] ?? ''}${user?.lastName?.[0] ?? ''}`.toUpperCase() || 'U';
+ const fullName = `${user?.firstName ?? ''} ${user?.lastName ?? ''}`.trim();
+ const role = user?.roles?.[0] ?? user?.role ?? 'Staff';
const handleLogout = () => {
Alert.alert('Sign Out', 'Are you sure you want to sign out?', [
{ text: 'Cancel', style: 'cancel' },
- {
- text: 'Sign Out', style: 'destructive',
- onPress: async () => {
- await logout();
- router.replace('/(auth)/company-code');
- }
- }
+ { text: 'Sign Out', style: 'destructive', onPress: async () => { await logout(); router.replace('/(auth)/company-code'); } },
]);
};
return (
-
-
-
-
- {user?.firstName?.[0]?.toUpperCase() ?? 'U'}
-
-
- {user?.firstName} {user?.lastName}
- {user?.role} ยท {tenantSlug}
-
-
-
-
- {[
- { label: 'Username', value: user?.username },
- { label: 'Email', value: user?.email },
- { label: 'Role', value: user?.role },
- { label: 'Company', value: tenantSlug },
- ].map((item, i) => (
- 0 ? 'border-t border-gray-100' : ''}`}>
- {item.label}
- {item.value ?? 'โ'}
-
- ))}
+
+
+ {/* Header */}
+
+
+ {initials}
+
+ {fullName}
+
+ {role}
+
-
- Sign Out
-
-
-
+
+ {/* Info */}
+
+ {[
+ { label: 'Email', value: user?.email },
+ { label: 'Company', value: tenantSlug },
+ { label: 'Role', value: role },
+ ].map((row, i, arr) => (
+
+ {row.label}
+ {row.value ?? 'โ'}
+
+ ))}
+
+
+ {/* User Management โ admin only */}
+ {(user?.roles?.includes('ADMIN') || user?.role === 'ADMIN' || role === 'ADMIN') && (
+ router.push('/(app)/users')}
+ activeOpacity={0.7}
+ >
+
+ User Management
+ Add & manage team members
+
+ โบ
+
+ )}
+
+ {/* App version */}
+
+ App
+ FiberOps Mobile v1.0.0
+
+
+ {/* Sign out */}
+
+ Sign Out
+
+
+
+
);
}
diff --git a/app/(app)/remittances/[id].tsx b/app/(app)/remittances/[id].tsx
index cbf8c4a..b24d04d 100644
--- a/app/(app)/remittances/[id].tsx
+++ b/app/(app)/remittances/[id].tsx
@@ -1,10 +1,24 @@
import { View, Text, ScrollView, TouchableOpacity, ActivityIndicator } from 'react-native';
+import { SafeAreaView } from 'react-native-safe-area-context';
import { useLocalSearchParams, router } from 'expo-router';
import { useQuery } from '@tanstack/react-query';
import { api } from '../../../services/api';
-const STATUS_COLOR: Record = { PENDING: '#D97706', CONFIRMED: '#16A34A', DISPUTED: '#DC2626' };
-const METHOD_ICON: Record = { CASH: '๐ต', GCASH: '๐ฑ', MAYA: '๐', BANK: '๐ฆ' };
+const STATUS_CONFIG: Record = {
+ PENDING: { color: '#92400E', bg: '#FEF3C7' },
+ CONFIRMED: { color: '#166534', bg: '#DCFCE7' },
+ DISPUTED: { color: '#991B1B', bg: '#FEE2E2' },
+};
+
+function InfoRow({ label, value, isLast }: { label: string; value?: string | null; isLast?: boolean }) {
+ if (!value) return null;
+ return (
+
+ {label}
+ {value}
+
+ );
+}
export default function RemittanceDetailScreen() {
const { id } = useLocalSearchParams<{ id: string }>();
@@ -14,76 +28,97 @@ export default function RemittanceDetailScreen() {
queryFn: () => api.get(`/api/v1/remittances/${id}`).then(r => r.data),
});
- if (isLoading) return (
-
-
-
- );
+ if (isLoading) {
+ return (
+
+
+
+
+
+ );
+ }
const status = data?.status ?? 'PENDING';
- const statusColor = STATUS_COLOR[status] ?? '#6B7280';
+ const st = STATUS_CONFIG[status] ?? { color: '#6B7280', bg: '#F1F5F9' };
+ const payments: any[] = data?.payments ?? [];
return (
-
-
- router.back()} className="mr-3 p-1">
- โ
-
-
- Remittance
- {data?.createdAt ? new Date(data.createdAt).toLocaleDateString() : ''}
-
-
- {status}
-
-
-
-
- {/* Summary card */}
-
- Total Amount
- โฑ{Number(data?.totalAmount ?? 0).toLocaleString()}
- {data?.notes && {data.notes}}
-
-
- {/* Details */}
-
- {[
- { label: 'Submitted by', value: data?.collector?.firstName ? `${data.collector.firstName} ${data.collector.lastName}` : undefined },
- { label: 'Submitted on', value: data?.createdAt ? new Date(data.createdAt).toLocaleString() : undefined },
- { label: 'Confirmed on', value: data?.confirmedAt ? new Date(data.confirmedAt).toLocaleString() : undefined },
- { label: 'Confirmed by', value: data?.confirmedBy?.firstName ? `${data.confirmedBy.firstName} ${data.confirmedBy.lastName}` : undefined },
- ].filter(r => r.value).map((row, i, arr) => (
-
- {row.label}
- {row.value}
+
+
+ {/* Header */}
+
+ router.back()} style={{ marginBottom: 12 }} activeOpacity={0.7}>
+ โ Back
+
+
+
+ Remittance
+
+ {data?.createdAt ? new Date(data.createdAt).toLocaleDateString('en-PH', { year: 'numeric', month: 'long', day: 'numeric' }) : ''}
+
- ))}
+
+ {status}
+
+
- {/* Included payments */}
- {(data?.payments ?? []).length > 0 && (
- <>
- Included Payments ({data.payments.length})
- {data.payments.map((p: any) => (
-
-
-
-
- {METHOD_ICON[p.paymentMethod] ?? '๐ณ'} {p.client?.firstName} {p.client?.lastName}
-
- {p.client?.accountNumber} ยท {p.paymentMethod}
- {p.referenceNumber && Ref: {p.referenceNumber}}
-
- โฑ{Number(p.amount).toLocaleString()}
-
-
- ))}
- >
- )}
+
+ {/* Total amount card */}
+
+ Total Amount
+ โฑ{Number(data?.totalAmount ?? 0).toLocaleString()}
+ {payments.length > 0 && (
+ {payments.length} payment{payments.length !== 1 ? 's' : ''} included
+ )}
+ {data?.notes && (
+ "{data.notes}"
+ )}
+
-
-
-
+ {/* Details */}
+
+
+
+
+
+
+
+ {/* Payments breakdown */}
+ {payments.length > 0 && (
+ <>
+
+ Payments ({payments.length})
+
+ {payments.map((p: any) => (
+
+
+
+
+ {p.client?.firstName} {p.client?.lastName}
+
+
+ {p.client?.accountNumber} ยท {p.channel ?? p.paymentMethod}
+
+ {p.referenceNumber && (
+ Ref: {p.referenceNumber}
+ )}
+
+
+ โฑ{Number(p.amount).toLocaleString()}
+
+
+
+ ))}
+ >
+ )}
+
+
+
);
}
diff --git a/app/(app)/remittances/_layout.tsx b/app/(app)/remittances/_layout.tsx
new file mode 100644
index 0000000..e0b3d48
--- /dev/null
+++ b/app/(app)/remittances/_layout.tsx
@@ -0,0 +1,4 @@
+import { Stack } from 'expo-router';
+export default function RemittancesLayout() {
+ return ;
+}
diff --git a/app/(app)/remittances/index.tsx b/app/(app)/remittances/index.tsx
index 0529a58..c5a6567 100644
--- a/app/(app)/remittances/index.tsx
+++ b/app/(app)/remittances/index.tsx
@@ -1,49 +1,120 @@
import { View, Text, FlatList, TouchableOpacity, ActivityIndicator, RefreshControl } from 'react-native';
-import { useQuery } from '@tanstack/react-query';
+import { SafeAreaView } from 'react-native-safe-area-context';
+import { useQueries } from '@tanstack/react-query';
import { router } from 'expo-router';
import { api } from '../../../services/api';
-const STATUS_COLOR: Record = { PENDING: '#D97706', CONFIRMED: '#16A34A', DISPUTED: '#DC2626' };
+const STATUS_CONFIG: Record = {
+ PENDING: { color: '#92400E', bg: '#FEF3C7' },
+ CONFIRMED: { color: '#166534', bg: '#DCFCE7' },
+ DISPUTED: { color: '#991B1B', bg: '#FEE2E2' },
+};
export default function RemittancesScreen() {
- const { data, isLoading, refetch, isRefetching } = useQuery({
- queryKey: ['remittances'],
- queryFn: () => api.get('/api/v1/remittances?limit=50').then(r => r.data?.data ?? r.data),
+ const [remittancesQ, unremittedQ] = useQueries({
+ queries: [
+ { queryKey: ['remittances'], queryFn: () => api.get('/api/v1/remittances?limit=50').then(r => r.data?.data ?? r.data) },
+ { queryKey: ['unremitted'], queryFn: () => api.get('/api/v1/payments?unremitted=true').then(r => r.data).catch(() => null) },
+ ],
});
+ const data = remittancesQ.data ?? [];
+ const isLoading = remittancesQ.isLoading;
+ const isRefetching = remittancesQ.isRefetching || unremittedQ.isRefetching;
+ const refetchAll = () => { remittancesQ.refetch(); unremittedQ.refetch(); };
+
+ // Compute unremitted total from raw payments or summary
+ const unremittedPayments: any[] = Array.isArray(unremittedQ.data?.data)
+ ? unremittedQ.data.data
+ : Array.isArray(unremittedQ.data)
+ ? unremittedQ.data
+ : [];
+ const unremittedTotal = unremittedQ.data?.totalUnremitted
+ ?? unremittedPayments.reduce((s: number, p: any) => s + Number(p.amount ?? 0), 0);
+ const unremittedCount = unremittedQ.data?.count ?? unremittedPayments.length;
+
return (
-
-
- Remittances
- router.push('/(app)/remittances/submit')}>
- + Submit
-
-
- {isLoading ? (
-
- ) : (
- item.id}
- refreshControl={}
- contentContainerStyle={{ padding: 16 }}
- renderItem={({ item }) => (
+
+
+ {/* Header */}
+
+ router.back()} style={{ marginBottom: 12 }} activeOpacity={0.7}>
+ โ Back
+
+
+
+ Remittances
+ {data.length} submissions
+
router.push(`/(app)/remittances/${item.id}`)}
+ style={{ backgroundColor: 'rgba(255,255,255,0.2)', borderRadius: 12, paddingHorizontal: 16, paddingVertical: 10 }}
+ onPress={() => router.push('/(app)/remittances/submit')}
+ activeOpacity={0.7}
>
-
- โฑ{Number(item.totalAmount).toLocaleString()}
-
- {item.status}
-
-
- {new Date(item.createdAt).toLocaleDateString()}
+ + Submit
- )}
- ListEmptyComponent={No remittances yet}
- />
- )}
-
+
+
+
+ {isLoading ? (
+
+
+
+ ) : (
+ item.id}
+ refreshControl={}
+ ListHeaderComponent={
+ unremittedTotal > 0 ? (
+ router.push('/(app)/remittances/submit')}
+ style={{ backgroundColor: '#FFF7ED', borderRadius: 16, padding: 18, marginBottom: 16, borderWidth: 1.5, borderColor: '#FED7AA' }}
+ activeOpacity={0.7}
+ >
+
+ Unremitted Amount
+
+
+ โฑ{Number(unremittedTotal).toLocaleString()}
+
+ {unremittedCount > 0 && (
+ {unremittedCount} payment{unremittedCount !== 1 ? 's' : ''} pending remittance
+ )}
+ Tap to submit โ
+
+ ) : null
+ }
+ contentContainerStyle={{ padding: 16, paddingBottom: 32 }}
+ renderItem={({ item }) => {
+ const st = STATUS_CONFIG[item.status] ?? { color: '#6B7280', bg: '#F1F5F9' };
+ return (
+ router.push(`/(app)/remittances/${item.id}`)}
+ activeOpacity={0.7}
+ >
+
+ โฑ{Number(item.totalAmount).toLocaleString()}
+
+ {item.status}
+
+
+ {new Date(item.createdAt).toLocaleDateString('en-PH', { year: 'numeric', month: 'long', day: 'numeric' })}
+ {item.payments?.length > 0 && (
+ {item.payments.length} payment{item.payments.length !== 1 ? 's' : ''}
+ )}
+
+ );
+ }}
+ ListEmptyComponent={
+
+ No remittances yet
+
+ }
+ />
+ )}
+
+
);
}
diff --git a/app/(app)/remittances/submit.tsx b/app/(app)/remittances/submit.tsx
index f8492c0..2450456 100644
--- a/app/(app)/remittances/submit.tsx
+++ b/app/(app)/remittances/submit.tsx
@@ -1,57 +1,112 @@
import { useState } from 'react';
import { View, Text, TextInput, TouchableOpacity, ScrollView, Alert, ActivityIndicator } from 'react-native';
+import { SafeAreaView } from 'react-native-safe-area-context';
import { router } from 'expo-router';
+import { useQuery } from '@tanstack/react-query';
import { api } from '../../../services/api';
export default function SubmitRemittanceScreen() {
- const [amount, setAmount] = useState('');
const [notes, setNotes] = useState('');
const [loading, setLoading] = useState(false);
+ // Fetch unremitted payments to auto-fill amount
+ const { data: unremittedData, isLoading: loadingUnremitted } = useQuery({
+ queryKey: ['unremitted'],
+ queryFn: () => api.get('/api/v1/payments?unremitted=true').then(r => r.data).catch(() => null),
+ });
+
+ const unremittedPayments: any[] = Array.isArray(unremittedData?.data)
+ ? unremittedData.data
+ : Array.isArray(unremittedData)
+ ? unremittedData
+ : [];
+ const totalAmount = unremittedData?.totalUnremitted
+ ?? unremittedPayments.reduce((s: number, p: any) => s + Number(p.amount ?? 0), 0);
+
const submit = async () => {
- if (!amount || isNaN(Number(amount))) return Alert.alert('Required', 'Enter a valid amount.');
+ if (totalAmount <= 0) return Alert.alert('Nothing to Submit', 'You have no unremitted payments to submit.');
setLoading(true);
try {
- await api.post('/api/v1/remittances', { totalAmount: Number(amount), notes });
- Alert.alert('Submitted', 'Remittance submitted successfully.', [{ text: 'OK', onPress: () => router.back() }]);
+ await api.post('/api/v1/remittances', { totalAmount: Number(totalAmount), notes: notes.trim() || undefined });
+ Alert.alert('Submitted!', `โฑ${Number(totalAmount).toLocaleString()} remittance submitted.`, [
+ { text: 'OK', onPress: () => router.back() },
+ ]);
} catch (e: any) {
- Alert.alert('Error', e?.response?.data?.message ?? 'Submission failed.');
+ Alert.alert('Error', e?.response?.data?.message ?? 'Submission failed. Please try again.');
} finally {
setLoading(false);
}
};
return (
-
-
- router.back()} className="mr-3">
- โ
-
- Submit Remittance
+
+
+
+ router.back()} style={{ marginBottom: 12 }} activeOpacity={0.7}>
+ โ Back
+
+ Submit Remittance
+ End-of-day collection
+
+
+
+ {/* Total amount summary card */}
+
+ Total to Remit
+ {loadingUnremitted ? (
+
+ ) : (
+ <>
+ 0 ? '#059669' : '#94A3B8' }}>
+ โฑ{Number(totalAmount).toLocaleString()}
+
+ {unremittedPayments.length > 0 && (
+
+ From {unremittedPayments.length} collection{unremittedPayments.length !== 1 ? 's' : ''}
+
+ )}
+ >
+ )}
+
+
+ {/* Breakdown of payments */}
+ {unremittedPayments.length > 0 && (
+
+ Breakdown
+ {unremittedPayments.map((p: any) => (
+
+
+ {p.client?.firstName} {p.client?.lastName}
+ {p.paymentMethod} ยท {p.client?.accountNumber}
+
+ โฑ{Number(p.amount).toLocaleString()}
+
+ ))}
+
+ )}
+
+ {/* Notes */}
+ Notes (optional)
+
+
+ 0 ? '#059669' : '#CBD5E1', borderRadius: 14, paddingVertical: 18, alignItems: 'center' }}
+ onPress={submit}
+ disabled={loading || loadingUnremitted || totalAmount <= 0}
+ activeOpacity={0.8}
+ >
+ {loading ? : Submit โฑ{Number(totalAmount).toLocaleString()}}
+
+
+
-
- Total Collection (โฑ)
-
- Notes (optional)
-
-
- {loading ? : Submit Remittance}
-
-
-
+
);
}
diff --git a/app/(app)/tasks/[id].tsx b/app/(app)/tasks/[id].tsx
new file mode 100644
index 0000000..ac9c6c9
--- /dev/null
+++ b/app/(app)/tasks/[id].tsx
@@ -0,0 +1,548 @@
+import { useState, useRef } from 'react';
+import {
+ View, Text, ScrollView, TextInput, TouchableOpacity,
+ ActivityIndicator, Alert, Modal, KeyboardAvoidingView, Platform,
+} from 'react-native';
+import { SafeAreaView } from 'react-native-safe-area-context';
+import { useLocalSearchParams, router } from 'expo-router';
+import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
+import * as Location from 'expo-location';
+import { api } from '../../../services/api';
+import { useAuthStore } from '../../../stores/authStore';
+
+// โโโ Constants โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+const STATUS_FLOW = ['OPEN', 'IN_PROGRESS', 'RESOLVED', 'CLOSED'] as const;
+type TaskStatus = typeof STATUS_FLOW[number];
+
+const STATUS_STYLE: Record = {
+ OPEN: { bg: '#ECFEFF', color: '#0891B2' },
+ IN_PROGRESS: { bg: '#FFFBEB', color: '#D97706' },
+ RESOLVED: { bg: '#F0FDF4', color: '#16A34A' },
+ CLOSED: { bg: '#F1F5F9', color: '#6B7280' },
+};
+const PRIORITY_COLOR: Record = { HIGH: '#DC2626', NORMAL: '#0891B2' };
+const PRIORITY_BG: Record = { HIGH: '#FEE2E2', NORMAL: '#ECFEFF' };
+const TYPE_COLOR: Record = { INSTALLATION: '#0891B2', SUPPORT: '#7C3AED', BILLING: '#D97706' };
+const TYPE_BG: Record = { INSTALLATION: '#ECFEFF', SUPPORT: '#F5F3FF', BILLING: '#FFFBEB' };
+
+function formatDate(iso: string) {
+ return new Date(iso).toLocaleDateString('en-PH', {
+ month: 'short', day: 'numeric', year: 'numeric',
+ hour: '2-digit', minute: '2-digit',
+ });
+}
+
+function InfoRow({ label, value, isLast }: { label: string; value?: string | null; isLast?: boolean }) {
+ if (!value) return null;
+ return (
+
+ {label}
+ {value}
+
+ );
+}
+
+// โโโ Main Screen โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+export default function TicketDetailScreen() {
+ const { id } = useLocalSearchParams<{ id: string }>();
+ const { user } = useAuthStore();
+ const qc = useQueryClient();
+ const scrollRef = useRef(null);
+
+ const [activeTab, setActiveTab] = useState<'details' | 'comments'>('details');
+ const [showStatusPicker, setShowStatusPicker] = useState(false);
+ const [instNotes, setInstNotes] = useState('');
+ const [instConfirming, setInstConfirming] = useState(false);
+ const [coords, setCoords] = useState<{ lat: number; lng: number } | null>(null);
+ const [locLoading, setLocLoading] = useState(false);
+ const [comment, setComment] = useState('');
+ const [sendingComment, setSendingComment] = useState(false);
+
+ const { data: ticket, isLoading, refetch } = useQuery({
+ queryKey: ['task', id],
+ queryFn: () => api.get(`/api/v1/tickets/${id}`).then(r => r.data),
+ });
+
+ const updateStatus = useMutation({
+ mutationFn: async (status: TaskStatus) => {
+ await api.patch(`/api/v1/tickets/${id}`, { status });
+ // Log status change as a system comment
+ const who = user?.firstName ?? 'Staff';
+ await api.post(`/api/v1/tickets/${id}/messages`, {
+ message: `Status changed to ${status.replace('_', ' ')} by ${who}`,
+ }).catch(() => {});
+ },
+ onSuccess: () => {
+ setShowStatusPicker(false);
+ refetch();
+ qc.invalidateQueries({ queryKey: ['tasks'] });
+ },
+ onError: () => Alert.alert('Error', 'Could not update status.'),
+ });
+
+ const captureLocation = async () => {
+ setLocLoading(true);
+ try {
+ const { status } = await Location.requestForegroundPermissionsAsync();
+ if (status !== 'granted') {
+ Alert.alert('Permission Denied', 'Location permission is required to record the installation site.');
+ return;
+ }
+ const loc = await Location.getCurrentPositionAsync({ accuracy: Location.Accuracy.High });
+ setCoords({ lat: loc.coords.latitude, lng: loc.coords.longitude });
+ } catch {
+ Alert.alert('Error', 'Could not get location. Make sure GPS is enabled.');
+ } finally {
+ setLocLoading(false);
+ }
+ };
+
+ const confirmInstallation = async () => {
+ if (!coords) {
+ Alert.alert('Location Required', 'Please capture the installation coordinates before confirming.', [
+ { text: 'Cancel', style: 'cancel' },
+ { text: 'Capture Now', onPress: captureLocation },
+ ]);
+ return;
+ }
+ setInstConfirming(true);
+ try {
+ // 1. Resolve the ticket
+ await api.patch(`/api/v1/tickets/${id}`, { status: 'RESOLVED' });
+
+ // 2. Update client location with recorded coordinates
+ if (ticket?.clientId) {
+ await api.patch(`/api/v1/clients/${ticket.clientId}`, {
+ lat: coords.lat,
+ lng: coords.lng,
+ }).catch(() => {});
+ }
+
+ // 3. Log activity comment
+ const coordStr = `${coords.lat.toFixed(6)}, ${coords.lng.toFixed(6)}`;
+ const note = instNotes.trim()
+ ? `Installation confirmed. Location recorded: ${coordStr}. Notes: ${instNotes.trim()}`
+ : `Installation confirmed. Location recorded: ${coordStr}`;
+ await api.post(`/api/v1/tickets/${id}/messages`, { message: note }).catch(() => {});
+
+ setInstNotes('');
+ setCoords(null);
+ Alert.alert('Installation Complete!', 'Ticket resolved and client location updated.');
+ refetch();
+ qc.invalidateQueries({ queryKey: ['tasks'] });
+ qc.invalidateQueries({ queryKey: ['client', ticket?.clientId] });
+ setActiveTab('comments');
+ } catch {
+ Alert.alert('Error', 'Could not confirm installation. Please try again.');
+ } finally {
+ setInstConfirming(false);
+ }
+ };
+
+ const sendComment = async () => {
+ if (!comment.trim()) return;
+ setSendingComment(true);
+ const text = comment.trim();
+ setComment(''); // clear immediately for responsiveness
+ try {
+ await api.post(`/api/v1/tickets/${id}/messages`, { message: text });
+ refetch();
+ setTimeout(() => scrollRef.current?.scrollToEnd({ animated: true }), 300);
+ } catch {
+ Alert.alert('Error', 'Could not send comment.');
+ setComment(text); // restore on failure
+ } finally {
+ setSendingComment(false);
+ }
+ };
+
+ if (isLoading) {
+ return (
+
+
+
+
+
+ );
+ }
+
+ const currentStatus: string = ticket?.status ?? 'OPEN';
+ const statusStyle = STATUS_STYLE[currentStatus] ?? STATUS_STYLE.OPEN;
+ const isInstallation = ticket?.type === 'INSTALLATION';
+ const isDone = currentStatus === 'RESOLVED' || currentStatus === 'CLOSED';
+ const typeColor = TYPE_COLOR[ticket?.type] ?? '#6B7280';
+ const typeBg = TYPE_BG[ticket?.type] ?? '#F1F5F9';
+ const messages: any[] = ticket?.messages ?? [];
+
+ return (
+
+
+
+
+ {/* โโ Header โโ */}
+
+ router.back()} style={{ marginBottom: 12 }} activeOpacity={0.7}>
+ โ Back
+
+
+ {ticket?.subject}
+
+
+ {/* Type */}
+
+ {ticket?.type}
+
+ {/* Status โ tappable to change */}
+ setShowStatusPicker(true)}
+ style={{ borderRadius: 20, paddingHorizontal: 14, paddingVertical: 7, backgroundColor: statusStyle.bg }}
+ activeOpacity={0.7}
+ >
+
+ {currentStatus.replace('_', ' ')} โพ
+
+
+ {/* Priority โ only show HIGH */}
+ {ticket?.priority === 'HIGH' && (
+
+ HIGH
+
+ )}
+
+ {ticket?.client && (
+
+ {ticket.client.firstName} {ticket.client.lastName} ยท {ticket.client.accountNumber}
+ {ticket.assignedTo
+ ? ` ยท Assigned: ${ticket.assignedTo.firstName} ${ticket.assignedTo.lastName}`
+ : ' ยท Unassigned'}
+
+ )}
+
+
+ {/* โโ Tabs โโ */}
+
+ {[
+ { key: 'details', label: 'Details' },
+ { key: 'comments', label: `Comments${messages.length > 0 ? ` (${messages.length})` : ''}` },
+ ].map(tab => (
+ setActiveTab(tab.key as 'details' | 'comments')}
+ style={{
+ flex: 1, paddingVertical: 16, alignItems: 'center',
+ borderBottomWidth: 2.5,
+ borderBottomColor: activeTab === tab.key ? '#0891B2' : 'transparent',
+ }}
+ activeOpacity={0.7}
+ >
+
+ {tab.label}
+
+
+ ))}
+
+
+ {/* โโ DETAILS TAB โโ */}
+ {activeTab === 'details' && (
+
+ {/* Info card */}
+
+
+
+
+
+
+
+
+
+ {/* Description */}
+ {ticket?.description ? (
+
+ Description
+ {ticket.description}
+
+ ) : null}
+
+ {/* โโ INSTALLATION SECTION โโ */}
+ {isInstallation && (
+ <>
+
+
+
+ Installation
+
+
+
+
+ {isDone ? (
+ /* โ Already confirmed โ */
+
+ โ
+ Installation Complete
+ {ticket?.resolvedAt && (
+
+ Confirmed on {formatDate(ticket.resolvedAt)}
+
+ )}
+ setActiveTab('comments')}
+ style={{ marginTop: 12 }}
+ activeOpacity={0.7}
+ >
+
+ View activity log โ
+
+
+
+ ) : (
+ /* โ Confirm installation form โ */
+
+
+ Confirm Installation
+
+
+ {/* โโ GPS Coordinates (required) โโ */}
+
+ ๐ Installation Location *
+
+ {coords ? (
+
+
+ โ Location Captured
+
+ {coords.lat.toFixed(6)}, {coords.lng.toFixed(6)}
+
+
+
+
+ {locLoading ? '...' : 'Retake'}
+
+
+
+ ) : (
+
+ {locLoading
+ ? <>Getting GPS...>
+ : <>๐Capture Current Location>
+ }
+
+ )}
+
+ {/* โโ Notes โโ */}
+
+ Notes / Remarks
+
+
+
+
+ Alert.alert(
+ 'Confirm Installation',
+ `Mark this installation as complete?\n\nLocation: ${coords ? `${coords.lat.toFixed(5)}, ${coords.lng.toFixed(5)}` : 'Not captured'}\n\nThis will update the client's location and resolve the ticket.`,
+ [
+ { text: 'Cancel', style: 'cancel' },
+ { text: 'Confirm', onPress: confirmInstallation },
+ ]
+ )
+ }
+ disabled={instConfirming || !coords}
+ activeOpacity={0.8}
+ >
+ {instConfirming
+ ?
+ :
+ {coords ? 'โ Mark Installation Complete' : 'Capture Location First'}
+
+ }
+
+
+ )}
+ >
+ )}
+
+ )}
+
+ {/* โโ COMMENTS TAB โโ */}
+ {activeTab === 'comments' && (
+
+
+ {messages.length === 0 ? (
+
+ No comments yet
+
+ Add a note or update below
+
+
+ ) : (
+ messages.map((m: any, i: number) => {
+ const isSystem = m.senderType === 'SYSTEM' || m.message?.startsWith('Status changed') || m.message?.startsWith('Installation confirmed');
+ const isMe = m.sender?.id === user?.id;
+
+ if (isSystem) {
+ // System messages โ centered pill
+ return (
+
+
+ {m.message}
+
+ {m.createdAt && (
+
+ {formatDate(m.createdAt)}
+
+ )}
+
+ );
+ }
+
+ // User messages โ chat bubbles
+ return (
+
+ {!isMe && (
+
+ {m.senderName ?? m.sender?.firstName ?? 'Staff'}
+
+ )}
+
+
+ {m.message}
+
+
+ {m.createdAt && (
+
+ {formatDate(m.createdAt)}
+
+ )}
+
+ );
+ })
+ )}
+
+
+ {/* โโ Comment input โ ALWAYS visible โโ */}
+
+
+
+ {sendingComment
+ ?
+ :
+ Send
+
+ }
+
+
+
+ )}
+
+
+ {/* โโ Status Picker Modal โโ */}
+ setShowStatusPicker(false)}>
+ setShowStatusPicker(false)}
+ >
+
+ Update Status
+
+ Current: {currentStatus.replace('_', ' ')}
+
+ {STATUS_FLOW.map(s => {
+ const style = STATUS_STYLE[s];
+ const isActive = s === currentStatus;
+ return (
+ !isActive && updateStatus.mutate(s)}
+ disabled={isActive || updateStatus.isPending}
+ style={{
+ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center',
+ padding: 18, borderRadius: 16, marginBottom: 10,
+ backgroundColor: style.bg, opacity: isActive ? 0.5 : 1,
+ }}
+ activeOpacity={0.7}
+ >
+ {s.replace('_', ' ')}
+ {isActive && โ Current}
+ {updateStatus.isPending && !isActive && }
+
+ );
+ })}
+ setShowStatusPicker(false)} style={{ paddingVertical: 14, alignItems: 'center' }}>
+ Cancel
+
+
+
+
+
+
+ );
+}
diff --git a/app/(app)/tasks/_layout.tsx b/app/(app)/tasks/_layout.tsx
new file mode 100644
index 0000000..8e14a2b
--- /dev/null
+++ b/app/(app)/tasks/_layout.tsx
@@ -0,0 +1,4 @@
+import { Stack } from 'expo-router';
+export default function TasksLayout() {
+ return ;
+}
diff --git a/app/(app)/tasks/index.tsx b/app/(app)/tasks/index.tsx
new file mode 100644
index 0000000..7c2f478
--- /dev/null
+++ b/app/(app)/tasks/index.tsx
@@ -0,0 +1,142 @@
+import { useState } from 'react';
+import { View, Text, FlatList, TextInput, TouchableOpacity, ActivityIndicator, RefreshControl, ScrollView } from 'react-native';
+import { SafeAreaView } from 'react-native-safe-area-context';
+import { useQuery } from '@tanstack/react-query';
+import { router } from 'expo-router';
+import { api } from '../../../services/api';
+
+const PRIORITY_COLOR: Record = { HIGH: '#DC2626', NORMAL: '#0891B2', LOW: '#6B7280' };
+const PRIORITY_BG: Record = { HIGH: '#FEE2E2', NORMAL: '#ECFEFF', LOW: '#F1F5F9' };
+const STATUS_COLOR: Record = { OPEN: '#0891B2', IN_PROGRESS: '#D97706', RESOLVED: '#16A34A', CLOSED: '#6B7280' };
+const STATUS_BG: Record = { OPEN: '#ECFEFF', IN_PROGRESS: '#FFFBEB', RESOLVED: '#F0FDF4', CLOSED: '#F1F5F9' };
+const TYPE_COLOR: Record = { INSTALLATION: '#0891B2', SUPPORT: '#7C3AED', BILLING: '#D97706' };
+const TYPE_BG: Record = { INSTALLATION: '#ECFEFF', SUPPORT: '#F5F3FF', BILLING: '#FFFBEB' };
+
+const STATUS_FILTERS = ['All', 'OPEN', 'IN_PROGRESS', 'RESOLVED', 'CLOSED'];
+
+export default function TasksScreen() {
+ const [search, setSearch] = useState('');
+ const [statusFilter, setStatusFilter] = useState('All');
+
+ const { data, isLoading, refetch, isRefetching } = useQuery({
+ queryKey: ['tasks'],
+ queryFn: () => api.get('/api/v1/tickets?limit=100').then(r => r.data?.data ?? r.data ?? []),
+ });
+
+ const tasks = (data ?? []).filter((t: any) => {
+ const matchSearch = `${t.subject} ${t.client?.firstName ?? ''} ${t.client?.lastName ?? ''}`.toLowerCase().includes(search.toLowerCase());
+ const matchStatus = statusFilter === 'All' || t.status === statusFilter;
+ return matchSearch && matchStatus;
+ });
+
+ return (
+
+
+
+
+ Tickets
+ {tasks.length} showing
+
+ router.push('/(app)/tasks/new')}
+ activeOpacity={0.7}
+ >
+ + Ticket
+
+
+
+
+
+
+ {search.length > 0 && (
+ setSearch('')} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}>
+
+ ร
+
+
+ )}
+
+
+
+ {STATUS_FILTERS.map(f => {
+ const isActive = statusFilter === f;
+ const color = f === 'All' ? '#0891B2' : STATUS_COLOR[f] ?? '#6B7280';
+ return (
+ setStatusFilter(f)}
+ style={{ borderRadius: 20, paddingHorizontal: 16, paddingVertical: 8, marginRight: 8, backgroundColor: isActive ? color : '#F1F5F9' }}
+ activeOpacity={0.7}
+ >
+
+ {f === 'All' ? 'All' : f.replace('_', ' ')}
+
+
+ );
+ })}
+
+
+
+ {isLoading ? (
+
+
+
+ ) : (
+ item.id}
+ refreshControl={}
+ contentContainerStyle={{ padding: 16, paddingBottom: 32 }}
+ renderItem={({ item }) => {
+ const typeColor = TYPE_COLOR[item.type] ?? '#6B7280';
+ const typeBg = TYPE_BG[item.type] ?? '#F1F5F9';
+ return (
+ router.push(`/(app)/tasks/${item.id}`)}
+ activeOpacity={0.7}
+ >
+
+
+
+ {item.type}
+
+ {item.priority === 'HIGH' && (
+
+ HIGH
+
+ )}
+
+
+ {item.status?.replace('_', ' ')}
+
+
+ {item.subject}
+
+ {item.client?.firstName} {item.client?.lastName}
+ {item.assignedTo ? ` ยท ${item.assignedTo.firstName} ${item.assignedTo.lastName}` : ' ยท Unassigned'}
+
+ {item._count?.messages > 0 && (
+ {item._count.messages} message{item._count.messages !== 1 ? 's' : ''}
+ )}
+
+ );
+ }}
+ ListEmptyComponent={
+
+ No tasks found
+
+ }
+ />
+ )}
+
+
+ );
+}
diff --git a/app/(app)/tasks/new.tsx b/app/(app)/tasks/new.tsx
new file mode 100644
index 0000000..ded4b30
--- /dev/null
+++ b/app/(app)/tasks/new.tsx
@@ -0,0 +1,202 @@
+import { useState } from 'react';
+import { View, Text, TextInput, TouchableOpacity, ScrollView, Alert, ActivityIndicator } from 'react-native';
+import { SafeAreaView } from 'react-native-safe-area-context';
+import { router } from 'expo-router';
+import { useQuery, useQueryClient } from '@tanstack/react-query';
+import { api } from '../../../services/api';
+
+const PRIORITIES = ['NORMAL', 'HIGH'];
+const PRIORITY_COLOR: Record = { HIGH: '#DC2626', NORMAL: '#0891B2' };
+const PRIORITY_BG: Record = { HIGH: '#FEE2E2', NORMAL: '#ECFEFF' };
+
+const TYPES = [
+ { value: 'SUPPORT', label: 'Support' },
+ { value: 'INSTALLATION', label: 'Installation' },
+ { value: 'BILLING', label: 'Billing' },
+];
+
+export default function NewTaskScreen() {
+ const qc = useQueryClient();
+ const [subject, setSubject] = useState('');
+ const [description, setDescription] = useState('');
+ const [priority, setPriority] = useState('NORMAL');
+ const [type, setType] = useState('SUPPORT');
+ const [search, setSearch] = useState('');
+ const [debouncedSearch, setDebouncedSearch] = useState('');
+ const [client, setClient] = useState(null);
+ const [loading, setLoading] = useState(false);
+
+ const { data: searchResults, isFetching: searching } = useQuery({
+ queryKey: ['client-search', debouncedSearch],
+ queryFn: () => api.get(`/api/v1/clients?search=${debouncedSearch}&limit=8`).then(r => r.data?.data ?? r.data ?? []),
+ enabled: debouncedSearch.trim().length >= 2,
+ });
+
+ const handleSearchChange = (v: string) => {
+ setSearch(v);
+ setTimeout(() => setDebouncedSearch(v), 400);
+ };
+
+ const submit = async () => {
+ if (!subject.trim()) return Alert.alert('Required', 'Please enter a subject.');
+ if (!client) return Alert.alert('Required', 'Please select a client.');
+ setLoading(true);
+ try {
+ await api.post('/api/v1/tickets', {
+ subject: subject.trim(),
+ description: description.trim() || undefined,
+ priority, type, clientId: client.id,
+ });
+ qc.invalidateQueries({ queryKey: ['tasks'] });
+ qc.invalidateQueries({ queryKey: ['dashboard'] });
+ Alert.alert('Task Created', subject, [{ text: 'OK', onPress: () => router.back() }]);
+ } catch (e: any) {
+ Alert.alert('Error', e?.response?.data?.message ?? 'Could not create task.');
+ } finally { setLoading(false); }
+ };
+
+ return (
+
+
+
+ router.back()} style={{ marginBottom: 12 }} activeOpacity={0.7}>
+ โ Back
+
+ New Ticket
+
+
+
+ {/* Client Search */}
+
+ Client *
+
+ {client ? (
+
+
+ {client.firstName} {client.lastName}
+ {client.accountNumber}
+
+ { setClient(null); setSearch(''); setDebouncedSearch(''); }} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}>
+ Change
+
+
+ ) : (
+
+
+
+ {search.length > 0 && (
+ { setSearch(''); setDebouncedSearch(''); }} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}>
+
+ ร
+
+
+ )}
+ {searching && }
+
+ {debouncedSearch.trim().length >= 2 && (
+
+ {(searchResults ?? []).length === 0 && !searching ? (
+ No clients found
+ ) : (
+ (searchResults ?? []).map((c: any, i: number, arr: any[]) => (
+ { setClient(c); setSearch(''); setDebouncedSearch(''); }}
+ activeOpacity={0.7}
+ >
+ {c.firstName} {c.lastName}
+ {c.accountNumber}
+
+ ))
+ )}
+
+ )}
+
+ )}
+
+ {/* Subject */}
+
+ Subject *
+
+
+
+ {/* Type */}
+ Type
+
+ {TYPES.map(t => (
+ setType(t.value)}
+ style={{ borderRadius: 20, paddingHorizontal: 16, paddingVertical: 10, marginRight: 8, marginBottom: 8, backgroundColor: type === t.value ? '#0891B2' : '#FFF', borderWidth: 1.5, borderColor: type === t.value ? '#0891B2' : '#E2E8F0' }}
+ activeOpacity={0.7}
+ >
+ {t.label}
+
+ ))}
+
+
+ {/* Priority */}
+ Priority
+
+ {PRIORITIES.map(p => {
+ const isSelected = priority === p;
+ const isHigh = p === 'HIGH';
+ const selectedBg = isHigh ? '#DC2626' : '#0891B2';
+ const unselectedBg = isHigh ? '#FEF2F2' : '#F0F9FF';
+ const selectedText = '#FFF';
+ const unselectedText = isHigh ? '#DC2626' : '#0891B2';
+ const desc = isHigh ? 'Urgent, escalate' : 'Standard queue';
+ return (
+ setPriority(p)}
+ style={{ flex: 1, borderRadius: 14, paddingVertical: 16, alignItems: 'center', marginHorizontal: 4, backgroundColor: isSelected ? selectedBg : unselectedBg, borderWidth: 1.5, borderColor: isSelected ? selectedBg : '#E2E8F0' }}
+ activeOpacity={0.7}
+ >
+ {p}
+ {desc}
+
+ );
+ })}
+
+
+ {/* Description */}
+
+ Description (optional)
+
+
+
+
+ {loading ? : Create Ticket}
+
+
+
+
+ );
+}
diff --git a/app/(app)/tickets/[id].tsx b/app/(app)/tickets/[id].tsx
deleted file mode 100644
index 984c065..0000000
--- a/app/(app)/tickets/[id].tsx
+++ /dev/null
@@ -1,216 +0,0 @@
-import { useState } from 'react';
-import {
- View, Text, ScrollView, TextInput, TouchableOpacity,
- ActivityIndicator, Alert, Modal,
-} from 'react-native';
-import { useLocalSearchParams, router } from 'expo-router';
-import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
-import { api } from '../../../services/api';
-
-const STATUS_FLOW = ['OPEN', 'IN_PROGRESS', 'RESOLVED', 'CLOSED'] as const;
-type TicketStatus = typeof STATUS_FLOW[number];
-
-const STATUS_STYLE: Record = {
- OPEN: { bg: '#EFF6FF', text: '#2563EB' },
- IN_PROGRESS: { bg: '#FFFBEB', text: '#D97706' },
- RESOLVED: { bg: '#F0FDF4', text: '#16A34A' },
- CLOSED: { bg: '#F3F4F6', text: '#6B7280' },
-};
-
-const PRIORITY_COLOR: Record = {
- HIGH: '#DC2626', MEDIUM: '#D97706', LOW: '#6B7280',
-};
-
-export default function TicketDetailScreen() {
- const { id } = useLocalSearchParams<{ id: string }>();
- const [reply, setReply] = useState('');
- const [showStatusPicker, setShowStatusPicker] = useState(false);
- const qc = useQueryClient();
-
- const { data, isLoading } = useQuery({
- queryKey: ['ticket', id],
- queryFn: () => api.get(`/api/v1/tickets/${id}`).then(r => r.data),
- });
-
- const addReply = useMutation({
- mutationFn: () => api.post(`/api/v1/tickets/${id}/messages`, { message: reply }),
- onSuccess: () => {
- setReply('');
- qc.invalidateQueries({ queryKey: ['ticket', id] });
- },
- onError: () => Alert.alert('Error', 'Could not send reply.'),
- });
-
- const updateStatus = useMutation({
- mutationFn: (status: TicketStatus) =>
- api.patch(`/api/v1/tickets/${id}`, { status }),
- onSuccess: () => {
- setShowStatusPicker(false);
- qc.invalidateQueries({ queryKey: ['ticket', id] });
- qc.invalidateQueries({ queryKey: ['tickets'] });
- },
- onError: () => Alert.alert('Error', 'Could not update status.'),
- });
-
- if (isLoading) {
- return (
-
-
-
- );
- }
-
- const currentStatus: string = data?.status ?? 'OPEN';
- const statusStyle = STATUS_STYLE[currentStatus] ?? { bg: '#F3F4F6', text: '#6B7280' };
- const priorityColor = PRIORITY_COLOR[data?.priority] ?? '#6B7280';
-
- return (
-
- {/* Header */}
-
-
- router.back()} className="mr-3">
- โ
-
-
- {data?.subject}
-
-
-
- {/* Status badge - tappable */}
- setShowStatusPicker(true)}
- className="rounded-full px-3 py-1 flex-row items-center"
- style={{ backgroundColor: statusStyle.bg }}
- >
-
- {currentStatus.replace('_', ' ')}
-
- โพ
-
- {/* Priority */}
-
-
- {data?.priority}
-
-
- {/* Client name */}
- {data?.client && (
-
- {data.client.firstName} {data.client.lastName}
-
- )}
-
-
-
- {/* Messages */}
-
- {data?.description && (
-
- Description
- {data.description}
-
- )}
-
- {(data?.messages ?? []).length === 0 && !data?.description && (
-
- No messages yet. Send the first reply.
-
- )}
-
- {(data?.messages ?? []).map((m: any) => {
- const isAgent = m.senderType === 'AGENT' || m.senderType === 'STAFF';
- return (
-
-
- {m.message}
-
-
- {m.senderName ?? m.sender?.name ?? 'System'}
-
-
- );
- })}
-
-
- {/* Reply bar โ hide if ticket is closed */}
- {currentStatus !== 'CLOSED' ? (
-
-
- reply.trim() && addReply.mutate()}
- disabled={addReply.isPending || !reply.trim()}
- style={{ opacity: !reply.trim() ? 0.5 : 1 }}
- >
- {addReply.isPending
- ?
- : Send
- }
-
-
- ) : (
-
- This ticket is closed
-
- )}
-
- {/* Status picker modal */}
- setShowStatusPicker(false)}
- >
- setShowStatusPicker(false)}
- >
-
- Update Status
-
- Current: {currentStatus.replace('_', ' ')}
-
- {STATUS_FLOW.map((s) => {
- const style = STATUS_STYLE[s] ?? { bg: '#F3F4F6', text: '#6B7280' };
- const isActive = s === currentStatus;
- return (
- !isActive && updateStatus.mutate(s)}
- disabled={isActive || updateStatus.isPending}
- className={`flex-row items-center justify-between p-4 rounded-xl mb-2 ${isActive ? 'opacity-40' : ''}`}
- style={{ backgroundColor: style.bg }}
- >
-
- {s.replace('_', ' ')}
-
- {isActive && โ Current}
- {updateStatus.isPending && !isActive && }
-
- );
- })}
- setShowStatusPicker(false)}
- >
- Cancel
-
-
-
-
-
- );
-}
diff --git a/app/(app)/tickets/index.tsx b/app/(app)/tickets/index.tsx
deleted file mode 100644
index ae9f600..0000000
--- a/app/(app)/tickets/index.tsx
+++ /dev/null
@@ -1,105 +0,0 @@
-import { useState } from 'react';
-import { View, Text, FlatList, TextInput, TouchableOpacity, ActivityIndicator, RefreshControl, ScrollView } from 'react-native';
-import { useQuery } from '@tanstack/react-query';
-import { router } from 'expo-router';
-import { api } from '../../../services/api';
-
-const PRIORITY_COLOR: Record = { HIGH: '#DC2626', MEDIUM: '#D97706', LOW: '#16A34A' };
-const STATUS_FILTERS = ['ALL', 'OPEN', 'IN_PROGRESS', 'RESOLVED', 'CLOSED'];
-
-export default function TicketsScreen() {
- const [search, setSearch] = useState('');
- const [statusFilter, setStatusFilter] = useState('ALL');
-
- const { data, isLoading, refetch, isRefetching } = useQuery({
- queryKey: ['tickets'],
- queryFn: () => api.get('/api/v1/tickets?limit=100').then(r => r.data?.data ?? r.data ?? []),
- });
-
- const tickets = (data ?? []).filter((t: any) => {
- const matchSearch = `${t.subject} ${t.client?.firstName} ${t.client?.lastName}`.toLowerCase().includes(search.toLowerCase());
- const matchStatus = statusFilter === 'ALL' || t.status === statusFilter;
- return matchSearch && matchStatus;
- });
-
- return (
-
- {/* Header */}
-
- Tickets
- router.push('/(app)/tickets/new')}
- >
- + New
-
-
-
- {/* Search */}
-
-
- {/* Status filter chips */}
-
- {STATUS_FILTERS.map(s => (
- setStatusFilter(s)}
- className={`rounded-full px-3 py-1.5 mr-2 ${statusFilter === s ? 'bg-primary' : 'bg-gray-100'}`}
- >
-
- {s.replace('_', ' ')}
-
-
- ))}
-
-
-
- {isLoading ? (
-
- ) : (
- item.id}
- refreshControl={}
- contentContainerStyle={{ paddingHorizontal: 16, paddingVertical: 12, paddingBottom: 32 }}
- renderItem={({ item }) => (
- router.push(`/(app)/tickets/${item.id}`)}
- >
-
- {item.subject}
-
- {item.priority}
-
-
-
-
- {item.client?.firstName} {item.client?.lastName}
-
- {item.status?.replace('_', ' ')}
-
-
- )}
- ListEmptyComponent={
-
- ๐ซ
- No tickets found
- router.push('/(app)/tickets/new')}
- >
- Create First Ticket
-
-
- }
- />
- )}
-
- );
-}
diff --git a/app/(app)/tickets/new.tsx b/app/(app)/tickets/new.tsx
deleted file mode 100644
index ff5c5b8..0000000
--- a/app/(app)/tickets/new.tsx
+++ /dev/null
@@ -1,182 +0,0 @@
-import { useState } from 'react';
-import { View, Text, TextInput, TouchableOpacity, ScrollView, Alert, ActivityIndicator } from 'react-native';
-import { router } from 'expo-router';
-import { useQuery, useQueryClient } from '@tanstack/react-query';
-import { api } from '../../../services/api';
-
-const PRIORITIES = ['LOW', 'MEDIUM', 'HIGH'];
-const PRIORITY_COLOR: Record = { HIGH: '#DC2626', MEDIUM: '#D97706', LOW: '#16A34A' };
-
-const CATEGORIES: { value: string; label: string }[] = [
- { value: 'NO_SIGNAL', label: 'No Signal' },
- { value: 'SLOW_CONNECTION', label: 'Slow Connection' },
- { value: 'BILLING', label: 'Billing' },
- { value: 'INSTALLATION', label: 'Installation' },
- { value: 'RELOCATION', label: 'Relocation' },
- { value: 'OTHER', label: 'Other' },
-];
-
-export default function NewTicketScreen() {
- const qc = useQueryClient();
- const [subject, setSubject] = useState('');
- const [description, setDescription] = useState('');
- const [priority, setPriority] = useState('MEDIUM');
- const [category, setCategory] = useState('NO_SIGNAL');
- const [search, setSearch] = useState('');
- const [debouncedSearch, setDebouncedSearch] = useState('');
- const [client, setClient] = useState(null);
- const [loading, setLoading] = useState(false);
-
- const { data: searchResults, isFetching: searching } = useQuery({
- queryKey: ['client-search', debouncedSearch],
- queryFn: () => api.get(`/api/v1/clients?search=${debouncedSearch}&limit=8`).then(r => r.data?.data ?? r.data ?? []),
- enabled: debouncedSearch.trim().length >= 2,
- });
-
- const handleSearchChange = (v: string) => {
- setSearch(v);
- setTimeout(() => setDebouncedSearch(v), 400);
- };
-
- const submit = async () => {
- if (!subject.trim()) return Alert.alert('Required', 'Enter a subject.');
- if (!client) return Alert.alert('Required', 'Select a client.');
- setLoading(true);
- try {
- await api.post('/api/v1/tickets', {
- subject: subject.trim(),
- description: description.trim() || undefined,
- priority,
- category,
- clientId: client.id,
- });
- qc.invalidateQueries({ queryKey: ['tickets'] });
- qc.invalidateQueries({ queryKey: ['dashboard'] });
- Alert.alert('โ
Ticket Created', subject, [{ text: 'OK', onPress: () => router.back() }]);
- } catch (e: any) {
- Alert.alert('Error', e?.response?.data?.message ?? 'Could not create ticket.');
- } finally {
- setLoading(false);
- }
- };
-
- return (
-
-
- router.back()} className="mr-3 p-1">
- โ
-
- New Ticket
-
-
-
- {/* Client */}
- Client *
- {client ? (
-
-
- {client.firstName} {client.lastName}
- {client.accountNumber}
-
- { setClient(null); setSearch(''); setDebouncedSearch(''); }} className="p-2">
- Change
-
-
- ) : (
-
-
-
- {searching && }
-
- {debouncedSearch.trim().length >= 2 && (
-
- {(searchResults ?? []).length === 0 && !searching && (
- No clients found
- )}
- {(searchResults ?? []).map((c: any) => (
- { setClient(c); setSearch(''); setDebouncedSearch(''); }}
- >
- {c.firstName} {c.lastName}
- {c.accountNumber}
-
- ))}
-
- )}
-
- )}
-
- {/* Subject */}
- Subject *
-
-
- {/* Category */}
- Category
-
- {CATEGORIES.map(c => (
- setCategory(c.value)}
- className={`rounded-xl px-3 py-2 mr-2 mb-2 border ${category === c.value ? 'bg-primary border-primary' : 'bg-white border-gray-200'}`}
- >
-
- {c.label}
-
-
- ))}
-
-
- {/* Priority */}
- Priority
-
- {PRIORITIES.map(p => (
- setPriority(p)}
- className={`flex-1 rounded-xl py-2.5 items-center mx-1 border ${priority === p ? 'border-transparent' : 'bg-white border-gray-200'}`}
- style={priority === p ? { backgroundColor: PRIORITY_COLOR[p] } : {}}
- >
- {p}
-
- ))}
-
-
- {/* Description */}
- Description (optional)
-
-
-
- {loading ? : Create Ticket}
-
-
-
-
-
- );
-}
diff --git a/app/(app)/users/[id].tsx b/app/(app)/users/[id].tsx
new file mode 100644
index 0000000..524cad5
--- /dev/null
+++ b/app/(app)/users/[id].tsx
@@ -0,0 +1,183 @@
+import { useState } from 'react';
+import { View, Text, TouchableOpacity, ScrollView, Alert, ActivityIndicator, Switch } from 'react-native';
+import { SafeAreaView } from 'react-native-safe-area-context';
+import { useLocalSearchParams, router } from 'expo-router';
+import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
+import { api } from '../../../services/api';
+
+const ROLE_COLOR: Record = { ADMIN: '#7C3AED', STAFF: '#0891B2', TECHNICIAN: '#059669', COLLECTOR: '#D97706' };
+const ROLE_BG: Record = { ADMIN: '#F5F3FF', STAFF: '#ECFEFF', TECHNICIAN: '#F0FDF4', COLLECTOR: '#FFFBEB' };
+
+const ROLES = [
+ { value: 'TECHNICIAN', label: 'Technician', desc: 'Field work & installations' },
+ { value: 'COLLECTOR', label: 'Collector', desc: 'Payments & remittances' },
+ { value: 'STAFF', label: 'Staff', desc: 'General access' },
+ { value: 'ADMIN', label: 'Admin', desc: 'Full access + user mgmt' },
+];
+
+function InfoRow({ label, value }: { label: string; value?: string | null }) {
+ return (
+
+ {label}
+ {value ?? 'โ'}
+
+ );
+}
+
+export default function UserDetailScreen() {
+ const { id } = useLocalSearchParams<{ id: string }>();
+ const qc = useQueryClient();
+ const [editingRole, setEditingRole] = useState(false);
+ const [newRole, setNewRole] = useState('');
+
+ const { data: user, isLoading } = useQuery({
+ queryKey: ['user', id],
+ queryFn: () => api.get(`/api/v1/users/${id}`).then(r => r.data),
+ });
+
+ const toggleActive = useMutation({
+ mutationFn: (isActive: boolean) => api.patch(`/api/v1/users/${id}`, { isActive }),
+ onSuccess: () => qc.invalidateQueries({ queryKey: ['user', id] }),
+ onError: () => Alert.alert('Error', 'Could not update user status.'),
+ });
+
+ const changeRole = useMutation({
+ mutationFn: (role: string) => api.patch(`/api/v1/users/${id}`, { role }),
+ onSuccess: () => {
+ setEditingRole(false);
+ qc.invalidateQueries({ queryKey: ['user', id] });
+ qc.invalidateQueries({ queryKey: ['users'] });
+ },
+ onError: () => Alert.alert('Error', 'Could not update role.'),
+ });
+
+ if (isLoading) {
+ return (
+
+
+
+
+
+ );
+ }
+
+ const role = user?.roleAssignments?.[0]?.role ?? 'STAFF';
+ const roleColor = ROLE_COLOR[role] ?? '#6B7280';
+ const roleBg = ROLE_BG[role] ?? '#F1F5F9';
+ const initials = `${user?.firstName?.[0] ?? ''}${user?.lastName?.[0] ?? ''}`.toUpperCase();
+ const isActive = user?.isActive ?? true;
+ const lastLogin = user?.lastLoginAt ? new Date(user.lastLoginAt).toLocaleDateString('en-PH', { month: 'long', day: 'numeric', year: 'numeric', hour: '2-digit', minute: '2-digit' }) : 'Never';
+
+ return (
+
+
+ {/* Header */}
+
+ router.back()} style={{ alignSelf: 'flex-start', marginBottom: 16 }} activeOpacity={0.7}>
+ โ Back
+
+
+ {initials}
+
+ {user?.firstName} {user?.lastName}
+
+ {role}
+
+ {!isActive && (
+
+ Inactive Account
+
+ )}
+
+
+
+ {/* Info Card */}
+
+
+
+
+
+ Account Status
+
+
+
+ {isActive ? 'Active' : 'Inactive'}
+
+
+ {isActive ? 'User can log in' : 'Login is blocked'}
+
+
+ Alert.alert(
+ val ? 'Activate User' : 'Deactivate User',
+ val ? `Allow ${user?.firstName} to log in?` : `Block ${user?.firstName} from logging in?`,
+ [
+ { text: 'Cancel', style: 'cancel' },
+ { text: val ? 'Activate' : 'Deactivate', onPress: () => toggleActive.mutate(val), style: val ? 'default' : 'destructive' },
+ ]
+ )}
+ trackColor={{ false: '#E2E8F0', true: '#0891B2' }}
+ thumbColor="#FFF"
+ />
+
+
+
+
+ {/* Role Change */}
+
+
+ Role
+ { setEditingRole(!editingRole); setNewRole(role); }} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}>
+ {editingRole ? 'Cancel' : 'Change'}
+
+
+ {editingRole && (
+
+ {ROLES.map(r => {
+ const isSelected = (newRole || role) === r.value;
+ const rc = ROLE_COLOR[r.value] ?? '#6B7280';
+ const rb = ROLE_BG[r.value] ?? '#F1F5F9';
+ return (
+ setNewRole(r.value)}
+ style={{ flexDirection: 'row', alignItems: 'center', borderRadius: 14, padding: 14, marginBottom: 8, borderWidth: 2, borderColor: isSelected ? rc : '#E2E8F0', backgroundColor: isSelected ? rb : '#FFF' }}
+ activeOpacity={0.7}
+ >
+
+ {r.label}
+ {r.desc}
+
+
+ {isSelected && }
+
+
+ );
+ })}
+ newRole && newRole !== role && Alert.alert(
+ 'Change Role',
+ `Change ${user?.firstName}'s role to ${newRole}?`,
+ [
+ { text: 'Cancel', style: 'cancel' },
+ { text: 'Change', onPress: () => changeRole.mutate(newRole) },
+ ]
+ )}
+ disabled={changeRole.isPending || !newRole || newRole === role}
+ activeOpacity={0.8}
+ >
+ {changeRole.isPending
+ ?
+ : Apply Role Change
+ }
+
+
+ )}
+
+
+
+
+ );
+}
diff --git a/app/(app)/users/_layout.tsx b/app/(app)/users/_layout.tsx
new file mode 100644
index 0000000..eb2f331
--- /dev/null
+++ b/app/(app)/users/_layout.tsx
@@ -0,0 +1,4 @@
+import { Stack } from 'expo-router';
+export default function UsersLayout() {
+ return ;
+}
diff --git a/app/(app)/users/index.tsx b/app/(app)/users/index.tsx
new file mode 100644
index 0000000..db3530a
--- /dev/null
+++ b/app/(app)/users/index.tsx
@@ -0,0 +1,141 @@
+import { useState } from 'react';
+import { View, Text, FlatList, TextInput, TouchableOpacity, ActivityIndicator, RefreshControl, Alert } from 'react-native';
+import { SafeAreaView } from 'react-native-safe-area-context';
+import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
+import { router } from 'expo-router';
+import { api } from '../../../services/api';
+
+const ROLE_COLOR: Record = {
+ ADMIN: '#7C3AED',
+ STAFF: '#0891B2',
+ TECHNICIAN: '#059669',
+ COLLECTOR: '#D97706',
+};
+const ROLE_BG: Record = {
+ ADMIN: '#F5F3FF',
+ STAFF: '#ECFEFF',
+ TECHNICIAN: '#F0FDF4',
+ COLLECTOR: '#FFFBEB',
+};
+
+export default function UsersScreen() {
+ const [search, setSearch] = useState('');
+ const qc = useQueryClient();
+
+ const { data, isLoading, refetch, isRefetching } = useQuery({
+ queryKey: ['users'],
+ queryFn: () => api.get('/api/v1/users').then(r => Array.isArray(r.data) ? r.data : r.data?.data ?? []),
+ });
+
+ const toggleActive = useMutation({
+ mutationFn: ({ id, isActive }: { id: string; isActive: boolean }) =>
+ api.patch(`/api/v1/users/${id}`, { isActive }),
+ onSuccess: () => qc.invalidateQueries({ queryKey: ['users'] }),
+ onError: () => Alert.alert('Error', 'Could not update user.'),
+ });
+
+ const users = (data ?? []).filter((u: any) =>
+ `${u.firstName} ${u.lastName} ${u.email}`.toLowerCase().includes(search.toLowerCase())
+ );
+
+ return (
+
+
+ {/* Header */}
+
+
+ router.back()} activeOpacity={0.7} style={{ marginBottom: 8 }}>
+ โ Back
+
+ Users
+ {users.length} members
+
+ router.push('/(app)/users/new')}
+ activeOpacity={0.7}
+ >
+ + Add User
+
+
+
+ {/* Search */}
+
+
+
+ {search.length > 0 && (
+ setSearch('')} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}>
+
+ ร
+
+
+ )}
+
+
+
+ {isLoading ? (
+
+
+
+ ) : (
+ item.id}
+ refreshControl={}
+ contentContainerStyle={{ padding: 16, paddingBottom: 32 }}
+ renderItem={({ item }) => {
+ const role = item.roleAssignments?.[0]?.role ?? 'STAFF';
+ const roleColor = ROLE_COLOR[role] ?? '#6B7280';
+ const roleBg = ROLE_BG[role] ?? '#F1F5F9';
+ const initials = `${item.firstName?.[0] ?? ''}${item.lastName?.[0] ?? ''}`.toUpperCase();
+
+ return (
+ router.push(`/(app)/users/${item.id}`)}
+ activeOpacity={0.7}
+ >
+ {/* Avatar */}
+
+ {initials}
+
+
+ {/* Info */}
+
+
+
+ {item.firstName} {item.lastName}
+
+ {!item.isActive && (
+
+ Inactive
+
+ )}
+
+ {item.email}
+
+
+ {/* Role badge */}
+
+ {role}
+
+
+ );
+ }}
+ ListEmptyComponent={
+
+ No users found
+
+ }
+ />
+ )}
+
+
+ );
+}
diff --git a/app/(app)/users/new.tsx b/app/(app)/users/new.tsx
new file mode 100644
index 0000000..3f0bdc2
--- /dev/null
+++ b/app/(app)/users/new.tsx
@@ -0,0 +1,175 @@
+import { useState } from 'react';
+import { View, Text, TextInput, TouchableOpacity, ScrollView, Alert, ActivityIndicator } from 'react-native';
+import { SafeAreaView } from 'react-native-safe-area-context';
+import { router } from 'expo-router';
+import { useQueryClient } from '@tanstack/react-query';
+import { api } from '../../../services/api';
+
+const ROLES = [
+ { value: 'TECHNICIAN', label: 'Technician', desc: 'Field work & installations', color: '#059669', bg: '#F0FDF4' },
+ { value: 'COLLECTOR', label: 'Collector', desc: 'Payments & remittances', color: '#D97706', bg: '#FFFBEB' },
+ { value: 'STAFF', label: 'Staff', desc: 'General access', color: '#0891B2', bg: '#ECFEFF' },
+ { value: 'ADMIN', label: 'Admin', desc: 'Full access + user mgmt', color: '#7C3AED', bg: '#F5F3FF' },
+];
+
+export default function NewUserScreen() {
+ const qc = useQueryClient();
+ const [firstName, setFirstName] = useState('');
+ const [lastName, setLastName] = useState('');
+ const [email, setEmail] = useState('');
+ const [phone, setPhone] = useState('');
+ const [password, setPassword] = useState('');
+ const [showPass, setShowPass] = useState(false);
+ const [role, setRole] = useState('TECHNICIAN');
+ const [loading, setLoading] = useState(false);
+
+ const isValid = firstName.trim() && lastName.trim() && email.trim() && password.length >= 8;
+
+ const submit = async () => {
+ if (!isValid) return Alert.alert('Required', 'Please fill all required fields. Password must be at least 8 characters.');
+ setLoading(true);
+ try {
+ await api.post('/api/v1/users', {
+ firstName: firstName.trim(),
+ lastName: lastName.trim(),
+ email: email.trim().toLowerCase(),
+ phone: phone.trim() || undefined,
+ password,
+ role,
+ });
+ qc.invalidateQueries({ queryKey: ['users'] });
+ Alert.alert('User Created!', `${firstName} ${lastName} can now log in with ${email.trim().toLowerCase()}`, [
+ { text: 'Add Another', onPress: () => { setFirstName(''); setLastName(''); setEmail(''); setPhone(''); setPassword(''); } },
+ { text: 'Done', onPress: () => router.back() },
+ ]);
+ } catch (e: any) {
+ const msg = e?.response?.data?.message;
+ Alert.alert('Error', Array.isArray(msg) ? msg.join('\n') : msg ?? 'Could not create user.');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+
+
+ {/* Header */}
+
+ router.back()} style={{ marginBottom: 12 }} activeOpacity={0.7}>
+ โ Back
+
+ Add User
+ Create a new team member
+
+
+
+ {/* Name row */}
+
+
+ First Name *
+
+
+
+ Last Name *
+
+
+
+
+ {/* Email */}
+ Email *
+
+
+ {/* Phone */}
+
+ Phone (optional)
+
+
+
+ {/* Password */}
+ Password *
+
+
+ setShowPass(!showPass)} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}>
+ {showPass ? 'Hide' : 'Show'}
+
+
+ They can change this after first login.
+
+ {/* Role */}
+ Role *
+ {ROLES.map(r => (
+ setRole(r.value)}
+ style={{ flexDirection: 'row', alignItems: 'center', backgroundColor: role === r.value ? r.bg : '#FFF', borderRadius: 16, padding: 18, marginBottom: 10, borderWidth: 2, borderColor: role === r.value ? r.color : '#E2E8F0' }}
+ activeOpacity={0.7}
+ >
+
+ {r.value.slice(0,4)}
+
+
+ {r.label}
+ {r.desc}
+
+
+ {role === r.value && }
+
+
+ ))}
+
+
+
+ {/* Submit */}
+
+ {loading
+ ?
+ : Create User
+ }
+
+
+
+
+ );
+}
diff --git a/app/(auth)/company-code.tsx b/app/(auth)/company-code.tsx
index 34fee8e..3918f56 100644
--- a/app/(auth)/company-code.tsx
+++ b/app/(auth)/company-code.tsx
@@ -1,5 +1,6 @@
import { useState } from 'react';
import { View, Text, TextInput, TouchableOpacity, ActivityIndicator, Alert, KeyboardAvoidingView, Platform } from 'react-native';
+import { SafeAreaView } from 'react-native-safe-area-context';
import { router } from 'expo-router';
import { api } from '../../services/api';
@@ -18,51 +19,51 @@ export default function CompanyCodeScreen() {
Alert.alert('Not Found', 'Company code not found. Please check and try again.');
}
} catch {
- Alert.alert('Error', 'Could not verify company code. Please try again.');
- } finally {
- setLoading(false);
- }
+ Alert.alert('Error', 'Could not verify. Please try again.');
+ } finally { setLoading(false); }
};
return (
-
-
-
-
- F
+
+
+
+ {/* Logo */}
+
+
+ F
+
+ FiberOps
+ Field Operations Platform
- FiberOps
- Field Operations
+
+ Enter Company Code
+ Ask your admin for your company's unique code.
+
+
+
+
+ {loading
+ ?
+ : Continue โ
+ }
+
-
- Enter Company Code
- Ask your admin for your company's unique code.
-
-
-
-
- {loading ? (
-
- ) : (
- Continue
- )}
-
-
-
+
+
);
}
diff --git a/app/(auth)/login.tsx b/app/(auth)/login.tsx
index ab3f93a..0cb4e9b 100644
--- a/app/(auth)/login.tsx
+++ b/app/(auth)/login.tsx
@@ -1,18 +1,20 @@
import { useState } from 'react';
import { View, Text, TextInput, TouchableOpacity, ActivityIndicator, Alert, KeyboardAvoidingView, Platform } from 'react-native';
+import { SafeAreaView } from 'react-native-safe-area-context';
import { useLocalSearchParams, router } from 'expo-router';
import { useAuthStore } from '../../stores/authStore';
export default function LoginScreen() {
const { tenantSlug } = useLocalSearchParams<{ tenantSlug: string }>();
- const [username, setUsername] = useState('');
+ const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
+ const [showPassword, setShowPassword] = useState(false);
const { login, isLoading } = useAuthStore();
const handleLogin = async () => {
- if (!username.trim() || !password) return Alert.alert('Required', 'Please enter username and password.');
+ if (!email.trim() || !password) return Alert.alert('Required', 'Please enter email and password.');
try {
- await login(tenantSlug, username.trim(), password);
+ await login(tenantSlug, email.trim(), password);
router.replace('/(app)/dashboard');
} catch (e: any) {
const msg = e?.response?.data?.message ?? 'Login failed. Check your credentials.';
@@ -21,52 +23,61 @@ export default function LoginScreen() {
};
return (
-
-
- router.back()}>
- โ Back
-
+
+
+
+ router.back()} style={{ marginBottom: 32 }} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}>
+ โ Back
+
- Welcome back
-
- Signing in to {tenantSlug}
-
+ Welcome back
+
+ Signing in to {tenantSlug}
+
- Username
-
+ {/* Email */}
+ Email
+
- Password
-
+ {/* Password */}
+ Password
+
+
+ setShowPassword(!showPassword)} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}>
+ {showPassword ? 'Hide' : 'Show'}
+
+
-
- {isLoading ? (
-
- ) : (
- Sign In
- )}
-
-
-
+
+ {isLoading
+ ?
+ : Sign In
+ }
+
+
+
+
);
}
diff --git a/assets/adaptive-icon.png b/assets/adaptive-icon.png
new file mode 100644
index 0000000..7165a53
Binary files /dev/null and b/assets/adaptive-icon.png differ
diff --git a/components/Icon.tsx b/components/Icon.tsx
new file mode 100644
index 0000000..22ab9fe
--- /dev/null
+++ b/components/Icon.tsx
@@ -0,0 +1,44 @@
+import { Svg, Path, Circle, Rect } from 'react-native-svg';
+
+type IconName = 'home' | 'users' | 'collect' | 'ticket' | 'user' | 'arrow-left' | 'phone' | 'refresh' | 'send' | 'plus' | 'check' | 'location' | 'camera';
+
+interface IconProps {
+ name: IconName;
+ size?: number;
+ color?: string;
+}
+
+export function Icon({ name, size = 24, color = '#111827' }: IconProps) {
+ const props = { width: size, height: size, viewBox: '0 0 24 24', fill: 'none' };
+
+ switch (name) {
+ case 'home':
+ return ;
+ case 'users':
+ return ;
+ case 'collect':
+ return ;
+ case 'ticket':
+ return ;
+ case 'user':
+ return ;
+ case 'arrow-left':
+ return ;
+ case 'phone':
+ return ;
+ case 'refresh':
+ return ;
+ case 'send':
+ return ;
+ case 'plus':
+ return ;
+ case 'check':
+ return ;
+ case 'location':
+ return ;
+ case 'camera':
+ return ;
+ default:
+ return null;
+ }
+}
diff --git a/constants/index.ts b/constants/index.ts
index ba256dd..a22e032 100644
--- a/constants/index.ts
+++ b/constants/index.ts
@@ -1,8 +1,8 @@
export const API_URL = process.env.EXPO_PUBLIC_API_URL ?? 'http://192.168.1.167:3001';
export const COLORS = {
- primary: '#2563EB',
- primaryDark: '#1D4ED8',
+ primary: '#0891B2',
+ primaryDark: '#0E7490',
danger: '#DC2626',
success: '#16A34A',
warning: '#D97706',
diff --git a/metro.config.js b/metro.config.js
index e621938..f3321ba 100644
--- a/metro.config.js
+++ b/metro.config.js
@@ -1,10 +1,6 @@
const { getDefaultConfig } = require('expo/metro-config');
const { withNativeWind } = require('nativewind/metro');
-const path = require('path');
const config = getDefaultConfig(__dirname);
-// Allow Metro to resolve assets (png/jpg) from inside node_modules
-config.resolver.assetExts.push('png', 'jpg', 'jpeg', 'gif', 'webp');
-
module.exports = withNativeWind(config, { input: './global.css' });
diff --git a/package-lock.json b/package-lock.json
index 4519a69..b4198af 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,37 +8,52 @@
"name": "fiberops-mobile",
"version": "1.0.0",
"dependencies": {
- "@react-native-async-storage/async-storage": "^2.2.0",
+ "@react-native-async-storage/async-storage": "2.2.0",
"@tanstack/react-query": "^5.95.0",
"axios": "^1.13.6",
- "expo": "~55.0.8",
- "expo-camera": "^55.0.10",
- "expo-constants": "^55.0.9",
- "expo-image-picker": "^55.0.13",
- "expo-linking": "^55.0.8",
- "expo-location": "^55.1.4",
- "expo-notifications": "^55.0.13",
- "expo-router": "^55.0.7",
- "expo-secure-store": "^55.0.9",
- "expo-status-bar": "~55.0.4",
- "expo-updates": "~55.0.15",
- "hermes-parser": "0.32.0",
+ "expo": "~54.0.33",
+ "expo-camera": "~17.0.10",
+ "expo-constants": "~18.0.13",
+ "expo-dev-client": "^55.0.18",
+ "expo-image-picker": "~17.0.10",
+ "expo-linking": "~8.0.11",
+ "expo-location": "~19.0.8",
+ "expo-notifications": "~0.32.16",
+ "expo-router": "~6.0.23",
+ "expo-secure-store": "~15.0.8",
+ "expo-status-bar": "~3.0.9",
+ "expo-updates": "~29.0.16",
"nativewind": "^4.1.23",
- "react": "19.2.0",
- "react-native": "0.83.2",
- "react-native-reanimated": "4.2.1",
- "react-native-safe-area-context": "^5.6.2",
- "react-native-screens": "^4.23.0",
- "react-native-worklets": "0.7.2",
+ "react": "19.1.0",
+ "react-native": "0.81.5",
+ "react-native-reanimated": "~4.1.1",
+ "react-native-safe-area-context": "~5.6.0",
+ "react-native-screens": "~4.16.0",
+ "react-native-svg": "^15.15.4",
+ "react-native-worklets": "^0.8.1",
"zustand": "^5.0.12"
},
"devDependencies": {
"@expo/ngrok": "^4.1.3",
- "@types/react": "~19.2.2",
+ "@types/react": "~19.1.10",
"tailwindcss": "^3.4.19",
"typescript": "~5.9.2"
}
},
+ "node_modules/@0no-co/graphql.web": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@0no-co/graphql.web/-/graphql.web-1.2.0.tgz",
+ "integrity": "sha512-/1iHy9TTr63gE1YcR5idjx8UREz1s0kFhydf3bBLCXyqjhkIc6igAzTOx3zPifCwFR87tsh/4Pa9cNts6d2otw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
+ },
+ "peerDependenciesMeta": {
+ "graphql": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@alloc/quick-lru": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
@@ -413,6 +428,92 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@babel/highlight": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz",
+ "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "license": "MIT"
+ },
+ "node_modules/@babel/highlight/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/@babel/parser": {
"version": "7.29.2",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz",
@@ -1488,11 +1589,128 @@
"node": ">=6.9.0"
}
},
- "node_modules/@expo-google-fonts/material-symbols": {
- "version": "0.4.27",
- "resolved": "https://registry.npmjs.org/@expo-google-fonts/material-symbols/-/material-symbols-0.4.27.tgz",
- "integrity": "sha512-cnb3DZnWUWpezGFkJ8y4MT5f/lw6FcgDzeJzic+T+vpQHLHG1cg3SC3i1w1i8Bk4xKR4HPY3t9iIRNvtr5ml8A==",
- "license": "MIT AND Apache-2.0"
+ "node_modules/@expo/cli": {
+ "version": "54.0.23",
+ "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-54.0.23.tgz",
+ "integrity": "sha512-km0h72SFfQCmVycH/JtPFTVy69w6Lx1cHNDmfLfQqgKFYeeHTjx7LVDP4POHCtNxFP2UeRazrygJhlh4zz498g==",
+ "license": "MIT",
+ "dependencies": {
+ "@0no-co/graphql.web": "^1.0.8",
+ "@expo/code-signing-certificates": "^0.0.6",
+ "@expo/config": "~12.0.13",
+ "@expo/config-plugins": "~54.0.4",
+ "@expo/devcert": "^1.2.1",
+ "@expo/env": "~2.0.8",
+ "@expo/image-utils": "^0.8.8",
+ "@expo/json-file": "^10.0.8",
+ "@expo/metro": "~54.2.0",
+ "@expo/metro-config": "~54.0.14",
+ "@expo/osascript": "^2.3.8",
+ "@expo/package-manager": "^1.9.10",
+ "@expo/plist": "^0.4.8",
+ "@expo/prebuild-config": "^54.0.8",
+ "@expo/schema-utils": "^0.1.8",
+ "@expo/spawn-async": "^1.7.2",
+ "@expo/ws-tunnel": "^1.0.1",
+ "@expo/xcpretty": "^4.3.0",
+ "@react-native/dev-middleware": "0.81.5",
+ "@urql/core": "^5.0.6",
+ "@urql/exchange-retry": "^1.3.0",
+ "accepts": "^1.3.8",
+ "arg": "^5.0.2",
+ "better-opn": "~3.0.2",
+ "bplist-creator": "0.1.0",
+ "bplist-parser": "^0.3.1",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.3.0",
+ "compression": "^1.7.4",
+ "connect": "^3.7.0",
+ "debug": "^4.3.4",
+ "env-editor": "^0.4.1",
+ "expo-server": "^1.0.5",
+ "freeport-async": "^2.0.0",
+ "getenv": "^2.0.0",
+ "glob": "^13.0.0",
+ "lan-network": "^0.1.6",
+ "minimatch": "^9.0.0",
+ "node-forge": "^1.3.3",
+ "npm-package-arg": "^11.0.0",
+ "ora": "^3.4.0",
+ "picomatch": "^3.0.1",
+ "pretty-bytes": "^5.6.0",
+ "pretty-format": "^29.7.0",
+ "progress": "^2.0.3",
+ "prompts": "^2.3.2",
+ "qrcode-terminal": "0.11.0",
+ "require-from-string": "^2.0.2",
+ "requireg": "^0.2.2",
+ "resolve": "^1.22.2",
+ "resolve-from": "^5.0.0",
+ "resolve.exports": "^2.0.3",
+ "semver": "^7.6.0",
+ "send": "^0.19.0",
+ "slugify": "^1.3.4",
+ "source-map-support": "~0.5.21",
+ "stacktrace-parser": "^0.1.10",
+ "structured-headers": "^0.4.1",
+ "tar": "^7.5.2",
+ "terminal-link": "^2.1.1",
+ "undici": "^6.18.2",
+ "wrap-ansi": "^7.0.0",
+ "ws": "^8.12.1"
+ },
+ "bin": {
+ "expo-internal": "build/bin/cli"
+ },
+ "peerDependencies": {
+ "expo": "*",
+ "expo-router": "*",
+ "react-native": "*"
+ },
+ "peerDependenciesMeta": {
+ "expo-router": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@expo/cli/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@expo/cli/node_modules/minimatch": {
+ "version": "9.0.9",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
+ "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@expo/cli/node_modules/picomatch": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-3.0.1.tgz",
+ "integrity": "sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
},
"node_modules/@expo/code-signing-certificates": {
"version": "0.0.6",
@@ -1504,33 +1722,35 @@
}
},
"node_modules/@expo/config": {
- "version": "55.0.10",
- "resolved": "https://registry.npmjs.org/@expo/config/-/config-55.0.10.tgz",
- "integrity": "sha512-qCHxo9H1ZoeW+y0QeMtVZ3JfGmumpGrgUFX60wLWMarraoQZSe47ZUm9kJSn3iyoPjUtUNanO3eXQg+K8k4rag==",
+ "version": "12.0.13",
+ "resolved": "https://registry.npmjs.org/@expo/config/-/config-12.0.13.tgz",
+ "integrity": "sha512-Cu52arBa4vSaupIWsF0h7F/Cg//N374nYb7HAxV0I4KceKA7x2UXpYaHOL7EEYYvp7tZdThBjvGpVmr8ScIvaQ==",
"license": "MIT",
"dependencies": {
- "@expo/config-plugins": "~55.0.7",
- "@expo/config-types": "^55.0.5",
- "@expo/json-file": "^10.0.12",
- "@expo/require-utils": "^55.0.3",
+ "@babel/code-frame": "~7.10.4",
+ "@expo/config-plugins": "~54.0.4",
+ "@expo/config-types": "^54.0.10",
+ "@expo/json-file": "^10.0.8",
"deepmerge": "^4.3.1",
"getenv": "^2.0.0",
"glob": "^13.0.0",
+ "require-from-string": "^2.0.2",
"resolve-from": "^5.0.0",
"resolve-workspace-root": "^2.0.0",
"semver": "^7.6.0",
- "slugify": "^1.3.4"
+ "slugify": "^1.3.4",
+ "sucrase": "~3.35.1"
}
},
"node_modules/@expo/config-plugins": {
- "version": "55.0.7",
- "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-55.0.7.tgz",
- "integrity": "sha512-XZUoDWrsHEkH3yasnDSJABM/UxP5a1ixzRwU/M+BToyn/f0nTrSJJe/Ay/FpxkI4JSNz2n0e06I23b2bleXKVA==",
+ "version": "54.0.4",
+ "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-54.0.4.tgz",
+ "integrity": "sha512-g2yXGICdoOw5i3LkQSDxl2Q5AlQCrG7oniu0pCPPO+UxGb7He4AFqSvPSy8HpRUj55io17hT62FTjYRD+d6j3Q==",
"license": "MIT",
"dependencies": {
- "@expo/config-types": "^55.0.5",
- "@expo/json-file": "~10.0.12",
- "@expo/plist": "^0.5.2",
+ "@expo/config-types": "^54.0.10",
+ "@expo/json-file": "~10.0.8",
+ "@expo/plist": "^0.4.8",
"@expo/sdk-runtime-versions": "^1.0.0",
"chalk": "^4.1.2",
"debug": "^4.3.5",
@@ -1538,17 +1758,27 @@
"glob": "^13.0.0",
"resolve-from": "^5.0.0",
"semver": "^7.5.4",
+ "slash": "^3.0.0",
"slugify": "^1.6.6",
"xcode": "^3.0.1",
"xml2js": "0.6.0"
}
},
"node_modules/@expo/config-types": {
- "version": "55.0.5",
- "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-55.0.5.tgz",
- "integrity": "sha512-sCmSUZG4mZ/ySXvfyyBdhjivz8Q539X1NondwDdYG7s3SBsk+wsgPJzYsqgAG/P9+l0xWjUD2F+kQ1cAJ6NNLg==",
+ "version": "54.0.10",
+ "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-54.0.10.tgz",
+ "integrity": "sha512-/J16SC2an1LdtCZ67xhSkGXpALYUVUNyZws7v+PVsFZxClYehDSoKLqyRaGkpHlYrCc08bS0RF5E0JV6g50psA==",
"license": "MIT"
},
+ "node_modules/@expo/config/node_modules/@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
"node_modules/@expo/devcert": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@expo/devcert/-/devcert-1.2.1.tgz",
@@ -1569,9 +1799,9 @@
}
},
"node_modules/@expo/devtools": {
- "version": "55.0.2",
- "resolved": "https://registry.npmjs.org/@expo/devtools/-/devtools-55.0.2.tgz",
- "integrity": "sha512-4VsFn9MUriocyuhyA+ycJP3TJhUsOFHDc270l9h3LhNpXMf6wvIdGcA0QzXkZtORXmlDybWXRP2KT1k36HcQkA==",
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/@expo/devtools/-/devtools-0.1.8.tgz",
+ "integrity": "sha512-SVLxbuanDjJPgc0sy3EfXUMLb/tXzp6XIHkhtPVmTWJAp+FOr6+5SeiCfJrCzZFet0Ifyke2vX3sFcKwEvCXwQ==",
"license": "MIT",
"dependencies": {
"chalk": "^4.1.2"
@@ -1589,38 +1819,25 @@
}
}
},
- "node_modules/@expo/dom-webview": {
- "version": "55.0.3",
- "resolved": "https://registry.npmjs.org/@expo/dom-webview/-/dom-webview-55.0.3.tgz",
- "integrity": "sha512-bY4/rfcZ0f43DvOtMn8/kmPlmo01tex5hRoc5hKbwBwQjqWQuQt0ACwu7akR9IHI4j0WNG48eL6cZB6dZUFrzg==",
- "license": "MIT",
- "peerDependencies": {
- "expo": "*",
- "react": "*",
- "react-native": "*"
- }
- },
"node_modules/@expo/env": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@expo/env/-/env-2.1.1.tgz",
- "integrity": "sha512-rVvHC4I6xlPcg+mAO09ydUi2Wjv1ZytpLmHOSzvXzBAz9mMrJggqCe4s4dubjJvi/Ino/xQCLhbaLCnTtLpikg==",
+ "version": "2.0.11",
+ "resolved": "https://registry.npmjs.org/@expo/env/-/env-2.0.11.tgz",
+ "integrity": "sha512-xV+ps6YCW7XIPVUwFVCRN2nox09dnRwy8uIjwHWTODu0zFw4kp4omnVkl0OOjuu2XOe7tdgAHxikrkJt9xB/7Q==",
"license": "MIT",
"dependencies": {
"chalk": "^4.0.0",
"debug": "^4.3.4",
+ "dotenv": "~16.4.5",
+ "dotenv-expand": "~11.0.6",
"getenv": "^2.0.0"
- },
- "engines": {
- "node": ">=20.12.0"
}
},
"node_modules/@expo/fingerprint": {
- "version": "0.16.6",
- "resolved": "https://registry.npmjs.org/@expo/fingerprint/-/fingerprint-0.16.6.tgz",
- "integrity": "sha512-nRITNbnu3RKSHPvKVehrSU4KG2VY9V8nvULOHBw98ukHCAU4bGrU5APvcblOkX3JAap+xEHsg/mZvqlvkLInmQ==",
+ "version": "0.15.4",
+ "resolved": "https://registry.npmjs.org/@expo/fingerprint/-/fingerprint-0.15.4.tgz",
+ "integrity": "sha512-eYlxcrGdR2/j2M6pEDXo9zU9KXXF1vhP+V+Tl+lyY+bU8lnzrN6c637mz6Ye3em2ANy8hhUR03Raf8VsT9Ogng==",
"license": "MIT",
"dependencies": {
- "@expo/env": "^2.0.11",
"@expo/spawn-async": "^1.7.2",
"arg": "^5.0.2",
"chalk": "^4.1.2",
@@ -1628,7 +1845,8 @@
"getenv": "^2.0.0",
"glob": "^13.0.0",
"ignore": "^5.3.1",
- "minimatch": "^10.2.2",
+ "minimatch": "^9.0.0",
+ "p-limit": "^3.1.0",
"resolve-from": "^5.0.0",
"semver": "^7.6.0"
},
@@ -1636,6 +1854,45 @@
"fingerprint": "bin/cli.js"
}
},
+ "node_modules/@expo/fingerprint/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@expo/fingerprint/node_modules/minimatch": {
+ "version": "9.0.9",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
+ "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@expo/fingerprint/node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/@expo/image-utils": {
"version": "0.8.12",
"resolved": "https://registry.npmjs.org/@expo/image-utils/-/image-utils-0.8.12.tgz",
@@ -1661,33 +1918,6 @@
"json5": "^2.2.3"
}
},
- "node_modules/@expo/local-build-cache-provider": {
- "version": "55.0.7",
- "resolved": "https://registry.npmjs.org/@expo/local-build-cache-provider/-/local-build-cache-provider-55.0.7.tgz",
- "integrity": "sha512-Qg9uNZn1buv4zJUA4ZQaz+ZnKDCipRgjoEg2Gcp8Qfy+2Gq5yZKX4YN1TThCJ01LJk/pvJsCRxXlXZSwdZppgg==",
- "license": "MIT",
- "dependencies": {
- "@expo/config": "~55.0.10",
- "chalk": "^4.1.2"
- }
- },
- "node_modules/@expo/log-box": {
- "version": "55.0.7",
- "resolved": "https://registry.npmjs.org/@expo/log-box/-/log-box-55.0.7.tgz",
- "integrity": "sha512-m7V1k2vlMp4NOj3fopjOg4zl/ANXyTRF3HMTMep2GZAKsPiDzgOQ41nm8CaU50/HlDIGXlCObss07gOn20UpHQ==",
- "license": "MIT",
- "dependencies": {
- "@expo/dom-webview": "^55.0.3",
- "anser": "^1.4.9",
- "stacktrace-parser": "^0.1.10"
- },
- "peerDependencies": {
- "@expo/dom-webview": "^55.0.3",
- "expo": "*",
- "react": "*",
- "react-native": "*"
- }
- },
"node_modules/@expo/metro": {
"version": "54.2.0",
"resolved": "https://registry.npmjs.org/@expo/metro/-/metro-54.2.0.tgz",
@@ -1710,6 +1940,133 @@
"metro-transform-worker": "0.83.3"
}
},
+ "node_modules/@expo/metro-config": {
+ "version": "54.0.14",
+ "resolved": "https://registry.npmjs.org/@expo/metro-config/-/metro-config-54.0.14.tgz",
+ "integrity": "sha512-hxpLyDfOR4L23tJ9W1IbJJsG7k4lv2sotohBm/kTYyiG+pe1SYCAWsRmgk+H42o/wWf/HQjE5k45S5TomGLxNA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.20.0",
+ "@babel/core": "^7.20.0",
+ "@babel/generator": "^7.20.5",
+ "@expo/config": "~12.0.13",
+ "@expo/env": "~2.0.8",
+ "@expo/json-file": "~10.0.8",
+ "@expo/metro": "~54.2.0",
+ "@expo/spawn-async": "^1.7.2",
+ "browserslist": "^4.25.0",
+ "chalk": "^4.1.0",
+ "debug": "^4.3.2",
+ "dotenv": "~16.4.5",
+ "dotenv-expand": "~11.0.6",
+ "getenv": "^2.0.0",
+ "glob": "^13.0.0",
+ "hermes-parser": "^0.29.1",
+ "jsc-safe-url": "^0.2.4",
+ "lightningcss": "^1.30.1",
+ "minimatch": "^9.0.0",
+ "postcss": "~8.4.32",
+ "resolve-from": "^5.0.0"
+ },
+ "peerDependencies": {
+ "expo": "*"
+ },
+ "peerDependenciesMeta": {
+ "expo": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@expo/metro-config/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@expo/metro-config/node_modules/hermes-estree": {
+ "version": "0.29.1",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.29.1.tgz",
+ "integrity": "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==",
+ "license": "MIT"
+ },
+ "node_modules/@expo/metro-config/node_modules/hermes-parser": {
+ "version": "0.29.1",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.29.1.tgz",
+ "integrity": "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA==",
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.29.1"
+ }
+ },
+ "node_modules/@expo/metro-config/node_modules/minimatch": {
+ "version": "9.0.9",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
+ "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@expo/metro-config/node_modules/postcss": {
+ "version": "8.4.49",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
+ "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/@expo/metro-runtime": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/@expo/metro-runtime/-/metro-runtime-6.1.2.tgz",
+ "integrity": "sha512-nvM+Qv45QH7pmYvP8JB1G8JpScrWND3KrMA6ZKe62cwwNiX/BjHU28Ear0v/4bQWXlOY0mv6B8CDIm8JxXde9g==",
+ "license": "MIT",
+ "dependencies": {
+ "anser": "^1.4.9",
+ "pretty-format": "^29.7.0",
+ "stacktrace-parser": "^0.1.10",
+ "whatwg-fetch": "^3.0.0"
+ },
+ "peerDependencies": {
+ "expo": "*",
+ "react": "*",
+ "react-dom": "*",
+ "react-native": "*"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@expo/ngrok": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/@expo/ngrok/-/ngrok-4.1.3.tgz",
@@ -1939,28 +2296,28 @@
}
},
"node_modules/@expo/plist": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.5.2.tgz",
- "integrity": "sha512-o4xdVdBpe4aTl3sPMZ2u3fJH4iG1I768EIRk1xRZP+GaFI93MaR3JvoFibYqxeTmLQ1p1kNEVqylfUjezxx45g==",
+ "version": "0.4.8",
+ "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.4.8.tgz",
+ "integrity": "sha512-pfNtErGGzzRwHP+5+RqswzPDKkZrx+Cli0mzjQaus1ZWFsog5ibL+nVT3NcporW51o8ggnt7x813vtRbPiyOrQ==",
"license": "MIT",
"dependencies": {
"@xmldom/xmldom": "^0.8.8",
- "base64-js": "^1.5.1",
+ "base64-js": "^1.2.3",
"xmlbuilder": "^15.1.1"
}
},
"node_modules/@expo/prebuild-config": {
- "version": "55.0.10",
- "resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-55.0.10.tgz",
- "integrity": "sha512-AMylDld5G7YJGfEhEyXtgWRuBB83802QBoewF1vJ6NMDtufukuPhMJzOs9E4UXNsjLTaQcgT4yTWhsAWl7o1AQ==",
+ "version": "54.0.8",
+ "resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-54.0.8.tgz",
+ "integrity": "sha512-EA7N4dloty2t5Rde+HP0IEE+nkAQiu4A/+QGZGT9mFnZ5KKjPPkqSyYcRvP5bhQE10D+tvz6X0ngZpulbMdbsg==",
"license": "MIT",
"dependencies": {
- "@expo/config": "~55.0.10",
- "@expo/config-plugins": "~55.0.7",
- "@expo/config-types": "^55.0.5",
- "@expo/image-utils": "^0.8.12",
- "@expo/json-file": "^10.0.12",
- "@react-native/normalize-colors": "0.83.2",
+ "@expo/config": "~12.0.13",
+ "@expo/config-plugins": "~54.0.4",
+ "@expo/config-types": "^54.0.10",
+ "@expo/image-utils": "^0.8.8",
+ "@expo/json-file": "^10.0.8",
+ "@react-native/normalize-colors": "0.81.5",
"debug": "^4.3.1",
"resolve-from": "^5.0.0",
"semver": "^7.6.0",
@@ -1990,9 +2347,9 @@
}
},
"node_modules/@expo/schema-utils": {
- "version": "55.0.2",
- "resolved": "https://registry.npmjs.org/@expo/schema-utils/-/schema-utils-55.0.2.tgz",
- "integrity": "sha512-QZ5WKbJOWkCrMq0/kfhV9ry8te/OaS34YgLVpG8u9y2gix96TlpRTbxM/YATjNcUR2s4fiQmPCOxkGtog4i37g==",
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/@expo/schema-utils/-/schema-utils-0.1.8.tgz",
+ "integrity": "sha512-9I6ZqvnAvKKDiO+ZF8BpQQFYWXOJvTAL5L/227RUbWG1OVZDInFifzCBiqAZ3b67NRfeAgpgvbA7rejsqhY62A==",
"license": "MIT"
},
"node_modules/@expo/sdk-runtime-versions": {
@@ -2019,6 +2376,17 @@
"integrity": "sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw==",
"license": "MIT"
},
+ "node_modules/@expo/vector-icons": {
+ "version": "15.1.1",
+ "resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-15.1.1.tgz",
+ "integrity": "sha512-Iu2VkcoI5vygbtYngm7jb4ifxElNVXQYdDrYkT7UCEIiKLeWnQY0wf2ZhHZ+Wro6Sc5TaumpKUOqDRpLi5rkvw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo-font": ">=14.0.4",
+ "react": "*",
+ "react-native": "*"
+ }
+ },
"node_modules/@expo/ws-tunnel": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@expo/ws-tunnel/-/ws-tunnel-1.0.6.tgz",
@@ -2057,6 +2425,24 @@
"js-yaml": "bin/js-yaml.js"
}
},
+ "node_modules/@ide/backoff": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@ide/backoff/-/backoff-1.0.0.tgz",
+ "integrity": "sha512-F0YfUDjvT+Mtt/R4xdl2X0EYCHMMiJqNLdxHD++jDT5ydEFIyqbCHh51Qx2E211dgZprPKhV7sHmnXKpLuvc5g==",
+ "license": "MIT"
+ },
+ "node_modules/@isaacs/fs-minipass": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
+ "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^7.0.4"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
"node_modules/@isaacs/ttlcache": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz",
@@ -2647,9 +3033,9 @@
}
},
"node_modules/@radix-ui/react-slot": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz",
- "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==",
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.0.tgz",
+ "integrity": "sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.2"
@@ -2664,6 +3050,36 @@
}
}
},
+ "node_modules/@radix-ui/react-tabs": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz",
+ "integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.3",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-presence": "1.1.5",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-roving-focus": "1.1.11",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@radix-ui/react-use-callback-ref": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
@@ -2762,26 +3178,155 @@
}
},
"node_modules/@react-native/assets-registry": {
- "version": "0.83.2",
- "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.83.2.tgz",
- "integrity": "sha512-9I5l3pGAKnlpQ15uVkeB9Mgjvt3cZEaEc8EDtdexvdtZvLSjtwBzgourrOW4yZUijbjJr8h3YO2Y0q+THwUHTA==",
+ "version": "0.81.5",
+ "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.81.5.tgz",
+ "integrity": "sha512-705B6x/5Kxm1RKRvSv0ADYWm5JOnoiQ1ufW7h8uu2E6G9Of/eE6hP/Ivw3U5jI16ERqZxiKQwk34VJbB0niX9w==",
"license": "MIT",
"engines": {
"node": ">= 20.19.4"
}
},
- "node_modules/@react-native/community-cli-plugin": {
- "version": "0.83.2",
- "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.83.2.tgz",
- "integrity": "sha512-sTEF0eiUKtmImEP07Qo5c3Khvm1LIVX1Qyb6zWUqPL6W3MqFiXutZvKBjqLz6p49Szx8cplQLoXfLHT0bcDXKg==",
+ "node_modules/@react-native/babel-plugin-codegen": {
+ "version": "0.81.5",
+ "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.81.5.tgz",
+ "integrity": "sha512-oF71cIH6je3fSLi6VPjjC3Sgyyn57JLHXs+mHWc9MoCiJJcM4nqsS5J38zv1XQ8d3zOW2JtHro+LF0tagj2bfQ==",
"license": "MIT",
"dependencies": {
- "@react-native/dev-middleware": "0.83.2",
+ "@babel/traverse": "^7.25.3",
+ "@react-native/codegen": "0.81.5"
+ },
+ "engines": {
+ "node": ">= 20.19.4"
+ }
+ },
+ "node_modules/@react-native/babel-preset": {
+ "version": "0.81.5",
+ "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.81.5.tgz",
+ "integrity": "sha512-UoI/x/5tCmi+pZ3c1+Ypr1DaRMDLI3y+Q70pVLLVgrnC3DHsHRIbHcCHIeG/IJvoeFqFM2sTdhSOLJrf8lOPrA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.25.2",
+ "@babel/plugin-proposal-export-default-from": "^7.24.7",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3",
+ "@babel/plugin-syntax-export-default-from": "^7.24.7",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-transform-arrow-functions": "^7.24.7",
+ "@babel/plugin-transform-async-generator-functions": "^7.25.4",
+ "@babel/plugin-transform-async-to-generator": "^7.24.7",
+ "@babel/plugin-transform-block-scoping": "^7.25.0",
+ "@babel/plugin-transform-class-properties": "^7.25.4",
+ "@babel/plugin-transform-classes": "^7.25.4",
+ "@babel/plugin-transform-computed-properties": "^7.24.7",
+ "@babel/plugin-transform-destructuring": "^7.24.8",
+ "@babel/plugin-transform-flow-strip-types": "^7.25.2",
+ "@babel/plugin-transform-for-of": "^7.24.7",
+ "@babel/plugin-transform-function-name": "^7.25.1",
+ "@babel/plugin-transform-literals": "^7.25.2",
+ "@babel/plugin-transform-logical-assignment-operators": "^7.24.7",
+ "@babel/plugin-transform-modules-commonjs": "^7.24.8",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7",
+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7",
+ "@babel/plugin-transform-numeric-separator": "^7.24.7",
+ "@babel/plugin-transform-object-rest-spread": "^7.24.7",
+ "@babel/plugin-transform-optional-catch-binding": "^7.24.7",
+ "@babel/plugin-transform-optional-chaining": "^7.24.8",
+ "@babel/plugin-transform-parameters": "^7.24.7",
+ "@babel/plugin-transform-private-methods": "^7.24.7",
+ "@babel/plugin-transform-private-property-in-object": "^7.24.7",
+ "@babel/plugin-transform-react-display-name": "^7.24.7",
+ "@babel/plugin-transform-react-jsx": "^7.25.2",
+ "@babel/plugin-transform-react-jsx-self": "^7.24.7",
+ "@babel/plugin-transform-react-jsx-source": "^7.24.7",
+ "@babel/plugin-transform-regenerator": "^7.24.7",
+ "@babel/plugin-transform-runtime": "^7.24.7",
+ "@babel/plugin-transform-shorthand-properties": "^7.24.7",
+ "@babel/plugin-transform-spread": "^7.24.7",
+ "@babel/plugin-transform-sticky-regex": "^7.24.7",
+ "@babel/plugin-transform-typescript": "^7.25.2",
+ "@babel/plugin-transform-unicode-regex": "^7.24.7",
+ "@babel/template": "^7.25.0",
+ "@react-native/babel-plugin-codegen": "0.81.5",
+ "babel-plugin-syntax-hermes-parser": "0.29.1",
+ "babel-plugin-transform-flow-enums": "^0.0.2",
+ "react-refresh": "^0.14.0"
+ },
+ "engines": {
+ "node": ">= 20.19.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "*"
+ }
+ },
+ "node_modules/@react-native/codegen": {
+ "version": "0.81.5",
+ "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.81.5.tgz",
+ "integrity": "sha512-a2TDA03Up8lpSa9sh5VRGCQDXgCTOyDOFH+aqyinxp1HChG8uk89/G+nkJ9FPd0rqgi25eCTR16TWdS3b+fA6g==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.25.2",
+ "@babel/parser": "^7.25.3",
+ "glob": "^7.1.1",
+ "hermes-parser": "0.29.1",
+ "invariant": "^2.2.4",
+ "nullthrows": "^1.1.1",
+ "yargs": "^17.6.2"
+ },
+ "engines": {
+ "node": ">= 20.19.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "*"
+ }
+ },
+ "node_modules/@react-native/codegen/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@react-native/codegen/node_modules/hermes-estree": {
+ "version": "0.29.1",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.29.1.tgz",
+ "integrity": "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==",
+ "license": "MIT"
+ },
+ "node_modules/@react-native/codegen/node_modules/hermes-parser": {
+ "version": "0.29.1",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.29.1.tgz",
+ "integrity": "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA==",
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.29.1"
+ }
+ },
+ "node_modules/@react-native/community-cli-plugin": {
+ "version": "0.81.5",
+ "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.81.5.tgz",
+ "integrity": "sha512-yWRlmEOtcyvSZ4+OvqPabt+NS36vg0K/WADTQLhrYrm9qdZSuXmq8PmdJWz/68wAqKQ+4KTILiq2kjRQwnyhQw==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-native/dev-middleware": "0.81.5",
"debug": "^4.4.0",
"invariant": "^2.2.4",
- "metro": "^0.83.3",
- "metro-config": "^0.83.3",
- "metro-core": "^0.83.3",
+ "metro": "^0.83.1",
+ "metro-config": "^0.83.1",
+ "metro-core": "^0.83.1",
"semver": "^7.1.3"
},
"engines": {
@@ -2801,36 +3346,22 @@
}
},
"node_modules/@react-native/debugger-frontend": {
- "version": "0.83.2",
- "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.83.2.tgz",
- "integrity": "sha512-t4fYfa7xopbUF5S4+ihNEwgaq4wLZLKLY0Ms8z72lkMteVd3bOX2Foxa8E2wTfRvdhPOkSpOsTeNDmD8ON4DoQ==",
+ "version": "0.81.5",
+ "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.81.5.tgz",
+ "integrity": "sha512-bnd9FSdWKx2ncklOetCgrlwqSGhMHP2zOxObJbOWXoj7GHEmih4MKarBo5/a8gX8EfA1EwRATdfNBQ81DY+h+w==",
"license": "BSD-3-Clause",
"engines": {
"node": ">= 20.19.4"
}
},
- "node_modules/@react-native/debugger-shell": {
- "version": "0.83.2",
- "resolved": "https://registry.npmjs.org/@react-native/debugger-shell/-/debugger-shell-0.83.2.tgz",
- "integrity": "sha512-z9go6NJMsLSDJT5MW6VGugRsZHjYvUTwxtsVc3uLt4U9W6T3J6FWI2wHpXIzd2dUkXRfAiRQ3Zi8ZQQ8fRFg9A==",
- "license": "MIT",
- "dependencies": {
- "cross-spawn": "^7.0.6",
- "fb-dotslash": "0.5.8"
- },
- "engines": {
- "node": ">= 20.19.4"
- }
- },
"node_modules/@react-native/dev-middleware": {
- "version": "0.83.2",
- "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.83.2.tgz",
- "integrity": "sha512-Zi4EVaAm28+icD19NN07Gh8Pqg/84QQu+jn4patfWKNkcToRFP5vPEbbp0eLOGWS+BVB1d1Fn5lvMrJsBbFcOg==",
+ "version": "0.81.5",
+ "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.81.5.tgz",
+ "integrity": "sha512-WfPfZzboYgo/TUtysuD5xyANzzfka8Ebni6RIb2wDxhb56ERi7qDrE4xGhtPsjCL4pQBXSVxyIlCy0d8I6EgGA==",
"license": "MIT",
"dependencies": {
"@isaacs/ttlcache": "^1.4.1",
- "@react-native/debugger-frontend": "0.83.2",
- "@react-native/debugger-shell": "0.83.2",
+ "@react-native/debugger-frontend": "0.81.5",
"chrome-launcher": "^0.15.2",
"chromium-edge-launcher": "^0.2.0",
"connect": "^3.6.5",
@@ -2839,27 +3370,68 @@
"nullthrows": "^1.1.1",
"open": "^7.0.3",
"serve-static": "^1.16.2",
- "ws": "^7.5.10"
+ "ws": "^6.2.3"
},
"engines": {
"node": ">= 20.19.4"
}
},
+ "node_modules/@react-native/dev-middleware/node_modules/ws": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz",
+ "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==",
+ "license": "MIT",
+ "dependencies": {
+ "async-limiter": "~1.0.0"
+ }
+ },
"node_modules/@react-native/gradle-plugin": {
- "version": "0.83.2",
- "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.83.2.tgz",
- "integrity": "sha512-PqN11fXRAU+uJ0inZY1HWYlwJOXHOhF4SPyeHBBxjajKpm2PGunmvFWwkmBjmmUkP/CNO0ezTUudV0oj+2wiHQ==",
+ "version": "0.81.5",
+ "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.81.5.tgz",
+ "integrity": "sha512-hORRlNBj+ReNMLo9jme3yQ6JQf4GZpVEBLxmTXGGlIL78MAezDZr5/uq9dwElSbcGmLEgeiax6e174Fie6qPLg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20.19.4"
+ }
+ },
+ "node_modules/@react-native/js-polyfills": {
+ "version": "0.81.5",
+ "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.81.5.tgz",
+ "integrity": "sha512-fB7M1CMOCIUudTRuj7kzxIBTVw2KXnsgbQ6+4cbqSxo8NmRRhA0Ul4ZUzZj3rFd3VznTL4Brmocv1oiN0bWZ8w==",
"license": "MIT",
"engines": {
"node": ">= 20.19.4"
}
},
"node_modules/@react-native/normalize-colors": {
- "version": "0.83.2",
- "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.83.2.tgz",
- "integrity": "sha512-gkZAb9LoVVzNuYzzOviH7DiPTXQoZPHuiTH2+O2+VWNtOkiznjgvqpwYAhg58a5zfRq5GXlbBdf5mzRj5+3Y5Q==",
+ "version": "0.81.5",
+ "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.81.5.tgz",
+ "integrity": "sha512-0HuJ8YtqlTVRXGZuGeBejLE04wSQsibpTI+RGOyVqxZvgtlLLC/Ssw0UmbHhT4lYMp2fhdtvKZSs5emWB1zR/g==",
"license": "MIT"
},
+ "node_modules/@react-native/virtualized-lists": {
+ "version": "0.81.5",
+ "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.81.5.tgz",
+ "integrity": "sha512-UVXgV/db25OPIvwZySeToXD/9sKKhOdkcWmmf4Jh8iBZuyfML+/5CasaZ1E7Lqg6g3uqVQq75NqIwkYmORJMPw==",
+ "license": "MIT",
+ "dependencies": {
+ "invariant": "^2.2.4",
+ "nullthrows": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 20.19.4"
+ },
+ "peerDependencies": {
+ "@types/react": "^19.1.0",
+ "react": "*",
+ "react-native": "*"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@react-navigation/bottom-tabs": {
"version": "7.15.6",
"resolved": "https://registry.npmjs.org/@react-navigation/bottom-tabs/-/bottom-tabs-7.15.6.tgz",
@@ -3095,12 +3667,6 @@
"@types/responselike": "^1.0.0"
}
},
- "node_modules/@types/emscripten": {
- "version": "1.41.5",
- "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.41.5.tgz",
- "integrity": "sha512-cMQm7pxu6BxtHyqJ7mQZ2kXWV5SLmugybFdHCBbJ5eHzOo6VhBckEgAT3//rP5FwPHNPeEiq4SmQ5ucBwsOo4Q==",
- "license": "MIT"
- },
"node_modules/@types/graceful-fs": {
"version": "4.1.9",
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
@@ -3161,13 +3727,13 @@
}
},
"node_modules/@types/react": {
- "version": "19.2.14",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
- "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
+ "version": "19.1.17",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.17.tgz",
+ "integrity": "sha512-Qec1E3mhALmaspIrhWt9jkQMNdw6bReVu64mjvhbhq2NFPftLPVr+l1SZgmw/66WwBNpDh7ao5AT6gF5v41PFA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "csstype": "^3.2.2"
+ "csstype": "^3.0.2"
}
},
"node_modules/@types/responselike": {
@@ -3207,6 +3773,29 @@
"integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
"license": "ISC"
},
+ "node_modules/@urql/core": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@urql/core/-/core-5.2.0.tgz",
+ "integrity": "sha512-/n0ieD0mvvDnVAXEQgX/7qJiVcvYvNkOHeBvkwtylfjydar123caCXcl58PXFY11oU1oquJocVXHxLAbtv4x1A==",
+ "license": "MIT",
+ "dependencies": {
+ "@0no-co/graphql.web": "^1.0.13",
+ "wonka": "^6.3.2"
+ }
+ },
+ "node_modules/@urql/exchange-retry": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@urql/exchange-retry/-/exchange-retry-1.3.2.tgz",
+ "integrity": "sha512-TQMCz2pFJMfpNxmSfX1VSfTjwUIFx/mL+p1bnfM1xjjdla7Z+KnGMW/EhFbpckp3LyWAH4PgOsMwOMnIN+MBFg==",
+ "license": "MIT",
+ "dependencies": {
+ "@urql/core": "^5.1.2",
+ "wonka": "^6.3.2"
+ },
+ "peerDependencies": {
+ "@urql/core": "^5.0.0"
+ }
+ },
"node_modules/@xmldom/xmldom": {
"version": "0.8.11",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz",
@@ -3323,7 +3912,6 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
"integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
- "dev": true,
"license": "MIT"
},
"node_modules/anymatch": {
@@ -3378,12 +3966,46 @@
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
"license": "MIT"
},
+ "node_modules/assert": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz",
+ "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "is-nan": "^1.3.2",
+ "object-is": "^1.1.5",
+ "object.assign": "^4.1.4",
+ "util": "^0.12.5"
+ }
+ },
+ "node_modules/async-limiter": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
+ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
+ "license": "MIT"
+ },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"license": "MIT"
},
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "license": "MIT",
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/axios": {
"version": "1.13.6",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz",
@@ -3511,12 +4133,27 @@
"license": "MIT"
},
"node_modules/babel-plugin-syntax-hermes-parser": {
- "version": "0.32.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.32.0.tgz",
- "integrity": "sha512-m5HthL++AbyeEA2FcdwOLfVFvWYECOBObLHNqdR8ceY4TsEdn4LdX2oTvbB2QJSSElE2AWA/b2MXZ/PF/CqLZg==",
+ "version": "0.29.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.29.1.tgz",
+ "integrity": "sha512-2WFYnoWGdmih1I1J5eIqxATOeycOqRwYxAQBu3cUu/rhwInwHUg7k60AFNbuGjSDL8tje5GDrAnxzRLcu2pYcA==",
"license": "MIT",
"dependencies": {
- "hermes-parser": "0.32.0"
+ "hermes-parser": "0.29.1"
+ }
+ },
+ "node_modules/babel-plugin-syntax-hermes-parser/node_modules/hermes-estree": {
+ "version": "0.29.1",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.29.1.tgz",
+ "integrity": "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==",
+ "license": "MIT"
+ },
+ "node_modules/babel-plugin-syntax-hermes-parser/node_modules/hermes-parser": {
+ "version": "0.29.1",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.29.1.tgz",
+ "integrity": "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA==",
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.29.1"
}
},
"node_modules/babel-plugin-transform-flow-enums": {
@@ -3555,12 +4192,11 @@
}
},
"node_modules/babel-preset-expo": {
- "version": "55.0.12",
- "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-55.0.12.tgz",
- "integrity": "sha512-oR46ExGZpRijmPUsr0rFH5X4lR/mvwqJAFXJRLpynZcvyv2pHPTeGMNfd/p5oPMbdbaeMS6G+3k18p48u2Qjbw==",
+ "version": "54.0.10",
+ "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-54.0.10.tgz",
+ "integrity": "sha512-wTt7POavLFypLcPW/uC5v8y+mtQKDJiyGLzYCjqr9tx0Qc3vCXcDKk1iCFIj/++Iy5CWhhTflEa7VvVPNWeCfw==",
"license": "MIT",
"dependencies": {
- "@babel/generator": "^7.20.5",
"@babel/helper-module-imports": "^7.25.9",
"@babel/plugin-proposal-decorators": "^7.12.9",
"@babel/plugin-proposal-export-default-from": "^7.24.7",
@@ -3576,10 +4212,10 @@
"@babel/plugin-transform-runtime": "^7.24.7",
"@babel/preset-react": "^7.22.15",
"@babel/preset-typescript": "^7.23.0",
- "@react-native/babel-preset": "0.83.2",
+ "@react-native/babel-preset": "0.81.5",
"babel-plugin-react-compiler": "^1.0.0",
"babel-plugin-react-native-web": "~0.21.0",
- "babel-plugin-syntax-hermes-parser": "^0.32.0",
+ "babel-plugin-syntax-hermes-parser": "^0.29.1",
"babel-plugin-transform-flow-enums": "^0.0.2",
"debug": "^4.3.4",
"resolve-from": "^5.0.0"
@@ -3587,7 +4223,6 @@
"peerDependencies": {
"@babel/runtime": "^7.20.0",
"expo": "*",
- "expo-widgets": "^55.0.6",
"react-refresh": ">=0.14.0 <1.0.0"
},
"peerDependenciesMeta": {
@@ -3596,154 +4231,9 @@
},
"expo": {
"optional": true
- },
- "expo-widgets": {
- "optional": true
}
}
},
- "node_modules/babel-preset-expo/node_modules/@react-native/babel-plugin-codegen": {
- "version": "0.83.2",
- "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.83.2.tgz",
- "integrity": "sha512-XbcN/BEa64pVlb0Hb/E/Ph2SepjVN/FcNKrJcQvtaKZA6mBSO8pW8Eircdlr61/KBH94LihHbQoQDzkQFpeaTg==",
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.25.3",
- "@react-native/codegen": "0.83.2"
- },
- "engines": {
- "node": ">= 20.19.4"
- }
- },
- "node_modules/babel-preset-expo/node_modules/@react-native/babel-preset": {
- "version": "0.83.2",
- "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.83.2.tgz",
- "integrity": "sha512-X/RAXDfe6W+om/Fw1i6htTxQXFhBJ2jgNOWx3WpI3KbjeIWbq7ib6vrpTeIAW2NUMg+K3mML1NzgD4dpZeqdjA==",
- "license": "MIT",
- "dependencies": {
- "@babel/core": "^7.25.2",
- "@babel/plugin-proposal-export-default-from": "^7.24.7",
- "@babel/plugin-syntax-dynamic-import": "^7.8.3",
- "@babel/plugin-syntax-export-default-from": "^7.24.7",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
- "@babel/plugin-syntax-optional-chaining": "^7.8.3",
- "@babel/plugin-transform-arrow-functions": "^7.24.7",
- "@babel/plugin-transform-async-generator-functions": "^7.25.4",
- "@babel/plugin-transform-async-to-generator": "^7.24.7",
- "@babel/plugin-transform-block-scoping": "^7.25.0",
- "@babel/plugin-transform-class-properties": "^7.25.4",
- "@babel/plugin-transform-classes": "^7.25.4",
- "@babel/plugin-transform-computed-properties": "^7.24.7",
- "@babel/plugin-transform-destructuring": "^7.24.8",
- "@babel/plugin-transform-flow-strip-types": "^7.25.2",
- "@babel/plugin-transform-for-of": "^7.24.7",
- "@babel/plugin-transform-function-name": "^7.25.1",
- "@babel/plugin-transform-literals": "^7.25.2",
- "@babel/plugin-transform-logical-assignment-operators": "^7.24.7",
- "@babel/plugin-transform-modules-commonjs": "^7.24.8",
- "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7",
- "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7",
- "@babel/plugin-transform-numeric-separator": "^7.24.7",
- "@babel/plugin-transform-object-rest-spread": "^7.24.7",
- "@babel/plugin-transform-optional-catch-binding": "^7.24.7",
- "@babel/plugin-transform-optional-chaining": "^7.24.8",
- "@babel/plugin-transform-parameters": "^7.24.7",
- "@babel/plugin-transform-private-methods": "^7.24.7",
- "@babel/plugin-transform-private-property-in-object": "^7.24.7",
- "@babel/plugin-transform-react-display-name": "^7.24.7",
- "@babel/plugin-transform-react-jsx": "^7.25.2",
- "@babel/plugin-transform-react-jsx-self": "^7.24.7",
- "@babel/plugin-transform-react-jsx-source": "^7.24.7",
- "@babel/plugin-transform-regenerator": "^7.24.7",
- "@babel/plugin-transform-runtime": "^7.24.7",
- "@babel/plugin-transform-shorthand-properties": "^7.24.7",
- "@babel/plugin-transform-spread": "^7.24.7",
- "@babel/plugin-transform-sticky-regex": "^7.24.7",
- "@babel/plugin-transform-typescript": "^7.25.2",
- "@babel/plugin-transform-unicode-regex": "^7.24.7",
- "@babel/template": "^7.25.0",
- "@react-native/babel-plugin-codegen": "0.83.2",
- "babel-plugin-syntax-hermes-parser": "0.32.0",
- "babel-plugin-transform-flow-enums": "^0.0.2",
- "react-refresh": "^0.14.0"
- },
- "engines": {
- "node": ">= 20.19.4"
- },
- "peerDependencies": {
- "@babel/core": "*"
- }
- },
- "node_modules/babel-preset-expo/node_modules/@react-native/codegen": {
- "version": "0.83.2",
- "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.83.2.tgz",
- "integrity": "sha512-9uK6X1miCXqtL4c759l74N/XbQeneWeQVjoV7SD2CGJuW7ZefxaoYenwGPs7rMoCdtS6wuIyR3hXQ+uWEBGYXA==",
- "license": "MIT",
- "dependencies": {
- "@babel/core": "^7.25.2",
- "@babel/parser": "^7.25.3",
- "glob": "^7.1.1",
- "hermes-parser": "0.32.0",
- "invariant": "^2.2.4",
- "nullthrows": "^1.1.1",
- "yargs": "^17.6.2"
- },
- "engines": {
- "node": ">= 20.19.4"
- },
- "peerDependencies": {
- "@babel/core": "*"
- }
- },
- "node_modules/babel-preset-expo/node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "license": "MIT"
- },
- "node_modules/babel-preset-expo/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/babel-preset-expo/node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
- "license": "ISC",
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/babel-preset-expo/node_modules/minimatch": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
- "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
"node_modules/babel-preset-jest": {
"version": "29.6.3",
"resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
@@ -3767,22 +4257,10 @@
"license": "MIT"
},
"node_modules/balanced-match": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
- "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
- "license": "MIT",
- "engines": {
- "node": "18 || 20 || >=22"
- }
- },
- "node_modules/barcode-detector": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/barcode-detector/-/barcode-detector-3.1.1.tgz",
- "integrity": "sha512-ghWlEAV93ZCUniO7Co3ih/01XPm+U30CV+NoPbO6Chj5lZzHydDAqKlrBEd+37TkoR+QTH3tnnwd8k8epGTfIg==",
- "license": "MIT",
- "dependencies": {
- "zxing-wasm": "3.0.1"
- }
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "license": "MIT"
},
"node_modules/base64-js": {
"version": "1.5.1",
@@ -3867,6 +4345,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+ "license": "ISC"
+ },
"node_modules/bplist-creator": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz",
@@ -3877,9 +4361,9 @@
}
},
"node_modules/bplist-parser": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz",
- "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==",
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz",
+ "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==",
"license": "MIT",
"dependencies": {
"big-integer": "1.6.x"
@@ -3889,15 +4373,13 @@
}
},
"node_modules/brace-expansion": {
- "version": "5.0.4",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz",
- "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==",
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"license": "MIT",
"dependencies": {
- "balanced-match": "^4.0.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
}
},
"node_modules/braces": {
@@ -3954,6 +4436,30 @@
"node-int64": "^0.4.0"
}
},
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
@@ -3998,6 +4504,24 @@
"node": ">=8"
}
},
+ "node_modules/call-bind": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
+ "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.0",
+ "es-define-property": "^1.0.0",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
@@ -4011,6 +4535,22 @@
"node": ">= 0.4"
}
},
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/camelcase": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
@@ -4107,6 +4647,15 @@
"node": ">= 6"
}
},
+ "node_modules/chownr": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
+ "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/chrome-launcher": {
"version": "0.15.2",
"resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz",
@@ -4140,10 +4689,19 @@
}
},
"node_modules/ci-info": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
- "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
- "license": "MIT"
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
},
"node_modules/cli-cursor": {
"version": "2.1.0",
@@ -4189,6 +4747,38 @@
"node": ">=12"
}
},
+ "node_modules/cliui/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/cliui/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/clone": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
@@ -4409,6 +4999,56 @@
"node": ">= 8"
}
},
+ "node_modules/css-select": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz",
+ "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^6.1.0",
+ "domhandler": "^5.0.2",
+ "domutils": "^3.0.1",
+ "nth-check": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/css-tree": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz",
+ "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==",
+ "license": "MIT",
+ "dependencies": {
+ "mdn-data": "2.0.14",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/css-tree/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/css-what": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
+ "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
"node_modules/cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
@@ -4484,6 +5124,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
"node_modules/deepmerge": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
@@ -4515,6 +5164,23 @@
"node": ">=10"
}
},
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/define-lazy-prop": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
@@ -4524,6 +5190,23 @@
"node": ">=8"
}
},
+ "node_modules/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -4581,11 +5264,87 @@
"dev": true,
"license": "MIT"
},
- "node_modules/dnssd-advertise": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/dnssd-advertise/-/dnssd-advertise-1.1.3.tgz",
- "integrity": "sha512-XENsHi3MBzWOCAXif3yZvU1Ah0l+nhJj1sjWL6TnOAYKvGiFhbTx32xHN7+wLMLUOCj7Nr0evADWG4R8JtqCDA==",
- "license": "MIT"
+ "node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
+ "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "16.4.7",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz",
+ "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/dotenv-expand": {
+ "version": "11.0.7",
+ "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz",
+ "integrity": "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "dotenv": "^16.4.5"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
},
"node_modules/dunder-proto": {
"version": "1.0.1",
@@ -4613,12 +5372,6 @@
"integrity": "sha512-L2C7Q279W2D/J4PLZLk7sebOILDSWos7bMsMNN06rK482umHUrh/3lM8G7IlHFOYip2oAg5nha1rCMxr/rs6ZQ==",
"license": "ISC"
},
- "node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "license": "MIT"
- },
"node_modules/encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
@@ -4638,6 +5391,27 @@
"once": "^1.4.0"
}
},
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/env-editor": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/env-editor/-/env-editor-0.4.2.tgz",
+ "integrity": "sha512-ObFo8v4rQJAE59M69QzwloxPZtd33TpYEIjtKD1rrFDcM1Gd7IkDxEBU+HriziN6HSHQnBJi8Dmy+JWkav5HKA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/error-stack-parser": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
@@ -4751,34 +5525,32 @@
}
},
"node_modules/expo": {
- "version": "55.0.8",
- "resolved": "https://registry.npmjs.org/expo/-/expo-55.0.8.tgz",
- "integrity": "sha512-sziDGiDmeRmaSpFwMuSxFhr4vfWrQS1UgVXSTovsUDY0ximABzYdnF5L2OwtD8zjtIww8x2oJGmD6mKS+AoVsw==",
+ "version": "54.0.33",
+ "resolved": "https://registry.npmjs.org/expo/-/expo-54.0.33.tgz",
+ "integrity": "sha512-3yOEfAKqo+gqHcV8vKcnq0uA5zxlohnhA3fu4G43likN8ct5ZZ3LjAh9wDdKteEkoad3tFPvwxmXW711S5OHUw==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.20.0",
- "@expo/cli": "55.0.18",
- "@expo/config": "~55.0.10",
- "@expo/config-plugins": "~55.0.7",
- "@expo/devtools": "55.0.2",
- "@expo/fingerprint": "0.16.6",
- "@expo/local-build-cache-provider": "55.0.7",
- "@expo/log-box": "55.0.7",
+ "@expo/cli": "54.0.23",
+ "@expo/config": "~12.0.13",
+ "@expo/config-plugins": "~54.0.4",
+ "@expo/devtools": "0.1.8",
+ "@expo/fingerprint": "0.15.4",
"@expo/metro": "~54.2.0",
- "@expo/metro-config": "55.0.11",
- "@expo/vector-icons": "^15.0.2",
+ "@expo/metro-config": "54.0.14",
+ "@expo/vector-icons": "^15.0.3",
"@ungap/structured-clone": "^1.3.0",
- "babel-preset-expo": "~55.0.12",
- "expo-asset": "~55.0.10",
- "expo-constants": "~55.0.9",
- "expo-file-system": "~55.0.11",
- "expo-font": "~55.0.4",
- "expo-keep-awake": "~55.0.4",
- "expo-modules-autolinking": "55.0.11",
- "expo-modules-core": "55.0.17",
+ "babel-preset-expo": "~54.0.10",
+ "expo-asset": "~12.0.12",
+ "expo-constants": "~18.0.13",
+ "expo-file-system": "~19.0.21",
+ "expo-font": "~14.0.11",
+ "expo-keep-awake": "~15.0.8",
+ "expo-modules-autolinking": "3.0.24",
+ "expo-modules-core": "3.0.29",
"pretty-format": "^29.7.0",
"react-refresh": "^0.14.2",
- "whatwg-url-minimum": "^0.1.1"
+ "whatwg-url-without-unicode": "8.0.0-3"
},
"bin": {
"expo": "bin/cli",
@@ -4805,21 +5577,36 @@
}
},
"node_modules/expo-application": {
- "version": "55.0.10",
- "resolved": "https://registry.npmjs.org/expo-application/-/expo-application-55.0.10.tgz",
- "integrity": "sha512-5ccf+S6hsQz+doi907TOJxKzV5AKgAgw004z4FoDWSoGhfab0LUPg6uyvOspuU4cbNvqw8EAy08hZbVO8nKc9Q==",
+ "version": "7.0.8",
+ "resolved": "https://registry.npmjs.org/expo-application/-/expo-application-7.0.8.tgz",
+ "integrity": "sha512-qFGyxk7VJbrNOQWBbE09XUuGuvkOgFS9QfToaK2FdagM2aQ+x3CvGV2DuVgl/l4ZxPgIf3b/MNh9xHpwSwn74Q==",
"license": "MIT",
"peerDependencies": {
"expo": "*"
}
},
- "node_modules/expo-camera": {
- "version": "55.0.10",
- "resolved": "https://registry.npmjs.org/expo-camera/-/expo-camera-55.0.10.tgz",
- "integrity": "sha512-ftDNJbGsAPNJ/QrM3j6g8/rQAOqTwZpqtvmzF7V9VX0movaCznZFdYsLi/Fff9WeEk1KzcnLIlmSz4Tj+BCrJA==",
+ "node_modules/expo-asset": {
+ "version": "12.0.12",
+ "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-12.0.12.tgz",
+ "integrity": "sha512-CsXFCQbx2fElSMn0lyTdRIyKlSXOal6ilLJd+yeZ6xaC7I9AICQgscY5nj0QcwgA+KYYCCEQEBndMsmj7drOWQ==",
"license": "MIT",
"dependencies": {
- "barcode-detector": "^3.0.0"
+ "@expo/image-utils": "^0.8.8",
+ "expo-constants": "~18.0.12"
+ },
+ "peerDependencies": {
+ "expo": "*",
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/expo-camera": {
+ "version": "17.0.10",
+ "resolved": "https://registry.npmjs.org/expo-camera/-/expo-camera-17.0.10.tgz",
+ "integrity": "sha512-w1RBw83mAGVk4BPPwNrCZyFop0VLiVSRE3c2V9onWbdFwonpRhzmB4drygG8YOUTl1H3wQvALJHyMPTbgsK1Jg==",
+ "license": "MIT",
+ "dependencies": {
+ "invariant": "^2.2.4"
},
"peerDependencies": {
"expo": "*",
@@ -4834,124 +5621,99 @@
}
},
"node_modules/expo-constants": {
- "version": "55.0.9",
- "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-55.0.9.tgz",
- "integrity": "sha512-iBiXjZeuU5S/8docQeNzsVvtDy4w0zlmXBpFEi1ypwugceEpdQQab65TVRbusXAcwpNVxCPMpNlDssYp0Pli2g==",
+ "version": "18.0.13",
+ "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-18.0.13.tgz",
+ "integrity": "sha512-FnZn12E1dRYKDHlAdIyNFhBurKTS3F9CrfrBDJI5m3D7U17KBHMQ6JEfYlSj7LG7t+Ulr+IKaj58L1k5gBwTcQ==",
"license": "MIT",
"dependencies": {
- "@expo/config": "~55.0.10",
- "@expo/env": "~2.1.1"
+ "@expo/config": "~12.0.13",
+ "@expo/env": "~2.0.8"
},
"peerDependencies": {
"expo": "*",
"react-native": "*"
}
},
- "node_modules/expo-eas-client": {
- "version": "55.0.2",
- "resolved": "https://registry.npmjs.org/expo-eas-client/-/expo-eas-client-55.0.2.tgz",
- "integrity": "sha512-fjOgSXaZFBK2Xmzn/uw0DTF3BsYv97JEa4PYXXqVCEvNJPwJB1cV1eX6Xyq6iKGIhMPH9k62sOc+oUdt094WCw==",
+ "node_modules/expo-dev-client": {
+ "version": "55.0.18",
+ "resolved": "https://registry.npmjs.org/expo-dev-client/-/expo-dev-client-55.0.18.tgz",
+ "integrity": "sha512-zQeCGk+doTMIKwPe9lNlGcUiBlMpJQNyrrsYc5eRdxuMwBrDVAU7zshARmamSw8zlAIHCsThJH2zeJg/lgQrKA==",
+ "license": "MIT",
+ "dependencies": {
+ "expo-dev-launcher": "55.0.19",
+ "expo-dev-menu": "55.0.16",
+ "expo-dev-menu-interface": "55.0.1",
+ "expo-manifests": "~55.0.11",
+ "expo-updates-interface": "~55.1.3"
+ },
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
+ "node_modules/expo-dev-client/node_modules/@expo/config": {
+ "version": "55.0.10",
+ "resolved": "https://registry.npmjs.org/@expo/config/-/config-55.0.10.tgz",
+ "integrity": "sha512-qCHxo9H1ZoeW+y0QeMtVZ3JfGmumpGrgUFX60wLWMarraoQZSe47ZUm9kJSn3iyoPjUtUNanO3eXQg+K8k4rag==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/config-plugins": "~55.0.7",
+ "@expo/config-types": "^55.0.5",
+ "@expo/json-file": "^10.0.12",
+ "@expo/require-utils": "^55.0.3",
+ "deepmerge": "^4.3.1",
+ "getenv": "^2.0.0",
+ "glob": "^13.0.0",
+ "resolve-from": "^5.0.0",
+ "resolve-workspace-root": "^2.0.0",
+ "semver": "^7.6.0",
+ "slugify": "^1.3.4"
+ }
+ },
+ "node_modules/expo-dev-client/node_modules/@expo/config-plugins": {
+ "version": "55.0.7",
+ "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-55.0.7.tgz",
+ "integrity": "sha512-XZUoDWrsHEkH3yasnDSJABM/UxP5a1ixzRwU/M+BToyn/f0nTrSJJe/Ay/FpxkI4JSNz2n0e06I23b2bleXKVA==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/config-types": "^55.0.5",
+ "@expo/json-file": "~10.0.12",
+ "@expo/plist": "^0.5.2",
+ "@expo/sdk-runtime-versions": "^1.0.0",
+ "chalk": "^4.1.2",
+ "debug": "^4.3.5",
+ "getenv": "^2.0.0",
+ "glob": "^13.0.0",
+ "resolve-from": "^5.0.0",
+ "semver": "^7.5.4",
+ "slugify": "^1.6.6",
+ "xcode": "^3.0.1",
+ "xml2js": "0.6.0"
+ }
+ },
+ "node_modules/expo-dev-client/node_modules/@expo/config-types": {
+ "version": "55.0.5",
+ "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-55.0.5.tgz",
+ "integrity": "sha512-sCmSUZG4mZ/ySXvfyyBdhjivz8Q539X1NondwDdYG7s3SBsk+wsgPJzYsqgAG/P9+l0xWjUD2F+kQ1cAJ6NNLg==",
"license": "MIT"
},
- "node_modules/expo-font": {
- "version": "55.0.4",
- "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-55.0.4.tgz",
- "integrity": "sha512-ZKeGTFffPygvY5dM/9ATM2p7QDkhsaHopH7wFAWgP2lKzqUMS9B/RxCvw5CaObr9Ro7x9YptyeRKX2HmgmMfrg==",
+ "node_modules/expo-dev-client/node_modules/@expo/plist": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.5.2.tgz",
+ "integrity": "sha512-o4xdVdBpe4aTl3sPMZ2u3fJH4iG1I768EIRk1xRZP+GaFI93MaR3JvoFibYqxeTmLQ1p1kNEVqylfUjezxx45g==",
"license": "MIT",
"dependencies": {
- "fontfaceobserver": "^2.1.0"
- },
- "peerDependencies": {
- "expo": "*",
- "react": "*",
- "react-native": "*"
+ "@xmldom/xmldom": "^0.8.8",
+ "base64-js": "^1.5.1",
+ "xmlbuilder": "^15.1.1"
}
},
- "node_modules/expo-glass-effect": {
- "version": "55.0.8",
- "resolved": "https://registry.npmjs.org/expo-glass-effect/-/expo-glass-effect-55.0.8.tgz",
- "integrity": "sha512-IvUjHb/4t6r2H/LXDjcQ4uDoHrmO2cLOvEb9leLavQ4HX5+P4LRtQrMDMlkWAn5Wo5DkLcG8+1CrQU2nqgogTA==",
- "license": "MIT",
- "peerDependencies": {
- "expo": "*",
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/expo-image": {
- "version": "55.0.6",
- "resolved": "https://registry.npmjs.org/expo-image/-/expo-image-55.0.6.tgz",
- "integrity": "sha512-TKuu0uBmgTZlhd91Glv+V4vSBMlfl0bdQxfl97oKKZUo3OBC13l3eLik7v3VNLJN7PZbiwOAiXkZkqSOBx/Xsw==",
- "license": "MIT",
- "dependencies": {
- "sf-symbols-typescript": "^2.2.0"
- },
- "peerDependencies": {
- "expo": "*",
- "react": "*",
- "react-native": "*",
- "react-native-web": "*"
- },
- "peerDependenciesMeta": {
- "react-native-web": {
- "optional": true
- }
- }
- },
- "node_modules/expo-image-loader": {
- "version": "55.0.0",
- "resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-55.0.0.tgz",
- "integrity": "sha512-NOjp56wDrfuA5aiNAybBIjqIn1IxKeGJ8CECWZncQ/GzjZfyTYAHTCyeApYkdKkMBLHINzI4BbTGSlbCa0fXXQ==",
- "license": "MIT",
- "peerDependencies": {
- "expo": "*"
- }
- },
- "node_modules/expo-image-picker": {
- "version": "55.0.13",
- "resolved": "https://registry.npmjs.org/expo-image-picker/-/expo-image-picker-55.0.13.tgz",
- "integrity": "sha512-G+W11rcoUi3rK+6cnKWkTfZilMkGVZnYe90TiM3R98nPSlzGBoto3a/TkGGTJXedz/dmMzr49L+STlWhuKKIFw==",
- "license": "MIT",
- "dependencies": {
- "expo-image-loader": "~55.0.0"
- },
- "peerDependencies": {
- "expo": "*"
- }
- },
- "node_modules/expo-json-utils": {
+ "node_modules/expo-dev-client/node_modules/expo-json-utils": {
"version": "55.0.0",
"resolved": "https://registry.npmjs.org/expo-json-utils/-/expo-json-utils-55.0.0.tgz",
"integrity": "sha512-aupt/o5PDAb8dXDCb0JcRdkqnTLxe/F+La7jrnyd/sXlYFfRgBJLFOa1SqVFXm1E/Xam1SE/yw6eAb+DGY7Arg==",
"license": "MIT"
},
- "node_modules/expo-linking": {
- "version": "55.0.8",
- "resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-55.0.8.tgz",
- "integrity": "sha512-O9QgKAfEqKfsjL6IKs5p7pFAjo/3/TQwjMzzNPl8BCndbxWMPQfMeViXPYYNS9bA2ujUqrtF1OYhO6woI7GNQQ==",
- "license": "MIT",
- "dependencies": {
- "expo-constants": "~55.0.8",
- "invariant": "^2.2.4"
- },
- "peerDependencies": {
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/expo-location": {
- "version": "55.1.4",
- "resolved": "https://registry.npmjs.org/expo-location/-/expo-location-55.1.4.tgz",
- "integrity": "sha512-0QWQ4QP8I6svtGUL895Y8bvKM3nGUWNp/MdCoCQNH3uAuwvLf2TQ6ZDVD3kdlkl2wGGdw6ziHQIYDHL96OlfnA==",
- "license": "MIT",
- "dependencies": {
- "@expo/image-utils": "^0.8.12"
- },
- "peerDependencies": {
- "expo": "*"
- }
- },
- "node_modules/expo-manifests": {
+ "node_modules/expo-dev-client/node_modules/expo-manifests": {
"version": "55.0.11",
"resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-55.0.11.tgz",
"integrity": "sha512-3+pFun4C9F/eFMVpwZgOBrBWq5sfu7rS1uxTrcg9G7jUFatNe5W6hr+M7z7aQPDf0J1afaSudUZPawx1LLf15w==",
@@ -4964,25 +5726,255 @@
"expo": "*"
}
},
- "node_modules/expo-modules-autolinking": {
- "version": "55.0.11",
- "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-55.0.11.tgz",
- "integrity": "sha512-9dqnPzQoIl1dIvEctMWpQ8eaiXDeBTgAwebCc1WF0BbEo+pcdKjZWoCSqlLj+d7IX+OnTgM+k6cY2kPDGIu4sg==",
+ "node_modules/expo-dev-client/node_modules/expo-updates-interface": {
+ "version": "55.1.3",
+ "resolved": "https://registry.npmjs.org/expo-updates-interface/-/expo-updates-interface-55.1.3.tgz",
+ "integrity": "sha512-UVVIiZqymQZJL+o/jh65kXOI97xdkbqBJJM0LMabaPMNLFnc6/WvOMOzmQs7SPyKb8+0PeBaFd7tj5DzF6JeQg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
+ "node_modules/expo-dev-launcher": {
+ "version": "55.0.19",
+ "resolved": "https://registry.npmjs.org/expo-dev-launcher/-/expo-dev-launcher-55.0.19.tgz",
+ "integrity": "sha512-RtiC/K7Cg7RafNlq32GtilMEO5cy61HPBKASQHwLK6Gz5+FYepx0KSHIXIhWqekZMfpcj1w80tvEjMNFjUJ9Dg==",
"license": "MIT",
"dependencies": {
+ "@expo/schema-utils": "^55.0.2",
+ "expo-dev-menu": "55.0.16",
+ "expo-manifests": "~55.0.11"
+ },
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
+ "node_modules/expo-dev-launcher/node_modules/@expo/config": {
+ "version": "55.0.10",
+ "resolved": "https://registry.npmjs.org/@expo/config/-/config-55.0.10.tgz",
+ "integrity": "sha512-qCHxo9H1ZoeW+y0QeMtVZ3JfGmumpGrgUFX60wLWMarraoQZSe47ZUm9kJSn3iyoPjUtUNanO3eXQg+K8k4rag==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/config-plugins": "~55.0.7",
+ "@expo/config-types": "^55.0.5",
+ "@expo/json-file": "^10.0.12",
"@expo/require-utils": "^55.0.3",
+ "deepmerge": "^4.3.1",
+ "getenv": "^2.0.0",
+ "glob": "^13.0.0",
+ "resolve-from": "^5.0.0",
+ "resolve-workspace-root": "^2.0.0",
+ "semver": "^7.6.0",
+ "slugify": "^1.3.4"
+ }
+ },
+ "node_modules/expo-dev-launcher/node_modules/@expo/config-plugins": {
+ "version": "55.0.7",
+ "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-55.0.7.tgz",
+ "integrity": "sha512-XZUoDWrsHEkH3yasnDSJABM/UxP5a1ixzRwU/M+BToyn/f0nTrSJJe/Ay/FpxkI4JSNz2n0e06I23b2bleXKVA==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/config-types": "^55.0.5",
+ "@expo/json-file": "~10.0.12",
+ "@expo/plist": "^0.5.2",
+ "@expo/sdk-runtime-versions": "^1.0.0",
+ "chalk": "^4.1.2",
+ "debug": "^4.3.5",
+ "getenv": "^2.0.0",
+ "glob": "^13.0.0",
+ "resolve-from": "^5.0.0",
+ "semver": "^7.5.4",
+ "slugify": "^1.6.6",
+ "xcode": "^3.0.1",
+ "xml2js": "0.6.0"
+ }
+ },
+ "node_modules/expo-dev-launcher/node_modules/@expo/config-types": {
+ "version": "55.0.5",
+ "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-55.0.5.tgz",
+ "integrity": "sha512-sCmSUZG4mZ/ySXvfyyBdhjivz8Q539X1NondwDdYG7s3SBsk+wsgPJzYsqgAG/P9+l0xWjUD2F+kQ1cAJ6NNLg==",
+ "license": "MIT"
+ },
+ "node_modules/expo-dev-launcher/node_modules/@expo/plist": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.5.2.tgz",
+ "integrity": "sha512-o4xdVdBpe4aTl3sPMZ2u3fJH4iG1I768EIRk1xRZP+GaFI93MaR3JvoFibYqxeTmLQ1p1kNEVqylfUjezxx45g==",
+ "license": "MIT",
+ "dependencies": {
+ "@xmldom/xmldom": "^0.8.8",
+ "base64-js": "^1.5.1",
+ "xmlbuilder": "^15.1.1"
+ }
+ },
+ "node_modules/expo-dev-launcher/node_modules/@expo/schema-utils": {
+ "version": "55.0.2",
+ "resolved": "https://registry.npmjs.org/@expo/schema-utils/-/schema-utils-55.0.2.tgz",
+ "integrity": "sha512-QZ5WKbJOWkCrMq0/kfhV9ry8te/OaS34YgLVpG8u9y2gix96TlpRTbxM/YATjNcUR2s4fiQmPCOxkGtog4i37g==",
+ "license": "MIT"
+ },
+ "node_modules/expo-dev-launcher/node_modules/expo-json-utils": {
+ "version": "55.0.0",
+ "resolved": "https://registry.npmjs.org/expo-json-utils/-/expo-json-utils-55.0.0.tgz",
+ "integrity": "sha512-aupt/o5PDAb8dXDCb0JcRdkqnTLxe/F+La7jrnyd/sXlYFfRgBJLFOa1SqVFXm1E/Xam1SE/yw6eAb+DGY7Arg==",
+ "license": "MIT"
+ },
+ "node_modules/expo-dev-launcher/node_modules/expo-manifests": {
+ "version": "55.0.11",
+ "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-55.0.11.tgz",
+ "integrity": "sha512-3+pFun4C9F/eFMVpwZgOBrBWq5sfu7rS1uxTrcg9G7jUFatNe5W6hr+M7z7aQPDf0J1afaSudUZPawx1LLf15w==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/config": "~55.0.10",
+ "expo-json-utils": "~55.0.0"
+ },
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
+ "node_modules/expo-dev-menu": {
+ "version": "55.0.16",
+ "resolved": "https://registry.npmjs.org/expo-dev-menu/-/expo-dev-menu-55.0.16.tgz",
+ "integrity": "sha512-UhduIh/6wQmFLIy1EeQJBCN09irOrC1kf/UMQ9CxXCkXit9SOtJx+26YfCmbrIRV/lYK2qZK8Y178/HNkt7yeA==",
+ "license": "MIT",
+ "dependencies": {
+ "expo-dev-menu-interface": "55.0.1"
+ },
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
+ "node_modules/expo-dev-menu-interface": {
+ "version": "55.0.1",
+ "resolved": "https://registry.npmjs.org/expo-dev-menu-interface/-/expo-dev-menu-interface-55.0.1.tgz",
+ "integrity": "sha512-FkNtwq1q6NmYoy28pj+ZLuHmirJgc039pQbJ167MZJIaprLcMN1yy67qA7xBHK+FNJ8AN8kGCtMTPByg5UC72A==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
+ "node_modules/expo-eas-client": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/expo-eas-client/-/expo-eas-client-1.0.8.tgz",
+ "integrity": "sha512-5or11NJhSeDoHHI6zyvQDW2cz/yFyE+1Cz8NTs5NK8JzC7J0JrkUgptWtxyfB6Xs/21YRNifd3qgbBN3hfKVgA==",
+ "license": "MIT"
+ },
+ "node_modules/expo-file-system": {
+ "version": "19.0.21",
+ "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-19.0.21.tgz",
+ "integrity": "sha512-s3DlrDdiscBHtab/6W1osrjGL+C2bvoInPJD7sOwmxfJ5Woynv2oc+Fz1/xVXaE/V7HE/+xrHC/H45tu6lZzzg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/expo-font": {
+ "version": "14.0.11",
+ "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-14.0.11.tgz",
+ "integrity": "sha512-ga0q61ny4s/kr4k8JX9hVH69exVSIfcIc19+qZ7gt71Mqtm7xy2c6kwsPTCyhBW2Ro5yXTT8EaZOpuRi35rHbg==",
+ "license": "MIT",
+ "dependencies": {
+ "fontfaceobserver": "^2.1.0"
+ },
+ "peerDependencies": {
+ "expo": "*",
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/expo-image-loader": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-6.0.0.tgz",
+ "integrity": "sha512-nKs/xnOGw6ACb4g26xceBD57FKLFkSwEUTDXEDF3Gtcu3MqF3ZIYd3YM+sSb1/z9AKV1dYT7rMSGVNgsveXLIQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
+ "node_modules/expo-image-picker": {
+ "version": "17.0.10",
+ "resolved": "https://registry.npmjs.org/expo-image-picker/-/expo-image-picker-17.0.10.tgz",
+ "integrity": "sha512-a2xrowp2trmvXyUWgX3O6Q2rZaa2C59AqivKI7+bm+wLvMfTEbZgldLX4rEJJhM8xtmEDTNU+lzjtObwzBRGaw==",
+ "license": "MIT",
+ "dependencies": {
+ "expo-image-loader": "~6.0.0"
+ },
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
+ "node_modules/expo-json-utils": {
+ "version": "0.15.0",
+ "resolved": "https://registry.npmjs.org/expo-json-utils/-/expo-json-utils-0.15.0.tgz",
+ "integrity": "sha512-duRT6oGl80IDzH2LD2yEFWNwGIC2WkozsB6HF3cDYNoNNdUvFk6uN3YiwsTsqVM/D0z6LEAQ01/SlYvN+Fw0JQ==",
+ "license": "MIT"
+ },
+ "node_modules/expo-keep-awake": {
+ "version": "15.0.8",
+ "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-15.0.8.tgz",
+ "integrity": "sha512-YK9M1VrnoH1vLJiQzChZgzDvVimVoriibiDIFLbQMpjYBnvyfUeHJcin/Gx1a+XgupNXy92EQJLgI/9ZuXajYQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*",
+ "react": "*"
+ }
+ },
+ "node_modules/expo-linking": {
+ "version": "8.0.11",
+ "resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-8.0.11.tgz",
+ "integrity": "sha512-+VSaNL5om3kOp/SSKO5qe6cFgfSIWnnQDSbA7XLs3ECkYzXRquk5unxNS3pg7eK5kNUmQ4kgLI7MhTggAEUBLA==",
+ "license": "MIT",
+ "dependencies": {
+ "expo-constants": "~18.0.12",
+ "invariant": "^2.2.4"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/expo-location": {
+ "version": "19.0.8",
+ "resolved": "https://registry.npmjs.org/expo-location/-/expo-location-19.0.8.tgz",
+ "integrity": "sha512-H/FI75VuJ1coodJbbMu82pf+Zjess8X8Xkiv9Bv58ZgPKS/2ztjC1YO1/XMcGz7+s9DrbLuMIw22dFuP4HqneA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
+ "node_modules/expo-manifests": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-1.0.10.tgz",
+ "integrity": "sha512-oxDUnURPcL4ZsOBY6X1DGWGuoZgVAFzp6PISWV7lPP2J0r8u1/ucuChBgpK7u1eLGFp6sDIPwXyEUCkI386XSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/config": "~12.0.11",
+ "expo-json-utils": "~0.15.0"
+ },
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
+ "node_modules/expo-modules-autolinking": {
+ "version": "3.0.24",
+ "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-3.0.24.tgz",
+ "integrity": "sha512-TP+6HTwhL7orDvsz2VzauyQlXJcAWyU3ANsZ7JGL4DQu8XaZv/A41ZchbtAYLfozNA2Ya1Hzmhx65hXryBMjaQ==",
+ "license": "MIT",
+ "dependencies": {
"@expo/spawn-async": "^1.7.2",
"chalk": "^4.1.0",
- "commander": "^7.2.0"
+ "commander": "^7.2.0",
+ "require-from-string": "^2.0.2",
+ "resolve-from": "^5.0.0"
},
"bin": {
"expo-modules-autolinking": "bin/expo-modules-autolinking.js"
}
},
"node_modules/expo-modules-core": {
- "version": "55.0.17",
- "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-55.0.17.tgz",
- "integrity": "sha512-pw3cZiaSlBrqRJUD/pHuMnKGsRTW6XJ255FrjDd3HC4QrqErCnfSQPmz+Sv4Qkelcvd9UGdAewyTqZdFwjLwOw==",
+ "version": "3.0.29",
+ "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-3.0.29.tgz",
+ "integrity": "sha512-LzipcjGqk8gvkrOUf7O2mejNWugPkf3lmd9GkqL9WuNyeN2fRwU0Dn77e3ZUKI3k6sI+DNwjkq4Nu9fNN9WS7Q==",
"license": "MIT",
"dependencies": {
"invariant": "^2.2.4"
@@ -4993,16 +5985,18 @@
}
},
"node_modules/expo-notifications": {
- "version": "55.0.13",
- "resolved": "https://registry.npmjs.org/expo-notifications/-/expo-notifications-55.0.13.tgz",
- "integrity": "sha512-vbtSBcMkYtNTO+6WKdeOzysOqvtmiq/sQrUKJpYcB75m9hBFcAfI2klpXdUiGg5kMr/ygBmFENSolQt1B9QY8A==",
+ "version": "0.32.16",
+ "resolved": "https://registry.npmjs.org/expo-notifications/-/expo-notifications-0.32.16.tgz",
+ "integrity": "sha512-QQD/UA6v7LgvwIJ+tS7tSvqJZkdp0nCSj9MxsDk/jU1GttYdK49/5L2LvE/4U0H7sNBz1NZAyhDZozg8xgBLXw==",
"license": "MIT",
"dependencies": {
- "@expo/image-utils": "^0.8.12",
+ "@expo/image-utils": "^0.8.8",
+ "@ide/backoff": "^1.0.0",
"abort-controller": "^3.0.0",
+ "assert": "^2.0.0",
"badgin": "^1.1.5",
- "expo-application": "~55.0.10",
- "expo-constants": "~55.0.8"
+ "expo-application": "~7.0.8",
+ "expo-constants": "~18.0.13"
},
"peerDependencies": {
"expo": "*",
@@ -5011,31 +6005,28 @@
}
},
"node_modules/expo-router": {
- "version": "55.0.7",
- "resolved": "https://registry.npmjs.org/expo-router/-/expo-router-55.0.7.tgz",
- "integrity": "sha512-UdraTi8/1LGCCEnq/3+wEVnM11b4ezFEIvMsWP9ajFvEhFGkcXlQitvSehT2yI5cbBrBaIMP2p/2naBiPyYVyw==",
+ "version": "6.0.23",
+ "resolved": "https://registry.npmjs.org/expo-router/-/expo-router-6.0.23.tgz",
+ "integrity": "sha512-qCxVAiCrCyu0npky6azEZ6dJDMt77OmCzEbpF6RbUTlfkaCA417LvY14SBkk0xyGruSxy/7pvJOI6tuThaUVCA==",
"license": "MIT",
"dependencies": {
- "@expo/metro-runtime": "^55.0.6",
- "@expo/schema-utils": "^55.0.2",
- "@radix-ui/react-slot": "^1.2.0",
+ "@expo/metro-runtime": "^6.1.2",
+ "@expo/schema-utils": "^0.1.8",
+ "@radix-ui/react-slot": "1.2.0",
"@radix-ui/react-tabs": "^1.1.12",
- "@react-navigation/bottom-tabs": "^7.15.5",
- "@react-navigation/native": "^7.1.33",
- "@react-navigation/native-stack": "^7.14.5",
+ "@react-navigation/bottom-tabs": "^7.4.0",
+ "@react-navigation/native": "^7.1.8",
+ "@react-navigation/native-stack": "^7.3.16",
"client-only": "^0.0.1",
"debug": "^4.3.4",
"escape-string-regexp": "^4.0.0",
- "expo-glass-effect": "^55.0.8",
- "expo-image": "^55.0.6",
- "expo-server": "^55.0.6",
- "expo-symbols": "^55.0.5",
+ "expo-server": "^1.0.5",
"fast-deep-equal": "^3.1.3",
"invariant": "^2.2.4",
"nanoid": "^3.3.8",
"query-string": "^7.1.3",
"react-fast-compare": "^3.2.2",
- "react-native-is-edge-to-edge": "^1.2.1",
+ "react-native-is-edge-to-edge": "^1.1.6",
"semver": "~7.6.3",
"server-only": "^0.0.1",
"sf-symbols-typescript": "^2.1.0",
@@ -5044,13 +6035,12 @@
"vaul": "^1.1.2"
},
"peerDependencies": {
- "@expo/log-box": "55.0.7",
- "@expo/metro-runtime": "^55.0.6",
- "@react-navigation/drawer": "^7.9.4",
- "@testing-library/react-native": ">= 13.2.0",
+ "@expo/metro-runtime": "^6.1.2",
+ "@react-navigation/drawer": "^7.5.0",
+ "@testing-library/react-native": ">= 12.0.0",
"expo": "*",
- "expo-constants": "^55.0.8",
- "expo-linking": "^55.0.8",
+ "expo-constants": "^18.0.13",
+ "expo-linking": "^8.0.11",
"react": "*",
"react-dom": "*",
"react-native": "*",
@@ -5085,60 +6075,6 @@
}
}
},
- "node_modules/expo-router/node_modules/@expo/metro-runtime": {
- "version": "55.0.6",
- "resolved": "https://registry.npmjs.org/@expo/metro-runtime/-/metro-runtime-55.0.6.tgz",
- "integrity": "sha512-l8VvgKN9md+URjeQDB+DnHVmvpcWI6zFLH6yv7GTv4sfRDKyaZ5zDXYjTP1phYdgW6ea2NrRtCGNIxylWhsgtg==",
- "license": "MIT",
- "dependencies": {
- "@expo/log-box": "55.0.7",
- "anser": "^1.4.9",
- "pretty-format": "^29.7.0",
- "stacktrace-parser": "^0.1.10",
- "whatwg-fetch": "^3.0.0"
- },
- "peerDependencies": {
- "expo": "*",
- "react": "*",
- "react-dom": "*",
- "react-native": "*"
- },
- "peerDependenciesMeta": {
- "react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/expo-router/node_modules/@radix-ui/react-tabs": {
- "version": "1.1.13",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz",
- "integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-direction": "1.1.1",
- "@radix-ui/react-id": "1.1.1",
- "@radix-ui/react-presence": "1.1.5",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-roving-focus": "1.1.11",
- "@radix-ui/react-use-controllable-state": "1.2.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
"node_modules/expo-router/node_modules/semver": {
"version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
@@ -5152,27 +6088,27 @@
}
},
"node_modules/expo-secure-store": {
- "version": "55.0.9",
- "resolved": "https://registry.npmjs.org/expo-secure-store/-/expo-secure-store-55.0.9.tgz",
- "integrity": "sha512-TIPGjM73LKlebpXwgAu/yL7lNWr6RQYmFw3vgYHOqLFYQMpsBqkQmopovbNX3c/0+RCE9KZlLAkcz8r6detILQ==",
+ "version": "15.0.8",
+ "resolved": "https://registry.npmjs.org/expo-secure-store/-/expo-secure-store-15.0.8.tgz",
+ "integrity": "sha512-lHnzvRajBu4u+P99+0GEMijQMFCOYpWRO4dWsXSuMt77+THPIGjzNvVKrGSl6mMrLsfVaKL8BpwYZLGlgA+zAw==",
"license": "MIT",
"peerDependencies": {
"expo": "*"
}
},
"node_modules/expo-server": {
- "version": "55.0.6",
- "resolved": "https://registry.npmjs.org/expo-server/-/expo-server-55.0.6.tgz",
- "integrity": "sha512-xI72FTm469FfuuBL2R5aNtthgH+GR7ygOpsx/KcPS0K8AZaZd7VjtEExbzn9/qyyYkWW3T+3dAmCDKOMX8gdmQ==",
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/expo-server/-/expo-server-1.0.5.tgz",
+ "integrity": "sha512-IGR++flYH70rhLyeXF0Phle56/k4cee87WeQ4mamS+MkVAVP+dDlOHf2nN06Z9Y2KhU0Gp1k+y61KkghF7HdhA==",
"license": "MIT",
"engines": {
"node": ">=20.16.0"
}
},
"node_modules/expo-status-bar": {
- "version": "55.0.4",
- "resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-55.0.4.tgz",
- "integrity": "sha512-BPDjUXKqv1F9j2YNGLRZfkBEZXIEEpqj+t81y4c+4fdSN3Pos7goIHXgcl2ozbKQLgKRZQyNZQtbUgh5UjHYUQ==",
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-3.0.9.tgz",
+ "integrity": "sha512-xyYyVg6V1/SSOZWh4Ni3U129XHCnFHBTcUo0dhWtFDrZbNp/duw5AGsQfb2sVeU0gxWHXSY1+5F0jnKYC7WuOw==",
"license": "MIT",
"dependencies": {
"react-native-is-edge-to-edge": "^1.2.1"
@@ -5183,43 +6119,27 @@
}
},
"node_modules/expo-structured-headers": {
- "version": "55.0.0",
- "resolved": "https://registry.npmjs.org/expo-structured-headers/-/expo-structured-headers-55.0.0.tgz",
- "integrity": "sha512-udaNvuWb45/Sryq9FLC/blwgOChhznuqlTrUzVjC0T83pMdcmscKJX23lnNDW6hCec8p81Y3z1DIFwIyk0g/PQ==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/expo-structured-headers/-/expo-structured-headers-5.0.0.tgz",
+ "integrity": "sha512-RmrBtnSphk5REmZGV+lcdgdpxyzio5rJw8CXviHE6qH5pKQQ83fhMEcigvrkBdsn2Efw2EODp4Yxl1/fqMvOZw==",
"license": "MIT"
},
- "node_modules/expo-symbols": {
- "version": "55.0.5",
- "resolved": "https://registry.npmjs.org/expo-symbols/-/expo-symbols-55.0.5.tgz",
- "integrity": "sha512-W/QYRvnYVes947ZYOHtuKL8Gobs7BUjeu9oknzbo4jGnou7Ks6bj1CwdT0ZWNBgaTopbS4/POXumJIkW4cTPSQ==",
- "license": "MIT",
- "dependencies": {
- "@expo-google-fonts/material-symbols": "^0.4.1",
- "sf-symbols-typescript": "^2.0.0"
- },
- "peerDependencies": {
- "expo": "*",
- "expo-font": "*",
- "react": "*",
- "react-native": "*"
- }
- },
"node_modules/expo-updates": {
- "version": "55.0.15",
- "resolved": "https://registry.npmjs.org/expo-updates/-/expo-updates-55.0.15.tgz",
- "integrity": "sha512-UE9Ik56trq//kNeJ/BlC5vOTYdNTvsHwhfWFYMazP1UOQK4lnX59/t0qz8Ut+3aPXZZT7+B6mnbWtic0QqN1wA==",
+ "version": "29.0.16",
+ "resolved": "https://registry.npmjs.org/expo-updates/-/expo-updates-29.0.16.tgz",
+ "integrity": "sha512-E9/fxRz/Eurtc7hxeI/6ZPyHH3To9Xoccm1kXoICZTRojmuTo+dx0Xv53UHyHn4G5zGMezyaKF2Qtj3AKcT93w==",
"license": "MIT",
"dependencies": {
"@expo/code-signing-certificates": "^0.0.6",
- "@expo/plist": "^0.5.2",
+ "@expo/plist": "^0.4.8",
"@expo/spawn-async": "^1.7.2",
- "arg": "^4.1.0",
+ "arg": "4.1.0",
"chalk": "^4.1.2",
"debug": "^4.3.4",
- "expo-eas-client": "~55.0.2",
- "expo-manifests": "~55.0.11",
- "expo-structured-headers": "~55.0.0",
- "expo-updates-interface": "~55.1.3",
+ "expo-eas-client": "~1.0.8",
+ "expo-manifests": "~1.0.10",
+ "expo-structured-headers": "~5.0.0",
+ "expo-updates-interface": "~2.0.0",
"getenv": "^2.0.0",
"glob": "^13.0.0",
"ignore": "^5.3.1",
@@ -5235,292 +6155,20 @@
}
},
"node_modules/expo-updates-interface": {
- "version": "55.1.3",
- "resolved": "https://registry.npmjs.org/expo-updates-interface/-/expo-updates-interface-55.1.3.tgz",
- "integrity": "sha512-UVVIiZqymQZJL+o/jh65kXOI97xdkbqBJJM0LMabaPMNLFnc6/WvOMOzmQs7SPyKb8+0PeBaFd7tj5DzF6JeQg==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/expo-updates-interface/-/expo-updates-interface-2.0.0.tgz",
+ "integrity": "sha512-pTzAIufEZdVPKql6iMi5ylVSPqV1qbEopz9G6TSECQmnNde2nwq42PxdFBaUEd8IZJ/fdJLQnOT3m6+XJ5s7jg==",
"license": "MIT",
"peerDependencies": {
"expo": "*"
}
},
"node_modules/expo-updates/node_modules/arg": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
- "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz",
+ "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==",
"license": "MIT"
},
- "node_modules/expo/node_modules/@expo/cli": {
- "version": "55.0.18",
- "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-55.0.18.tgz",
- "integrity": "sha512-3sJwu8KvCvQIXBnhUlHgLBZBe+ZK4Da9R5rgI4znaowJavYWMqzRClLzyE6Kri66WVoMX7Q4HUVIh8prRlO0XA==",
- "license": "MIT",
- "dependencies": {
- "@expo/code-signing-certificates": "^0.0.6",
- "@expo/config": "~55.0.10",
- "@expo/config-plugins": "~55.0.7",
- "@expo/devcert": "^1.2.1",
- "@expo/env": "~2.1.1",
- "@expo/image-utils": "^0.8.12",
- "@expo/json-file": "^10.0.12",
- "@expo/log-box": "55.0.7",
- "@expo/metro": "~54.2.0",
- "@expo/metro-config": "~55.0.11",
- "@expo/osascript": "^2.4.2",
- "@expo/package-manager": "^1.10.3",
- "@expo/plist": "^0.5.2",
- "@expo/prebuild-config": "^55.0.10",
- "@expo/require-utils": "^55.0.3",
- "@expo/router-server": "^55.0.11",
- "@expo/schema-utils": "^55.0.2",
- "@expo/spawn-async": "^1.7.2",
- "@expo/ws-tunnel": "^1.0.1",
- "@expo/xcpretty": "^4.4.0",
- "@react-native/dev-middleware": "0.83.2",
- "accepts": "^1.3.8",
- "arg": "^5.0.2",
- "better-opn": "~3.0.2",
- "bplist-creator": "0.1.0",
- "bplist-parser": "^0.3.1",
- "chalk": "^4.0.0",
- "ci-info": "^3.3.0",
- "compression": "^1.7.4",
- "connect": "^3.7.0",
- "debug": "^4.3.4",
- "dnssd-advertise": "^1.1.3",
- "expo-server": "^55.0.6",
- "fetch-nodeshim": "^0.4.6",
- "getenv": "^2.0.0",
- "glob": "^13.0.0",
- "lan-network": "^0.2.0",
- "multitars": "^0.2.3",
- "node-forge": "^1.3.3",
- "npm-package-arg": "^11.0.0",
- "ora": "^3.4.0",
- "picomatch": "^4.0.3",
- "pretty-format": "^29.7.0",
- "progress": "^2.0.3",
- "prompts": "^2.3.2",
- "resolve-from": "^5.0.0",
- "semver": "^7.6.0",
- "send": "^0.19.0",
- "slugify": "^1.3.4",
- "source-map-support": "~0.5.21",
- "stacktrace-parser": "^0.1.10",
- "structured-headers": "^0.4.1",
- "terminal-link": "^2.1.1",
- "toqr": "^0.1.1",
- "wrap-ansi": "^7.0.0",
- "ws": "^8.12.1",
- "zod": "^3.25.76"
- },
- "bin": {
- "expo-internal": "build/bin/cli"
- },
- "peerDependencies": {
- "expo": "*",
- "expo-router": "*",
- "react-native": "*"
- },
- "peerDependenciesMeta": {
- "expo-router": {
- "optional": true
- },
- "react-native": {
- "optional": true
- }
- }
- },
- "node_modules/expo/node_modules/@expo/cli/node_modules/@expo/router-server": {
- "version": "55.0.11",
- "resolved": "https://registry.npmjs.org/@expo/router-server/-/router-server-55.0.11.tgz",
- "integrity": "sha512-Kd8J1OOlFR00DZxn+1KfiQiXZtRut6cj8+ynqHJa7dtt/lTL4tGkYistqmVhpKJ6w886eRY5WivKy7o0ZBFkJA==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.3.4"
- },
- "peerDependencies": {
- "@expo/metro-runtime": "^55.0.6",
- "expo": "*",
- "expo-constants": "^55.0.9",
- "expo-font": "^55.0.4",
- "expo-router": "*",
- "expo-server": "^55.0.6",
- "react": "*",
- "react-dom": "*",
- "react-server-dom-webpack": "~19.0.1 || ~19.1.2 || ~19.2.1"
- },
- "peerDependenciesMeta": {
- "@expo/metro-runtime": {
- "optional": true
- },
- "expo-router": {
- "optional": true
- },
- "react-dom": {
- "optional": true
- },
- "react-server-dom-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/expo/node_modules/@expo/metro-config": {
- "version": "55.0.11",
- "resolved": "https://registry.npmjs.org/@expo/metro-config/-/metro-config-55.0.11.tgz",
- "integrity": "sha512-qGxq7RwWpj0zNvZO/e5aizKrOKYYBrVPShSbxPOVB1EXcexxTPTxnOe4pYFg/gKkLIJe0t3jSSF8IDWlGdaaOg==",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.20.0",
- "@babel/core": "^7.20.0",
- "@babel/generator": "^7.20.5",
- "@expo/config": "~55.0.10",
- "@expo/env": "~2.1.1",
- "@expo/json-file": "~10.0.12",
- "@expo/metro": "~54.2.0",
- "@expo/spawn-async": "^1.7.2",
- "browserslist": "^4.25.0",
- "chalk": "^4.1.0",
- "debug": "^4.3.2",
- "getenv": "^2.0.0",
- "glob": "^13.0.0",
- "hermes-parser": "^0.32.0",
- "jsc-safe-url": "^0.2.4",
- "lightningcss": "^1.30.1",
- "picomatch": "^4.0.3",
- "postcss": "~8.4.32",
- "resolve-from": "^5.0.0"
- },
- "peerDependencies": {
- "expo": "*"
- },
- "peerDependenciesMeta": {
- "expo": {
- "optional": true
- }
- }
- },
- "node_modules/expo/node_modules/@expo/vector-icons": {
- "version": "15.1.1",
- "resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-15.1.1.tgz",
- "integrity": "sha512-Iu2VkcoI5vygbtYngm7jb4ifxElNVXQYdDrYkT7UCEIiKLeWnQY0wf2ZhHZ+Wro6Sc5TaumpKUOqDRpLi5rkvw==",
- "license": "MIT",
- "peerDependencies": {
- "expo-font": ">=14.0.4",
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/expo/node_modules/ci-info": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
- "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/sibiraj-s"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/expo/node_modules/expo-asset": {
- "version": "55.0.10",
- "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-55.0.10.tgz",
- "integrity": "sha512-wxjNBKIaDyachq7oJgVlWVFzZ6SnNpJFJhkkcymXoTPt5O3XmDM+a6fT91xQQawCXTyZuCc1sNxKMetEofeYkg==",
- "license": "MIT",
- "dependencies": {
- "@expo/image-utils": "^0.8.12",
- "expo-constants": "~55.0.9"
- },
- "peerDependencies": {
- "expo": "*",
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/expo/node_modules/expo-file-system": {
- "version": "55.0.11",
- "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-55.0.11.tgz",
- "integrity": "sha512-KMUd6OY375J9WD79ZvjvCDZMveT7YfgiGWdi58/gfuTBsr14TRuoPk8RRQHAtc4UquzWViKcHwna9aPY7/XPpw==",
- "license": "MIT",
- "peerDependencies": {
- "expo": "*",
- "react-native": "*"
- }
- },
- "node_modules/expo/node_modules/expo-keep-awake": {
- "version": "55.0.4",
- "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-55.0.4.tgz",
- "integrity": "sha512-vwfdMtMS5Fxaon8gC0AiE70SpxTsHJ+rjeoVJl8kdfdbxczF7OIaVmfjFJ5Gfigd/WZiLqxhfZk34VAkXF4PNg==",
- "license": "MIT",
- "peerDependencies": {
- "expo": "*",
- "react": "*"
- }
- },
- "node_modules/expo/node_modules/picomatch": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
- "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/expo/node_modules/postcss": {
- "version": "8.4.49",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
- "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "nanoid": "^3.3.7",
- "picocolors": "^1.1.1",
- "source-map-js": "^1.2.1"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/expo/node_modules/ws": {
- "version": "8.20.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz",
- "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==",
- "license": "MIT",
- "engines": {
- "node": ">=10.0.0"
- },
- "peerDependencies": {
- "bufferutil": "^4.0.1",
- "utf-8-validate": ">=5.0.2"
- },
- "peerDependenciesMeta": {
- "bufferutil": {
- "optional": true
- },
- "utf-8-validate": {
- "optional": true
- }
- }
- },
"node_modules/exponential-backoff": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz",
@@ -5579,18 +6227,6 @@
"reusify": "^1.0.4"
}
},
- "node_modules/fb-dotslash": {
- "version": "0.5.8",
- "resolved": "https://registry.npmjs.org/fb-dotslash/-/fb-dotslash-0.5.8.tgz",
- "integrity": "sha512-XHYLKk9J4BupDxi9bSEhkfss0m+Vr9ChTrjhf9l2iw3jB5C7BnY4GVPoMcqbrTutsKJso6yj2nAB6BI/F2oZaA==",
- "license": "(MIT OR Apache-2.0)",
- "bin": {
- "dotslash": "bin/dotslash"
- },
- "engines": {
- "node": ">=20"
- }
- },
"node_modules/fb-watchman": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
@@ -5600,12 +6236,6 @@
"bser": "2.1.1"
}
},
- "node_modules/fetch-nodeshim": {
- "version": "0.4.9",
- "resolved": "https://registry.npmjs.org/fetch-nodeshim/-/fetch-nodeshim-0.4.9.tgz",
- "integrity": "sha512-XIQWlB2A4RZ7NebXWGxS0uDMdvRHkiUDTghBVJKFg9yEOd45w/PP8cZANuPf2H08W6Cor3+2n7Q6TTZgAS3Fkw==",
- "license": "MIT"
- },
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
@@ -5705,6 +6335,21 @@
"integrity": "sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg==",
"license": "BSD-2-Clause"
},
+ "node_modules/for-each": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+ "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/form-data": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
@@ -5721,6 +6366,15 @@
"node": ">= 6"
}
},
+ "node_modules/freeport-async": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/freeport-async/-/freeport-async-2.0.0.tgz",
+ "integrity": "sha512-K7od3Uw45AJg00XUmy15+Hae2hOcgKcmN3/EF6Y7i01O0gaqiRx8sUSpsb9+BRNL8RPBrhzPsVfy8q9ADlJuWQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
@@ -5759,6 +6413,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/generator-function": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
+ "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
@@ -5887,6 +6550,42 @@
"node": ">=10.13.0"
}
},
+ "node_modules/glob/node_modules/balanced-match": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
+ "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "license": "MIT",
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/glob/node_modules/brace-expansion": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz",
+ "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/glob/node_modules/minimatch": {
+ "version": "10.2.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
+ "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "brace-expansion": "^5.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@@ -5940,6 +6639,18 @@
"node": ">=8"
}
},
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
@@ -5979,27 +6690,6 @@
"node": ">= 0.4"
}
},
- "node_modules/hermes-compiler": {
- "version": "0.14.1",
- "resolved": "https://registry.npmjs.org/hermes-compiler/-/hermes-compiler-0.14.1.tgz",
- "integrity": "sha512-+RPPQlayoZ9n6/KXKt5SFILWXCGJ/LV5d24L5smXrvTDrPS4L6dSctPczXauuvzFP3QEJbD1YO7Z3Ra4a+4IhA==",
- "license": "MIT"
- },
- "node_modules/hermes-estree": {
- "version": "0.32.0",
- "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.32.0.tgz",
- "integrity": "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ==",
- "license": "MIT"
- },
- "node_modules/hermes-parser": {
- "version": "0.32.0",
- "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.32.0.tgz",
- "integrity": "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw==",
- "license": "MIT",
- "dependencies": {
- "hermes-estree": "0.32.0"
- }
- },
"node_modules/hosted-git-info": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz",
@@ -6081,6 +6771,26 @@
"node": ">= 14"
}
},
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -6131,6 +6841,12 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
+ "node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "license": "ISC"
+ },
"node_modules/invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
@@ -6140,6 +6856,22 @@
"loose-envify": "^1.0.0"
}
},
+ "node_modules/is-arguments": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz",
+ "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-arrayish": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz",
@@ -6159,6 +6891,18 @@
"node": ">=8"
}
},
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-core-module": {
"version": "2.16.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
@@ -6208,6 +6952,25 @@
"node": ">=8"
}
},
+ "node_modules/is-generator-function": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz",
+ "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.4",
+ "generator-function": "^2.0.0",
+ "get-proto": "^1.0.1",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@@ -6221,6 +6984,22 @@
"node": ">=0.10.0"
}
},
+ "node_modules/is-nan": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz",
+ "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.0",
+ "define-properties": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -6239,6 +7018,39 @@
"node": ">=8"
}
},
+ "node_modules/is-regex": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
+ "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
+ "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
+ "license": "MIT",
+ "dependencies": {
+ "which-typed-array": "^1.1.16"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-wsl": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
@@ -6402,21 +7214,6 @@
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/jest-util/node_modules/ci-info": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
- "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/sibiraj-s"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/jest-validate": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
@@ -6556,9 +7353,9 @@
}
},
"node_modules/lan-network": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/lan-network/-/lan-network-0.2.0.tgz",
- "integrity": "sha512-EZgbsXMrGS+oK+Ta12mCjzBFse+SIewGdwrSTr5g+MSymnjpox2x05ceI20PQejJOFvOgzcXrfDk/SdY7dSCtw==",
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/lan-network/-/lan-network-0.1.7.tgz",
+ "integrity": "sha512-mnIlAEMu4OyEvUNdzco9xpuB9YVcPkQec+QsgycBCtPZvEqWPCDPfbAE4OJMdBBWpZWtpCn1xw9jJYlwjWI5zQ==",
"license": "MIT",
"bin": {
"lan-network": "dist/lan-network-cli.js"
@@ -6864,7 +7661,6 @@
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
- "dev": true,
"license": "MIT"
},
"node_modules/locate-path": {
@@ -7029,6 +7825,12 @@
"node": ">= 0.4"
}
},
+ "node_modules/mdn-data": {
+ "version": "2.0.14",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
+ "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==",
+ "license": "CC0-1.0"
+ },
"node_modules/memoize-one": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
@@ -7132,6 +7934,21 @@
"node": ">=20.19.4"
}
},
+ "node_modules/metro-babel-transformer/node_modules/hermes-estree": {
+ "version": "0.32.0",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.32.0.tgz",
+ "integrity": "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ==",
+ "license": "MIT"
+ },
+ "node_modules/metro-babel-transformer/node_modules/hermes-parser": {
+ "version": "0.32.0",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.32.0.tgz",
+ "integrity": "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw==",
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.32.0"
+ }
+ },
"node_modules/metro-cache": {
"version": "0.83.3",
"resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.83.3.tgz",
@@ -7332,6 +8149,48 @@
"node": ">=20.19.4"
}
},
+ "node_modules/metro/node_modules/ci-info": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
+ "license": "MIT"
+ },
+ "node_modules/metro/node_modules/hermes-estree": {
+ "version": "0.32.0",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.32.0.tgz",
+ "integrity": "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ==",
+ "license": "MIT"
+ },
+ "node_modules/metro/node_modules/hermes-parser": {
+ "version": "0.32.0",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.32.0.tgz",
+ "integrity": "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw==",
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.32.0"
+ }
+ },
+ "node_modules/metro/node_modules/ws": {
+ "version": "7.5.10",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
+ "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.3.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": "^5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
"node_modules/micromatch": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
@@ -7378,15 +8237,6 @@
"node": ">= 0.6"
}
},
- "node_modules/mimic-fn": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
- "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/mimic-response": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
@@ -7398,18 +8248,24 @@
}
},
"node_modules/minimatch": {
- "version": "10.2.4",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
- "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
- "license": "BlueOak-1.0.0",
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+ "license": "ISC",
"dependencies": {
- "brace-expansion": "^5.0.2"
+ "brace-expansion": "^1.1.7"
},
"engines": {
- "node": "18 || 20 || >=22"
- },
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "license": "MIT",
"funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/minipass": {
@@ -7421,6 +8277,18 @@
"node": ">=16 || 14 >=14.17"
}
},
+ "node_modules/minizlib": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz",
+ "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==",
+ "license": "MIT",
+ "dependencies": {
+ "minipass": "^7.1.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
"node_modules/mkdirp": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
@@ -7439,17 +8307,10 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
- "node_modules/multitars": {
- "version": "0.2.4",
- "resolved": "https://registry.npmjs.org/multitars/-/multitars-0.2.4.tgz",
- "integrity": "sha512-XgLbg1HHchFauMCQPRwMj6MSyDd5koPlTA1hM3rUFkeXzGpjU/I9fP3to7yrObE9jcN8ChIOQGrM0tV0kUZaKg==",
- "license": "MIT"
- },
"node_modules/mz": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
- "dev": true,
"license": "MIT",
"dependencies": {
"any-promise": "^1.0.0",
@@ -7501,6 +8362,12 @@
"node": ">= 0.6"
}
},
+ "node_modules/nested-error-stacks": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.0.1.tgz",
+ "integrity": "sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A==",
+ "license": "MIT"
+ },
"node_modules/node-forge": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.3.tgz",
@@ -7559,6 +8426,18 @@
"node": "^16.14.0 || >=18.0.0"
}
},
+ "node_modules/nth-check": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
+ }
+ },
"node_modules/nullthrows": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz",
@@ -7581,7 +8460,6 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -7597,6 +8475,51 @@
"node": ">= 6"
}
},
+ "node_modules/object-is": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
+ "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
+ "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0",
+ "has-symbols": "^1.1.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
@@ -7627,18 +8550,6 @@
"wrappy": "1"
}
},
- "node_modules/onetime": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
- "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==",
- "license": "MIT",
- "dependencies": {
- "mimic-fn": "^1.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/open": {
"version": "7.4.2",
"resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
@@ -7949,6 +8860,15 @@
"node": ">=4.0.0"
}
},
+ "node_modules/possible-typed-array-names": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
+ "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/postcss": {
"version": "8.5.8",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
@@ -8112,6 +9032,18 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/pretty-bytes": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
+ "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/pretty-format": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
@@ -8201,6 +9133,23 @@
"once": "^1.3.1"
}
},
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/qrcode-terminal": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.11.0.tgz",
+ "integrity": "sha512-Uu7ii+FQy4Qf82G4xu7ShHhjhGahEpCWc3x8UavY3CTcWV+ufmmCtwkr7ZKsX42jdL0kr1B5FKUeqJvAn51jzQ==",
+ "bin": {
+ "qrcode-terminal": "bin/qrcode-terminal.js"
+ }
+ },
"node_modules/query-string": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz",
@@ -8271,10 +9220,25 @@
"node": ">= 0.6"
}
},
+ "node_modules/rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
+ "dependencies": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "bin": {
+ "rc": "cli.js"
+ }
+ },
"node_modules/react": {
- "version": "19.2.0",
- "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
- "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==",
+ "version": "19.1.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
+ "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -8290,6 +9254,27 @@
"ws": "^7"
}
},
+ "node_modules/react-devtools-core/node_modules/ws": {
+ "version": "7.5.10",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
+ "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.3.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": "^5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
"node_modules/react-fast-compare": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
@@ -8315,45 +9300,44 @@
"license": "MIT"
},
"node_modules/react-native": {
- "version": "0.83.2",
- "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.83.2.tgz",
- "integrity": "sha512-ZDma3SLkRN2U2dg0/EZqxNBAx4of/oTnPjXAQi299VLq2gdnbZowGy9hzqv+O7sTA62g+lM1v+2FM5DUnJ/6hg==",
+ "version": "0.81.5",
+ "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.81.5.tgz",
+ "integrity": "sha512-1w+/oSjEXZjMqsIvmkCRsOc8UBYv163bTWKTI8+1mxztvQPhCRYGTvZ/PL1w16xXHneIj/SLGfxWg2GWN2uexw==",
"license": "MIT",
"dependencies": {
"@jest/create-cache-key-function": "^29.7.0",
- "@react-native/assets-registry": "0.83.2",
- "@react-native/codegen": "0.83.2",
- "@react-native/community-cli-plugin": "0.83.2",
- "@react-native/gradle-plugin": "0.83.2",
- "@react-native/js-polyfills": "0.83.2",
- "@react-native/normalize-colors": "0.83.2",
- "@react-native/virtualized-lists": "0.83.2",
+ "@react-native/assets-registry": "0.81.5",
+ "@react-native/codegen": "0.81.5",
+ "@react-native/community-cli-plugin": "0.81.5",
+ "@react-native/gradle-plugin": "0.81.5",
+ "@react-native/js-polyfills": "0.81.5",
+ "@react-native/normalize-colors": "0.81.5",
+ "@react-native/virtualized-lists": "0.81.5",
"abort-controller": "^3.0.0",
"anser": "^1.4.9",
"ansi-regex": "^5.0.0",
"babel-jest": "^29.7.0",
- "babel-plugin-syntax-hermes-parser": "0.32.0",
+ "babel-plugin-syntax-hermes-parser": "0.29.1",
"base64-js": "^1.5.1",
"commander": "^12.0.0",
"flow-enums-runtime": "^0.0.6",
"glob": "^7.1.1",
- "hermes-compiler": "0.14.1",
"invariant": "^2.2.4",
"jest-environment-node": "^29.7.0",
"memoize-one": "^5.0.0",
- "metro-runtime": "^0.83.3",
- "metro-source-map": "^0.83.3",
+ "metro-runtime": "^0.83.1",
+ "metro-source-map": "^0.83.1",
"nullthrows": "^1.1.1",
"pretty-format": "^29.7.0",
"promise": "^8.3.0",
"react-devtools-core": "^6.1.5",
"react-refresh": "^0.14.0",
"regenerator-runtime": "^0.13.2",
- "scheduler": "0.27.0",
+ "scheduler": "0.26.0",
"semver": "^7.1.3",
"stacktrace-parser": "^0.1.10",
"whatwg-fetch": "^3.0.0",
- "ws": "^7.5.10",
+ "ws": "^6.2.3",
"yargs": "^17.6.2"
},
"bin": {
@@ -8363,8 +9347,8 @@
"node": ">= 20.19.4"
},
"peerDependencies": {
- "@types/react": "^19.1.1",
- "react": "^19.2.0"
+ "@types/react": "^19.1.0",
+ "react": "^19.1.0"
},
"peerDependenciesMeta": {
"@types/react": {
@@ -8414,40 +9398,18 @@
}
},
"node_modules/react-native-reanimated": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-4.2.1.tgz",
- "integrity": "sha512-/NcHnZMyOvsD/wYXug/YqSKw90P9edN0kEPL5lP4PFf1aQ4F1V7MKe/E0tvfkXKIajy3Qocp5EiEnlcrK/+BZg==",
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-4.1.7.tgz",
+ "integrity": "sha512-Q4H6xA3Tn7QL0/E/KjI86I1KK4tcf+ErRE04LH34Etka2oVQhW6oXQ+Q8ZcDCVxiWp5vgbBH6XcH8BOo4w/Rhg==",
"license": "MIT",
"dependencies": {
- "react-native-is-edge-to-edge": "1.2.1",
- "semver": "7.7.3"
+ "react-native-is-edge-to-edge": "^1.2.1",
+ "semver": "^7.7.2"
},
"peerDependencies": {
"react": "*",
- "react-native": "*",
- "react-native-worklets": ">=0.7.0"
- }
- },
- "node_modules/react-native-reanimated/node_modules/react-native-is-edge-to-edge": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.2.1.tgz",
- "integrity": "sha512-FLbPWl/MyYQWz+KwqOZsSyj2JmLKglHatd3xLZWskXOpRaio4LfEDEz8E/A6uD8QoTHW6Aobw1jbEwK7KMgR7Q==",
- "license": "MIT",
- "peerDependencies": {
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/react-native-reanimated/node_modules/semver": {
- "version": "7.7.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
- "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
+ "react-native": "0.78 - 0.82",
+ "react-native-worklets": "0.5 - 0.8"
}
},
"node_modules/react-native-safe-area-context": {
@@ -8461,12 +9423,13 @@
}
},
"node_modules/react-native-screens": {
- "version": "4.23.0",
- "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.23.0.tgz",
- "integrity": "sha512-XhO3aK0UeLpBn4kLecd+J+EDeRRJlI/Ro9Fze06vo1q163VeYtzfU9QS09/VyDFMWR1qxDC1iazCArTPSFFiPw==",
+ "version": "4.16.0",
+ "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.16.0.tgz",
+ "integrity": "sha512-yIAyh7F/9uWkOzCi1/2FqvNvK6Wb9Y1+Kzn16SuGfN9YFJDTbwlzGRvePCNTOX0recpLQF3kc2FmvMUhyTCH1Q==",
"license": "MIT",
"dependencies": {
"react-freeze": "^1.0.0",
+ "react-native-is-edge-to-edge": "^1.2.1",
"warn-once": "^0.1.0"
},
"peerDependencies": {
@@ -8474,195 +9437,44 @@
"react-native": "*"
}
},
- "node_modules/react-native-worklets": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/react-native-worklets/-/react-native-worklets-0.7.2.tgz",
- "integrity": "sha512-DuLu1kMV/Uyl9pQHp3hehAlThoLw7Yk2FwRTpzASOmI+cd4845FWn3m2bk9MnjUw8FBRIyhwLqYm2AJaXDXsog==",
+ "node_modules/react-native-svg": {
+ "version": "15.15.4",
+ "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.15.4.tgz",
+ "integrity": "sha512-boT/vIRgj6zZKBpfTPJJiYWMbZE9duBMOwPK6kCSTgxsS947IFMOq9OgIFkpWZTB7t229H24pDRkh3W9ZK/J1A==",
"license": "MIT",
"dependencies": {
- "@babel/plugin-transform-arrow-functions": "7.27.1",
- "@babel/plugin-transform-class-properties": "7.27.1",
- "@babel/plugin-transform-classes": "7.28.4",
- "@babel/plugin-transform-nullish-coalescing-operator": "7.27.1",
- "@babel/plugin-transform-optional-chaining": "7.27.1",
- "@babel/plugin-transform-shorthand-properties": "7.27.1",
- "@babel/plugin-transform-template-literals": "7.27.1",
- "@babel/plugin-transform-unicode-regex": "7.27.1",
- "@babel/preset-typescript": "7.27.1",
- "convert-source-map": "2.0.0",
- "semver": "7.7.3"
+ "css-select": "^5.1.0",
+ "css-tree": "^1.1.3",
+ "warn-once": "0.1.1"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/react-native-worklets": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/react-native-worklets/-/react-native-worklets-0.8.1.tgz",
+ "integrity": "sha512-oWP/lStsAHU6oYCaWDXrda/wOHVdhusQJz1e6x9gPnXdFf4ndNDAOtWCmk2zGrAnlapfyA3rM6PCQq94mPg9cw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/plugin-transform-arrow-functions": "^7.27.1",
+ "@babel/plugin-transform-class-properties": "^7.27.1",
+ "@babel/plugin-transform-classes": "^7.28.4",
+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1",
+ "@babel/plugin-transform-optional-chaining": "^7.27.1",
+ "@babel/plugin-transform-shorthand-properties": "^7.27.1",
+ "@babel/plugin-transform-template-literals": "^7.27.1",
+ "@babel/plugin-transform-unicode-regex": "^7.27.1",
+ "@babel/preset-typescript": "^7.27.1",
+ "convert-source-map": "^2.0.0",
+ "semver": "^7.7.3"
},
"peerDependencies": {
"@babel/core": "*",
+ "@react-native/metro-config": "*",
"react": "*",
- "react-native": "*"
- }
- },
- "node_modules/react-native-worklets/node_modules/@babel/plugin-transform-class-properties": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz",
- "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.27.1",
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/react-native-worklets/node_modules/@babel/plugin-transform-classes": {
- "version": "7.28.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz",
- "integrity": "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.27.3",
- "@babel/helper-compilation-targets": "^7.27.2",
- "@babel/helper-globals": "^7.28.0",
- "@babel/helper-plugin-utils": "^7.27.1",
- "@babel/helper-replace-supers": "^7.27.1",
- "@babel/traverse": "^7.28.4"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/react-native-worklets/node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz",
- "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/react-native-worklets/node_modules/@babel/plugin-transform-optional-chaining": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz",
- "integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/react-native-worklets/node_modules/@babel/preset-typescript": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.1.tgz",
- "integrity": "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1",
- "@babel/helper-validator-option": "^7.27.1",
- "@babel/plugin-syntax-jsx": "^7.27.1",
- "@babel/plugin-transform-modules-commonjs": "^7.27.1",
- "@babel/plugin-transform-typescript": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/react-native-worklets/node_modules/semver": {
- "version": "7.7.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
- "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/react-native/node_modules/@react-native/codegen": {
- "version": "0.83.2",
- "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.83.2.tgz",
- "integrity": "sha512-9uK6X1miCXqtL4c759l74N/XbQeneWeQVjoV7SD2CGJuW7ZefxaoYenwGPs7rMoCdtS6wuIyR3hXQ+uWEBGYXA==",
- "license": "MIT",
- "dependencies": {
- "@babel/core": "^7.25.2",
- "@babel/parser": "^7.25.3",
- "glob": "^7.1.1",
- "hermes-parser": "0.32.0",
- "invariant": "^2.2.4",
- "nullthrows": "^1.1.1",
- "yargs": "^17.6.2"
- },
- "engines": {
- "node": ">= 20.19.4"
- },
- "peerDependencies": {
- "@babel/core": "*"
- }
- },
- "node_modules/react-native/node_modules/@react-native/js-polyfills": {
- "version": "0.83.2",
- "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.83.2.tgz",
- "integrity": "sha512-dk6fIY2OrKW/2Nk2HydfYNrQau8g6LOtd7NVBrgaqa+lvuRyIML5iimShP5qPqQnx2ofHuzjFw+Ya0b5Q7nDbA==",
- "license": "MIT",
- "engines": {
- "node": ">= 20.19.4"
- }
- },
- "node_modules/react-native/node_modules/@react-native/virtualized-lists": {
- "version": "0.83.2",
- "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.83.2.tgz",
- "integrity": "sha512-N7mRjHLW/+KWxMp9IHRWyE3VIkeG1m3PnZJAGEFLCN8VFb7e4VfI567o7tE/HYcdcXCylw+Eqhlciz8gDeQ71g==",
- "license": "MIT",
- "dependencies": {
- "invariant": "^2.2.4",
- "nullthrows": "^1.1.1"
- },
- "engines": {
- "node": ">= 20.19.4"
- },
- "peerDependencies": {
- "@types/react": "^19.2.0",
- "react": "*",
- "react-native": "*"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/react-native/node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "license": "MIT"
- },
- "node_modules/react-native/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "react-native": "0.81 - 0.85"
}
},
"node_modules/react-native/node_modules/commander": {
@@ -8695,16 +9507,13 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/react-native/node_modules/minimatch": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
- "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
- "license": "ISC",
+ "node_modules/react-native/node_modules/ws": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz",
+ "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==",
+ "license": "MIT",
"dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
+ "async-limiter": "~1.0.0"
}
},
"node_modules/react-refresh": {
@@ -8876,6 +9685,37 @@
"node": ">=0.10.0"
}
},
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/requireg": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/requireg/-/requireg-0.2.2.tgz",
+ "integrity": "sha512-nYzyjnFcPNGR3lx9lwPPPnuQxv6JWEZd2Ci0u9opN7N5zUEPIhY/GbL3vMGOr2UXwEg9WwSyV9X9Y/kLFgPsOg==",
+ "dependencies": {
+ "nested-error-stacks": "~2.0.1",
+ "rc": "~1.2.7",
+ "resolve": "~1.7.1"
+ },
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/requireg/node_modules/resolve": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz",
+ "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==",
+ "license": "MIT",
+ "dependencies": {
+ "path-parse": "^1.0.5"
+ }
+ },
"node_modules/resolve": {
"version": "1.22.11",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
@@ -8918,6 +9758,15 @@
"integrity": "sha512-nR23LHAvaI6aHtMg6RWoaHpdR4D881Nydkzi2CixINyg9T00KgaJdJI6Vwty+Ps8WLxZHuxsS0BseWjxSA4C+w==",
"license": "MIT"
},
+ "node_modules/resolve.exports": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz",
+ "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/responselike": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz",
@@ -8944,6 +9793,27 @@
"node": ">=4"
}
},
+ "node_modules/restore-cursor/node_modules/mimic-fn": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/restore-cursor/node_modules/onetime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+ "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==",
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/reusify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
@@ -8971,22 +9841,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/rimraf/node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "license": "MIT"
- },
- "node_modules/rimraf/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
"node_modules/rimraf/node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -9008,18 +9862,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/rimraf/node_modules/minimatch": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
- "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -9064,6 +9906,23 @@
],
"license": "MIT"
},
+ "node_modules/safe-regex-test": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
+ "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-regex": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/sax": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz",
@@ -9074,9 +9933,9 @@
}
},
"node_modules/scheduler": {
- "version": "0.27.0",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
- "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
+ "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
"license": "MIT"
},
"node_modules/semver": {
@@ -9199,6 +10058,23 @@
"integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==",
"license": "MIT"
},
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
@@ -9270,6 +10146,18 @@
"plist": "^3.0.5"
}
},
+ "node_modules/simple-plist/node_modules/bplist-parser": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz",
+ "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==",
+ "license": "MIT",
+ "dependencies": {
+ "big-integer": "1.6.x"
+ },
+ "engines": {
+ "node": ">= 5.10.0"
+ }
+ },
"node_modules/simple-swizzle": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz",
@@ -9421,30 +10309,13 @@
"node": ">=4"
}
},
- "node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "node_modules/strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
"license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
"engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
+ "node": ">=0.10.0"
}
},
"node_modules/structured-headers": {
@@ -9457,7 +10328,6 @@
"version": "3.35.1",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz",
"integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.2",
@@ -9480,7 +10350,6 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 6"
@@ -9523,18 +10392,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/tagged-tag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz",
- "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==",
- "license": "MIT",
- "engines": {
- "node": ">=20"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/tailwindcss": {
"version": "3.4.19",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz",
@@ -9573,6 +10430,31 @@
"node": ">=14.0.0"
}
},
+ "node_modules/tar": {
+ "version": "7.5.12",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.12.tgz",
+ "integrity": "sha512-9TsuLcdhOn4XztcQqhNyq1KOwOOED/3k58JAvtULiYqbO8B/0IBAAIE1hj0Svmm58k27TmcigyDI0deMlgG3uw==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/fs-minipass": "^4.0.0",
+ "chownr": "^3.0.0",
+ "minipass": "^7.1.2",
+ "minizlib": "^3.1.0",
+ "yallist": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tar/node_modules/yallist": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
+ "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/terminal-link": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",
@@ -9627,22 +10509,6 @@
"node": ">=8"
}
},
- "node_modules/test-exclude/node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "license": "MIT"
- },
- "node_modules/test-exclude/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
"node_modules/test-exclude/node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -9664,23 +10530,10 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/test-exclude/node_modules/minimatch": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
- "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
"node_modules/thenify": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
"integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"any-promise": "^1.0.0"
@@ -9690,7 +10543,6 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
"integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"thenify": ">= 3.1.0 < 4"
@@ -9709,7 +10561,6 @@
"version": "0.2.15",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"fdir": "^6.5.0",
@@ -9726,7 +10577,6 @@
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=12.0.0"
@@ -9744,7 +10594,6 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
@@ -9780,17 +10629,10 @@
"node": ">=0.6"
}
},
- "node_modules/toqr": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/toqr/-/toqr-0.1.1.tgz",
- "integrity": "sha512-FWAPzCIHZHnrE/5/w9MPk0kK25hSQSH2IKhYh9PyjS3SG/+IEMvlwIHbhz+oF7xl54I+ueZlVnMjyzdSwLmAwA==",
- "license": "MIT"
- },
"node_modules/ts-interface-checker": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
- "dev": true,
"license": "Apache-2.0"
},
"node_modules/tslib": {
@@ -9831,6 +10673,15 @@
"node": ">=14.17"
}
},
+ "node_modules/undici": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-6.24.1.tgz",
+ "integrity": "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.17"
+ }
+ },
"node_modules/undici-types": {
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
@@ -9977,6 +10828,19 @@
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
+ "node_modules/util": {
+ "version": "0.12.5",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
+ "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "is-arguments": "^1.0.4",
+ "is-generator-function": "^1.0.7",
+ "is-typed-array": "^1.1.3",
+ "which-typed-array": "^1.1.2"
+ }
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -9993,15 +10857,6 @@
"node": ">= 0.4.0"
}
},
- "node_modules/uuid": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz",
- "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==",
- "license": "MIT",
- "bin": {
- "uuid": "dist/bin/uuid"
- }
- },
"node_modules/validate-npm-package-name": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz",
@@ -10069,11 +10924,28 @@
"integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==",
"license": "MIT"
},
- "node_modules/whatwg-url-minimum": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/whatwg-url-minimum/-/whatwg-url-minimum-0.1.1.tgz",
- "integrity": "sha512-u2FNVjFVFZhdjb502KzXy1gKn1mEisQRJssmSJT8CPhZdZa0AP6VCbWlXERKyGu0l09t0k50FiDiralpGhBxgA==",
- "license": "MIT"
+ "node_modules/whatwg-url-without-unicode": {
+ "version": "8.0.0-3",
+ "resolved": "https://registry.npmjs.org/whatwg-url-without-unicode/-/whatwg-url-without-unicode-8.0.0-3.tgz",
+ "integrity": "sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer": "^5.4.3",
+ "punycode": "^2.1.1",
+ "webidl-conversions": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/whatwg-url-without-unicode/node_modules/webidl-conversions": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz",
+ "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=8"
+ }
},
"node_modules/which": {
"version": "2.0.2",
@@ -10090,6 +10962,33 @@
"node": ">= 8"
}
},
+ "node_modules/which-typed-array": {
+ "version": "1.1.20",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz",
+ "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==",
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "for-each": "^0.3.5",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/wonka": {
+ "version": "6.3.5",
+ "resolved": "https://registry.npmjs.org/wonka/-/wonka-6.3.5.tgz",
+ "integrity": "sha512-SSil+ecw6B4/Dm7Pf2sAshKQ5hWFvfyGlfPbEd6A14dOH6VDjrmbY86u6nZvy9omGwwIPFR8V41+of1EezgoUw==",
+ "license": "MIT"
+ },
"node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
@@ -10107,6 +11006,38 @@
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
+ "node_modules/wrap-ansi/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/wrap-ansi/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@@ -10127,16 +11058,16 @@
}
},
"node_modules/ws": {
- "version": "7.5.10",
- "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
- "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz",
+ "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==",
"license": "MIT",
"engines": {
- "node": ">=8.3.0"
+ "node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
- "utf-8-validate": "^5.0.2"
+ "utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
@@ -10160,6 +11091,15 @@
"node": ">=10.0.0"
}
},
+ "node_modules/xcode/node_modules/uuid": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz",
+ "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==",
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
"node_modules/xml2js": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.0.tgz",
@@ -10248,13 +11188,48 @@
"node": ">=12"
}
},
- "node_modules/zod": {
- "version": "3.25.76",
- "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
- "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
+ "node_modules/yargs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/yargs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
"funding": {
- "url": "https://github.com/sponsors/colinhacks"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/zustand": {
@@ -10285,34 +11260,6 @@
"optional": true
}
}
- },
- "node_modules/zxing-wasm": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/zxing-wasm/-/zxing-wasm-3.0.1.tgz",
- "integrity": "sha512-3CLj6iaGkpqPWXAB4pIWkFOR63MwqGekpMzaROFKto4dFowiPmLlC56KoMoOSXzqOCOpI5DAvMdB8ku2va6fUg==",
- "license": "MIT",
- "dependencies": {
- "@types/emscripten": "^1.41.5",
- "type-fest": "^5.4.4"
- },
- "peerDependencies": {
- "@types/emscripten": ">=1.39.6"
- }
- },
- "node_modules/zxing-wasm/node_modules/type-fest": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.5.0.tgz",
- "integrity": "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==",
- "license": "(MIT OR CC0-1.0)",
- "dependencies": {
- "tagged-tag": "^1.0.0"
- },
- "engines": {
- "node": ">=20"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
}
}
}
diff --git a/package.json b/package.json
index a97bbe0..8622a7b 100644
--- a/package.json
+++ b/package.json
@@ -9,33 +9,34 @@
"web": "expo start --web"
},
"dependencies": {
- "@react-native-async-storage/async-storage": "^2.2.0",
+ "@react-native-async-storage/async-storage": "2.2.0",
"@tanstack/react-query": "^5.95.0",
"axios": "^1.13.6",
- "expo": "~55.0.8",
- "expo-camera": "^55.0.10",
- "expo-constants": "^55.0.9",
- "expo-image-picker": "^55.0.13",
- "expo-linking": "^55.0.8",
- "expo-location": "^55.1.4",
- "expo-notifications": "^55.0.13",
- "expo-router": "^55.0.7",
- "expo-secure-store": "^55.0.9",
- "expo-status-bar": "~55.0.4",
- "expo-updates": "~55.0.15",
- "hermes-parser": "0.32.0",
+ "expo": "~54.0.33",
+ "expo-camera": "~17.0.10",
+ "expo-constants": "~18.0.13",
+ "expo-dev-client": "^55.0.18",
+ "expo-image-picker": "~17.0.10",
+ "expo-linking": "~8.0.11",
+ "expo-location": "~19.0.8",
+ "expo-notifications": "~0.32.16",
+ "expo-router": "~6.0.23",
+ "expo-secure-store": "~15.0.8",
+ "expo-status-bar": "~3.0.9",
+ "expo-updates": "~29.0.16",
"nativewind": "^4.1.23",
- "react": "19.2.0",
- "react-native": "0.83.2",
- "react-native-reanimated": "4.2.1",
- "react-native-safe-area-context": "^5.6.2",
- "react-native-screens": "^4.23.0",
- "react-native-worklets": "0.7.2",
+ "react": "19.1.0",
+ "react-native": "0.81.5",
+ "react-native-reanimated": "~4.1.1",
+ "react-native-safe-area-context": "~5.6.0",
+ "react-native-screens": "~4.16.0",
+ "react-native-svg": "^15.15.4",
+ "react-native-worklets": "^0.8.1",
"zustand": "^5.0.12"
},
"devDependencies": {
"@expo/ngrok": "^4.1.3",
- "@types/react": "~19.2.2",
+ "@types/react": "~19.1.10",
"tailwindcss": "^3.4.19",
"typescript": "~5.9.2"
},
diff --git a/services/api.ts b/services/api.ts
index a9b10ec..2987cd3 100644
--- a/services/api.ts
+++ b/services/api.ts
@@ -11,7 +11,7 @@ export const api = axios.create({
});
api.interceptors.request.use(async (config) => {
- const token = await SecureStore.getItemAsync(STORAGE_KEYS.TOKEN);
+ const token = await SecureStore.getItemAsync('fiberops_token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
@@ -22,8 +22,8 @@ api.interceptors.response.use(
(response) => response,
async (error) => {
if (error.response?.status === 401) {
- await SecureStore.deleteItemAsync(STORAGE_KEYS.TOKEN);
- await SecureStore.deleteItemAsync(STORAGE_KEYS.USER);
+ await SecureStore.deleteItemAsync('fiberops_token');
+ await SecureStore.deleteItemAsync('fiberops_tenant');
}
return Promise.reject(error);
}
diff --git a/stores/authStore.ts b/stores/authStore.ts
index 88144aa..6d1a799 100644
--- a/stores/authStore.ts
+++ b/stores/authStore.ts
@@ -2,12 +2,15 @@ import { create } from 'zustand';
import * as SecureStore from 'expo-secure-store';
import { api } from '../services/api';
+const TOKEN_KEY = 'fiberops_token';
+const TENANT_KEY = 'fiberops_tenant';
+
interface AuthState {
token: string | null;
tenantSlug: string | null;
user: any | null;
isLoading: boolean;
- login: (tenantSlug: string, username: string, password: string) => Promise;
+ login: (tenantSlug: string, email: string, password: string) => Promise;
logout: () => Promise;
hydrate: () => Promise;
}
@@ -20,8 +23,8 @@ export const useAuthStore = create((set) => ({
hydrate: async () => {
try {
- const token = await SecureStore.getItemAsync('auth_token');
- const tenantSlug = await SecureStore.getItemAsync('tenant_slug');
+ const token = await SecureStore.getItemAsync(TOKEN_KEY);
+ const tenantSlug = await SecureStore.getItemAsync(TENANT_KEY);
if (token && tenantSlug) {
const res = await api.get('/api/v1/auth/me');
set({ token, tenantSlug, user: res.data, isLoading: false });
@@ -29,23 +32,23 @@ export const useAuthStore = create((set) => ({
set({ isLoading: false });
}
} catch {
- await SecureStore.deleteItemAsync('auth_token');
- await SecureStore.deleteItemAsync('tenant_slug');
+ await SecureStore.deleteItemAsync(TOKEN_KEY);
+ await SecureStore.deleteItemAsync(TENANT_KEY);
set({ token: null, tenantSlug: null, user: null, isLoading: false });
}
},
- login: async (tenantSlug, username, password) => {
- const res = await api.post('/api/v1/auth/login', { tenantSlug, username, password });
- const { token, user } = res.data;
- await SecureStore.setItemAsync('auth_token', token);
- await SecureStore.setItemAsync('tenant_slug', tenantSlug);
- set({ token, tenantSlug, user });
+ login: async (tenantSlug, email, password) => {
+ const res = await api.post('/api/v1/auth/login', { tenantSlug, email, password });
+ const { accessToken, user } = res.data;
+ await SecureStore.setItemAsync(TOKEN_KEY, accessToken);
+ await SecureStore.setItemAsync(TENANT_KEY, tenantSlug);
+ set({ token: accessToken, tenantSlug, user });
},
logout: async () => {
- await SecureStore.deleteItemAsync('auth_token');
- await SecureStore.deleteItemAsync('tenant_slug');
+ await SecureStore.deleteItemAsync(TOKEN_KEY);
+ await SecureStore.deleteItemAsync(TENANT_KEY);
set({ token: null, tenantSlug: null, user: null });
},
}));
diff --git a/tailwind.config.js b/tailwind.config.js
index 86cf3a4..53f4c75 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -5,7 +5,7 @@ module.exports = {
theme: {
extend: {
colors: {
- primary: '#2563EB',
+ primary: '#0891B2',
'primary-dark': '#1D4ED8',
danger: '#DC2626',
success: '#16A34A',
diff --git a/tsconfig.json b/tsconfig.json
index 56c26ad..bd8aed9 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -4,12 +4,24 @@
"strict": true,
"baseUrl": ".",
"paths": {
- "@/*": ["./*"],
- "@/components/*": ["./components/*"],
- "@/stores/*": ["./stores/*"],
- "@/services/*": ["./services/*"],
- "@/hooks/*": ["./hooks/*"],
- "@/constants/*": ["./constants/*"]
+ "@/*": [
+ "./*"
+ ],
+ "@/components/*": [
+ "./components/*"
+ ],
+ "@/stores/*": [
+ "./stores/*"
+ ],
+ "@/services/*": [
+ "./services/*"
+ ],
+ "@/hooks/*": [
+ "./hooks/*"
+ ],
+ "@/constants/*": [
+ "./constants/*"
+ ]
}
},
"include": [
@@ -17,7 +29,6 @@
"**/*.tsx",
"nativewind-env.d.ts",
"types/**/*.d.ts",
- ".expo/types/**/*.d.ts",
- "expo-env.d.ts"
+ ".expo/types/**/*.d.ts"
]
}