diff --git a/package-lock.json b/package-lock.json index d4a8d80..27eacef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,6 @@ "crypto-js": "^4.2.0", "dayjs": "^1.11.13", "html-to-image": "^1.11.11", - "html2canvas": "^1.4.1", "jsqr": "^1.4.0", "qr-scanner": "^1.4.2", "qrcode.react": "^3.1.0", @@ -32,6 +31,7 @@ "react-router-dom": "^6.24.0", "react-scripts": "5.0.1", "react-switch": "^7.0.0", + "react-to-print": "^3.1.1", "react-youtube": "^10.1.0", "smooth-scroll-into-view-if-needed": "^2.0.2", "socket.io-client": "^4.7.5", @@ -6951,15 +6951,6 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "license": "MIT" }, - "node_modules/base64-arraybuffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", - "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -7874,15 +7865,6 @@ "postcss": "^8.4" } }, - "node_modules/css-line-break": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", - "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", - "license": "MIT", - "dependencies": { - "utrie": "^1.0.2" - } - }, "node_modules/css-loader": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", @@ -11155,19 +11137,6 @@ } } }, - "node_modules/html2canvas": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", - "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", - "license": "MIT", - "dependencies": { - "css-line-break": "^2.1.0", - "text-segmentation": "^1.0.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/htmlparser2": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", @@ -18206,6 +18175,15 @@ "react-dom": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/react-to-print": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/react-to-print/-/react-to-print-3.1.1.tgz", + "integrity": "sha512-N0MUMhpl8nkGri13BjP7zusj3B/j+1eMOTt8N8PYuhBYGzA4PqTXqcihJ9cZw996dvhV6mBdwafIQCg3Ap5bKg==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ~19" + } + }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -20504,15 +20482,6 @@ "node": ">=8" } }, - "node_modules/text-segmentation": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", - "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", - "license": "MIT", - "dependencies": { - "utrie": "^1.0.2" - } - }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -21055,15 +21024,6 @@ "node": ">= 0.4.0" } }, - "node_modules/utrie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", - "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", - "license": "MIT", - "dependencies": { - "base64-arraybuffer": "^1.0.2" - } - }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", diff --git a/package.json b/package.json index fe2433e..e489d82 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,6 @@ "crypto-js": "^4.2.0", "dayjs": "^1.11.13", "html-to-image": "^1.11.11", - "html2canvas": "^1.4.1", "jsqr": "^1.4.0", "qr-scanner": "^1.4.2", "qrcode.react": "^3.1.0", @@ -28,6 +27,7 @@ "react-router-dom": "^6.24.0", "react-scripts": "5.0.1", "react-switch": "^7.0.0", + "react-to-print": "^3.1.1", "react-youtube": "^10.1.0", "smooth-scroll-into-view-if-needed": "^2.0.2", "socket.io-client": "^4.7.5", diff --git a/src/App.js b/src/App.js index 6a122b2..c0dc639 100644 --- a/src/App.js +++ b/src/App.js @@ -377,7 +377,7 @@ function App() { setGuestSides(connectedGuestSides.sessionDatas); console.log("getting guest side"); setDeviceType("clerk"); - checkNotifications(); + // checkNotifications(); } else { setDeviceType("guestDevice"); } diff --git a/src/components/Item.js b/src/components/Item.js index de6a522..7933490 100644 --- a/src/components/Item.js +++ b/src/components/Item.js @@ -29,10 +29,51 @@ const Item = ({ const [itemDescription, setItemDescription] = useState(initialDescription); const fileInputRef = useRef(null); + const formatToRupiah = (value) => { if (typeof value !== "number") return value; return value.toLocaleString("id-ID"); + + // const stringValue = (value || '').toString(); + + // // Ambil hanya angka + // const cleaned = stringValue.replace(/[^0-9]/g, ''); + + // // Pastikan cleaned bukan kosong + // if (!cleaned) return 'Rp0'; + + // // Ubah ke number dan kalikan 1000 + // const number = Number(cleaned) * 1000; + + // // Kalau gagal parsing, fallback + // if (isNaN(number)) return 'Rp0'; + + // // Format rupiah tanpa desimal + // return number.toLocaleString('id-ID', { + // style: 'currency', + // currency: 'IDR', + // minimumFractionDigits: 0, + // maximumFractionDigits: 0 + // }); }; + +const rupiahFormat = (angka, prefix = "Rp. ") => { + let number_string = angka.toString().replace(/[^,\d]/g, ''); + let split = number_string.split(','); + let sisa = split[0].length % 3; + let rupiah = split[0].substr(0, sisa); + let ribuan = split[0].substr(sisa).match(/\d{3}/gi); + + // tambahkan titik jika yang di input sudah menjadi angka ribuan + if(ribuan){ + let separator = sisa ? '.' : ''; + rupiah += separator + ribuan.join('.'); + } + + rupiah = split[1] != undefined ? rupiah + ',' + split[1] : rupiah; + return rupiah ? prefix + rupiah : ""; + } + useEffect(() => { console.log(imageUrl); console.log(selectedImage); @@ -305,7 +346,9 @@ const formatToRupiah = (value) => { ))} {forInvoice && ( -

Rp {itemQty * (promoPrice > 0? formatToRupiah(promoPrice) : formatToRupiah(itemPrice))}

+

Rp {formatToRupiah(itemQty * (promoPrice > 0? promoPrice : itemPrice))}

+ + //

{itemQty * (promoPrice > 0? rupiahFormat(promoPrice) : rupiahFormat(itemPrice))}

)} {forCart && ( diff --git a/src/components/ItemLister.module.css b/src/components/ItemLister.module.css index 5bba86b..3d15ef6 100644 --- a/src/components/ItemLister.module.css +++ b/src/components/ItemLister.module.css @@ -119,7 +119,7 @@ .TotalContainer { display: flex; justify-content: space-between; - width: 80vw; + /* width: 80vw; */ margin: 0 auto; font-family: "Plus Jakarta Sans", sans-serif; font-weight: 600; diff --git a/src/helpers/transactionHelpers.js b/src/helpers/transactionHelpers.js index fa1aeb3..adec83c 100644 --- a/src/helpers/transactionHelpers.js +++ b/src/helpers/transactionHelpers.js @@ -217,7 +217,8 @@ export const handlePaymentFromClerk = async ( user_email, payment_type, serving_type, - tableNo + tableNo, + notes ) => { try { const token = getLocalStorage("auth"); @@ -245,6 +246,7 @@ export const handlePaymentFromClerk = async ( serving_type, tableNo, transactions: structuredItems, + notes }), } ); diff --git a/src/pages/CafePage.js b/src/pages/CafePage.js index ad6e564..e184609 100644 --- a/src/pages/CafePage.js +++ b/src/pages/CafePage.js @@ -429,7 +429,7 @@ function CafePage({ } /> ))} - {!isEditMode && !isTablet && (user.username || cartItemsLength > 0) && ( + {!isEditMode && (user.username || cartItemsLength > 0) && (
- {(lastTransaction != null || cartItemsLength > 0) && ( + {(!isTablet &&(lastTransaction != null || cartItemsLength > 0)) && (
{ + if (typeof value !== "number") return value; + return value.toLocaleString("id-ID"); +}; + export default function Invoice({ shopId, setModal, @@ -292,8 +297,11 @@ export default function Invoice({ email, orderMethod, orderType, - tableNumber + tableNumber, + textareaRef.current.value ); + if (pay) window.location.reload(); + } else if (deviceType == "guestSide") { const pay = await handlePaymentFromGuestSide( shopId, @@ -302,6 +310,8 @@ export default function Invoice({ orderType, tableNumber ); + if (pay) window.location.reload(); + } else if (deviceType == "guestDevice") { const socketId = socket.id; const pay = await handlePaymentFromGuestDevice( @@ -312,6 +322,7 @@ export default function Invoice({ textareaRef.current.value, socketId ); + if (pay) window.location.reload(); } console.log("transaction from " + deviceType + "success"); @@ -598,7 +609,7 @@ export default function Invoice({ Pesan )} - Rp{totalPrice} + Rp{formatToRupiah(totalPrice)}
)} @@ -654,17 +665,19 @@ export default function Invoice({ Rp - {transactionData.DetailedTransactions.reduce( - (total, transaction) => { - return ( - total + - (transaction.promoPrice == 0 || - transaction.promoPrice == null - ? transaction.price * transaction.qty - : transaction.promoPrice * transaction.qty) - ); - }, - 0 + {formatToRupiah( + transactionData.DetailedTransactions.reduce( + (total, transaction) => { + return ( + total + + (transaction.promoPrice == 0 || + transaction.promoPrice == null + ? transaction.price * transaction.qty + : transaction.promoPrice * transaction.qty) + ); + }, + 0 + ) )}
@@ -694,7 +707,7 @@ export default function Invoice({ Pesan )} - Rp{totalPrice} + Rp{formatToRupiah(totalPrice)} )} diff --git a/src/pages/Invoice.module.css b/src/pages/Invoice.module.css index f439e9e..69ecd75 100644 --- a/src/pages/Invoice.module.css +++ b/src/pages/Invoice.module.css @@ -69,7 +69,7 @@ .TotalContainer { display: flex; justify-content: space-between; - width: 80vw; + /* width: 80vw; */ margin: 0 auto; font-family: "Plus Jakarta Sans", sans-serif; font-weight: 600; @@ -466,7 +466,7 @@ .TotalContainer { display: flex; justify-content: space-between; - width: 80vw; + /* width: 80vw; */ margin: 0 auto; font-family: "Plus Jakarta Sans", sans-serif; font-weight: 600; diff --git a/src/pages/Transaction.js b/src/pages/Transaction.js index e6c7596..81a17d4 100644 --- a/src/pages/Transaction.js +++ b/src/pages/Transaction.js @@ -67,7 +67,7 @@ export default function Transactions({ propsShopId, sendParam, deviceType, handl if (c) { console.log(c) setTransaction(c); - setTransactionRefreshKey(transactionRefreshKey+1); + setTransactionRefreshKey(transactionRefreshKey + 1); } } catch (error) { console.error("Error processing payment:", error); @@ -84,7 +84,7 @@ export default function Transactions({ propsShopId, sendParam, deviceType, handl if (c) { console.log(c) setTransaction({ ...transaction, confirmed: c.confirmed }); - setTransactionRefreshKey(transactionRefreshKey+1); + setTransactionRefreshKey(transactionRefreshKey + 1); } // if (c) { // // Update the confirmed status locally @@ -115,6 +115,9 @@ export default function Transactions({ propsShopId, sendParam, deviceType, handl autoResizeTextArea(noteRef.current); } }, [transaction?.notes]); + const handlePrint = () => { + window.print(); + }; return (
@@ -128,18 +131,17 @@ export default function Transactions({ propsShopId, sendParam, deviceType, handl setSelectedTable(transaction.Table || { tableId: 0 }) } > -
-

{transaction.payment_type == 'cash' ? 'Tunai' : transaction.payment_type == 'cashless' ? 'Non tunai' : transaction.payment_type == 'paylater' ? 'Open bill' :'Close bill' }

+

{transaction.payment_type == 'cash' ? 'Tunai' : transaction.payment_type == 'cashless' ? 'Non tunai' : transaction.payment_type == 'paylater' ? 'Open bill' : 'Close bill'}

Transaction ID: {transaction.transactionId}

{ transaction.payment_type == 'paylater/cash' ? -

Cash

- : - (transaction.payment_type == 'paylater/cashless' && -

Non tunai

- ) +

Cash

+ : + (transaction.payment_type == 'paylater/cashless' && +

Non tunai

+ ) }
@@ -161,8 +163,8 @@ export default function Transactions({ propsShopId, sendParam, deviceType, handl
{depth > 0 && -
{depth}
-} +
{depth}
+ }
handleMoveToTransaction('next', transaction.transactionId)}> @@ -188,7 +190,7 @@ export default function Transactions({ propsShopId, sendParam, deviceType, handl
{transaction.DetailedTransactions.map((detail) => (
-
= 0 && detail.acceptedStatus == 0 ? 'visible' : 'hidden', margin: transaction.confirmed >= 0 && detail.acceptedStatus == 0 ? '4px 10px 0px 10px' : '4px 0px 0px 0px' }} +
= 0 && detail.acceptedStatus == 0 ? 'visible' : 'hidden', margin: transaction.confirmed >= 0 && detail.acceptedStatus == 0 ? '4px 10px 0px 10px' : '4px 0px 0px 0px' }} onClick={() => setNotAcceptedItems(prevState => prevState.includes(detail.detailedTransactionId) @@ -225,27 +227,27 @@ export default function Transactions({ propsShopId, sendParam, deviceType, handl overflow: 'hidden', textOverflow: 'ellipsis' }}> - {detail.Item.name} - {notAcceptedItems.includes(detail.detailedTransactionId) || detail.qty < 1 ? 'tidak tersedia' : `${detail.qty} x Rp + {detail.Item.name} - {notAcceptedItems.includes(detail.detailedTransactionId) || detail.qty < 1 ? 'tidak tersedia' : `${detail.qty} x Rp ${detail.promoPrice ? detail.promoPrice : detail.price}`}
))}
- {!transaction.is_paid && transaction.confirmed > -1 && -
{ - localStorage.setItem('lastTransaction', JSON.stringify(transaction)); - setModal("message", { captMessage: 'Silahkan tambahkan pesanan', descMessage: 'Pembayaran akan ditambahkan ke transaksi sebelumnya.' }, null, null); + {!transaction.is_paid && transaction.confirmed > -1 && +
{ + localStorage.setItem('lastTransaction', JSON.stringify(transaction)); + setModal("message", { captMessage: 'Silahkan tambahkan pesanan', descMessage: 'Pembayaran akan ditambahkan ke transaksi sebelumnya.' }, null, null); - // Dispatch the custom event - window.dispatchEvent(new Event("localStorageUpdated")); - }} - className={styles["addNewItem"]} - > - Tambah pesanan -
- } + // Dispatch the custom event + window.dispatchEvent(new Event("localStorageUpdated")); + }} + className={styles["addNewItem"]} + > + Tambah pesanan +
+ }

{transaction.serving_type === "pickup" @@ -311,9 +313,55 @@ export default function Transactions({ propsShopId, sendParam, deviceType, handl batalkan

)} + {transaction.confirmed > 1 && ( +
handlePrint()} + > + Cetak struk +
+ )}
)}
+ {transaction && + + + } +
); } diff --git a/src/pages/Transactions.js b/src/pages/Transactions.js index 91f8ed1..34dd7d7 100644 --- a/src/pages/Transactions.js +++ b/src/pages/Transactions.js @@ -198,7 +198,7 @@ console.log(aggregatedItems.values())
{transaction.confirmed === 1 ? ( - ) : transaction.confirmed === -1 && !transaction.is_paid || transaction.confirmed === -2 && !transaction.is_paid ? ( + ) : (transaction.confirmed == -1 && !transaction.is_paid) || (transaction.confirmed === -2 && !transaction.is_paid) ? (