319 lines
11 KiB
TypeScript
319 lines
11 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
|
import { View, Text, TextInput, FlatList, Image, TouchableOpacity, StyleSheet, ImageBackground, Dimensions } 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';
|
|
import { GestureHandlerRootView, NativeViewGestureHandler, ScrollView } from 'react-native-gesture-handler';
|
|
import Nav from '@/components/nav';
|
|
|
|
const StockScreen = () => {
|
|
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
|
const [selectedValue, setSelectedValue] = useState('')
|
|
const [showFilter, setShowFilter] = useState(false)
|
|
useFocusEffect(
|
|
React.useCallback(() => {
|
|
const onBackPress = () => {
|
|
navigation.navigate('home')
|
|
return true; // Prevent default behavior (exit app)
|
|
};
|
|
|
|
BackHandler.addEventListener('hardwareBackPress', onBackPress);
|
|
navigation.setOptions({ headerLeft: () => null }); // Remove back button
|
|
|
|
return () => {
|
|
BackHandler.removeEventListener('hardwareBackPress', onBackPress);
|
|
};
|
|
}, [navigation])
|
|
);
|
|
const [searchQuery, setSearchQuery] = 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" },
|
|
{ id: 4, name: "TP-F12", sku: "-", price: 15500, qoh: 7, backgroundColor: "#fef9c3", titleColor: "#eab308" },
|
|
{ id: 5, name: "TP-F16", sku: "-", price: 20900, qoh: 113, backgroundColor: "#c7e3ff", titleColor: "#1e90ff" },
|
|
{ id: 6, name: "A1-BOLD20", sku: "-", price: 25900, qoh: 136, backgroundColor: "#c7e3ff", titleColor: "#1e90ff" },
|
|
{ id: 7, name: "ASA K-12", sku: "-", price: 7300, qoh: 138, backgroundColor: "#c7e3ff", titleColor: "#1e90ff" },
|
|
{ id: 8, name: "NRTN - K12", sku: "-", price: 7300, qoh: 0, backgroundColor: "#fecaca", titleColor: "#dc2626" },
|
|
{ id: 9, name: "JRG - K12", sku: "-", price: 8700, qoh: 71, backgroundColor: "#bbf7d0", titleColor: "#22c55e" },
|
|
{ id: 10, name: "SGN - K16", sku: "-", price: 8900, qoh: 10, backgroundColor: "#fef9c3", titleColor: "#eab308" },
|
|
{ id: 11, name: "SGN - K16", sku: "-", price: 6800, qoh: 140, backgroundColor: "#c7e3ff", titleColor: "#1e90ff" },
|
|
{ id: 12, name: "NTN - K16", sku: "-", price: 9200, qoh: 151, backgroundColor: "#c7e3ff", titleColor: "#1e90ff" },
|
|
{ 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: "#fff", borderLeftWidth: 4, borderLeftColor: config.color.textbiru }]}>
|
|
<Text style={[styles.cardTitle, { color: config.color.textbiru }]}>{item.name}</Text>
|
|
<View style={styles.cardDates}>
|
|
<Text style={styles.cardDate}>Rp {item.price}</Text>
|
|
<View style={{alignItems:'flex-end'}}>
|
|
<Text style={{color: config.color.primary, fontSize:18, fontWeight: 'bold'}}>Balance: {item.qoh}</Text>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
</>
|
|
);
|
|
|
|
const searchFilter = (item : any) => {
|
|
const query = searchQuery.toLowerCase();
|
|
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={{ backgroundColor: config.color.primary, height: 20 }}></View>
|
|
<View style={{
|
|
overflow: "hidden",
|
|
height: 70,
|
|
flexDirection: "row",
|
|
alignItems: "center",
|
|
backgroundColor: config.color.primary
|
|
, paddingHorizontal: 10
|
|
, paddingLeft:20
|
|
}}>
|
|
<View style={[{
|
|
flexDirection: 'row'
|
|
, flex: 1
|
|
, alignItems: 'center'
|
|
, justifyContent: 'center'
|
|
}]}>
|
|
<TextInput
|
|
style={styles.searchInput}
|
|
placeholder="Search..."
|
|
value={searchQuery}
|
|
onChangeText={setSearchQuery}
|
|
/>
|
|
</View>
|
|
<View style={[{ justifyContent: "center", alignItems: "center", width: 60, paddingVertical: 20, paddingBottom: 30 }]}>
|
|
<TouchableOpacity>
|
|
<Ionicons name="search" size={24} color="white" />
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
<View style={styles.container}>
|
|
|
|
{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>
|
|
</> :<></>}
|
|
<View style={{flexDirection:"column"}}>
|
|
<View style={{height: Dimensions.get('window').height-120, flexDirection:"column"}}>
|
|
<FlatList
|
|
contentContainerStyle={[styles.listContainer]}
|
|
data={products.filter(searchFilter)}
|
|
renderItem={renderStockCard}
|
|
keyExtractor={(item:any) => item.id.toString()}
|
|
numColumns={0}
|
|
/>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
<View style={{
|
|
height: 60,
|
|
backgroundColor: "#fff",
|
|
flexDirection: "row",
|
|
shadowColor: "#000",
|
|
shadowOffset: {
|
|
width: 0,
|
|
height: 2,
|
|
},
|
|
shadowOpacity: 0.25,
|
|
shadowRadius: 3.84,
|
|
elevation: 5,
|
|
}}>
|
|
<TouchableOpacity onPress={() => navigation.navigate('home')} style={{ width: 140 }}>
|
|
<View style={{ justifyContent: "center", height: 60, flexDirection: "column", alignItems: "center" }}>
|
|
<Ionicons name="home" size={24} color={config.color.textbiru} />
|
|
<Text style={{ color: config.color.textbiru }}>Home</Text>
|
|
</View>
|
|
</TouchableOpacity>
|
|
<View style={{ flex: 1 }}>
|
|
<TouchableOpacity onPress={() => navigation.navigate('order')} activeOpacity={1} style={{ justifyContent: "center", height: 60, flexDirection: "column", alignItems: "center" }}>
|
|
<Image style={{
|
|
width: 60,
|
|
height: 60,
|
|
marginBottom: 30,
|
|
resizeMode: 'contain'
|
|
}} source={require('../../assets/images/g42.png')} />
|
|
</TouchableOpacity>
|
|
</View>
|
|
<TouchableOpacity onPress={() => navigation.navigate('profile')} style={{ width: 140 }}>
|
|
<View style={{ justifyContent: "center", height: 60, flexDirection: "column", alignItems: "center" }}>
|
|
<Ionicons name="person" size={24} color={config.color.textbiru} />
|
|
<Text style={{ color: config.color.textbiru }}>Profile</Text>
|
|
</View>
|
|
</TouchableOpacity>
|
|
</View>
|
|
</>
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
padding: 10,
|
|
},
|
|
listContainer:{
|
|
paddingHorizontal:5
|
|
},
|
|
title: {
|
|
fontSize: 20,
|
|
fontWeight: 'bold',
|
|
marginBottom: 10,
|
|
},
|
|
searchInput: {
|
|
flex:1,
|
|
height: 40,
|
|
paddingHorizontal: 10,
|
|
backgroundColor:"#fff",
|
|
borderRadius: 5,
|
|
},
|
|
card: {
|
|
flex:1,
|
|
marginBottom: 20,
|
|
padding: 10,
|
|
marginHorizontal:10,
|
|
borderRadius: 8,
|
|
shadowColor: '#000',
|
|
shadowOpacity: 0.2,
|
|
shadowOffset: { width: 0, height: 2 },
|
|
shadowRadius: 4,
|
|
},
|
|
cardTitle: {
|
|
fontSize:18,
|
|
fontWeight: 'bold',
|
|
paddingVertical: 5,
|
|
},
|
|
cardDates: {
|
|
flexDirection: 'row',
|
|
paddingVertical: 5,
|
|
justifyContent: 'space-between',
|
|
},
|
|
cardDate: {
|
|
color: '#888',
|
|
fontSize: 18,
|
|
fontWeight:'semibold'
|
|
},
|
|
cardContent: {
|
|
justifyContent: 'space-between',
|
|
paddingTop: 10,
|
|
},
|
|
attendeesContainer: {
|
|
flexWrap:'wrap',
|
|
flexDirection: 'row',
|
|
paddingHorizontal: 10,
|
|
},
|
|
attendeeImage: {
|
|
width: 30,
|
|
height: 30,
|
|
borderRadius: 20,
|
|
marginLeft: -10,
|
|
borderWidth:0.5,
|
|
marginTop:3,
|
|
},
|
|
buttonsContainer: {
|
|
flexDirection: 'row',
|
|
},
|
|
actionButton: {
|
|
marginTop:15,
|
|
backgroundColor: '#DCDCDC',
|
|
padding:8,
|
|
borderRadius: 5,
|
|
borderWidth:1,
|
|
borderColor:'#00008B',
|
|
marginRight: 10,
|
|
},
|
|
buttonText: {
|
|
color: '#00008B',
|
|
},
|
|
});
|
|
|
|
export default StockScreen; |