816 lines
25 KiB
TypeScript
816 lines
25 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
|
import { StyleSheet, View, Text, Dimensions, TextInput, FlatList, TouchableOpacity, Alert, BackHandler, Modal, ImageBackground, Image } from 'react-native';
|
|
import { Picker } from '@react-native-picker/picker';
|
|
import { RootStackParamList } from '@/types';
|
|
import { useNavigation, NavigationProp, useFocusEffect } from '@react-navigation/native';
|
|
import { currency } from '@/components/Helper';
|
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
import { cfg, generateUUID } from '@/components/lib/cfg';
|
|
import { DB } from '@/components/lib/db';
|
|
import CustomPicker from '@/components/native/dropdown';
|
|
import { Ionicons } from '@expo/vector-icons'; // Optional for adding icons
|
|
import config from '../../components/data/config.json';
|
|
import InvoiceScreen from '@/components/pageComponent/invoice';
|
|
import TimeLive from '@/components/Time';
|
|
|
|
var width = Dimensions.get('window').width;
|
|
var height = Dimensions.get('window').height;
|
|
|
|
const ProductCard = ({ item, onSlopChange, onBalChange, onBoxChange }: {
|
|
item: { id: number; name: string; price: number; slop: number; bal: number; box: number };
|
|
onSlopChange: (id: number, value: string) => void;
|
|
onBalChange: (id: number, value: string) => void;
|
|
onBoxChange: (id: number, value: string) => void;
|
|
}) => {
|
|
|
|
|
|
return (
|
|
<View style={styles.productCard}>
|
|
<View style={styles.productRow}>
|
|
<View style={styles.productInfo}>
|
|
<Text style={styles.productName}>{item.name}</Text>
|
|
</View>
|
|
<View style={{ alignItems: 'flex-end' }}>
|
|
<Text style={styles.productPrice}>Rp{currency(item.price*10, 0)}</Text>
|
|
</View>
|
|
</View>
|
|
<View style={styles.productRow}>
|
|
<View>
|
|
<View style={styles.satuan}>
|
|
<Text style={[styles.textSatuan,{ color: '#fff' }]}>DOS</Text>
|
|
</View>
|
|
<TextInput
|
|
style={styles.input}
|
|
keyboardType="numeric"
|
|
value={String(item.box)}
|
|
onChangeText={(text) => onBoxChange(item.id, text)}
|
|
/>
|
|
</View>
|
|
<View>
|
|
<View style={styles.satuan}>
|
|
<Text style={[styles.textSatuan,{ color: '#fff' }]}>BAL</Text>
|
|
</View>
|
|
<TextInput
|
|
style={styles.input}
|
|
keyboardType="numeric"
|
|
value={String(item.bal)}
|
|
onChangeText={(text) => onBalChange(item.id, text)}
|
|
/>
|
|
</View>
|
|
<View>
|
|
<View style={styles.satuan}>
|
|
<Text style={[styles.textSatuan,{ color: '#fff' }]}>SLOP</Text>
|
|
</View>
|
|
<TextInput
|
|
style={styles.input}
|
|
keyboardType="numeric"
|
|
value={String(item.slop)}
|
|
onChangeText={(text) => onSlopChange(item.id, text)}
|
|
/>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
);
|
|
};
|
|
|
|
const App = () => {
|
|
const [employeeData, setEmployeeData] = useState({ name: '', work_email: '', work_phone: '' });
|
|
const [products, setProducts] = useState<any>([]);
|
|
const [alamat,SetAlamat] = useState('-');
|
|
const [loaderStatus, setLoaderStatus] = useState(false);
|
|
const [salesName, setSalesName] = useState('-')
|
|
const [sendData, setSendData] = useState<any>({ invoice: {}, dataPilihan :{}})
|
|
const [invoice , setInvoice] = useState(false)
|
|
|
|
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
|
|
|
useFocusEffect(
|
|
React.useCallback(() => {
|
|
const onBackPress = () => {
|
|
console.log(invoice)
|
|
if (invoice == true) {
|
|
setInvoice(false);
|
|
} else {
|
|
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,invoice, setInvoice])
|
|
);
|
|
|
|
const ToInsert = function (array: any, table: any, wht: any) {
|
|
array = array ? array : [];
|
|
wht = wht ? wht : [];
|
|
table = table ? table : "example";
|
|
let s = array;
|
|
if (s.length > 0) {
|
|
var y = Object.keys(s[0]);
|
|
var x = '';
|
|
x += 'INSERT INTO ';
|
|
x += table;
|
|
x += '(';
|
|
x += y.map(function (u) {
|
|
return ` ${u} `
|
|
}).join(',');
|
|
x += ')';
|
|
x += '\n';
|
|
x += 'SELECT ';
|
|
x += y.map(function (g) {
|
|
return `a.${g}`;
|
|
});
|
|
x += ' FROM (';
|
|
x += s.map(function (w: any) {
|
|
var f = ` SELECT `;
|
|
f += y.map(function (q) {
|
|
if (w[q] != null) {
|
|
if (typeof w[q] === 'boolean') {
|
|
return `${w[q]} AS ${q}`;
|
|
}
|
|
if (typeof w[q] === 'number') {
|
|
return `${w[q]} AS ${q}`;
|
|
}
|
|
if (typeof w[q] === 'object' && w[q] == null) {
|
|
return `null AS ${q}`;
|
|
}
|
|
if (w[q] == 'timestamp') {
|
|
return `now() AS ${q}`;
|
|
}
|
|
return `'${w[q].toString().replace(/\"/g, "\\\"")}' AS ${q}`;
|
|
}
|
|
else {
|
|
return `'-' AS ${q}`;
|
|
}
|
|
}).join(",");
|
|
return f;
|
|
}).join("\n UNION ALL \n")
|
|
x += ') a';
|
|
if (Array.isArray(wht) && wht.length > 0) {
|
|
x += ` LEFT JOIN ${table} ON `
|
|
x += wht.map(function (whtx) {
|
|
return ` ${table}.${whtx} = a.${whtx} `;
|
|
}).join(" AND ");
|
|
x += ` WHERE `;
|
|
x += wht.map(function (whtx) {
|
|
return ` ${table}.${whtx} IS NULL `;
|
|
}).join(" AND ");
|
|
}
|
|
return x;
|
|
} else {
|
|
return [];
|
|
}
|
|
};
|
|
|
|
useEffect(()=>{
|
|
(async function(){
|
|
let data : any = cfg.dataPilihan.product;
|
|
let y = data.map((d:any, i:any)=>{
|
|
return {
|
|
id: d.id,
|
|
name: d.name,
|
|
sku:'-',
|
|
price: Number(d.list_price),
|
|
slop:0,
|
|
bal:0,
|
|
box:0
|
|
}
|
|
});
|
|
setProducts(y);
|
|
})();
|
|
},[])
|
|
|
|
const [isChanged, setIsChanged] = useState(false);
|
|
|
|
const handleSlopChange = (id:any, value:any) => {
|
|
setProducts(
|
|
products.map((product:any) =>
|
|
product.id === id ? { ...product, slop: parseInt(value) || 0 } : product
|
|
)
|
|
);
|
|
setIsChanged(true);
|
|
};
|
|
|
|
const handleBalChange = (id:any, value:any) => {
|
|
setProducts(
|
|
products.map((product:any) =>
|
|
product.id === id ? { ...product, bal: parseInt(value) || 0 } : product
|
|
)
|
|
);
|
|
setIsChanged(true);
|
|
};
|
|
|
|
const handleBoxChange = (id:any, value:any) => {
|
|
setProducts(
|
|
products.map((product:any) =>
|
|
product.id === id ? { ...product, box: parseInt(value) || 0 } : product
|
|
)
|
|
);
|
|
setIsChanged(true);
|
|
};
|
|
|
|
const calculateTotal = () => {
|
|
return products.reduce((total:any, product:any) => {
|
|
return total + ((product.slop*10) + (product.bal*100) + (product.box*500)) * product.price;
|
|
}, 0);
|
|
};
|
|
|
|
|
|
const renderProductItem = (props:any) => (
|
|
<ProductCard
|
|
item={props?.item}
|
|
onSlopChange={handleSlopChange}
|
|
onBalChange={handleBalChange}
|
|
onBoxChange={handleBoxChange}
|
|
/>
|
|
);
|
|
|
|
const [selectedValue, setSelectedValue] = useState('');
|
|
|
|
const options = cfg.dataPilihan.customer.length > 0 ? [{ label: "Pilih Customer", value:""}].concat(cfg.dataPilihan.customer.map((data:any, i:number)=>{
|
|
return { label: data.name, value: typeof data.id === 'number' ? data.id.toString(): data.id };
|
|
})) : [
|
|
{ label: 'CAHAYA UTAMA', value: 'CAHAYA UTAMA' },
|
|
{ label: 'MERTASARI', value: 'MERTASARI' },
|
|
{ label: 'PRIMA JAYA', value: 'PRIMA JAYA' },
|
|
{ label: 'ARIS Dalung', value: 'ARIS Dalung' },
|
|
{ label: 'JAYA KERTI Ubung', value: 'JAYA KERTI Ubung' },
|
|
{ label: 'JAYA KERTI Gatsu', value: 'JAYA KERTI Gatsu' },
|
|
{ label: 'AGUS WISNU', value: 'AGUS WISNU' },
|
|
{ label: 'SINAR WANGI', value: 'SINAR WANGI' },
|
|
{ label: 'CRYSTAL', value: 'CRYSTAL' },
|
|
];
|
|
|
|
useEffect(() => {
|
|
getEmployeeData();
|
|
}, []);
|
|
|
|
const getEmployeeData = async () => {
|
|
try {
|
|
const jsonValue = await AsyncStorage.getItem('login');
|
|
if (jsonValue !== null) {
|
|
const data = JSON.parse(jsonValue);
|
|
const sales = data[0];
|
|
setEmployeeData(data[0]);
|
|
setSalesName(sales.name.toUpperCase())
|
|
}
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
};
|
|
|
|
const mapTax = function(){
|
|
|
|
}
|
|
|
|
const mapsDataOrder = function(data:any){
|
|
cfg.invoice.token_access = generateUUID()
|
|
return [{
|
|
company_id: data.company_id ? data.company_id : 1,
|
|
partner_id: data.partner_id ? data.partner_id : null,
|
|
partner_invoice_id: data.partner_id ? data.partner_id : null,
|
|
partner_shipping_id: data.partner_id ? data.partner_id : null,
|
|
user_id : data.user_id ? data.user_id : null ,
|
|
team_id : data.team_id ? data.team_id : 1 ,
|
|
create_uid: data.create_uid ? data.create_uid : null,
|
|
write_uid : data.create_uid ? data.create_uid : 1 ,
|
|
name : data.name ? data.name : null ,
|
|
state: 'draft' ,
|
|
access_token: cfg.invoice.token_access,
|
|
client_order_ref: data.email ? data.email :null ,
|
|
invoice_status: data.invoice_status ? data.invoice_status :"no" ,
|
|
validity_date: data.validity_date ? data.validity_date :"timestamp" ,
|
|
currency_id: data.currency_id ? data.currency_id :12 ,
|
|
currency_rate: data.currency_rate ? data.currency_rate :1.0 ,
|
|
amount_untaxed: data.amount_untaxed ? data.amount_untaxed :null ,
|
|
amount_tax: data.amount_tax ? data.amount_tax :null ,
|
|
amount_total: data.amount_total ? data.amount_total :null ,
|
|
amount_to_invoice: data.amount_to_invoice ? data.amount_to_invoice :null ,
|
|
locked: data.locked ? data.locked :false ,
|
|
require_signature: data.require_signature ? data.require_signature :true ,
|
|
require_payment: data.require_payment ? data.require_payment :false ,
|
|
create_date: data.create_date ? data.require_payment :"timestamp" ,
|
|
date_order: data.date_order ? data.date_order :"timestamp" ,
|
|
write_date: data.write_date ? data.write_date :"timestamp" ,
|
|
prepayment_percent: data.prepayment_percent ? data.prepayment_percent :1 ,
|
|
warehouse_id: data.warehouse_id ? data.warehouse_id :1 ,
|
|
picking_policy: data.picking_policy ? data.picking_policy :"direct" ,
|
|
x_studio_sales_man: data.x_studio_sales_man ? data.x_studio_sales_man : null
|
|
}];
|
|
}
|
|
|
|
const mapsDataOrderLine = function(data:any){
|
|
return Array.isArray(data) ? data.map((d,i)=>{
|
|
return {
|
|
order_id: d.order_id? d.order_id : null,
|
|
sequence : d.sequence ? d.sequence : 10,
|
|
company_id: d.company_id ? d.company_id : 1,
|
|
currency_id: d.currency_id ? d.currency_id : 12,
|
|
order_partner_id: d.order_partner_id ? d.order_partner_id : null,
|
|
salesman_id: d.salesman_id ? d.salesman_id : 2,
|
|
product_id: d.product_id ? d.product_id : null,
|
|
product_uom: d.product_uom ? d.product_uom : 27,
|
|
create_uid: d.create_uid ? d.create_uid : null,
|
|
write_uid: d.write_uid ? d.write_uid : null,
|
|
state: d.state ? d.state : "sale",
|
|
qty_delivered_method: d.qty_delivered_method ? d.qty_delivered_method : "stock_move",
|
|
invoice_status: d.invoice_status ? d.invoice_status : "no",
|
|
name: d.name ? d.name : null,
|
|
product_uom_qty: d.product_uom_qty ? d.product_uom_qty : 0,
|
|
price_unit: d.price_unit ? d.price_unit : 0,
|
|
discount: d.discount ? d.discount : 0,
|
|
price_subtotal: d.price_subtotal ? d.price_subtotal : 0,
|
|
price_total: d.price_total ? d.price_total : 0,
|
|
price_reduce_taxexcl: d.price_reduce_taxexcl ? d.price_reduce_taxexcl : 0,
|
|
price_reduce_taxinc: d.price_reduce_taxinc ? d.price_reduce_taxinc : 0,
|
|
qty_delivered: d.qty_delivered ? d.qty_delivered : 0,
|
|
qty_invoiced: d.qty_invoiced ? d.qty_invoiced : 0,
|
|
qty_to_invoice: d.qty_to_invoice ? d.qty_to_invoice : 0,
|
|
untaxed_amount_invoiced: d.untaxed_amount_invoiced ? d.untaxed_amount_invoiced : 0,
|
|
untaxed_amount_to_invoice: d.untaxed_amount_to_invoice ? d.untaxed_amount_to_invoice : 0,
|
|
is_downpayment: d.is_downpayment ? d.is_downpayment : false,
|
|
create_date: d.create_date ? d.create_date : 'timestamp',
|
|
write_date: d.write_date ? d.write_date : 'timestamp',
|
|
price_tax: d.price_tax ? d.price_tax : 0,
|
|
product_packaging_qty: d.product_packaging_qty ? d.product_pakaging_qty : 0,
|
|
customer_lead: d.customer_lead ? d.customer_lead : 0,
|
|
is_service: d.is_service ? d.is_service : false,
|
|
planning_hours_planned: d.planning_hours_planned ? d.planning_hours_planned : 0,
|
|
planning_hours_to_plan: d.planning_hours_to_plan ? d.planning_hours_to_plan : 0,
|
|
}
|
|
}):[];
|
|
}
|
|
|
|
function getFormattedDate() {
|
|
const today = new Date();
|
|
const day = String(today.getDate()).padStart(2, '0');
|
|
const month = String(today.getMonth() + 1).padStart(2, '0'); // Months are zero-based
|
|
const year = today.getFullYear();
|
|
|
|
return `${day}/${month}/${year}`;
|
|
}
|
|
|
|
const saveAction = async ()=>{
|
|
|
|
|
|
const activeTax = 1;
|
|
const [tax] = cfg.dataPilihan.tax.filter((s:any)=> s.id == activeTax );
|
|
const taxValue = Number(tax?.amount) / 100;
|
|
const sales: any = await AsyncStorage.getItem('login')
|
|
const [salesman]: any = JSON.parse(sales);
|
|
let [cus] = cfg.dataPilihan.customer.filter((data:any)=> data.id == selectedValue );
|
|
if(!cus){
|
|
Alert.alert("Warning", "silahkan pilih customer terlebih dahulu!");
|
|
return true;
|
|
}
|
|
cus = cus ? cus:null;
|
|
let totalHarga = 0;
|
|
let amount_untaxed = 0;
|
|
let amount_tax = 0;
|
|
let amount_total = 0;
|
|
let amount_to_invoice = 0;
|
|
// fungsi penghiungan tax
|
|
const taxCount = function(){
|
|
return {
|
|
nilaiTax : (taxValue * totalHarga),
|
|
nilaiTotalAndTax : ((1+taxValue) * totalHarga),
|
|
nilaiTotal : totalHarga
|
|
}
|
|
}
|
|
|
|
const perbandinganHarga = {
|
|
pcs : 1,
|
|
slop : 10,
|
|
bal : 100,
|
|
box : 500
|
|
}
|
|
|
|
let getProduk = products.filter((s:any)=>{
|
|
if(s.box != 0 || s.bal != 0 || s.slop != 0 ){
|
|
return s;
|
|
}
|
|
});
|
|
|
|
products.forEach((n: any, i: any) => {
|
|
let box = n.box * perbandinganHarga.box * n.price;
|
|
let bal = n.bal * perbandinganHarga.bal * n.price;
|
|
let slop = n.slop * perbandinganHarga.slop * n.price;
|
|
totalHarga += (box + bal + slop);
|
|
});
|
|
|
|
if (totalHarga === 0) {
|
|
Alert.alert("Warning", "silahkan isi total pesanan terlebih dahulu!");
|
|
return true;
|
|
}
|
|
setLoaderStatus(true)
|
|
|
|
const [newName]: any = await DB(`
|
|
SELECT 'S' || LPAD((name + 1)::text, 5, '0') as name
|
|
FROM (
|
|
SELECT split_part(name, 'S', -1)::integer AS name
|
|
FROM sale_order
|
|
ORDER BY name DESC
|
|
LIMIT 1
|
|
) a;
|
|
`);
|
|
const name = newName.name;
|
|
// default user_id menggunakan administrator
|
|
|
|
const user_id = 2;
|
|
|
|
// default company_id administrator
|
|
const company_id = 1;
|
|
|
|
let dataNilai = taxCount();
|
|
amount_untaxed = dataNilai.nilaiTotal
|
|
amount_tax = dataNilai.nilaiTax;
|
|
amount_total = dataNilai.nilaiTotalAndTax;
|
|
|
|
try{
|
|
(async function SimpanData(){
|
|
|
|
let dataOrder = mapsDataOrder({
|
|
user_id: user_id,
|
|
company_id: company_id,
|
|
partner_id: cus ? cus.id : 0,
|
|
create_uid: salesman ? salesman.id : null,
|
|
email: salesman ? salesman.work_email : '',
|
|
amount_untaxed: amount_untaxed,
|
|
amount_tax: amount_tax,
|
|
amount_total: amount_total,
|
|
amount_to_invoice: amount_total,
|
|
name: name,
|
|
x_studio_sales_man: salesman?.id
|
|
});
|
|
|
|
cfg.invoice.sales_order = dataOrder;
|
|
cfg.invoice.times = getFormattedDate();
|
|
|
|
setSendData((function (d: any) {
|
|
d.invoice.sales_order = cfg.invoice.sales_order;
|
|
d.invoice.times = cfg.invoice.times;
|
|
d.dataPilihan = cfg.dataPilihan;
|
|
return d;
|
|
})(sendData));
|
|
|
|
let data: any = await DB(
|
|
ToInsert(dataOrder, "sale_order", [])
|
|
);
|
|
|
|
let ds: any = await DB(`SELECT id as newId FROM sale_order ORDER BY id DESC LIMIT 1`);
|
|
|
|
let newProduct:any = [];
|
|
|
|
getProduk.forEach((c:any)=>{
|
|
// dos
|
|
if(c.box > 0){
|
|
newProduct.push({
|
|
id: c.id,
|
|
name: c.name,
|
|
price: c.price * 500,
|
|
product_uom: 30,
|
|
qty : c.box,
|
|
sku : c.sku
|
|
});
|
|
}
|
|
// bal
|
|
if(c.bal > 0){
|
|
newProduct.push({
|
|
id: c.id,
|
|
name: c.name,
|
|
price: c.price * 100,
|
|
product_uom: 29,
|
|
qty : c.bal,
|
|
sku : c.sku
|
|
});
|
|
}
|
|
// slop
|
|
if(c.slop > 0){
|
|
newProduct.push({
|
|
id: c.id,
|
|
name: c.name,
|
|
price: c.price * 10,
|
|
product_uom: 28,
|
|
qty : c.slop,
|
|
sku : c.sku
|
|
});
|
|
}
|
|
});
|
|
|
|
|
|
let dataItem: any = mapsDataOrderLine(newProduct.map((s: any) => {
|
|
return {
|
|
company_id: company_id,
|
|
product_id: s.id,
|
|
salesman_id : salesman.id,
|
|
order_partner_id: cus.id,
|
|
create_uid: salesman.id,
|
|
write_uid: salesman.id,
|
|
name : s.name,
|
|
product_uom: s.product_uom,
|
|
product_uom_qty : s.qty,
|
|
price_unit: s.price,
|
|
price_subtotal: s.qty * s.price,
|
|
price_total: (s.qty * s.price) * (1 + taxValue),
|
|
price_reduce_taxexcl: s.price,
|
|
price_reduce_taxinc: s.price * (taxValue),
|
|
price_tax: s.price * (1+taxValue),
|
|
order_id: Number(ds[0].newid)
|
|
}
|
|
}));
|
|
|
|
cfg.invoice.sales_order_line = dataItem;
|
|
|
|
setSendData((function(d:any){
|
|
d.invoice.sales_order_line = dataItem;
|
|
return d;
|
|
})(sendData));
|
|
|
|
// console.log("Produk :", ToInsert(dataItem, "sale_order_line",[]));
|
|
let data2:any = await DB(
|
|
ToInsert(dataItem, "sale_order_line", [])
|
|
);
|
|
|
|
let saveTax:any = await DB(`SELECT * FROM sale_order_line WHERE order_id = ${ds[0].newid}`)
|
|
let saveTaxItem = saveTax.map(function(item:any){
|
|
return {
|
|
sale_order_line_id : item.id,
|
|
account_tax_id : 1
|
|
}
|
|
});
|
|
|
|
let data3: any = await DB(
|
|
ToInsert(saveTaxItem, "account_tax_sale_order_line_rel", [])
|
|
);
|
|
|
|
console.log("Order :", "----------------------------------------");
|
|
setLoaderStatus(false)
|
|
clearForm()
|
|
setInvoice(true);
|
|
})();
|
|
}catch(e){
|
|
console.log(e);
|
|
setLoaderStatus(false)
|
|
}
|
|
|
|
}
|
|
|
|
const clearForm = () => {
|
|
setSelectedValue('')
|
|
setProducts(
|
|
products.map((product: any) => ({ ...product, slop: 0, bal: 0, box: 0 }))
|
|
);
|
|
}
|
|
|
|
const callNumber = () => {
|
|
console.log("call")
|
|
}
|
|
|
|
let c:any = 1;
|
|
|
|
return (
|
|
<>
|
|
{
|
|
invoice?<>
|
|
<InvoiceScreen cfg={sendData} navigation={navigation} />
|
|
</>:<>
|
|
{loaderStatus === true ? <>
|
|
<View style={styles.loader}>
|
|
<Image
|
|
source={require('../../assets/images/loader/load.gif')}
|
|
style={{ width: 120, height: 120 }}
|
|
resizeMode="contain" // You can adjust this based on how you want the image to scale
|
|
/>
|
|
</View>
|
|
</>:<></>}
|
|
<View style={styles.container}>
|
|
<ImageBackground
|
|
source={require('../../assets/images/bg/SORT_bg_Order.png')}
|
|
style={{ justifyContent: 'flex-start', top: 0, height:300 }}
|
|
>
|
|
<View style={{padding: 20}}>
|
|
<View style={styles.informationContainer}>
|
|
<View style={{
|
|
flexDirection:"row",
|
|
width:width-80
|
|
}}>
|
|
<View style={{flex:1}}>
|
|
<Text style={styles.label}>SALES</Text>
|
|
<Text style={styles.name}>{salesName}</Text>
|
|
</View>
|
|
<View>
|
|
<TimeLive/>
|
|
</View>
|
|
</View>
|
|
<Text style={styles.label}>CUSTOMER</Text>
|
|
<View style={{ marginBottom:10, flexDirection: "row", width: width - 60 }}>
|
|
<View style={{ width: width - 120 }}>
|
|
<CustomPicker
|
|
options={options}
|
|
selectedValue={selectedValue}
|
|
onValueChange={setSelectedValue}
|
|
/>
|
|
</View>
|
|
<View style={{flex:1, justifyContent:'center', alignItems:'flex-end'}}>
|
|
<TouchableOpacity onPress={callNumber}>
|
|
<Ionicons
|
|
name="logo-whatsapp"
|
|
size={30}
|
|
color={"white"}
|
|
style={{ marginRight: 15 }}
|
|
/>
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
<Text style={styles.label}>ALAMAT</Text>
|
|
{selectedValue && selectedValue.toLocaleLowerCase() != 'pilih customer' ? <>
|
|
<Text style={styles.alamat}>{(function(data:any){
|
|
if(Array.isArray(data)){
|
|
let [d] = data;
|
|
return d.street ? d.street:'-';
|
|
}
|
|
return '-'
|
|
})(cfg.dataPilihan.customer.filter((pop: any) => pop.id == selectedValue)) }</Text>
|
|
</> : <>
|
|
<Text style={styles.alamat}>-</Text>
|
|
</>}
|
|
</View>
|
|
</View>
|
|
</ImageBackground>
|
|
<FlatList
|
|
data={products}
|
|
style={styles.productList}
|
|
renderItem={renderProductItem}
|
|
keyExtractor={(item) => item.id.toString()}
|
|
contentContainerStyle={{ paddingHorizontal: 16, paddingBottom: 100 }}
|
|
/>
|
|
<View style={styles.bottomContainer}>
|
|
<View>
|
|
<Text style={styles.totalText}>Total:</Text>
|
|
<Text style={styles.totalPrice}>Rp{currency(calculateTotal(), 0)}</Text>
|
|
</View>
|
|
<TouchableOpacity style={styles.continueButton} onPress={() => {
|
|
saveAction()
|
|
}}>
|
|
<Text style={styles.continueButtonText}>Simpan</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
</>
|
|
}
|
|
</>
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
loader:{
|
|
position:'absolute',
|
|
zIndex:1,
|
|
height:'100%',
|
|
width:'100%',
|
|
backgroundColor: config.color.primary,
|
|
flexDirection :'row',
|
|
justifyContent:'center',
|
|
alignItems:'center'
|
|
},
|
|
container: {
|
|
position:'relative',
|
|
flex: 1,
|
|
backgroundColor: '#f0f0f0',
|
|
paddingTop: 0,
|
|
overflow: "hidden"
|
|
},
|
|
alamat:{
|
|
fontSize: 14,
|
|
color:'white'
|
|
},
|
|
header: {
|
|
position: "absolute",
|
|
top: 0,
|
|
left: 0,
|
|
height: 200,
|
|
width: "100%",
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
paddingHorizontal: 16,
|
|
},
|
|
informationContainer: {
|
|
width: width,
|
|
height: 200,
|
|
marginLeft: 16,
|
|
marginTop: 16,
|
|
},
|
|
name: {
|
|
fontSize: 20,
|
|
marginBottom: 5,
|
|
fontWeight: 'bold',
|
|
color: '#ffffff',
|
|
},
|
|
label: {
|
|
fontSize: 12,
|
|
color: '#ffffff',
|
|
marginBottom: 5,
|
|
marginTop: 10,
|
|
fontWeight:'700'
|
|
},
|
|
productList: {
|
|
flex: 1,
|
|
paddingTop: 5,
|
|
},
|
|
productCard: {
|
|
backgroundColor: '#fff',
|
|
borderRadius: 8,
|
|
shadowColor: '#000',
|
|
shadowOpacity: 0.2,
|
|
shadowOffset: { width: 0, height: 2 },
|
|
shadowRadius: 4,
|
|
padding: 16,
|
|
marginBottom: 16,
|
|
},
|
|
productRow: {
|
|
flexDirection: 'row',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
},
|
|
productInfo: {
|
|
flex: 1,
|
|
marginRight: 16,
|
|
},
|
|
productName: {
|
|
fontSize: 18,
|
|
fontWeight: 'bold',
|
|
marginBottom: 4,
|
|
},
|
|
productPrice: {
|
|
fontSize: 16,
|
|
fontWeight: 'bold',
|
|
color: 'red',
|
|
},
|
|
textSatuan: {
|
|
fontSize: 16,
|
|
fontWeight:'600'
|
|
},
|
|
satuan: {
|
|
fontWeight: 'bold',
|
|
height: 40,
|
|
width: 75,
|
|
backgroundColor: '#2563eb',
|
|
borderRadius: 4,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
marginTop: 10,
|
|
marginBottom: 5,
|
|
paddingVertical: 5
|
|
},
|
|
input: {
|
|
height: 40,
|
|
borderColor: '#ccc',
|
|
borderWidth: 1,
|
|
borderRadius: 8,
|
|
paddingHorizontal: 10,
|
|
marginTop: 10,
|
|
marginBottom: 10,
|
|
textAlign: 'center',
|
|
},
|
|
bottomContainer: {
|
|
position: 'absolute',
|
|
bottom: 0,
|
|
left: 0,
|
|
right: 0,
|
|
padding: 15,
|
|
flexDirection: 'row',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
backgroundColor: '#2563eb',
|
|
},
|
|
totalText: {
|
|
fontSize: 14,
|
|
fontWeight: 'bold',
|
|
color: '#fff',
|
|
},
|
|
totalPrice: {
|
|
fontSize: 24,
|
|
fontWeight: 'bold',
|
|
color: '#fff',
|
|
},
|
|
continueButton: {
|
|
backgroundColor: '#93C854',
|
|
borderRadius: 8,
|
|
paddingVertical: 10,
|
|
paddingHorizontal: 20,
|
|
alignItems: 'center',
|
|
},
|
|
continueButtonText: {
|
|
color: '#fff',
|
|
fontSize: 18,
|
|
fontWeight: 'bold',
|
|
},
|
|
});
|
|
|
|
export default App;
|