This commit is contained in:
Gugus Darmayanto 2024-09-24 07:17:23 +07:00
parent 09c19b9423
commit 2259540ba0
16 changed files with 1292 additions and 417 deletions

View File

@ -1,5 +1,5 @@
import { Tabs, useNavigation } from 'expo-router';
import React, { useEffect } from 'react';
import React, { useEffect, useRef } from 'react';
import { TabBarIcon } from '@/components/navigation/TabBarIcon';
import { Colors } from '@/constants/Colors';
@ -9,7 +9,8 @@ import AsyncStorage from '@react-native-async-storage/async-storage';
import { addStorage, cfg } from '@/components/lib/cfg';
import { DB } from '@/components/lib/db';
import ProfileScreen from './profile';
import { AppProvider } from '@/components/AppContext';
export default function TabLayout() {
const colorScheme = useColorScheme();
@ -24,6 +25,8 @@ export default function TabLayout() {
})();
},[])
const profileScreenRef = useRef(null); // Move this line outside of CekLogin function
const CekLogin = async (name:any) => {
let cekLogin = await AsyncStorage.getItem('login');
if (cekLogin === null && name != 'index') {
@ -40,214 +43,216 @@ export default function TabLayout() {
const navigation = useNavigation<{ navigate: (screen: string) => void }>(); // Explicitly type navigation
return (
<Tabs
<AppProvider>
<Tabs
screenOptions={{
screenOptions={{
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
headerShown: false,
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
headerShown: false,
}}
screenListeners={{
focus : (e)=>{
let data = e.target?.split('-') || []
if (data[0]) {
let name = data[0];
console.log(name);
(function(){
CekLogin(name);
cfg.activeTabs = name;
cfg.call(name);
return true;
})();
}
},
}}
screenListeners={{
focus : (e)=>{
let data = e.target?.split('-') || []
if (data[0]) {
let name = data[0];
(function(){
CekLogin(name);
cfg.activeTabs = name;
cfg.call(name);
return true;
})();
}
},
}}
>
}}
>
<Tabs.Screen
name="index"
options={{
title: 'Login',
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="index"
options={{
title: 'Login',
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="signup"
options={{
title: 'Register',
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="signup"
options={{
title: 'Register',
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="home"
options={{
title: 'Home',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'home' : 'home-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="home"
options={{
title: 'Home',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'home' : 'home-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="explore"
options={{
title: 'Explore',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="explore"
options={{
title: 'Explore',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="setting"
options={{
title: 'Setting',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="order"
options={{
title: 'Order',
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="profile"
options={{
title: 'Profile',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
<Tabs.Screen
name="setting"
options={{
title: 'Setting',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="order"
options={{
title: 'Order',
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="profile"
options={{
title: 'Profile',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="history"
options={{
title: 'history',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="dashboard"
options={{
title: 'dashboard',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="stock"
options={{
title: 'stock',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="customer"
options={{
title: 'customer',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="detailcontact"
options={{
title: 'detailcontact',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="singleedit"
options={{
title: 'singleedit',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="formcustomer"
options={{
title: 'formcustomer',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="pelunasan"
options={{
title: 'formcustomer',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="orderlunas"
options={{
title: 'formcustomer',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="orderbelumlunas"
options={{
title: 'formcustomer',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
</Tabs>
}}
/>
<Tabs.Screen
name="history"
options={{
title: 'history',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="dashboard"
options={{
title: 'dashboard',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="stock"
options={{
title: 'stock',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="customer"
options={{
title: 'customer',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="detailcontact"
options={{
title: 'detailcontact',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="singleedit"
options={{
title: 'singleedit',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="formcustomer"
options={{
title: 'formcustomer',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="pelunasan"
options={{
title: 'formcustomer',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="orderlunas"
options={{
title: 'formcustomer',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
<Tabs.Screen
name="orderbelumlunas"
options={{
title: 'formcustomer',
tabBarIcon: ({ color, focused }) => (
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
),
tabBarStyle: { display: 'none' },
tabBarButton: () => null,
}}
/>
</Tabs>
</AppProvider>
);
}

View File

@ -1,4 +1,4 @@
import React, { useEffect, useRef, useState } from 'react';
import React, { useEffect, useRef, useState, useCallback } from 'react';
import { ScrollView, View, Text, Image, TouchableOpacity, BackHandler, Dimensions, ImageBackground } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import config from '../../components/data/config.json'
@ -9,6 +9,7 @@ import AsyncStorage from '@react-native-async-storage/async-storage';
import { cfg, getStorage } from '@/components/lib/cfg';
import { DB } from '@/components/lib/db';
import DetailOrder from '@/components/pageComponent/detailOrder';
import debounce from 'lodash.debounce';
const formatNumber = function (number: any) {
return number.toLocaleString('id-ID', {
@ -45,7 +46,7 @@ const Contact = ({ data: mapOfData, setDataOrder, setDataOrderList, setShowDetai
return (
<>
{(Array.isArray(mapOfData)?mapOfData:[]).map((data: any, key: number) =>
<TouchableOpacity onPress={() => {
<TouchableOpacity key={key} onPress={() => {
DB(`
SELECT
s.name
@ -64,7 +65,7 @@ const Contact = ({ data: mapOfData, setDataOrder, setDataOrderList, setShowDetai
setDataOrderList(list);
setShowDetail(true)
})
}} key={key}>
}}>
<View style={{
paddingLeft: 10,
backgroundColor: "green",
@ -179,13 +180,9 @@ const HistorySreen = () => {
};
}, [navigation, showDetail, setShowDetail])
);
const callData = async () => {
let data: any = await AsyncStorage.getItem('login');
data = JSON.parse(data);
data = data.length > 0 ? data[0] : {};
const [pagin, setPagin] = useState(0);
const [search, setSearch] = useState('');
const callData = async (pagin=0) => {
let sales: any = await DB(`
SELECT
sa.write_date,
@ -203,37 +200,44 @@ const HistorySreen = () => {
sa.amount_to_invoice
FROM sale_order sa
LEFT JOIN res_partner rp ON sa.partner_id = rp.id
ORDER BY sa.name DESC
WHERE lower(rp.name) LIKE '%${search}%'
ORDER BY sa.name DESC LIMIT 10 OFFSET ${pagin}
`);
let salesTotalNumber: any = await DB(`
SELECT
count(*) as total
FROM sale_order sa
`);
setSalesTotal(salesTotalNumber.length > 0 ? Number(salesTotalNumber[0].total):0)
setId(data?.id)
setNama(data?.name)
setEmail("Salesman")
let country = 'Indonesia';
if (data?.country_id) {
const negara: any = await getStorage('negara')
const [{ name }] = negara.filter((s: any) => s?.id == data?.country_id);
country = name;
console.log(pagin)
if(pagin == 0){
setContact(sales);
}else{
setContact(contact.concat(sales) );
}
setContact(sales);
};
cfg.action['history'] = () => {
callData()
setPagin(0);
setSearch('')
callData(pagin)
}
useEffect(() => {
(function () {
(async function () {
callData()
let data: any = await AsyncStorage.getItem('login');
data = JSON.parse(data);
data = data.length > 0 ? data[0] : {};
setId(data?.id)
setNama(data?.name)
setEmail("Salesman")
let country = 'Indonesia';
if (data?.country_id) {
const negara: any = await getStorage('negara')
const [{ name }] = negara.filter((s: any) => s?.id == data?.country_id);
country = name;
}
})();
}, [])
@ -241,10 +245,6 @@ const HistorySreen = () => {
navigation.navigate('home')
}
const fabAction = function () {
// console.log("action")
}
const onScroll = (event: any) => {
const yOffset = event.nativeEvent.contentOffset.y;
if (yOffset > 190) {
@ -254,11 +254,21 @@ const HistorySreen = () => {
}
};
const debouncedFetchData = useCallback(debounce((query) => {
callData();
}, 300), [callData]);
const handleInputChange = (text:string) => {
setSearch(text);
setPagin(0)
debouncedFetchData(text); // Mengambil data setelah 500ms tidak mengetik
};
return (
<>
{
showDetail === true?
<DetailOrder order={dataOrder} orderlist={dataOrderList} config={config} act={setShowDetail} />
<DetailOrder order={dataOrder} orderlist={dataOrderList} config={config} act={setShowDetail} />
:<>
<GestureHandlerRootView>
<ScrollView onScroll={onScroll}>
@ -296,24 +306,24 @@ const HistorySreen = () => {
<View style={{position:"static", top:-80}}>
<View style={{ paddingHorizontal: 20, paddingVertical: 10 }}>
<View style={{
backgroundColor: "orange"
, padding: 10
, paddingVertical: 20
, borderRadius: 15
, flexDirection: 'row'
backgroundColor : "orange"
, padding : 10
, paddingVertical : 20
, borderRadius : 15
, flexDirection : 'row'
}}>
<View style={{ flex: 1 }}>
<Text style={{
fontSize: 12
, color: '#000'
, fontWeight: '600'
, textAlign: 'center'
fontSize : 12
, color : '#000'
, fontWeight : '600'
, textAlign : 'center'
}}>{(`total\nSemua Order`).toUpperCase()}</Text>
<Text style={{
fontSize: 28
, color: '#000'
, fontWeight: 'bold'
, textAlign: 'center'
fontSize : 28
, color : '#000'
, fontWeight : 'bold'
, textAlign : 'center'
}}>{salesTotal}</Text>
</View>
<View style={{ flex: 1 }}>
@ -362,7 +372,9 @@ const HistorySreen = () => {
</View>
</View>
<View style={{marginVertical:10, flexDirection:"row", paddingHorizontal:20}}>
<TextInput style={{
<TextInput
value={search}
onChangeText={handleInputChange} style={{
flex:1,
backgroundColor:"white",
height:40,
@ -390,7 +402,24 @@ const HistorySreen = () => {
<Text style={{fontSize:24, textAlign:'center', fontWeight:'600'}}>List Order</Text>
</View>
<View style={[{ paddingHorizontal: 20, paddingVertical: 5 }]}>
<Contact setShowDetail={setShowDetail} setDataOrderList={setDataOrderList} setDataOrder={setDataOrder} data={contact}></Contact>
<Contact setShowDetail={setShowDetail} setDataOrderList={setDataOrderList} setDataOrder={setDataOrder} data={contact}></Contact>
</View>
<View>
<View style={{
flexDirection:"row",
justifyContent:"center",
alignItems:"center"
}}>
<TouchableOpacity onPress={()=>{
let p = pagin+10;
setPagin( p )
callData(p)
}}>
<View style={{padding: 10, backgroundColor:'white', borderWidth:2, borderColor:"#ddd"}}>
<Text>Lebih Banyak</Text>
</View>
</TouchableOpacity>
</View>
</View>
</View>
</View>

View File

@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { View, Image, Text, StyleSheet, Dimensions, ScrollView, BackHandler, Alert, TouchableOpacity, ImageBackground } from 'react-native';
import { useNavigation, NavigationProp } from '@react-navigation/native';
import { ProgressChart } from 'react-native-chart-kit';
@ -9,18 +9,28 @@ import { DB } from '@/components/lib/db';
import { Asset } from 'expo-asset';
import config from '../../components/data/config.json';
import TimeLive from '@/components/Time';
import { useAppContext } from '@/components/AppContext';
import { useFocusEffect } from 'expo-router';
import { formatRupiah } from '@/components/Helper';
const screenWidth = Dimensions.get("window").width;
const HomeScreen = () => {
const {loadData:profileLoad}:any = useAppContext();
const profileScreenRef = useRef(null);
const navigation = useNavigation<NavigationProp<any>>();
const [greeting, setGreeting] = useState('');
const [employeeData, setEmployeeData] = useState({job_title:'', name: '', work_email: '', work_phone: '' });
const [orderData, setOrderData] = useState([0]);
const [visitData, setVisitData] = useState([0]);
const [svgData, setSvgData] = useState('');
useEffect(() => {
const [order, setOrder] = useState(0)
const [invoice, setInvoice] = useState(0)
const [order2, setOrder2] = useState(0)
const [invoice2, setInvoice2] = useState(0)
useEffect(() => {
const loadSvg = async () => {
const asset = Asset.fromModule(require('../../assets/images/bg/SORT_bg_Home.svg'));
await asset.downloadAsync();
@ -61,10 +71,23 @@ const HomeScreen = () => {
return true;
};
(async function(){
let [ord, inv]:any = await DB(`SELECT * FROM total_order`);
let [ord2, inv2]: any = await DB(`SELECT * FROM total_order_count`);
setInvoice(Number(inv.total))
setOrder(Number(ord.total))
setInvoice2(Number(inv2.total))
setOrder2(Number(ord2.total))
setOrderData([Math.min(100, ((Number(ord2.total) / (Number(ord2.total) + Number(inv2.total)) )) )]);
setVisitData([Math.min(100, ((Number(inv2.total) / (Number(ord2.total) + Number(inv2.total)))))]);
})();
const backHandler = BackHandler.addEventListener('hardwareBackPress', backAction);
return () => backHandler.remove();
}, []);
}, [setSvgData, setInvoice,setOrder]);
const getEmployeeData = async () => {
try {
@ -78,6 +101,8 @@ const HomeScreen = () => {
}
};
const getGreeting = () => {
const hour = new Date().getHours();
if (hour < 12) {
@ -140,6 +165,7 @@ const HomeScreen = () => {
<View style={styles.menuRow} key={`row-${i}`}>
{items.map((item, index) => (
<TouchableOpacity style={{ padding: 0, margin: 0 }} onPress={() => {
// profileLoad()
navigation.navigate(item.action);
}} key={`item-${i}-${index}`}>
<View style={[styles.cardMenu]}>
@ -279,7 +305,7 @@ const HomeScreen = () => {
<ScrollView>
<View style={styles.gaugeRow}>
<View style={styles.card}>
<Text style={{ fontWeight: '700', fontSize: 16 }}>28 Orders</Text>
<Text style={{ fontWeight: '700', fontSize: 16 }}>{order2} Orders</Text>
<ProgressChart
data={{ data: orderData }}
width={(screenWidth / 2) - 50}
@ -296,7 +322,7 @@ const HomeScreen = () => {
<Text style={{ fontSize: 16, fontWeight: '600', textAlign: 'center' }}>22 Pending</Text>
</View>
<View style={styles.card}>
<Text style={{ fontWeight: '700', fontSize: 16 }}>31 Visits</Text>
<Text style={{ fontWeight: '700', fontSize: 16 }}>{invoice2} Visits</Text>
<ProgressChart
data={{ data: visitData }}
width={(screenWidth / 2) - 50}
@ -334,11 +360,11 @@ const HomeScreen = () => {
<View style={{flex:1}}>
<View style={{padding:10, borderBottomColor:"#ddd", borderBottomWidth:1}}>
<Text style={styles.statLabel}>TOTAL ORDER</Text>
<Text style={styles.statValue}>Rp 45.600.000</Text>
<Text style={styles.statValue}>Rp {formatRupiah(order.toString())}</Text>
</View>
<View style={{ padding: 10}}>
<Text style={styles.statLabel}>TOTAL COLLECTED</Text>
<Text style={styles.statValue}>Rp 25.550.000</Text>
<Text style={styles.statValue}>Rp {formatRupiah(invoice.toString())}</Text>
</View>
</View>
</View>

View File

@ -1,7 +1,8 @@
import React, { useState } from 'react';
import { View, Text, TextInput, TouchableOpacity, StyleSheet, Alert, Image } from 'react-native';
import { useNavigation, NavigationProp, Link } from '@react-navigation/native';
import { RootStackParamList } from '@/types';
// Update the import path to the correct one
import { RootStackParamList } from '../../types';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { DB } from '@/components/lib/db';
import { GestureHandlerRootView, ScrollView } from 'react-native-gesture-handler';
@ -24,12 +25,6 @@ const LoginScreen = () => {
})
.catch(function(err){
})
// Alert.alert(JSON.stringify(data));
// if(data.length > 0){
// await AsyncStorage.setItem('login', JSON.stringify(data));
// }else{
// Alert.alert("Login", "Email atau Password salah")
// }
}catch(e){
Alert.alert(JSON.stringify(e))
}
@ -45,95 +40,101 @@ const LoginScreen = () => {
return (
<>
<View style={{ flex: 1, backgroundColor:'#2563eb'}}>
<View style={{
flexDirection:"column"
, height:300
, justifyContent:"center"
, alignItems:"center"
}}>
<View style={{
width:"auto",
backgroundColor:"white",
padding: 10,
borderRadius: 20
<GestureHandlerRootView>
<ScrollView>
<View style={{ flex: 1, backgroundColor:'#2563eb'}}>
<View style={{
flexDirection:"column"
, height:300
, justifyContent:"center"
, alignItems:"center"
}}>
<Image
source={require('../../assets/images/logo.png')}
style={{
width: 75
, height: 75
}}
resizeMode="contain" // You can adjust this based on how you want the image to scale
/>
<View style={{
width:"auto",
backgroundColor:"white",
padding: 10,
borderRadius: 20
}}>
<Image
source={require('../../assets/images/logo.png')}
style={{
width: 75
, height: 75
}}
resizeMode="contain" // You can adjust this based on how you want the image to scale
/>
</View>
<Text style={{
color:"white",
paddingVertical: 10,
fontWeight:"bold",
fontSize: 30
}}>S.O.R.T</Text>
</View>
<View style={[styles.container]}>
<Text style={{
textAlign:"center"
, fontSize:50
, fontWeight:'bold'
, color:"#2563eb"
}}>Login</Text>
<Text style={{
textAlign:"center"
, fontSize:18
, fontWeight:'bold'
, color:"#777"
, marginVertical:20
}}>Silahkan login ke akun anda</Text>
<Text style={{
textAlign:"left"
, fontSize:18
, fontWeight:'bold'
, color:"#777"
, marginTop:10
, marginBottom: 10
,width:'100%'
}}>EMAIL</Text>
<TextInput
style={styles.input}
placeholder="youremail@gmail.com"
value={username}
onChangeText={setUsername}
/>
<Text style={{
textAlign: "left"
, fontSize: 18
, fontWeight: 'bold'
, color: "#777"
, marginBottom: 10
, marginTop: 10
, width: '100%'
}}>PASSWORD</Text>
<TextInput
style={styles.input}
placeholder="******"
value={password}
onChangeText={setPassword}
secureTextEntry
/>
<TouchableOpacity style={styles.button} onPress={handleLogin}>
<Text style={styles.buttonText}>Log In</Text>
</TouchableOpacity>
<TouchableOpacity onPress={handleForgotPassword}>
<Text style={styles.forgotPasswordText}>Lupa Password?</Text>
</TouchableOpacity>
<View style={{flexDirection:"row"}}>
<Text>Belum memiliki akun?</Text>
<TouchableOpacity onPress={handleSignUp} style={{marginHorizontal:5}}>
<Text style={{
color:"blue",
fontWeight:"bold"
}}>Daftar disini!</Text>
</TouchableOpacity>
</View>
<Text style={{
color:"white",
paddingVertical: 10,
fontWeight:"bold",
fontSize: 30
}}>S.O.R.T</Text>
</View>
<View style={[styles.container]}>
<Text style={{
textAlign:"center"
, fontSize:50
, fontWeight:'bold'
, color:"#2563eb"
}}>Login</Text>
<Text style={{
textAlign:"center"
, fontSize:18
, fontWeight:'bold'
, color:"#777"
, marginVertical:20
}}>Silahkan login ke akun anda</Text>
<Text style={{
textAlign:"left"
, fontSize:18
, fontWeight:'bold'
, color:"#777"
, marginTop:10
,width:'100%'
}}>EMAIL</Text>
<TextInput
style={styles.input}
placeholder="youremail@gmail.com"
value={username}
onChangeText={setUsername}
/>
<Text style={{
textAlign: "left"
, fontSize: 18
, fontWeight: 'bold'
, color: "#777"
, marginTop: 10
, width: '100%'
}}>PASSWORD</Text>
<TextInput
style={styles.input}
placeholder="******"
value={password}
onChangeText={setPassword}
secureTextEntry
/>
<TouchableOpacity style={styles.button} onPress={handleLogin}>
<Text style={styles.buttonText}>Log In</Text>
</TouchableOpacity>
<TouchableOpacity onPress={handleForgotPassword}>
<Text style={styles.forgotPasswordText}>Lupa Password?</Text>
</TouchableOpacity>
<View style={{flexDirection:"row"}}>
<Text>Belum memiliki akun?</Text>
<TouchableOpacity onPress={handleSignUp} style={{marginHorizontal:5}}>
<Text style={{
color:"blue",
fontWeight:"bold"
}}>Daftar disini!</Text>
</TouchableOpacity>
</View>
</View>
</View>
</ScrollView>
</GestureHandlerRootView>
</>
);
};
@ -164,10 +165,11 @@ const styles = StyleSheet.create({
},
input: {
width: '100%',
borderWidth:1,
borderColor:"#ddd",
borderWidth: 2,
borderColor:"#333",
borderRadius: 10,
padding: 15,
shadowColor: "#000",
marginBottom: 20,
fontSize: 16,
},

View File

@ -181,7 +181,7 @@ const App = () => {
box:0
}
});
setProducts(y)
setProducts(y);
})();
},[])
@ -426,7 +426,6 @@ const App = () => {
// default company_id administrator
const company_id = 1;
let dataNilai = taxCount();
amount_untaxed = dataNilai.nilaiTotal
amount_tax = dataNilai.nilaiTax;

View File

@ -9,6 +9,7 @@ import AsyncStorage from '@react-native-async-storage/async-storage';
import { cfg, getStorage } from '@/components/lib/cfg';
import { DB } from '@/components/lib/db';
import DetailOrder from '@/components/pageComponent/detailOrder';
import debounce from 'lodash.debounce';
const formatNumber = function (number: any) {
return number.toLocaleString('id-ID', {
@ -17,7 +18,6 @@ const formatNumber = function (number: any) {
});
}
function formatDate(dateString: any) {
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
@ -141,7 +141,6 @@ const OrderLunasSreen = () => {
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
useFocusEffect(
React.useCallback(() => {
@ -163,24 +162,19 @@ const OrderLunasSreen = () => {
}, [navigation, showDetail, setShowDetail])
);
const callData = async () => {
let data : any = await AsyncStorage.getItem('login');
data = JSON.parse(data);
data = data.length > 0 ? data[0] : {};
let sales: any = await DB(`
SELECT * FROM view_sales_payment_status
`);
let [salesLunas]: any = await DB(`
SELECT count(*) total FROM view_sales_payment_status_lunas
`);
let [salesPasial]: any = await DB(`
SELECT count(*) total FROM view_sales_payment_status_parsial
`);
let apiUrl = config.apihost +'/data/odoo/lunas';
let dataFromApi = await fetch(apiUrl);
let { invoice, invoiceCount, invoicePartialCount } = await dataFromApi.json();
let sales: any = invoice;
let [salesLunas]: any = invoiceCount;
let [salesPasial]: any = invoicePartialCount;
setSalesTotal(Number(salesLunas?.total))
setSalesTotal2(Number(salesPasial?.total))
setSalesTotal(Number(salesLunas?.total));
setSalesTotal2(Number(salesPasial?.total));
setId(data?.id)
setNama(data?.name)
@ -192,11 +186,10 @@ const OrderLunasSreen = () => {
const [{ name }] = negara.filter((s: any) => s?.id == data?.country_id);
country = name;
}
setContact(sales);
};
cfg.action['history'] = () => {
cfg.action['orderlunas'] = () => {
callData()
}
@ -217,7 +210,7 @@ const OrderLunasSreen = () => {
const onScroll = (event: any) => {
const yOffset = event.nativeEvent.contentOffset.y;
if (yOffset > 190) {
setBgHead(config.color.primary)
setBgHead( config.color.primary )
} else {
setBgHead(null)
}

View File

@ -41,7 +41,7 @@ function formatDate(dateString: any) {
};
}
const Contact = ({ setData, setForm, data: mapOfData, setDataOrder, setDataOrderList, setShowDetail }: any) => {
const Contact = ({ setData, setForm, data: mapOfData, updateList, setDataOrder, setDataOrderList, setShowDetail }: any) => {
return (
<>
{(Array.isArray(mapOfData) ? mapOfData : []).map((data: any, key: number) =>
@ -146,7 +146,7 @@ const PelunasanSreen = () => {
useFocusEffect(
React.useCallback(() => {
callData();
const onBackPress = () => {
if (showDetail === true) {
setShowDetail(false)
@ -178,7 +178,7 @@ const PelunasanSreen = () => {
name VARCHAR(100),
data JSON
)`);
console.log("hallo")
let sales: any = await DB(`
SELECT
sa.write_date,
@ -196,7 +196,10 @@ const PelunasanSreen = () => {
sa.amount_to_invoice
FROM sale_order sa
LEFT JOIN res_partner rp ON sa.partner_id = rp.id
ORDER BY sa.name DESC LIMIT 10
LEFT JOIN (
SELECT DISTINCT invoice_origin FROM account_move WHERE invoice_origin IS NOT NULL
) ori ON ori.invoice_origin = sa.name
WHERE ori.invoice_origin IS NULL ORDER BY sa.name DESC
`);
let salesTotalNumber: any = await DB(`
SELECT
@ -220,9 +223,6 @@ const PelunasanSreen = () => {
setContact(sales);
};
cfg.action['history'] = () => {
callData()
}
useEffect(() => {
(function () {
@ -330,9 +330,12 @@ const PelunasanSreen = () => {
SELECT 1 FROM sort_payment WHERE name = '${dataPaan.name}'
);
`;
// console.log(query);
console.log(query);
DB(query).then(function(){
setDataForm(false);
(function(){
callData();
setDataForm(false);
})();
});
}
}}>
@ -348,6 +351,21 @@ const PelunasanSreen = () => {
}}>Simpan Pembayaran</Text>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={()=>{
setDataForm(false)
}}>
<View>
<Text style={{
padding:10,
backgroundColor:'lightblue',
fontSize: 18,
textAlign:'center'
, borderRadius: 10
, marginTop: 20
, fontWeight: '600'
}}>Kembali</Text>
</View>
</TouchableOpacity>
</View>
</View>
</View>
@ -424,7 +442,7 @@ const PelunasanSreen = () => {
<View style={[{ paddingHorizontal: 20, paddingVertical: 5 }]}>
</View>
<View style={[{ paddingHorizontal: 20, paddingVertical: 5 }]}>
<Contact setData={setDataPaan} setForm={setDataForm} setShowDetail={setShowDetail} setDataOrderList={setDataOrderList} setDataOrder={setDataOrder} data={contact}></Contact>
<Contact updateList={callData} setData={setDataPaan} setForm={setDataForm} setShowDetail={setShowDetail} setDataOrderList={setDataOrderList} setDataOrder={setDataOrder} data={contact}></Contact>
</View>
</View>
</View>

View File

@ -1,4 +1,4 @@
import React, { useEffect, useRef, useState } from 'react';
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react';
import { ScrollView, View, Text, Image, TouchableOpacity, BackHandler, Dimensions, Keyboard, ImageBackground } from 'react-native';
import { FontAwesome, Ionicons } from '@expo/vector-icons';
import config from '../../components/data/config.json'
@ -12,7 +12,7 @@ import { DB } from '@/components/lib/db';
import { LineChart } from 'react-native-chart-kit';
const ProfileSreen = () => {
const ProfileSreen = forwardRef((props, ref) => {
const [bgHead, setBgHead] = useState<any>(null)
const [nama, setNama] = useState('John Doe');
const [Id, setId] = useState('John Doe');
@ -36,8 +36,12 @@ const ProfileSreen = () => {
, value: string
}[]>([]);
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
const Contact = (props: any) => {
return (
<>
@ -75,12 +79,11 @@ const ProfileSreen = () => {
)
}
useFocusEffect(
React.useCallback(() => {
callData();
const onBackPress = () => {
navigation.navigate("home");
return true; // Prevent default behavior (exit app)
@ -92,9 +95,12 @@ const ProfileSreen = () => {
return () => {
BackHandler.removeEventListener('hardwareBackPress', onBackPress);
};
}, [navigation])
}, [navigation, callData])
);
const callData = async () => {
@ -148,9 +154,12 @@ const ProfileSreen = () => {
]);
};
cfg.action['detailcontact'] = () => {
callData()
}
useImperativeHandle(ref, () => ({
loadData() {
console.log('Data di ContactScreen sedang di-load...');
// Lakukan operasi loading data di sini
},
}));
useEffect(() => {
(function () {
@ -345,7 +354,7 @@ const ProfileSreen = () => {
</GestureHandlerRootView>
</>
);
};
});
export default ProfileSreen;

View File

@ -1,11 +1,17 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { View, Text, TextInput, FlatList, Image, TouchableOpacity, StyleSheet, ImageBackground } from 'react-native';
import { useNavigation, NavigationProp, useFocusEffect } from '@react-navigation/native';
import { BackHandler } from 'react-native';
import config from '../../components/data/config.json'
import { Ionicons } from '@expo/vector-icons';
import CustomPicker from '@/components/native/dropdown';
import { cfg } from '@/components/lib/cfg';
import { DB } from '@/components/lib/db';
const StockScreen = () => {
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
const [selectedValue, setSelectedValue] = useState('')
const [showFilter, setShowFilter] = useState(false)
useFocusEffect(
React.useCallback(() => {
const onBackPress = () => {
@ -22,7 +28,7 @@ const StockScreen = () => {
}, [navigation])
);
const [searchQuery, setSearchQuery] = useState('');
const [products, setProducts] = useState([
const settingFormat = [
{ id: 1, name: "A1-F12", sku: "-", price: 15500, qoh: 122, backgroundColor: "#c7e3ff", titleColor: "#1e90ff" },
{ id: 2, name: "A1-K12", sku: "-", price: 7300, qoh: 60, backgroundColor: "#bbf7d0", titleColor: "#22c55e" },
{ id: 3, name: "A1-F16", sku: "-", price: 20900, qoh: 180, backgroundColor: "#c7e3ff", titleColor: "#1e90ff" },
@ -38,17 +44,24 @@ const StockScreen = () => {
{ id: 13, name: "SHR F12", sku: "-", price: 13800, qoh: 46, backgroundColor: "#bbf7d0", titleColor: "#22c55e" },
{ id: 14, name: "SHR K12", sku: "-", price: 7800, qoh: 150, backgroundColor: "#c7e3ff", titleColor: "#1e90ff" },
{ id: 15, name: "EVEREST", sku: "-", price: 25400, qoh: 156, backgroundColor: "#c7e3ff", titleColor: "#1e90ff" }
]);
];
const warna = settingFormat.map((w) => w.backgroundColor);
const warnatitle = settingFormat.map((w) => w.titleColor);
const [products, setProducts] = useState([]);
const renderStockCard = ({ item } : any) => (
<>
<View style={[styles.card, { backgroundColor: item.backgroundColor, borderTopWidth:4, borderTopColor: item.titleColor}]}>
<View style={[styles.card, { backgroundColor: item.backgroundColor, borderLeftWidth:4, borderLeftColor: item.titleColor}]}>
<Text style={[styles.cardTitle, { color: item.titleColor }]}>{item.name}</Text>
<View style={styles.cardDates}>
<Text style={styles.cardDate}>Rp {item.price}</Text>
<View style={{alignItems:'flex-end'}}>
<Text style={{color: item.titleColor, fontWeight: 'bold'}}>Saldo : {item.qoh}</Text>
<Text style={{color: item.titleColor, fontSize:18, fontWeight: 'bold'}}>Saldo : {item.qoh}</Text>
</View>
</View>
</View>
@ -60,6 +73,45 @@ const StockScreen = () => {
return item.name.toLowerCase().includes(query);
};
const callData = async () =>{
let data:any = await DB(`SELECT
pt.id,
ss.name,
ss.masuk,
ss.keluar,
ss.sisa,
pt.list_price price
FROM sisa_stock ss
LEFT JOIN product_template pt ON pt.name->>'en_US' = ss.name
ORDER BY pt.id ASC`);
let databaru:[] = data.map((s:any,i:number)=>{
return {
id: i
, name: s?.name
, sku: "-"
, price: s?.price
, qoh: s?.sisa
, backgroundColor: warna[i] ? warna[i]:warna.pop()
, titleColor: warnatitle[i] ? warnatitle[i] : warnatitle.pop()
}
});
setProducts(databaru);
}
useEffect(()=>{
callData();
},[callData]);
cfg.action['stock'] = () => {
callData()
}
const dataPilih = [
{ label: 'SISA STOCK', value: 1 },
{ label: 'STOCK KELUAR', value: 2 },
{ label: 'STOCK MASUK', value: 3 },
]
return (
<>
<View style={{
@ -89,12 +141,71 @@ const StockScreen = () => {
</ImageBackground>
</View>
<View style={styles.container}>
<TextInput
style={styles.searchInput}
placeholder="Search..."
value={searchQuery}
onChangeText={setSearchQuery}
/>
<View style={[{flexDirection:"row", paddingHorizontal:15,marginBottom:10}]}>
<TouchableOpacity onPress={()=>{navigation.navigate('home')}}>
<View style={[{ borderRadius: 8, paddingHorizontal: 8, paddingVertical: 5, backgroundColor: config.color.primary }]}>
<Text style={{fontSize:16, color:"white"}}>Back</Text>
</View>
</TouchableOpacity>
</View>
<View style={[{
marginHorizontal:15
, flexDirection: 'row',
}]}>
<TextInput
style={styles.searchInput}
placeholder="Search..."
value={searchQuery}
onChangeText={setSearchQuery}
/>
<TouchableOpacity onPress={()=>{
setShowFilter(!showFilter);
}}>
<View style={[{height:40, width:40,marginLeft:10,borderRadius:5,backgroundColor:"gray", flexDirection:"row", alignItems:"center", justifyContent:"center"}]}>
<Ionicons name="filter-outline" color={"white"} style={{fontSize:20}} />
</View>
</TouchableOpacity>
</View>
{showFilter? <>
<View style={[{height:75, flexDirection:"row", marginHorizontal:15}]}>
<View style={{flex:1, backgroundColor:"gray", height:60, padding:15, borderRadius:5}}>
<CustomPicker
options={dataPilih}
selectedValue={selectedValue}
onValueChange={setSelectedValue}
label={`Pilih Type`}
/>
</View>
<TouchableOpacity>
<View style={{
flexDirection:"row"
, justifyContent:"center"
, alignItems: "center"
, height: 60
, width: 40
, backgroundColor:"#eee"
, borderRadius:10
, marginHorizontal:5
}}>
<Ionicons name="chevron-up" style={{fontSize:30}} />
</View>
</TouchableOpacity>
<TouchableOpacity>
<View style={{
flexDirection:"row"
, justifyContent:"center"
, alignItems: "center"
, height: 60
, width: 40
, backgroundColor:"#eee"
, borderRadius:10
, marginHorizontal:5
}}>
<Ionicons name="chevron-down" style={{fontSize:30}} />
</View>
</TouchableOpacity>
</View>
</> :<></>}
<FlatList
contentContainerStyle={styles.listContainer}
data={products.filter(searchFilter)}
@ -121,11 +232,12 @@ const styles = StyleSheet.create({
marginBottom: 10,
},
searchInput: {
flex:1,
height: 40,
borderWidth: 2,
borderRadius:5,
borderColor:'#A9A9A9',
marginBottom: 10,
marginBottom: 15,
paddingHorizontal: 10,
},
card: {
@ -153,6 +265,8 @@ const styles = StyleSheet.create({
},
cardDate: {
color: '#888',
fontSize: 16,
fontWeight:'medium'
},
cardContent: {
justifyContent: 'space-between',

23
components/AppContext.tsx Normal file
View File

@ -0,0 +1,23 @@
// AppContext.js
import React, { createContext, useContext, useState } from 'react';
// Membuat Context
const AppContext = createContext({});
// Hook untuk menggunakan Context
export const useAppContext = () => useContext(AppContext);
// Provider untuk membungkus aplikasi
export const AppProvider = ({ children }: any) => {
const [data, setData] = useState(null);
const loadData = () => {
console.log('Data sedang di-load...');
};
return (
<AppContext.Provider value={{ data, loadData }}>
{children}
</AppContext.Provider>
);
};

View File

@ -4,4 +4,5 @@
},
"api" : "http://193.203.167.219:8282/data/query/odoo"
,"api2" : "https://app.rumahjo.com/data/query/odoo"
, "apihost" : "https://app.rumahjo.com"
}

View File

@ -2,7 +2,7 @@ import React, { useState } from 'react';
import { View, Text, Modal, TouchableOpacity, FlatList } from 'react-native';
import { Ionicons } from '@expo/vector-icons'; // Optional for adding icons
const CustomPicker = ({ options, selectedValue, onValueChange }) => {
const CustomPicker = ({ label, options, selectedValue, onValueChange }:any) => {
const [isVisible, setIsVisible] = useState(false);
const handleSelect = (item:any) => {
@ -32,7 +32,7 @@ const CustomPicker = ({ options, selectedValue, onValueChange }) => {
>
<View style={{flex:1}}>
<Text style={{ color: 'white', fontSize: 20, fontWeight:'600' }}>
{(optionSet.find(option => option.value === selectedValue)?.label || 'PILIH CUSTOMER').toUpperCase()}
{(optionSet.find((option:any) => option.value === selectedValue)?.label || (label?label:'PILIH CUSTOMER')).toUpperCase()}
</Text>
</View>
<Ionicons

View File

@ -0,0 +1,12 @@
// Rename this sample file to main.js to use on your project.
// The main.js file will be overwritten in updates/reinstalls.
var rn_bridge = require('rn-bridge');
// Echo every message received from react-native.
rn_bridge.channel.on('message', (msg) => {
rn_bridge.channel.send(msg);
} );
// Inform react-native node is initialized.
rn_bridge.channel.send("Node was initialized.");

View File

@ -0,0 +1,12 @@
{
"//":
["Rename this sample file to package.json to use on your project."
, "The sample-package.json file will be overwritten in updates/reinstalls."
],
"name": "sample-node-project",
"version": "0.0.1",
"description": "node part of the project",
"main": "main.js",
"author": "janeasystems",
"license": ""
}

635
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "sort",
"version": "1.0.0",
"version": "1.0.7",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "sort",
"version": "1.0.0",
"version": "1.0.7",
"dependencies": {
"@expo-google-fonts/inter": "^0.2.3",
"@expo/vector-icons": "^14.0.2",
@ -29,8 +29,11 @@
"expo-system-ui": "~3.0.7",
"expo-updates": "~0.25.24",
"expo-web-browser": "~13.0.3",
"lodash": "^4.17.21",
"nodejs-mobile-react-native": "^18.17.8",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-loader-spinner": "^6.1.6",
"react-native": "0.74.5",
"react-native-bluetooth-escpos-printer": "^0.0.5",
"react-native-calendars": "^1.1306.0",
@ -49,11 +52,13 @@
"react-native-svg-transformer": "^1.5.0",
"react-native-tab-view": "^3.5.2",
"react-native-web": "~0.19.10",
"react-native-webview": "13.8.6"
"react-native-webview": "13.8.6",
"socket.io-client": "^4.7.5"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@types/jest": "^29.5.12",
"@types/lodash.debounce": "^4.0.9",
"@types/react": "~18.2.45",
"@types/react-test-renderer": "^18.0.7",
"jest": "^29.2.1",
@ -2178,6 +2183,24 @@
"node": ">=0.8.0"
}
},
"node_modules/@emotion/is-prop-valid": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz",
"integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==",
"dependencies": {
"@emotion/memoize": "^0.8.1"
}
},
"node_modules/@emotion/memoize": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
"integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
},
"node_modules/@emotion/unitless": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
"integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ=="
},
"node_modules/@expo-google-fonts/inter": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/@expo-google-fonts/inter/-/inter-0.2.3.tgz",
@ -4419,6 +4442,61 @@
"node": ">= 8"
}
},
"node_modules/@npmcli/agent": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.2.tgz",
"integrity": "sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==",
"dependencies": {
"agent-base": "^7.1.0",
"http-proxy-agent": "^7.0.0",
"https-proxy-agent": "^7.0.1",
"lru-cache": "^10.0.1",
"socks-proxy-agent": "^8.0.3"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/@npmcli/agent/node_modules/agent-base": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
"integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
"dependencies": {
"debug": "^4.3.4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@npmcli/agent/node_modules/http-proxy-agent": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
"integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
"dependencies": {
"agent-base": "^7.1.0",
"debug": "^4.3.4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@npmcli/agent/node_modules/https-proxy-agent": {
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
"integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
"dependencies": {
"agent-base": "^7.0.2",
"debug": "4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@npmcli/agent/node_modules/lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="
},
"node_modules/@npmcli/fs": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz",
@ -6796,6 +6874,11 @@
"@sinonjs/commons": "^3.0.0"
}
},
"node_modules/@socket.io/component-emitter": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
"integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA=="
},
"node_modules/@svgr/babel-plugin-add-jsx-attribute": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz",
@ -7280,6 +7363,21 @@
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="
},
"node_modules/@types/lodash": {
"version": "4.17.7",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz",
"integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==",
"dev": true
},
"node_modules/@types/lodash.debounce": {
"version": "4.0.9",
"resolved": "https://registry.npmjs.org/@types/lodash.debounce/-/lodash.debounce-4.0.9.tgz",
"integrity": "sha512-Ma5JcgTREwpLRwMM+XwBR7DaWe96nC38uCBDFKZWbNKD+osjVzdpnUSwBcqCptrp16sSOLBAUb50Car5I0TCsQ==",
"dev": true,
"dependencies": {
"@types/lodash": "*"
}
},
"node_modules/@types/node": {
"version": "18.19.42",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.42.tgz",
@ -7359,6 +7457,11 @@
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
"integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="
},
"node_modules/@types/stylis": {
"version": "4.2.5",
"resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz",
"integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw=="
},
"node_modules/@types/tough-cookie": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
@ -7433,6 +7536,14 @@
"deprecated": "Use your platform's native atob() and btoa() methods instead",
"dev": true
},
"node_modules/abbrev": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz",
"integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==",
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
@ -9613,7 +9724,6 @@
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
"optional": true,
"peer": true,
"dependencies": {
"iconv-lite": "^0.6.2"
}
@ -9626,6 +9736,46 @@
"once": "^1.4.0"
}
},
"node_modules/engine.io-client": {
"version": "6.5.4",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.4.tgz",
"integrity": "sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.2.1",
"ws": "~8.17.1",
"xmlhttprequest-ssl": "~2.0.0"
}
},
"node_modules/engine.io-client/node_modules/ws": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
"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/engine.io-parser": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
"integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
@ -9645,6 +9795,14 @@
"node": ">=8"
}
},
"node_modules/env-paths": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
"engines": {
"node": ">=6"
}
},
"node_modules/envinfo": {
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz",
@ -9661,6 +9819,11 @@
"resolved": "https://registry.npmjs.org/eol/-/eol-0.9.1.tgz",
"integrity": "sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg=="
},
"node_modules/err-code": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
"integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA=="
},
"node_modules/error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@ -11378,6 +11541,11 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/http-cache-semantics": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
"integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="
},
"node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
@ -11615,6 +11783,23 @@
"loose-envify": "^1.0.0"
}
},
"node_modules/ip-address": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
"integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
"dependencies": {
"jsbn": "1.1.0",
"sprintf-js": "^1.1.3"
},
"engines": {
"node": ">= 12"
}
},
"node_modules/ip-address/node_modules/sprintf-js": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="
},
"node_modules/ip-regex": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
@ -11860,6 +12045,11 @@
"node": ">=0.10.0"
}
},
"node_modules/is-lambda": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
"integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ=="
},
"node_modules/is-negative-zero": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
@ -14253,6 +14443,11 @@
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/jsbn": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
},
"node_modules/jsc-android": {
"version": "250231.0.0",
"resolved": "https://registry.npmjs.org/jsc-android/-/jsc-android-250231.0.0.tgz",
@ -14970,6 +15165,36 @@
"node": ">=10"
}
},
"node_modules/make-fetch-happen": {
"version": "13.0.1",
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz",
"integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==",
"dependencies": {
"@npmcli/agent": "^2.0.0",
"cacache": "^18.0.0",
"http-cache-semantics": "^4.1.1",
"is-lambda": "^1.0.1",
"minipass": "^7.0.2",
"minipass-fetch": "^3.0.0",
"minipass-flush": "^1.0.5",
"minipass-pipeline": "^1.2.4",
"negotiator": "^0.6.3",
"proc-log": "^4.2.0",
"promise-retry": "^2.0.1",
"ssri": "^10.0.0"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/make-fetch-happen/node_modules/proc-log": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz",
"integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==",
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/makeerror": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
@ -15577,6 +15802,22 @@
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/minipass-fetch": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz",
"integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==",
"dependencies": {
"minipass": "^7.0.3",
"minipass-sized": "^1.0.3",
"minizlib": "^2.1.2"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
},
"optionalDependencies": {
"encoding": "^0.1.13"
}
},
"node_modules/minipass-flush": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
@ -15631,6 +15872,33 @@
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/minipass-sized": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
"integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
"dependencies": {
"minipass": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/minipass-sized/node_modules/minipass": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/minipass-sized/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/minizlib": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
@ -15725,6 +15993,14 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true
},
"node_modules/ncp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
"integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==",
"bin": {
"ncp": "bin/ncp"
}
},
"node_modules/negotiator": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
@ -15827,6 +16103,16 @@
"node": ">= 6.13.0"
}
},
"node_modules/node-gyp-build-mobile": {
"version": "4.6.0-2",
"resolved": "https://registry.npmjs.org/node-gyp-build-mobile/-/node-gyp-build-mobile-4.6.0-2.tgz",
"integrity": "sha512-5Fkii5Jrvjgcsx+rhrby7IDYKmbM4+c6klvhryyCFr9p/sHLvUAE2Vyrb0vWjZpkwz5rc6mGT7PdyFGZiJ6eaw==",
"bin": {
"node-gyp-build-mobile": "bin.js",
"node-gyp-build-mobile-optional": "optional.js",
"node-gyp-build-mobile-test": "build-test.js"
}
},
"node_modules/node-int64": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
@ -15849,11 +16135,159 @@
"url": "https://github.com/sponsors/antelle"
}
},
"node_modules/nodejs-mobile-gyp": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/nodejs-mobile-gyp/-/nodejs-mobile-gyp-0.4.0.tgz",
"integrity": "sha512-10vkX/+msYevC66DE+OfvfLe0bfxjkHQpxc/HoaKP4P7BGuXygzNI8oz5F6pl23Lb9cxRr+fq2W6XjR53QriUQ==",
"dependencies": {
"env-paths": "^2.2.0",
"exponential-backoff": "^3.1.1",
"glob": "^10.3.10",
"graceful-fs": "^4.2.6",
"make-fetch-happen": "^13.0.0",
"nopt": "^7.0.0",
"proc-log": "^3.0.0",
"semver": "^7.3.5",
"tar": "^6.1.2",
"which": "^4.0.0"
},
"bin": {
"nodejs-mobile-gyp": "bin/node-gyp.js"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/nodejs-mobile-gyp/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/nodejs-mobile-gyp/node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
"minimatch": "^9.0.4",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^1.11.1"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/nodejs-mobile-gyp/node_modules/isexe": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz",
"integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==",
"engines": {
"node": ">=16"
}
},
"node_modules/nodejs-mobile-gyp/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/nodejs-mobile-gyp/node_modules/semver": {
"version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/nodejs-mobile-gyp/node_modules/which": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
"integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
"dependencies": {
"isexe": "^3.1.1"
},
"bin": {
"node-which": "bin/which.js"
},
"engines": {
"node": "^16.13.0 || >=18.0.0"
}
},
"node_modules/nodejs-mobile-react-native": {
"version": "18.17.8",
"resolved": "https://registry.npmjs.org/nodejs-mobile-react-native/-/nodejs-mobile-react-native-18.17.8.tgz",
"integrity": "sha512-GapuxMAKZ4Z878/aTFAY3LlQYXGmGfZBavAbTdB1AV/LR1yhzNipVp/deBnpY+HerYAb7Loep/sZEOyN3YT8xQ==",
"hasInstallScript": true,
"dependencies": {
"mkdirp": "^0.5.1",
"ncp": "^2.0.0",
"node-gyp-build-mobile": "4.6.0-2",
"nodejs-mobile-gyp": "^0.4.0",
"xcode": "^2.0.0"
},
"peerDependencies": {
"react-native": ">=0.60.0"
}
},
"node_modules/nodejs-mobile-react-native/node_modules/uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
"bin": {
"uuid": "bin/uuid"
}
},
"node_modules/nodejs-mobile-react-native/node_modules/xcode": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/xcode/-/xcode-2.1.0.tgz",
"integrity": "sha512-uCrmPITrqTEzhn0TtT57fJaNaw8YJs1aCzs+P/QqxsDbvPZSv7XMPPwXrKvHtD6pLjBM/NaVwraWJm8q83Y4iQ==",
"dependencies": {
"simple-plist": "^1.0.0",
"uuid": "^3.3.2"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/noop-fn": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/noop-fn/-/noop-fn-1.0.0.tgz",
"integrity": "sha512-pQ8vODlgXt2e7A3mIbFDlizkr46r75V+BJxVAyat8Jl7YmI513gG5cfyRL0FedKraoZ+VAouI1h4/IWpus5pcQ=="
},
"node_modules/nopt": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz",
"integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==",
"dependencies": {
"abbrev": "^2.0.0"
},
"bin": {
"nopt": "bin/nopt.js"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@ -16524,6 +16958,14 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
},
"node_modules/proc-log": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz",
"integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==",
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@ -16545,6 +16987,18 @@
"asap": "~2.0.3"
}
},
"node_modules/promise-retry": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
"integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
"dependencies": {
"err-code": "^2.0.2",
"retry": "^0.12.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/prompts": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
@ -16786,6 +17240,27 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/react-loader-spinner": {
"version": "6.1.6",
"resolved": "https://registry.npmjs.org/react-loader-spinner/-/react-loader-spinner-6.1.6.tgz",
"integrity": "sha512-x5h1Jcit7Qn03MuKlrWcMG9o12cp9SNDVHVJTNRi9TgtGPKcjKiXkou4NRfLAtXaFB3+Z8yZsVzONmPzhv2ErA==",
"dependencies": {
"react-is": "^18.2.0",
"styled-components": "^6.1.2"
},
"engines": {
"node": ">= 12"
},
"peerDependencies": {
"react": "^16.0.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-loader-spinner/node_modules/react-is": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
},
"node_modules/react-native": {
"version": "0.74.5",
"resolved": "https://registry.npmjs.org/react-native/-/react-native-0.74.5.tgz",
@ -17658,6 +18133,14 @@
"node": ">=4"
}
},
"node_modules/retry": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
"integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
"engines": {
"node": ">= 4"
}
},
"node_modules/reusify": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
@ -18100,6 +18583,15 @@
"node": ">=8.0.0"
}
},
"node_modules/smart-buffer": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/snake-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz",
@ -18109,6 +18601,69 @@
"tslib": "^2.0.3"
}
},
"node_modules/socket.io-client": {
"version": "4.7.5",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.5.tgz",
"integrity": "sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.2",
"engine.io-client": "~6.5.2",
"socket.io-parser": "~4.2.4"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/socket.io-parser": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/socks": {
"version": "2.8.3",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
"integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==",
"dependencies": {
"ip-address": "^9.0.5",
"smart-buffer": "^4.2.0"
},
"engines": {
"node": ">= 10.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/socks-proxy-agent": {
"version": "8.0.4",
"resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz",
"integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==",
"dependencies": {
"agent-base": "^7.1.1",
"debug": "^4.3.4",
"socks": "^2.8.3"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/socks-proxy-agent/node_modules/agent-base": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
"integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
"dependencies": {
"debug": "^4.3.4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/source-map": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
@ -18482,11 +19037,75 @@
"resolved": "https://registry.npmjs.org/structured-headers/-/structured-headers-0.4.1.tgz",
"integrity": "sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg=="
},
"node_modules/styled-components": {
"version": "6.1.13",
"resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.13.tgz",
"integrity": "sha512-M0+N2xSnAtwcVAQeFEsGWFFxXDftHUD7XrKla06QbpUMmbmtFBMMTcKWvFXtWxuD5qQkB8iU5gk6QASlx2ZRMw==",
"dependencies": {
"@emotion/is-prop-valid": "1.2.2",
"@emotion/unitless": "0.8.1",
"@types/stylis": "4.2.5",
"css-to-react-native": "3.2.0",
"csstype": "3.1.3",
"postcss": "8.4.38",
"shallowequal": "1.1.0",
"stylis": "4.3.2",
"tslib": "2.6.2"
},
"engines": {
"node": ">= 16"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/styled-components"
},
"peerDependencies": {
"react": ">= 16.8.0",
"react-dom": ">= 16.8.0"
}
},
"node_modules/styled-components/node_modules/postcss": {
"version": "8.4.38",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
"integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
"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"
}
],
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.0.0",
"source-map-js": "^1.2.0"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/styled-components/node_modules/tslib": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
},
"node_modules/styleq": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/styleq/-/styleq-0.1.3.tgz",
"integrity": "sha512-3ZUifmCDCQanjeej1f6kyl/BeP/Vae5EYkQ9iJfUm/QwZvlgnZzyflqAsAWYURdtea8Vkvswu2GrC57h3qffcA=="
},
"node_modules/stylis": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz",
"integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg=="
},
"node_modules/sucrase": {
"version": "3.34.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz",
@ -19756,6 +20375,14 @@
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
"dev": true
},
"node_modules/xmlhttprequest-ssl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz",
"integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",

View File

@ -1,7 +1,7 @@
{
"name": "sort",
"main": "expo-router/entry",
"version": "1.0.5",
"version": "1.0.7",
"scripts": {
"start": "expo start",
"reset-project": "node ./scripts/reset-project.js",
@ -36,8 +36,11 @@
"expo-system-ui": "~3.0.7",
"expo-updates": "~0.25.24",
"expo-web-browser": "~13.0.3",
"lodash": "^4.17.21",
"nodejs-mobile-react-native": "^18.17.8",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-loader-spinner": "^6.1.6",
"react-native": "0.74.5",
"react-native-bluetooth-escpos-printer": "^0.0.5",
"react-native-calendars": "^1.1306.0",
@ -56,11 +59,13 @@
"react-native-svg-transformer": "^1.5.0",
"react-native-tab-view": "^3.5.2",
"react-native-web": "~0.19.10",
"react-native-webview": "13.8.6"
"react-native-webview": "13.8.6",
"socket.io-client": "^4.7.5"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@types/jest": "^29.5.12",
"@types/lodash.debounce": "^4.0.9",
"@types/react": "~18.2.45",
"@types/react-test-renderer": "^18.0.7",
"jest": "^29.2.1",