This commit is contained in:
insvrgent
2025-01-29 15:39:55 +07:00
parent c5927469eb
commit b0813e1519
3 changed files with 216 additions and 189 deletions

View File

@@ -2,7 +2,7 @@
"name": "groovebrew-mockup", "name": "groovebrew-mockup",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"homepage": "https://dev.kedaimaster.com", "homepage": "https://kedaimaster.com",
"dependencies": { "dependencies": {
"@emotion/react": "^11.13.3", "@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0", "@emotion/styled": "^11.13.0",

View File

@@ -1,5 +1,5 @@
// src/config.js // src/config.js
const API_BASE_URL = 'https://dev.api.kedaimaster.com'; const API_BASE_URL = 'https://api.kedaimaster.com';
export default API_BASE_URL; export default API_BASE_URL;

View File

@@ -21,14 +21,14 @@ const RoundedRectangle = ({
loading = false, loading = false,
children, // Assuming this is a React component or JSX children, // Assuming this is a React component or JSX
isChildren, isChildren,
width='calc(100% / 2 - 10px)' width = 'calc(100% / 2 - 10px)'
}) => { }) => {
const containerStyle = { const containerStyle = {
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
alignItems: "flex-start", alignItems: "flex-start",
justifyContent: "center", justifyContent: "center",
width: !children && !isChildren && width, width: width,
height: "auto", height: "auto",
borderRadius: "15px", borderRadius: "15px",
padding: "20px", padding: "20px",
@@ -104,7 +104,7 @@ const RoundedRectangle = ({
); );
}; };
const App = ({ forCafe = true, cafeId="", const App = ({ forCafe = true, cafeId = -1,
handleClose, otherCafes }) => { handleClose, otherCafes }) => {
const [selectedCafeId, setSelectedCafeId] = useState(cafeId); const [selectedCafeId, setSelectedCafeId] = useState(cafeId);
const [analytics, setAnalytics] = useState({}); const [analytics, setAnalytics] = useState({});
@@ -112,13 +112,13 @@ const App = ({ forCafe = true, cafeId="",
const [filter, setFilter] = useState("yesterday"); const [filter, setFilter] = useState("yesterday");
const fetchData = async (filter) => { const fetchData = async (filter) => {
if(selectedCafeId == '-1') return; if (selectedCafeId == '-1') return;
try { try {
setLoading(true); setLoading(true);
// Fetch the analytics data with the selected filter // Fetch the analytics data with the selected filter
const analyticsData = (selectedCafeId !== '' && selectedCafeId !== 0) const analyticsData = (selectedCafeId !== '' && selectedCafeId !== 0)
? await getReports(selectedCafeId, filter) ? await getReports(selectedCafeId, filter)
: await getAnalytics(filter); : await getAnalytics(filter);
console.log(analyticsData); console.log(analyticsData);
if (analyticsData) setAnalytics(analyticsData); if (analyticsData) setAnalytics(analyticsData);
@@ -210,7 +210,7 @@ const App = ({ forCafe = true, cafeId="",
console.log(selectedCafeId) console.log(selectedCafeId)
console.log(segments) console.log(segments)
const formatIncome = (amount) => { const formatIncome = (amount) => {
if (amount >= 1_000_000_000) { if (amount >= 1_000_000_000) {
@@ -262,7 +262,7 @@ console.log(segments)
["buat kedai", -1] ["buat kedai", -1]
]; ];
setSelectedCafeId(otherCafes[0].cafeId); // Get the cafeId (second part of the pair) setSelectedCafeId(otherCafes[0].cafeId); // Get the cafeId (second part of the pair)
} else { } else {
updatedFullTexts = [ updatedFullTexts = [
["semua", 0], // First entry is "semua" ["semua", 0], // First entry is "semua"
@@ -298,7 +298,7 @@ console.log(segments)
setTexts((prevTexts) => { setTexts((prevTexts) => {
const newTexts = [...prevTexts]; const newTexts = [...prevTexts];
console.log(prevTexts.length) console.log(prevTexts.length)
const nextText = fullTexts[fullTexts.findIndex(item => item[0] === texts[2])+1][0]; // Get the next item in the full list const nextText = fullTexts[fullTexts.findIndex(item => item[0] === texts[2]) + 1][0]; // Get the next item in the full list
newTexts.shift(); // Remove the first element newTexts.shift(); // Remove the first element
newTexts.push(nextText); // Add the next item to the end newTexts.push(nextText); // Add the next item to the end
setSelectedSwitch(1); // Change the selected index setSelectedSwitch(1); // Change the selected index
@@ -342,186 +342,213 @@ console.log(segments)
return ( return (
<div style={{ <div style={{
position: forCafe? 'fixed': 'relative', position: forCafe ? 'fixed' : 'relative',
height: '100vh', height: '100vh',
width: '100vw', width: '100vw',
top: 0, top: 0,
right: 0, right: 0,
backgroundColor: 'white', backgroundColor: 'white',
overflowY: forCafe? 'auto' : 'none', overflowY: forCafe ? 'auto' : 'none',
color: 'black', color: 'black',
marginTop: forCafe ? 0 : '-22vh' marginTop: forCafe ? 0 : '-22vh'
}} }}
> >
<div style={{ display: 'flex', alignItems: 'center', padding: forCafe? '0px 20px' : '0px 15px', justifyContent: forCafe? 'flex-start':'space-between' }}> <div style={{ display: 'flex', alignItems: 'center', padding: forCafe ? '0px 20px' : '0px 15px', justifyContent: forCafe ? 'flex-start' : 'space-between' }}>
{forCafe && <div style={{marginTop: '49px', marginRight: '10px'}} onClick={handleClose}><svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 512 512"><path d="M48,256c0,114.87,93.13,208,208,208s208-93.13,208-208S370.87,48,256,48,48,141.13,48,256Zm212.65-91.36a16,16,0,0,1,.09,22.63L208.42,240H342a16,16,0,0,1,0,32H208.42l52.32,52.73A16,16,0,1,1,238,347.27l-79.39-80a16,16,0,0,1,0-22.54l79.39-80A16,16,0,0,1,260.65,164.64Z"/></svg></div>} {forCafe && <div style={{ marginTop: '49px', marginRight: '10px' }} onClick={handleClose}><svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 512 512"><path d="M48,256c0,114.87,93.13,208,208,208s208-93.13,208-208S370.87,48,256,48,48,141.13,48,256Zm212.65-91.36a16,16,0,0,1,.09,22.63L208.42,240H342a16,16,0,0,1,0,32H208.42l52.32,52.73A16,16,0,1,1,238,347.27l-79.39-80a16,16,0,0,1,0-22.54l79.39-80A16,16,0,0,1,260.65,164.64Z" /></svg></div>}
<div style={{ marginTop: '10px' }}> <div style={{ marginTop: '10px' }}>
{!forCafe && {!forCafe &&
// <MultiSwitch // <MultiSwitch
// key={resetKey} // Add key to reset the component and force it to re-render // key={resetKey} // Add key to reset the component and force it to re-render
// texts={texts} // texts={texts}
// selectedSwitch={selectedSwitch} // selectedSwitch={selectedSwitch}
// bgColor={'#f4efe6'} // bgColor={'#f4efe6'}
// borderColor={'transparent'} // borderColor={'transparent'}
// borderWidth={0.1} // borderWidth={0.1}
// onToggleCallback={onItemToggle} // onToggleCallback={onItemToggle}
// fontColor={"#af9463"} // fontColor={"#af9463"}
// selectedFontColor={"black"} // selectedFontColor={"black"}
// selectedSwitchColor={"white"} // selectedSwitchColor={"white"}
// eachSwitchWidth={70} // eachSwitchWidth={70}
// height={"25px"} // height={"25px"}
// fontSize={"12px"} // fontSize={"12px"}
// /> // />
<div className={styles.dateSelectorWrapper} style={{fontSize: '13px'}}> <div className={styles.dateSelectorWrapper} style={{ fontSize: '13px' }}>
{texts.map((item, indexx) => { {texts.map((item, indexx) => {
return ( return (
<div <div
key={indexx} key={indexx}
className={`${styles.dateSelector} ${styles.dateSelectorActive}`} style={{position: 'relative', width: 'calc(32vw - 30px)'}} className={`${styles.dateSelector} ${styles.dateSelectorActive}`} style={{ position: 'relative', width: 'calc(32vw - 30px)' }}
onClick={()=>onItemToggle(indexx)} onClick={() => onItemToggle(indexx)}
> >
<div style={{position: 'absolute', bottom: 0, left: '10%', right: '10%', borderBottom: selectedSwitch == indexx ? `1px solid green` : 'none'}}></div> <div style={{ position: 'absolute', bottom: 0, left: '10%', right: '10%', borderBottom: selectedSwitch == indexx ? `1px solid green` : 'none' }}></div>
<div <div
style={{ color: 'black' }}> style={{ color: 'black' }}>
{item} {item}
</div> </div>
</div> </div>
); );
})} })}
</div> </div>
} }
</div> </div>
</div> </div>
<div style={{ {!forCafe && selectedCafeId != -1 &&
textAlign: "center", <div style={{
marginTop: '30px' textAlign: "center",
}}> marginTop: '30px'
<MultiSwitch }}>
texts={["kemarin", "minggu ini", "bulan ini", "tahun ini"]} <MultiSwitch
selectedSwitch={["yesterday", "weekly", "monthly", "yearly"].indexOf( texts={["kemarin", "minggu ini", "bulan ini", "tahun ini"]}
filter selectedSwitch={["yesterday", "weekly", "monthly", "yearly"].indexOf(
)} filter
bgColor={'#f4efe6'} )}
borderColor={'transparent'} bgColor={'#f4efe6'}
borderWidth={0.1} borderColor={'transparent'}
onToggleCallback={onToggle} borderWidth={0.1}
fontColor={"#af9463"} onToggleCallback={onToggle}
selectedFontColor={"black"} fontColor={"#af9463"}
selectedSwitchColor={"white"} selectedFontColor={"black"}
eachSwitchWidth={70} selectedSwitchColor={"white"}
height={"25px"} eachSwitchWidth={70}
fontSize={"12px"} height={"25px"}
/> fontSize={"12px"}
<div
style={{
display: "flex",
flexWrap: "wrap",
justifyContent: "center",
padding: "20px",
}}
>
<RoundedRectangle
title="Pendapatan"
fontSize="12px"
value={!loading && "Rp" + formatIncome(analytics?.currentTotals?.income)}
percentage={roundToInteger(analytics?.growth?.incomeGrowth)}
invert={false}
loading={loading}
/> />
<div
style={{
display: "flex",
flexWrap: "wrap",
justifyContent: "center",
padding: "20px",
}}
>
<RoundedRectangle
title="Pendapatan"
fontSize="12px"
value={!loading && "Rp" + formatIncome(analytics?.currentTotals?.income)}
percentage={roundToInteger(analytics?.growth?.incomeGrowth)}
invert={false}
loading={loading}
/>
<RoundedRectangle <RoundedRectangle
title="Pengeluaran" title="Pengeluaran"
fontSize="12px" fontSize="12px"
value={!loading && "Rp" + formatIncome(analytics?.currentTotals?.outcome)} value={!loading && "Rp" + formatIncome(analytics?.currentTotals?.outcome)}
percentage={roundToInteger(analytics?.growth?.outcomeGrowth)} percentage={roundToInteger(analytics?.growth?.outcomeGrowth)}
invert={true} invert={true}
loading={loading} loading={loading}
/> />
<RoundedRectangle <RoundedRectangle
title="Transaksi" title="Transaksi"
value={analytics?.currentTotals?.transactions} value={analytics?.currentTotals?.transactions}
percentage={roundToInteger(analytics?.growth?.transactionGrowth)} percentage={roundToInteger(analytics?.growth?.transactionGrowth)}
invert={false} invert={false}
loading={loading} loading={loading}
/> />
{analytics?.itemSales && {analytics?.itemSales &&
analytics?.itemSales.length > 0 && ( analytics?.itemSales.length > 0 && (
<RoundedRectangle
title={"Item favorit"}
value={analytics?.itemSales[0]?.itemName}
loading={loading}
/>
)}
{(!analytics?.itemSales ||
analytics?.itemSales.length === 0) && (
<RoundedRectangle
title={"Item favorit"}
value={"-"}
loading={loading}
/>
)}
{!forCafe && selectedCafeId != -1 && selectedCafeId != 0 && (
<RoundedRectangle <RoundedRectangle
title={"Kunjungi kedai"} title={"Item favorit"}
value={analytics?.itemSales[0]?.itemName}
loading={loading} loading={loading}
width="calc(100% - 10px)"
onClick={() => window.location.href = window.location.origin + '/' + otherCafes.find(item => item.cafeId === selectedCafeId).cafeIdentifyName}
/> />
)} )}
{(!analytics?.itemSales ||
analytics?.itemSales.length === 0) && (
<RoundedRectangle
title={"Item favorit"}
value={"-"}
loading={loading}
/>
)}
{!forCafe && selectedCafeId != -1 && selectedCafeId != 0 && (
<RoundedRectangle
title={"Kunjungi kedai"}
loading={loading}
width="calc(100% - 10px)"
onClick={() => window.location.href = window.location.origin + '/' + otherCafes.find(item => item.cafeId === selectedCafeId).cafeIdentifyName}
/>
)}
<div
style={{ display: "flex", alignItems: "center", margin: "10px" }}
>
<div style={{ marginRight: "5px", fontSize: "1.2em" }}></div>
<h6 style={{ margin: 0, textAlign: "left", fontSize: '10px', fontWeight: 500 }}>
Persentase pertumbuhan dihitung dengan membandingkan {" "}
{comparisonText} hari terakhir dengan {comparisonText} hari sebelumnya.
</h6>
</div>
</div>
<div <div
style={{ display: "flex", alignItems: "center", margin: "10px" }} style={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
padding: "20px",
}}
> >
<div style={{ marginRight: "5px", fontSize: "1.2em" }}></div> <div style={{ flex: 1 }}>
<h6 style={{ margin: 0, textAlign: "left", fontSize: '10px', fontWeight: 500 }}> <CircularDiagram segments={segments} />
Persentase pertumbuhan dihitung dengan membandingkan {" "} </div>
{comparisonText} hari terakhir dengan {comparisonText} hari sebelumnya. <div style={{ flex: 1, marginLeft: "20px" }}>
</h6> {segments.map((item, index) => (
</div>
</div>
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
padding: "20px",
}}
>
<div style={{ flex: 1 }}>
<CircularDiagram segments={segments} />
</div>
<div style={{ flex: 1, marginLeft: "20px" }}>
{segments.map((item, index) => (
<div
key={index}
style={{
display: "flex",
alignItems: "center",
margin: "10px",
}}
>
<div <div
key={index}
style={{ style={{
marginRight: "5px", display: "flex",
fontSize: "1.2em", alignItems: "center",
color: colors[index], margin: "10px",
}} }}
> >
<div
style={{
marginRight: "5px",
fontSize: "1.2em",
color: colors[index],
}}
>
</div>
<h5 style={{ margin: 0, textAlign: "left" }}>{item.itemName}</h5>
</div> </div>
<h5 style={{ margin: 0, textAlign: "left" }}>{item.itemName}</h5> ))}
</div> </div>
))} </div>
{filter == 'yesterday' || filter == 'weekly' ?
<DailyCharts transactionGraph={analytics?.transactionGraph || analytics?.combinedTransactionGraph} type={filter} colors={colors} />
:
<PeriodCharts type={filter} aggregatedCurrentReports={analytics?.aggregatedCurrentReports} aggregatedPreviousReports={analytics?.aggregatedPreviousReports} colors={colors} />
}
</div>
}
{!forCafe && selectedCafeId == -1 &&
<div style={{
textAlign: "center",
marginTop: '30px'
}}>
<div
style={{
display: "flex",
flexWrap: "wrap",
justifyContent: "center",
padding: "20px",
}}
>
<RoundedRectangle
title={"Masukkan nama kedai"}
width="calc(100% - 10px)"
><input style={{width: '70%', fontSize: '25px'}}/></RoundedRectangle>
<RoundedRectangle
title={"Buat kedai"}
width="calc(100% - 10px)"
/>
</div> </div>
</div> </div>
{filter == 'yesterday' || filter == 'weekly' ? }
<DailyCharts transactionGraph={analytics?.transactionGraph || analytics?.combinedTransactionGraph} type={filter} colors={colors} />
:
<PeriodCharts type={filter} aggregatedCurrentReports={analytics?.aggregatedCurrentReports} aggregatedPreviousReports={analytics?.aggregatedPreviousReports} colors={colors} />
}
</div>
</div> </div>
); );
}; };