diff --git a/src/App.js b/src/App.js index e2ddc9f..f435b54 100644 --- a/src/App.js +++ b/src/App.js @@ -819,8 +819,10 @@ function App() { welcomePageConfig={shop.welcomePageConfig} onClose={closeModal} setModal={setModal} + setIsModalOpen={setIsModalOpen} onModalCloseFunction={onModalCloseFunction} onModalYesFunction={onModalYesFunction} + shopIdentifier={shopIdentifier} /> ); diff --git a/src/components/DailyCharts.js b/src/components/DailyCharts.js index a005baf..74f3210 100644 --- a/src/components/DailyCharts.js +++ b/src/components/DailyCharts.js @@ -43,7 +43,7 @@ const DailyCharts = ({ incomeGraph, transactionGraph, materialGraph, colors, typ Array.isArray(transactions) ? transactions.reduce((acc, t) => acc + t.totalPrice, 0) : transactions?.income || 0; const sumOutcome = (transactions) => - Array.isArray(transactions) ? transactions.reduce((acc, t) => acc + (t.materialOutcome || t.price), 0) : transactions?.outcome || 0; + Array.isArray(transactions) ? transactions.reduce((acc, t) => acc + (t.materialOutcome || t.price * t.stockDifference), 0) : transactions?.outcome || 0; let seriesData = [] @@ -83,16 +83,19 @@ const DailyCharts = ({ incomeGraph, transactionGraph, materialGraph, colors, typ sumOutcome(dayData?.hour21To24MaterialIds), ]; } + let totalValue = seriesData.reduce((acc, val) => acc + val, 0); return { date: new Date(dayData.date).toLocaleDateString(), categories, series: [ { - name: graphFilter === 'transactions' ? 'Transaksi' : (graphFilter === 'Pemasukan' ? 'Pemasukan' : 'Pengeluaran'), + name: graphFilter === 'transactions' ? 'Transaksi' : (graphFilter === 'income' ? 'Pemasukan' : 'Pengeluaran'), data: seriesData, }, ], + totalValue, // ⬅️ Tambahkan ini }; + }); }; @@ -144,7 +147,8 @@ const DailyCharts = ({ incomeGraph, transactionGraph, materialGraph, colors, typ type == 'yesterday' && selectedIndex == -1 || type != 'yesterday' && selectedIndex !== index ? setSelectedIndex(index) : setSelectedIndex(-1) } > -
+ +
{indexx !== chartData.length - 1 ? ( @@ -153,10 +157,18 @@ const DailyCharts = ({ incomeGraph, transactionGraph, materialGraph, colors, typ {(indexx === 0 || (formatDate(chartData[indexx - 1].date).month !== month && type != 'weekly')) && month} ) : ( - 'Hari ini' + <> + {type != 'weekly' ? 'Hari ini' : day} + )}
+ {index == indexx &&

+ {graphFilter === 'transactions' + ? chartData[indexx].totalValue + : formatRupiah(chartData[indexx].totalValue)} +

} + ); })} @@ -181,10 +193,11 @@ const DailyCharts = ({ incomeGraph, transactionGraph, materialGraph, colors, typ } else { return formatRupiah(val); // format Rupiah } + }, style: { colors: [(index == chartData.length - 1 || selectedIndex != -1) ? "#000" : "transparent"], - fontSize: '10px', + fontSize: '7px', }, offsetY: -10, background: { diff --git a/src/components/Modal.js b/src/components/Modal.js index e3ef0ae..e85d8e4 100644 --- a/src/components/Modal.js +++ b/src/components/Modal.js @@ -35,7 +35,7 @@ import CreateCoupon from "../pages/CreateCoupon"; import CheckCoupon from "../pages/CheckCoupon"; import CreateUserWithCoupon from "../pages/CreateUserWithCoupon"; -const Modal = ({ user, shop, isOpen, onClose, modalContent, deviceType, setModal, handleMoveToTransaction, depth,welcomePageConfig, onModalCloseFunction, onModalYesFunction }) => { +const Modal = ({ user, shop, shopIdentifier, isOpen, onClose, modalContent, deviceType, setModal, setIsModalOpen, handleMoveToTransaction, depth,welcomePageConfig, onModalCloseFunction, onModalYesFunction }) => { const [shopImg, setShopImg] = useState(''); const [updateKey, setUpdateKey] = useState(0); @@ -88,10 +88,10 @@ const Modal = ({ user, shop, isOpen, onClose, modalContent, deviceType, setModal {modalContent === "create_tenant" && } {modalContent === "edit_tables" && } {modalContent === "new_transaction" && ( - + )} {modalContent === "transaction_canceled" && ( - + )} {modalContent === "transaction_pending" && } {modalContent === "transaction_item" && } diff --git a/src/components/PeriodCharts.js b/src/components/PeriodCharts.js index f0c9617..8055246 100644 --- a/src/components/PeriodCharts.js +++ b/src/components/PeriodCharts.js @@ -7,182 +7,195 @@ const PeriodCharts = ({ type, graphFilter, aggregatedCurrentReports, aggregatedP useEffect(() => { setSelectedIndex(-1); - }, [aggregatedCurrentReports, aggregatedPreviousReports]); + }, [aggregatedCurrentReports, aggregatedPreviousReports, graphFilter]); const monthly = ["1 - 7", "8 - 14", "15 - 21", "22 - 28", "29 - 31"]; const yearly = ["Kuartal 1", "Kuartal 2", "Kuartal 3", "Kuartal 4"]; - const cat = type == 'monthly' ? monthly : yearly; + const cat = type === "monthly" ? monthly : yearly; + + // Helper Rupiah formatter + const formatRupiah = (number) => { + if (number === null || number === undefined) return "Rp 0"; + return new Intl.NumberFormat("id-ID", { + style: "currency", + currency: "IDR", + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }).format(number); + }; + + let currentIncomeData, + currentOutcomeData, + currentTransactionData, + previousIncomeData, + previousOutcomeData, + previousTransactionData = null; - // Map the data for the current reports - let currentIncomeData, currentOutcomeData, currentTransactionData, previousIncomeData, previousOutcomeData, previousTransactionData = null; if (aggregatedCurrentReports) { - currentIncomeData = aggregatedCurrentReports.map((report) => report.income); - currentOutcomeData = aggregatedCurrentReports.map((report) => report.outcome); - currentTransactionData = aggregatedCurrentReports.map((report) => report.transactions); + currentIncomeData = aggregatedCurrentReports.map((r) => r.income); + currentOutcomeData = aggregatedCurrentReports.map((r) => r.outcome); + currentTransactionData = aggregatedCurrentReports.map((r) => r.transactions); - if (type == 'monthly' && currentIncomeData.length === 4) { + if (type === "monthly" && currentIncomeData.length === 4) { currentIncomeData.push(null); - } - if (type == 'monthly' && currentOutcomeData.length === 4) { currentOutcomeData.push(null); - } - if (type == 'monthly' && currentTransactionData.length === 4) { currentTransactionData.push(null); } } - if (aggregatedPreviousReports) { - // Map the data for the previous reports - previousIncomeData = aggregatedPreviousReports.map((report) => report.income); - previousOutcomeData = aggregatedPreviousReports.map((report) => report.outcome); - previousTransactionData = aggregatedPreviousReports.map((report) => report.transactions); - if (type == 'monthly' && previousIncomeData.length === 4) { + if (aggregatedPreviousReports) { + previousIncomeData = aggregatedPreviousReports.map((r) => r.income); + previousOutcomeData = aggregatedPreviousReports.map((r) => r.outcome); + previousTransactionData = aggregatedPreviousReports.map((r) => r.transactions); + + if (type === "monthly" && previousIncomeData.length === 4) { previousIncomeData.push(null); - } - if (type == 'monthly' && previousOutcomeData.length === 4) { previousOutcomeData.push(null); - } - if (type == 'monthly' && previousTransactionData.length === 4) { previousTransactionData.push(null); } } -let globalMax = null; -if (aggregatedCurrentReports || aggregatedPreviousReports) { - // Find the global maximum for the y-axis - globalMax = Math.max( - ...(graphFilter === 'income' - ? [...currentIncomeData, ...previousIncomeData] - : graphFilter === 'outcome' - ? [...currentOutcomeData, ...previousOutcomeData] - : [...currentTransactionData, ...previousTransactionData]) - ); -} + + // cari global max untuk y-axis + let globalMax = 0; + if (aggregatedCurrentReports || aggregatedPreviousReports) { + const dataset = + graphFilter === "income" + ? [...(currentIncomeData || []), ...(previousIncomeData || [])] + : graphFilter === "outcome" + ? [...(currentOutcomeData || []), ...(previousOutcomeData || [])] + : [...(currentTransactionData || []), ...(previousTransactionData || [])]; + globalMax = Math.max(...dataset); + } + + const getSeries = (isCurrent) => { + if (graphFilter === "income") + return isCurrent ? currentIncomeData : previousIncomeData; + if (graphFilter === "outcome") + return isCurrent ? currentOutcomeData : previousOutcomeData; + return isCurrent ? currentTransactionData : previousTransactionData; + }; return ( -
- {aggregatedPreviousReports && ( -
- -
-
- selectedIndex === -1 ? setSelectedIndex(0) : setSelectedIndex(-1) - } - style={{ color: 'black', position: 'relative' }} - > -
-
{type == 'monthly' ? 'bulan lalu' : 'tahun lalu'}
-
+
+ {[aggregatedPreviousReports, aggregatedCurrentReports].map( + (dataset, i) => + dataset && (
- selectedIndex === 0 ? setSelectedIndex(-1) : setSelectedIndex(1) - }> -
{type == 'monthly' ? 'bulan ini' : 'tahun ini'}
-
-
-
- -
-
- )} - {aggregatedCurrentReports && ( -
-
-
- selectedIndex === 1 ? setSelectedIndex(-1) : setSelectedIndex(0) - }> -
{type == 'monthly' ? 'bulan lalu' : 'tahun lalu'}
-
-
- selectedIndex === -1 ? setSelectedIndex(1) : setSelectedIndex(-1) - } - - style={{ color: 'black', position: 'relative' }} > -
-
{type == 'monthly' ? 'bulan ini' : 'tahun ini'}
-
-
-
- + {[0, 1].map((idx) => ( +
+ selectedIndex == idx ? setSelectedIndex(-1) : setSelectedIndex(idx) } - } - }, - yaxis: { max: globalMax, min: 0, labels: { maxWidth: 20, style: { colors: "transparent" } } }, - grid: { show: false }, - fill: { opacity: 0.5 }, - colors: [colors[1]], - }} - series={[ - // { name: "Pemasukan", data: currentIncomeData }, - // { name: "Pengeluaran", data: currentOutcomeData }, - { name: "Total transaksi", data: graphFilter == 'income' ? currentIncomeData : graphFilter == 'outcome' ? currentOutcomeData : currentTransactionData }, - ]} - type="area" - height={200} - width="100%" - /> -
-
+ > + {idx === i && ( +
+ )} +
+ {type === "monthly" + ? idx === 0 + ? "bulan lalu" + : "bulan ini" + : idx === 0 + ? "tahun lalu" + : "tahun ini"} +
+
+ ))} +
+ +
+ + graphFilter === "transactions" ? val : formatRupiah(val), + }, + }, + dataLabels: { + enabled: true, + formatter: (val) => + graphFilter === "transactions" ? val : formatRupiah(val), + style: { + colors: ["#000"], // <- Selalu tampil hitam + fontSize: "10px", + }, + offsetY: -10, + background: { + enabled: true, // <- Selalu tampil background label + }, + }, + + + chart: { + type: "area", + zoom: { enabled: false }, + toolbar: { show: false }, + }, + xaxis: { + categories: cat, + labels: { + style: { + colors: cat.map(() => + i === selectedIndex || selectedIndex === -1 ? "#000" : "transparent" + ), + }, + }, + }, + yaxis: { + max: globalMax, + min: 0, + labels: { + maxWidth: 20, + style: { colors: "transparent" }, + formatter: (val) => formatRupiah(val), + }, + }, + grid: { show: false }, + fill: { opacity: 0.5 }, + colors: [colors[i]], + }} + series={[ + { + name: + graphFilter === "transactions" + ? "Transaksi" + : graphFilter === "income" + ? "Pemasukan" + : "Pengeluaran", + data: getSeries(i === 1), + }, + ]} + type="area" + height={200} + width="100%" + /> +
+
+ ) )} ); diff --git a/src/pages/CircularDiagram.js b/src/pages/CircularDiagram.js index 83f5403..cc20c58 100644 --- a/src/pages/CircularDiagram.js +++ b/src/pages/CircularDiagram.js @@ -19,7 +19,7 @@ const HorizontalBarDiagram = ({ segments, width = 300 }) => { style={{ display: "block", margin: "0 auto" }} > {visibleSegments.map((segment, index) => { - const { name, value, color } = segment; + const { name, value, color, unit} = segment; const percentage = total > 0 ? ((value / total) * 100).toFixed(1) : 0; const barWidth = (width * percentage) / 100; @@ -61,7 +61,7 @@ const HorizontalBarDiagram = ({ segments, width = 300 }) => { fontWeight="bold" style={{ pointerEvents: "none", textTransform: "capitalize" }} > - {`${name}: ${value} (${percentage}%)`} + {unit ? (name + ' ( ' + value +' '+ unit+')') : (name + ' ' + value +' ('+ percentage + '%)')} ); diff --git a/src/pages/Dashboard.js b/src/pages/Dashboard.js index 5dae758..101a315 100644 --- a/src/pages/Dashboard.js +++ b/src/pages/Dashboard.js @@ -234,7 +234,7 @@ const LinktreePage = ({ user, setModal }) => { return ( <> - {user && user.roleId < 2 ? ( + {getLocalStorage("auth") ? (
diff --git a/src/pages/MaterialList.js b/src/pages/MaterialList.js index 86dc0a1..de1c07d 100644 --- a/src/pages/MaterialList.js +++ b/src/pages/MaterialList.js @@ -180,7 +180,7 @@ const SetPaymentQr = ({ cafeId }) => { setLatestMutation(latestMutation); setCurrentQuantity(latestMutation.newStock); setCurrentPrice(formatCurrency(latestMutation.priceAtp)); - setNewPrice(formatCurrency(latestMutation.priceAtp)); + setNewPrice(formatCurrency(latestMutation.priceAtp) || 0); } else { setCurrentQuantity(0); // Default value if no mutations exist setLatestMutation({ newStock: 0 }); @@ -195,12 +195,12 @@ const SetPaymentQr = ({ cafeId }) => { const handleUpdateStock = async () => { setLoading(true); + console.log('aaa') try { - const newprice = convertToInteger(newPrice) const newStock = currentQuantity + quantityChange; const formData = new FormData(); formData.append("newStock", newStock); - formData.append("priceAtp", newprice); + formData.append("priceAtp", newPrice); formData.append("reason", "Stock update"); await createMaterialMutation(materials[selectedMaterialIndex].materialId, formData); diff --git a/src/pages/Reports.js b/src/pages/Reports.js index 5ec305c..3f29c2f 100644 --- a/src/pages/Reports.js +++ b/src/pages/Reports.js @@ -240,6 +240,7 @@ let materialSegments = return { name: item.materialName, value: item.spend, + unit: item.unit, color, }; }); @@ -250,6 +251,8 @@ let materialSegments = return { name: item.materialName, value: item.spend, + unit: item.unit, + color, }; }); diff --git a/src/pages/Transaction.js b/src/pages/Transaction.js index d37cba9..73cbb21 100644 --- a/src/pages/Transaction.js +++ b/src/pages/Transaction.js @@ -13,7 +13,7 @@ import { getTables } from "../helpers/tableHelper"; import TableCanvas from "../components/TableCanvas"; import { useSearchParams } from "react-router-dom"; -export default function Transactions({ propsShopId, sendParam, deviceType, handleMoveToTransaction, depth, shopImg, setModal }) { +export default function Transactions({ propsShopId,setIsModalOpen,cafeIdentityName, sendParam, deviceType, handleMoveToTransaction, depth, shopImg, setModal }) { const { shopId, tableId } = useParams(); if (sendParam) sendParam({ shopId, tableId }); @@ -140,7 +140,8 @@ const handlePrint = (transaction) => { const queryString = qs.stringify({ data: JSON.stringify(printableData) }); // Navigate to /print with query string - navigate(`/print?${queryString}`); + setIsModalOpen(false); + navigate(`/${cafeIdentityName}/print?${queryString}`); }; return ( diff --git a/src/pages/Transactions.js b/src/pages/Transactions.js index aadfd86..297305c 100644 --- a/src/pages/Transactions.js +++ b/src/pages/Transactions.js @@ -165,7 +165,7 @@ export default function Transactions({ shop, shopId, propsShopId, sendParam, dev const queryString = qs.stringify({ data: JSON.stringify(printableData) }); // Navigate to /print with query string - navigate(`/print?${queryString}`); + navigate(`/${shopIdentifier}/print?${queryString}`); }; if (loading) return (