ok banget
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import './GuidePage.css';
|
||||
|
||||
import API_BASE_URL from '../config.js';
|
||||
const GuidePage = ({ guideType }) => {
|
||||
const renderGuideContent = () => {
|
||||
switch (guideType) {
|
||||
@@ -10,7 +10,7 @@ const GuidePage = ({ guideType }) => {
|
||||
<h2>Setup Guide</h2>
|
||||
<p>1. Turn on edit mode and create item type</p>
|
||||
<video
|
||||
src="https://api.kedaimaster.com/uploads/create_item_guide_1.mkv"
|
||||
src={`${API_BASE_URL}/uploads/create_item_guide_1.mkv`}
|
||||
autoPlay
|
||||
muted
|
||||
loop
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import API_BASE_URL from "../config.js";
|
||||
import {
|
||||
getMaterials,
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
getMaterialMutations,
|
||||
} from "../helpers/materialMutationHelpers";
|
||||
|
||||
const MaterialList = ({ cafeId }) => {
|
||||
const MaterialList = ({ cafeId, handleClose }) => {
|
||||
const [materials, setMaterials] = useState([]);
|
||||
const [mutations, setMutations] = useState([]);
|
||||
const [newMaterialName, setNewMaterialName] = useState("");
|
||||
@@ -21,9 +21,12 @@ const MaterialList = ({ cafeId }) => {
|
||||
const [error, setError] = useState(null);
|
||||
const [showForm, setShowForm] = useState(false);
|
||||
const [selectedMaterialId, setSelectedMaterialId] = useState(null);
|
||||
const [latestMutation, setLatestMutation] = useState([]);
|
||||
const [currentQuantity, setCurrentQuantity] = useState(0);
|
||||
const [currentPrice, setCurrentPrice] = useState(0);
|
||||
const [quantityChange, setQuantityChange] = useState(0);
|
||||
const [sortOrder, setSortOrder] = useState("desc");
|
||||
const priceInputRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMaterials = async () => {
|
||||
@@ -69,9 +72,13 @@ const MaterialList = ({ cafeId }) => {
|
||||
: latest,
|
||||
materialMutations[0]
|
||||
);
|
||||
setLatestMutation(latestMutation);
|
||||
setCurrentQuantity(latestMutation.newStock);
|
||||
setCurrentPrice(latestMutation.priceAtp);
|
||||
} else {
|
||||
setCurrentQuantity(0); // Default value if no mutations exist
|
||||
setLatestMutation({newStock: 0});
|
||||
setCurrentPrice(0);
|
||||
}
|
||||
}
|
||||
}, [selectedMaterialId, mutations]);
|
||||
@@ -174,6 +181,10 @@ const MaterialList = ({ cafeId }) => {
|
||||
const handleQuantityChange = (change) => {
|
||||
setQuantityChange((prev) => prev + change);
|
||||
};
|
||||
// useEffect to log the latest quantityChange value
|
||||
useEffect(() => {
|
||||
if(quantityChange >= latestMutation.newStock) priceInputRef.current.focus();
|
||||
}, [quantityChange]);
|
||||
|
||||
const handleUpdateStock = async () => {
|
||||
if (selectedMaterialId) {
|
||||
@@ -182,6 +193,7 @@ const MaterialList = ({ cafeId }) => {
|
||||
const newStock = currentQuantity + quantityChange;
|
||||
const formData = new FormData();
|
||||
formData.append("newStock", newStock);
|
||||
formData.append("priceAtp", currentPrice);
|
||||
formData.append("reason", "Stock update");
|
||||
|
||||
await createMaterialMutation(selectedMaterialId, formData);
|
||||
@@ -209,7 +221,7 @@ const MaterialList = ({ cafeId }) => {
|
||||
|
||||
return (
|
||||
<div style={styles.container}>
|
||||
<h1 style={styles.heading}>Materials List</h1>
|
||||
<h1 style={styles.heading}>Stok barang</h1>
|
||||
|
||||
{error && <p style={styles.error}>{error}</p>}
|
||||
{loading && <p>Loading materials and mutations...</p>}
|
||||
@@ -220,7 +232,7 @@ const MaterialList = ({ cafeId }) => {
|
||||
style={styles.toggleButton}
|
||||
disabled={loading}
|
||||
>
|
||||
{showForm ? "Hide Form" : "Add New Material"}
|
||||
{showForm ? "Batalkan" : "Tambah barang"}
|
||||
</button>
|
||||
)}
|
||||
|
||||
@@ -291,7 +303,13 @@ const MaterialList = ({ cafeId }) => {
|
||||
(material) => material.materialId === selectedMaterialId
|
||||
) === 0
|
||||
}
|
||||
style={styles.navigationButton}
|
||||
style={{...styles.navigationButton,
|
||||
backgroundColor:
|
||||
!selectedMaterialId ||
|
||||
materials.findIndex((material) => material.materialId === selectedMaterialId) === 0
|
||||
? '#a3a3a3'
|
||||
: '#5b81ff',
|
||||
}}
|
||||
>
|
||||
{"<"}
|
||||
</button>
|
||||
@@ -319,6 +337,7 @@ const MaterialList = ({ cafeId }) => {
|
||||
<button style={styles.quantityDisplay}>
|
||||
{currentQuantity + quantityChange}
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => handleQuantityChange(1)}
|
||||
style={styles.quantityButton}
|
||||
@@ -326,6 +345,8 @@ const MaterialList = ({ cafeId }) => {
|
||||
+
|
||||
</button>
|
||||
</div>
|
||||
<p>harga per {currentMaterial.unit}</p>
|
||||
<input ref={priceInputRef} disabled={(currentQuantity+quantityChange) <= latestMutation.newStock} value={currentPrice} onChange={(e)=>setCurrentPrice(e.target.value)} style={styles.priceAtp}/>
|
||||
<button
|
||||
onClick={handleUpdateStock}
|
||||
style={styles.updateMutation}
|
||||
@@ -357,7 +378,13 @@ const MaterialList = ({ cafeId }) => {
|
||||
) ===
|
||||
materials.length - 1
|
||||
}
|
||||
style={styles.navigationButton}
|
||||
style={{...styles.navigationButton,
|
||||
backgroundColor:
|
||||
!selectedMaterialId ||
|
||||
materials.findIndex((material) => material.materialId === selectedMaterialId) === materials.length - 1
|
||||
? '#a3a3a3'
|
||||
: '#5b81ff',
|
||||
}}
|
||||
>
|
||||
{">"}
|
||||
</button>
|
||||
@@ -394,19 +421,19 @@ const MaterialList = ({ cafeId }) => {
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div class="ItemLister_PaymentOption__YZlDL"><div style={{marginTop:'20px'}} onClick={handleClose} class="ItemLister_Pay2Button__+MIxX">Kembali</div></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = {
|
||||
container: {
|
||||
paddingLeft: "10px",
|
||||
paddingRight: "10px",
|
||||
maxWidth: "800px",
|
||||
margin: "0 auto",
|
||||
height: "100%", // Adjust height based on your needs
|
||||
overflowY: "auto", // Enables vertical scrolling
|
||||
backgroundColor: "white",
|
||||
position: 'fixed',
|
||||
height: '100vh',
|
||||
width: '100vw',
|
||||
top: 0,
|
||||
right: 0,
|
||||
backgroundColor: 'rgb(207, 207, 207)'
|
||||
},
|
||||
heading: {
|
||||
textAlign: "center",
|
||||
@@ -569,6 +596,16 @@ const styles = {
|
||||
textAlign: "center",
|
||||
margin: "0 5px",
|
||||
},
|
||||
priceAtp: {
|
||||
padding: "8px 12px",
|
||||
border: "1px solid #ddd",
|
||||
borderRadius: "5px",
|
||||
textAlign: 'left',
|
||||
backgroundColor: "#fff",
|
||||
color: "#000",
|
||||
fontSize: "16px",
|
||||
margin: "0 5px",
|
||||
},
|
||||
updateMutation: {
|
||||
marginTop: "10px",
|
||||
padding: "12px 20px",
|
||||
|
||||
@@ -141,7 +141,7 @@ const styles = {
|
||||
},
|
||||
};
|
||||
|
||||
const MaterialMutationPage = ({ cafeId }) => {
|
||||
const MaterialMutationPage = ({ cafeId, handleClose }) => {
|
||||
const [materials, setMaterials] = useState([]);
|
||||
const [mutations, setMutations] = useState([]);
|
||||
const [selectedMaterialId, setSelectedMaterialId] = useState("");
|
||||
@@ -331,6 +331,8 @@ const MaterialMutationPage = ({ cafeId }) => {
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div class="ItemLister_PaymentOption__YZlDL"><div style={{marginTop:'20px'}} onClick={handleClose} class="ItemLister_Pay2Button__+MIxX">Kembali</div></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@ const RoundedRectangle = ({
|
||||
title,
|
||||
value,
|
||||
percentage,
|
||||
invert,
|
||||
fontSize = "15px",
|
||||
loading = false,
|
||||
children, // Assuming this is a React component or JSX
|
||||
@@ -73,7 +74,7 @@ const RoundedRectangle = ({
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
textAlign: "right",
|
||||
color: loading ? "black" : percentage > 0 ? "#007bff" : "red",
|
||||
color: loading ? "black" : percentage >= 0 ? (invert ? "red" : "#2fd45e") : (invert ? "#2fd45e" : "red"),
|
||||
};
|
||||
|
||||
const arrowStyle = {
|
||||
@@ -102,7 +103,8 @@ const RoundedRectangle = ({
|
||||
);
|
||||
};
|
||||
|
||||
const App = ({ cafeId }) => {
|
||||
const App = ({ cafeId,
|
||||
handleClose }) => {
|
||||
const [favouriteItems, setFavouriteItems] = useState([]);
|
||||
const [analytics, setAnalytics] = useState({});
|
||||
const [loading, setLoading] = useState(true);
|
||||
@@ -128,7 +130,7 @@ const App = ({ cafeId }) => {
|
||||
}, [filter]);
|
||||
|
||||
const [sold, percentage] = analytics[filter] || [0, 0];
|
||||
const filteredItems = analytics.currentFavoriteItems || [];
|
||||
const filteredItems = analytics.items || [];
|
||||
|
||||
const totalSold = filteredItems.reduce((sum, item) => sum + item.count, 0);
|
||||
const colors = [
|
||||
@@ -187,7 +189,7 @@ const App = ({ cafeId }) => {
|
||||
setFilter(filterMap[selectedItem]);
|
||||
}
|
||||
|
||||
const filterTexts = ["1 day", "7 days", "30 days", "365 days"];
|
||||
const filterTexts = ["1", "7", "30", "365"];
|
||||
const comparisonText =
|
||||
filterTexts[["daily", "weekly", "monthly", "yearly"].indexOf(filter)];
|
||||
const formatDate = (isoDateString) => {
|
||||
@@ -201,11 +203,18 @@ const App = ({ cafeId }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.Transactions} style={{ backgroundColor: "#cfcfcf" }}>
|
||||
<div style={{
|
||||
position: 'fixed',
|
||||
height: '100vh',
|
||||
width: '100vw',
|
||||
top: 0,
|
||||
right: 0,
|
||||
backgroundColor: 'rgb(207, 207, 207)'}}
|
||||
>
|
||||
<h2 className={styles["Transactions-title"]}>Reports</h2>
|
||||
<div style={{ textAlign: "center" }}>
|
||||
<MultiSwitch
|
||||
texts={["Yesterday", "Last 7", "Last 30", "Last 365"]}
|
||||
texts={["Yesterday", "This week", "This Month", "This year"]}
|
||||
selectedSwitch={["daily", "weekly", "monthly", "yearly"].indexOf(
|
||||
filter
|
||||
)}
|
||||
@@ -229,62 +238,56 @@ const App = ({ cafeId }) => {
|
||||
>
|
||||
<RoundedRectangle
|
||||
bgColor="#E3F5FF"
|
||||
title="Transactions"
|
||||
value={analytics.transactionCount}
|
||||
percentage={roundToInteger(analytics.transactionGrowth)}
|
||||
title="Pendapatan"
|
||||
fontSize="12px"
|
||||
value={!loading && "Rp" + formatIncome(analytics?.totalIncome)}
|
||||
percentage={roundToInteger(analytics.growthIncome)}
|
||||
invert={false}
|
||||
loading={loading}
|
||||
/>
|
||||
|
||||
<RoundedRectangle
|
||||
bgColor="#E5ECF6"
|
||||
title="Pengeluaran"
|
||||
fontSize="12px"
|
||||
value={!loading && "Rp" + formatIncome(analytics?.currentOutcome)}
|
||||
percentage={roundToInteger(analytics.growthOutcome)}
|
||||
invert={true}
|
||||
loading={loading}
|
||||
/>
|
||||
<RoundedRectangle
|
||||
bgColor="#E5ECF6"
|
||||
title="Income"
|
||||
fontSize="12px"
|
||||
value={!loading && "Rp" + formatIncome(analytics?.totalIncome)}
|
||||
percentage={roundToInteger(analytics.incomeGrowth)}
|
||||
title="Transaksi"
|
||||
value={analytics.totalTransactions}
|
||||
percentage={roundToInteger(analytics.growthTransactions)}
|
||||
invert={false}
|
||||
loading={loading}
|
||||
/>
|
||||
|
||||
{analytics?.currentFavoriteItems &&
|
||||
analytics?.currentFavoriteItems.length > 0 && (
|
||||
{analytics?.items &&
|
||||
analytics?.items.length > 0 && (
|
||||
<RoundedRectangle
|
||||
bgColor="#E5ECF6"
|
||||
title={"Fav item"}
|
||||
value={analytics?.currentFavoriteItems[0]?.name}
|
||||
bgColor="#E3F5FF"
|
||||
title={"Item favorit"}
|
||||
value={analytics?.items[0]?.name}
|
||||
loading={loading}
|
||||
/>
|
||||
)}
|
||||
{(!analytics?.items ||
|
||||
analytics?.items.length === 0) && (
|
||||
<RoundedRectangle
|
||||
bgColor="#E5ECF6"
|
||||
title={"Item favorit"}
|
||||
value={"-"}
|
||||
loading={loading}
|
||||
/>
|
||||
)}
|
||||
{(!analytics?.currentFavoriteItems ||
|
||||
analytics?.currentFavoriteItems.length === 0) && (
|
||||
<RoundedRectangle
|
||||
bgColor="#E5ECF6"
|
||||
title={"No fav item"}
|
||||
value={"-"}
|
||||
loading={loading}
|
||||
/>
|
||||
)}
|
||||
{analytics?.previousFavoriteItem !== null && (
|
||||
<RoundedRectangle
|
||||
bgColor="#E3F5FF"
|
||||
title={"Fav before"}
|
||||
value={analytics?.previousFavoriteItem?.name}
|
||||
loading={loading}
|
||||
/>
|
||||
)}
|
||||
{analytics?.previousFavoriteItem === null && (
|
||||
<RoundedRectangle
|
||||
bgColor="#E3F5FF"
|
||||
title={"No fav item"}
|
||||
value={"-"}
|
||||
loading={loading}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div
|
||||
style={{ display: "flex", alignItems: "center", margin: "10px" }}
|
||||
>
|
||||
<div style={{ marginRight: "5px", fontSize: "1.2em" }}>ⓘ</div>
|
||||
<h6 style={{ margin: 0, textAlign: "left" }}>
|
||||
Growth percentages are based on comparing the last{" "}
|
||||
{comparisonText} with the preceding {comparisonText}.
|
||||
Persentase pertumbuhan dihitung dengan membandingkan periode{" "}
|
||||
{comparisonText} terakhir dengan {comparisonText} hari sebelumnya.
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
@@ -324,36 +327,8 @@ const App = ({ cafeId }) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 className={styles["Transactions-title"]}>Stock changes</h3>
|
||||
|
||||
{analytics.materialMutations?.length > 0 &&
|
||||
analytics?.materialMutations.map((item, index) => (
|
||||
<RoundedRectangle
|
||||
key={index}
|
||||
bgColor="rgb(59 59 59 / 41%)"
|
||||
title={item.name}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
justifyContent: "left",
|
||||
padding: "20px",
|
||||
}}
|
||||
>
|
||||
{item.mutations.map((mutation, mutationIndex) => (
|
||||
<RoundedRectangle
|
||||
bgColor="rgb(59 59 59 / 41%)"
|
||||
key={mutationIndex}
|
||||
isChildren={true}
|
||||
title={`from ${mutation.oldStock} to ${mutation.newStock}`}
|
||||
value={formatDate(mutation.changeDate)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</RoundedRectangle>
|
||||
))}
|
||||
</div>
|
||||
<div class="ItemLister_PaymentOption__YZlDL"><div style={{marginTop:'20px'}} onClick={handleClose} class="ItemLister_Pay2Button__+MIxX">Kembali</div></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -4,9 +4,9 @@ import { useParams } from "react-router-dom";
|
||||
import { ColorRing } from "react-loader-spinner";
|
||||
import {
|
||||
getMyTransactions,
|
||||
getTransactions,
|
||||
confirmTransaction,
|
||||
declineTransaction,
|
||||
getTransactionsFromCafe,
|
||||
} from "../helpers/transactionHelpers";
|
||||
import { getTables } from "../helpers/tableHelper";
|
||||
import TableCanvas from "../components/TableCanvas";
|
||||
@@ -18,17 +18,17 @@ export default function Transactions({ propsShopId, sendParam, deviceType }) {
|
||||
const [tables, setTables] = useState([]);
|
||||
const [selectedTable, setSelectedTable] = useState(null);
|
||||
const [transactions, setTransactions] = useState([]);
|
||||
const [myTransactions, setMyTransactions] = useState([]);
|
||||
const [isPaymentLoading, setIsPaymentLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchTransactions = async () => {
|
||||
try {
|
||||
let response;
|
||||
if (deviceType == "clerk")
|
||||
response = await getTransactions(shopId || propsShopId, 5);
|
||||
else if (deviceType == "guestDevice")
|
||||
response = await getTransactionsFromCafe(shopId || propsShopId, 5);
|
||||
setTransactions(response);
|
||||
response = await getMyTransactions(shopId || propsShopId, 5);
|
||||
setTransactions(response);
|
||||
setMyTransactions(response);
|
||||
} catch (error) {
|
||||
console.error("Error fetching transactions:", error);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.fileInput {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.circular-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// WelcomePage.js
|
||||
import React from "react";
|
||||
import React,{useRef} from "react";
|
||||
import "./WelcomePage.css";
|
||||
|
||||
const WelcomePage = ({
|
||||
@@ -9,7 +9,12 @@ const WelcomePage = ({
|
||||
welcomingText,
|
||||
backgroundColor,
|
||||
textColor,
|
||||
onImageChange
|
||||
}) => {
|
||||
const fileInputRef = useRef(null);
|
||||
const handleImageClick = () => {
|
||||
fileInputRef.current.click();
|
||||
};
|
||||
return (
|
||||
<div
|
||||
className={`welcome-page ${isFullscreen ? "fullscreen" : ""}`} // Corrected the className syntax
|
||||
@@ -19,11 +24,20 @@ const WelcomePage = ({
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: image ? "transparent" : "black",
|
||||
backgroundColor: image ? "transparent" : "black",position:'relative'
|
||||
}}
|
||||
className="image-container"
|
||||
>
|
||||
{image && <img src={image} alt="Welcome" className="circular-image" />} {/* Added conditional rendering */}
|
||||
{!isFullscreen &&
|
||||
<div onClick={handleImageClick} style={{width: '100%', height: '100%', position:'absolute'}}>
|
||||
<h1 style={{textAlign:'left'}}>
|
||||
{image ? "Click To Change Image" : "Click To Add Image"}
|
||||
</h1>
|
||||
<input
|
||||
ref={fileInputRef} style={{display: 'none', width:'100%', height: '100%'}}type="file" accept="image/*" onChange={onImageChange} />
|
||||
</div>
|
||||
}
|
||||
{image && <img src={image} alt="Welcome" className="circular-image" />} {/* Added conditional rendering */}
|
||||
</div>
|
||||
<h1 className="welcoming-text" style={{ color: textColor }}>
|
||||
{welcomingText}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
padding: 20px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
background-color: #f9f9f9;
|
||||
background-color: rgb(207, 207, 207);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,6 @@ const WelcomePageEditor = ({ cafeId, welcomePageConfig }) => {
|
||||
>
|
||||
<h2>Edit Welcome Page</h2>
|
||||
<div style={{ display: "flex", flexDirection: "column" }}>
|
||||
<input type="file" accept="image/*" onChange={handleImageChange} />
|
||||
<textarea
|
||||
value={welcomingText}
|
||||
onChange={handleTextChange}
|
||||
@@ -120,7 +119,7 @@ const WelcomePageEditor = ({ cafeId, welcomePageConfig }) => {
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
style={{ width: "100%", height: "100%", position: "relative", flex: 1 }}
|
||||
style={{ width: "100%", height: "100%", position: "relative", flex: 1, borderRadius: '15px' }}
|
||||
>
|
||||
<WelcomePage
|
||||
image={image}
|
||||
@@ -129,6 +128,7 @@ const WelcomePageEditor = ({ cafeId, welcomePageConfig }) => {
|
||||
textColor={textColor}
|
||||
onGetStarted={() => setIsFullscreen(false)}
|
||||
isFullscreen={isFullscreen}
|
||||
onImageChange={handleImageChange}
|
||||
/>
|
||||
<div style={{ position: "absolute", bottom: 0, right: 0 }}>
|
||||
<svg
|
||||
|
||||
Reference in New Issue
Block a user