1105 lines
38 KiB
JavaScript
1105 lines
38 KiB
JavaScript
import React, { useState, useRef, useEffect } from "react";
|
||
import API_BASE_URL from "../config.js";
|
||
import { getImageUrl } from "../helpers/itemHelper";
|
||
import { getTables, updateTable, createTable } from "../helpers/tableHelper";
|
||
import {
|
||
getCafe,
|
||
saveCafeDetails,
|
||
setConfirmationStatus,
|
||
} from "../helpers/cafeHelpers";
|
||
|
||
import { toPng } from 'html-to-image';
|
||
import { ColorRing } from "react-loader-spinner";
|
||
|
||
const SetPaymentQr = ({ shop }) => {
|
||
const [initialPos, setInitialPos] = useState({
|
||
left: shop.xposition,
|
||
top: shop.yposition,
|
||
});
|
||
|
||
const [isViewingQR, setIsViewingQR] = useState(false);
|
||
const [isConfigFont, setIsConfigFont] = useState(false);
|
||
const [fontsize, setfontsize] = useState(shop.fontsize);
|
||
const [fontcolor, setfontcolor] = useState(shop.fontcolor);
|
||
const [initialFontPos, setInitialFontPos] = useState({
|
||
left: shop.fontxposition,
|
||
top: shop.fontyposition,
|
||
});
|
||
|
||
const [initialSize, setInitialSize] = useState(shop.scale);
|
||
const [bgImageUrl, setBgImageUrl] = useState(getImageUrl(shop.qrBackground));
|
||
const qrBackgroundInputRef = useRef(null);
|
||
|
||
const [cafeIdentifyNameUpdate, setCafeIdentifyNameUpdate] = useState(shop.cafeIdentifyName);
|
||
const shopUrl = window.location.hostname + "/" + cafeIdentifyNameUpdate;
|
||
|
||
|
||
const cafeIdentifyNameRef = useRef(null);
|
||
const [isconfigcafeidentityname, setIsConfigCafeIdentityName] = useState(false);
|
||
|
||
|
||
const generateQRCodeUrl = (tableCode) => {
|
||
if (tableCode != null) {
|
||
return `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(
|
||
shopUrl + "/" + tableCode
|
||
)}`;
|
||
} else {
|
||
return `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(
|
||
shopUrl
|
||
)}`;
|
||
}
|
||
};
|
||
|
||
const [isConfig, setIsConfig] = useState(false);
|
||
const [isConfigQR, setIsConfigQR] = useState(false);
|
||
const [isViewTables, setIsViewTables] = useState(false);
|
||
|
||
const [tables, setTables] = useState([]);
|
||
|
||
const [selectedTable, setSelectedTable] = useState(null);
|
||
|
||
const [tableNo, setTableNo] = useState(null);
|
||
const [isLoading, setIsLoading] = useState(false);
|
||
const [identifyNameResponse, setIdentifyNameResponse] = useState('-----------------');
|
||
|
||
useEffect(() => {
|
||
const fetchData = async () => {
|
||
try {
|
||
console.log(shop);
|
||
const fetchedTables = await getTables(shop.cafeId);
|
||
setTables(fetchedTables);
|
||
} catch (error) {
|
||
console.error("Error fetching tables:", error);
|
||
}
|
||
};
|
||
|
||
fetchData();
|
||
}, [shop.cafeId]);
|
||
|
||
const handleSave = () => {
|
||
const qrBackgroundFile = qrBackgroundInputRef.current.files[0]; // Get the selected file for qrBackground
|
||
|
||
// Prepare the details object
|
||
const details = {
|
||
qrSize: initialSize,
|
||
qrPosition: initialPos,
|
||
qrBackgroundFile,
|
||
fontsize,
|
||
fontcolor,
|
||
fontPosition: initialFontPos,
|
||
};
|
||
|
||
// Call saveCafeDetails function with the updated details object
|
||
saveCafeDetails(shop.cafeId, details)
|
||
.then((response) => {
|
||
console.log("Cafe details saved:", response);
|
||
})
|
||
.catch((error) => {
|
||
console.error("Error saving cafe details:", error);
|
||
});
|
||
};
|
||
|
||
|
||
const handlePositionChange = (e) => {
|
||
const { name, value } = e.target;
|
||
setInitialPos((prevPosition) => ({
|
||
...prevPosition,
|
||
[name]: parseFloat(value).toFixed(2),
|
||
}));
|
||
};
|
||
|
||
const handleFontPositionChange = (e) => {
|
||
const { name, value } = e.target;
|
||
setInitialFontPos((prevPosition) => ({
|
||
...prevPosition,
|
||
[name]: parseFloat(value).toFixed(2),
|
||
}));
|
||
};
|
||
|
||
const handleSizeChange = (e) => {
|
||
setInitialSize(parseFloat(e.target.value).toFixed(2));
|
||
};
|
||
|
||
const handleFontSizeChange = (e) => {
|
||
setfontsize(parseFloat(e.target.value).toFixed(2));
|
||
};
|
||
|
||
const handleFileChange = (e) => {
|
||
const file = e.target.files[0];
|
||
if (file) {
|
||
const newBgImage = URL.createObjectURL(file); // Create a temporary URL for display
|
||
setBgImageUrl(newBgImage);
|
||
}
|
||
};
|
||
|
||
const handleCreate = async () => {
|
||
// if (newTable) {
|
||
try {
|
||
const createdTable = await createTable(shop.cafeId, {
|
||
// ...newTable,
|
||
tableNo,
|
||
});
|
||
setTables([...tables, createdTable]);
|
||
setTableNo("");
|
||
} catch (error) {
|
||
console.error("Error creating table:", error);
|
||
}
|
||
};
|
||
|
||
function downloadQrCodeContainer({ selectedTable, shop }) {
|
||
const node = document.getElementById('qr-code-container');
|
||
|
||
if (!node) return;
|
||
|
||
// Save the original background color
|
||
const originalBackgroundColor = node.style.backgroundColor;
|
||
|
||
// Temporarily remove the background color
|
||
node.style.backgroundColor = 'transparent';
|
||
|
||
const isTableSelected = selectedTable != null;
|
||
|
||
toPng(node, { pixelRatio: 2 }) // Adjust pixel ratio for higher resolution
|
||
.then((dataUrl) => {
|
||
const link = document.createElement('a');
|
||
link.href = dataUrl;
|
||
|
||
// Set the file name based on whether selectedTable exists
|
||
link.download = isTableSelected
|
||
? `QR Meja (${selectedTable.tableNo}).png`
|
||
: `QR ${shop.name}.png`;
|
||
|
||
link.click();
|
||
})
|
||
.catch((err) => {
|
||
console.error('Could not download the image', err);
|
||
})
|
||
.finally(() => {
|
||
// Restore the original background color after the download
|
||
node.style.backgroundColor = originalBackgroundColor;
|
||
});
|
||
}
|
||
|
||
// This will hold the timeout ID so we can clear it when needed
|
||
const typingTimeoutRef = useRef(null);
|
||
|
||
const handleInputChange = (e) => {
|
||
setIsLoading(true)
|
||
const updatedValue = e.target.value
|
||
.toLowerCase()
|
||
.replace(/ /g, '_')
|
||
.replace(/[^a-z0-9_]/g, '');
|
||
setCafeIdentifyNameUpdate(updatedValue);
|
||
|
||
// Clear the existing timeout
|
||
if (typingTimeoutRef.current) {
|
||
clearTimeout(typingTimeoutRef.current);
|
||
}
|
||
|
||
// Set a new timeout
|
||
typingTimeoutRef.current = setTimeout(() => {
|
||
// Call the function to check if the name is already used
|
||
checkIfNameIsUsed(updatedValue);
|
||
}, 1000); // 1 second delay
|
||
};
|
||
|
||
const checkIfNameIsUsed = async (newIdentifyName) => {
|
||
// Replace this with your actual API call
|
||
try {
|
||
const response = await fetch(API_BASE_URL+`/cafe/check-identifyName/${newIdentifyName}`);
|
||
console.log(response)
|
||
if (response.ok) {
|
||
setIsLoading(false);
|
||
setIdentifyNameResponse(200)
|
||
}
|
||
else {
|
||
setIsLoading(false);
|
||
setIdentifyNameResponse(409)
|
||
}
|
||
} catch (error) {
|
||
|
||
}
|
||
};
|
||
|
||
return (
|
||
<div style={styles.container}>
|
||
<h3 style={styles.title}>Identifikasi kedai</h3>
|
||
<div style={{ height: 80, position: 'relative', scale: '80%', transformOrigin: 'left', left: 0, width: '125%' }}>
|
||
<div
|
||
style={{
|
||
width: '100%',
|
||
height: 38,
|
||
left: 0,
|
||
top: 42,
|
||
position: 'absolute',
|
||
zIndex: 1,
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
width: '100%',
|
||
height: 38,
|
||
left: 0,
|
||
top: 0,
|
||
position: 'absolute',
|
||
overflow: 'hidden'
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
width: '100%',
|
||
height: 38,
|
||
left: 0,
|
||
top: 0,
|
||
position: 'absolute',
|
||
background: '#35363A',
|
||
boxShadow: '0px -1px 0px #DADCE0 inset',
|
||
}}
|
||
/>
|
||
<div
|
||
style={{
|
||
width: 51,
|
||
height: 22,
|
||
left: 1375,
|
||
top: 8,
|
||
position: 'absolute',
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
width: 16,
|
||
height: 16,
|
||
left: 35,
|
||
top: 3,
|
||
position: 'absolute',
|
||
}}
|
||
>
|
||
<img
|
||
style={{
|
||
width: 3,
|
||
height: 12,
|
||
left: 6.67,
|
||
top: 2,
|
||
position: 'absolute',
|
||
}}
|
||
src='https://via.placeholder.com/3x12'
|
||
/>
|
||
</div>
|
||
<img
|
||
style={{
|
||
width: 22,
|
||
height: 22,
|
||
left: 0,
|
||
top: 0,
|
||
position: 'absolute',
|
||
borderRadius: 9999,
|
||
}}
|
||
src='https://via.placeholder.com/22x22'
|
||
/>
|
||
</div>
|
||
<div
|
||
style={{
|
||
height: 28,
|
||
left: isconfigcafeidentityname ? 0 : 69,
|
||
right: 0,
|
||
top: 5,
|
||
position: 'absolute',
|
||
zIndex: 3
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
width: '100%',
|
||
height: 28,
|
||
top: 0,
|
||
position: 'absolute',
|
||
background: '#202124',
|
||
borderRadius: isconfigcafeidentityname ? 0 : '14px 0 0 14px',
|
||
}}
|
||
/>
|
||
<div
|
||
style={{
|
||
width: 16,
|
||
height: 16,
|
||
left: 1199,
|
||
top: 6,
|
||
position: 'absolute',
|
||
}}
|
||
>
|
||
<img
|
||
style={{
|
||
width: 12,
|
||
height: 11.47,
|
||
left: 2,
|
||
top: 2,
|
||
position: 'absolute',
|
||
}}
|
||
src='https://via.placeholder.com/12x11'
|
||
/>
|
||
</div>
|
||
<div
|
||
style={{
|
||
height: 16,
|
||
left: 33,
|
||
right: 0,
|
||
top: 4,
|
||
position: 'absolute',
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
left: 0,
|
||
right: 0,
|
||
top: 0,
|
||
position: 'absolute',
|
||
justifyContent: 'flex-start',
|
||
alignItems: 'center',
|
||
display: 'inline-flex',
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
color: 'white',
|
||
fontSize: 14,
|
||
fontFamily: 'Roboto',
|
||
fontWeight: '400',
|
||
letterSpacing: 0.25,
|
||
wordWrap: 'break-word',
|
||
}}
|
||
>
|
||
{window.location.hostname}/
|
||
</div>
|
||
<input
|
||
ref={cafeIdentifyNameRef}
|
||
style={{
|
||
width: '100%',
|
||
color: '#86888A',
|
||
fontSize: 14,
|
||
fontFamily: 'Roboto',
|
||
fontWeight: '400',
|
||
letterSpacing: 0.25,
|
||
wordWrap: 'break-word',
|
||
backgroundColor: 'transparent',
|
||
borderColor: 'transparent',
|
||
paddingLeft: isconfigcafeidentityname ? '10px' : '0', // Adjust padding when focused
|
||
borderLeft: isconfigcafeidentityname ? '1px solid #ccc' : '0', // Adjust border when focused
|
||
}}
|
||
onChange={
|
||
handleInputChange
|
||
}
|
||
value={cafeIdentifyNameUpdate}
|
||
onFocus={() => {
|
||
setIsConfigCafeIdentityName(true); // Set the state to true when input is focused
|
||
}}
|
||
/>
|
||
|
||
</div>
|
||
</div>
|
||
<div
|
||
style={{
|
||
width: 12,
|
||
height: 12,
|
||
left: 11,
|
||
top: 8,
|
||
position: 'absolute',
|
||
}}
|
||
>
|
||
<svg style={{
|
||
left: 2,
|
||
top: 0.5,
|
||
position: 'absolute',
|
||
}} xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none">
|
||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9 4H8.5V3C8.5 1.62 7.38 0.5 6 0.5C4.62 0.5 3.5 1.62 3.5 3V4H3C2.45 4 2 4.45 2 5V10C2 10.55 2.45 11 3 11H9C9.55 11 10 10.55 10 10V5C10 4.45 9.55 4 9 4ZM4.5 4V3C4.5 2.17 5.17 1.5 6 1.5C6.83 1.5 7.5 2.17 7.5 3V4H4.5Z" fill="#EAEAEA" />
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
<div
|
||
style={{
|
||
width: 109,
|
||
height: 16,
|
||
left: 12,
|
||
top: 11,
|
||
position: 'absolute',
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
width: 16,
|
||
height: 16,
|
||
left: 31,
|
||
top: 0,
|
||
position: 'absolute',
|
||
}}
|
||
><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
|
||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.9979 6.33122V2.80455C13.9979 2.50455 13.6379 2.35788 13.4312 2.57122L12.2446 3.75788C11.0379 2.55122 9.31789 1.85788 7.43789 2.02455C4.64456 2.27788 2.34456 4.52455 2.03789 7.31788C1.63789 10.9312 4.45789 13.9979 7.99789 13.9979C11.0579 13.9979 13.5846 11.7046 13.9512 8.74455C13.9979 8.34455 13.6846 7.99788 13.2846 7.99788C12.9512 7.99788 12.6712 8.24455 12.6312 8.57122C12.3446 10.8979 10.3379 12.6979 7.93122 12.6645C5.45789 12.6312 3.37122 10.5445 3.33122 8.06455C3.29122 5.46455 5.40456 3.33122 7.99789 3.33122C9.28456 3.33122 10.4512 3.85788 11.2979 4.69788L9.90456 6.09122C9.69122 6.30455 9.83789 6.66455 10.1379 6.66455H13.6646C13.8512 6.66455 13.9979 6.51788 13.9979 6.33122Z" fill="white" />
|
||
</svg>
|
||
</div>
|
||
<div
|
||
style={{
|
||
width: 16,
|
||
height: 16,
|
||
left: 0,
|
||
top: 0,
|
||
position: 'absolute',
|
||
}}
|
||
>
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
|
||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.2299 7.07685H4.62795L8.38601 3.31879C8.68635 3.01845 8.68635 2.52559 8.38601 2.22525C8.08567 1.92492 7.60051 1.92492 7.30018 2.22525L2.22525 7.30018C1.92492 7.60051 1.92492 8.08567 2.22525 8.38601L7.30018 13.4609C7.60051 13.7613 8.08567 13.7613 8.38601 13.4609C8.68635 13.1606 8.68635 12.6754 8.38601 12.3751L4.62795 8.61704H13.2299C13.6535 8.61704 14 8.2705 14 7.84694C14 7.42339 13.6535 7.07685 13.2299 7.07685Z" fill="#86888A" />
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div
|
||
style={{
|
||
width: '100%',
|
||
height: 42,
|
||
left: 0,
|
||
top: 0,
|
||
position: 'absolute',
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
width: '100%',
|
||
height: 42,
|
||
left: 0,
|
||
top: 0,
|
||
position: 'absolute',
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
width: '100%',
|
||
height: 42,
|
||
left: 0,
|
||
top: 0,
|
||
position: 'absolute',
|
||
background: '#202124',
|
||
boxShadow: '0px 4px 4px rgba(0, 0, 0, 0.25)',
|
||
borderTopLeftRadius: 8,
|
||
borderTopRightRadius: 8,
|
||
}}
|
||
/>
|
||
<div
|
||
style={{
|
||
width: 167,
|
||
height: 34,
|
||
left: 72,
|
||
top: 8,
|
||
position: 'absolute',
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
width: 131,
|
||
height: 34,
|
||
left: 8,
|
||
top: 0,
|
||
position: 'absolute',
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
left: -6,
|
||
top: 0,
|
||
position: 'absolute',
|
||
justifyContent: 'flex-start',
|
||
alignItems: 'center',
|
||
gap: 8,
|
||
display: 'inline-flex',
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
justifyContent: 'flex-start',
|
||
alignItems: 'flex-start',
|
||
display: 'flex',
|
||
}}
|
||
>
|
||
<div
|
||
style={{ width: 6, height: 8, background: '#35363A' }}
|
||
></div>
|
||
<div
|
||
style={{
|
||
padding: 8,
|
||
background: '#35363A',
|
||
borderTopLeftRadius: 8,
|
||
borderTopRightRadius: 8,
|
||
overflow: 'hidden',
|
||
justifyContent: 'flex-start',
|
||
alignItems: 'center',
|
||
gap: 9,
|
||
display: 'flex',
|
||
}}
|
||
>
|
||
<img
|
||
style={{ width: 16, height: 16 }}
|
||
src='./kedaimaster150.png'
|
||
/>
|
||
<div>
|
||
<span
|
||
style={{
|
||
color: 'white',
|
||
fontSize: 12,
|
||
fontFamily: 'Roboto',
|
||
fontWeight: '400',
|
||
letterSpacing: 0.2,
|
||
wordWrap: 'break-word',
|
||
}}
|
||
>
|
||
KedaiMaster
|
||
</span>
|
||
<span
|
||
style={{
|
||
color: '#35363A',
|
||
fontSize: 12,
|
||
fontFamily: 'Roboto',
|
||
fontWeight: '400',
|
||
letterSpacing: 0.2,
|
||
wordWrap: 'break-word',
|
||
}}
|
||
>
|
||
.
|
||
</span>
|
||
</div>
|
||
|
||
<div
|
||
style={{ width: 18, height: 18, position: 'relative' }}
|
||
><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" fill="none">
|
||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.5836 5.42207C12.3618 5.20023 12.0034 5.20023 11.7816 5.42207L9 8.19795L6.21843 5.41638C5.99659 5.19454 5.63823 5.19454 5.41638 5.41638C5.19454 5.63823 5.19454 5.99659 5.41638 6.21843L8.19795 9L5.41638 11.7816C5.19454 12.0034 5.19454 12.3618 5.41638 12.5836C5.63823 12.8055 5.99659 12.8055 6.21843 12.5836L9 9.80205L11.7816 12.5836C12.0034 12.8055 12.3618 12.8055 12.5836 12.5836C12.8055 12.3618 12.8055 12.0034 12.5836 11.7816L9.80205 9L12.5836 6.21843C12.7998 6.00228 12.7998 5.63823 12.5836 5.42207Z" fill="white" />
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
<div
|
||
style={{
|
||
width: 6,
|
||
height: 8,
|
||
transform: 'rotate(180deg)',
|
||
transformOrigin: '0 0',
|
||
background: '#35363A',
|
||
}}
|
||
></div>
|
||
</div>
|
||
<div style={{ width: 20, height: 20, position: 'relative' }}>
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.7142 10.9524H10.9523V15.7143C10.9523 16.2381 10.5237 16.6667 9.99992 16.6667C9.47611 16.6667 9.04754 16.2381 9.04754 15.7143V10.9524H4.28563C3.76182 10.9524 3.33325 10.5238 3.33325 10C3.33325 9.47623 3.76182 9.04766 4.28563 9.04766H9.04754V4.28575C9.04754 3.76195 9.47611 3.33337 9.99992 3.33337C10.5237 3.33337 10.9523 3.76195 10.9523 4.28575V9.04766H15.7142C16.238 9.04766 16.6666 9.47623 16.6666 10C16.6666 10.5238 16.238 10.9524 15.7142 10.9524Z" fill="#BDC1C6" />
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div
|
||
style={{
|
||
width: 52,
|
||
height: 12,
|
||
left: 13,
|
||
top: 15.5,
|
||
position: 'absolute',
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
width: 12,
|
||
height: 12,
|
||
left: 40,
|
||
top: 0,
|
||
position: 'absolute',
|
||
background: '#27CA40',
|
||
borderRadius: 9999,
|
||
border: '0.50px #3EAF3F solid',
|
||
}}
|
||
/>
|
||
<div
|
||
style={{
|
||
width: 12,
|
||
height: 12,
|
||
left: 20,
|
||
top: 0,
|
||
position: 'absolute',
|
||
background: '#FFC130',
|
||
borderRadius: 9999,
|
||
border: '0.50px #E1A325 solid',
|
||
}}
|
||
/>
|
||
<div
|
||
style={{
|
||
width: 12,
|
||
height: 12,
|
||
left: 0,
|
||
top: 0,
|
||
position: 'absolute',
|
||
background: '#FF6058',
|
||
borderRadius: 9999,
|
||
border: '0.50px #E14942 solid',
|
||
}}
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
|
||
{!isconfigcafeidentityname ?
|
||
<>
|
||
<div style={styles.uploadMessage}>
|
||
<p>Klik untuk ganti alamat</p>
|
||
</div>
|
||
<div style={styles.resultMessage}>
|
||
<p>-----------------</p>
|
||
<div
|
||
onClick={() => { setIsConfigCafeIdentityName(true); cafeIdentifyNameRef.current && cafeIdentifyNameRef.current.focus(); }} style={styles.changeButton}>Ganti
|
||
</div>
|
||
</div>
|
||
</> : (
|
||
<>
|
||
|
||
<div style={styles.uploadMessage}>
|
||
<p>{cafeIdentifyNameUpdate == shop.cafeIdentifyName ?
|
||
'-----------------' :
|
||
!isLoading && identifyNameResponse == 200 ?
|
||
'Alamat tersedia'
|
||
:
|
||
!isLoading && identifyNameResponse != 200 ?
|
||
'Alamat terpakai'
|
||
:
|
||
< ColorRing
|
||
height="16"
|
||
width="16" style={{ marginTop: '5px' }} />
|
||
|
||
}
|
||
</p>
|
||
</div>
|
||
<div style={styles.resultMessage}>
|
||
<p>{cafeIdentifyNameUpdate != shop.cafeIdentifyName && identifyNameResponse == 200 && !isLoading ?
|
||
<div
|
||
onClick={() => setIsConfigCafeIdentityName(false)} style={styles.changeButton2}>Terapkan
|
||
</div>
|
||
:
|
||
'----------'}</p>
|
||
{isconfigcafeidentityname ?
|
||
<div
|
||
onClick={() => { setIdentifyNameResponse(0); setCafeIdentifyNameUpdate(shop.cafeIdentifyName); setIsConfigCafeIdentityName(false); }} style={styles.changeButton}>Batal
|
||
</div>
|
||
:
|
||
<div
|
||
onClick={() => { setIsConfigCafeIdentityName(true); cafeIdentifyNameRef.current && cafeIdentifyNameRef.current.focus(); }} style={styles.changeButton}>Ganti
|
||
</div>
|
||
}
|
||
</div>
|
||
{/* <div
|
||
onClick={() => { }} style={styles.changeButton}>Simpan
|
||
{isLoading &&
|
||
<ColorRing
|
||
height="20"
|
||
width="20" style={{ marginTop: '5px' }} />
|
||
}
|
||
</div> */}
|
||
</>
|
||
)}
|
||
<div
|
||
id="qr-code-container"
|
||
style={{
|
||
...styles.qrCodeContainer,
|
||
backgroundColor: '#cdcdcd'
|
||
}}
|
||
>
|
||
<img
|
||
src={bgImageUrl}
|
||
alt="QR Code"
|
||
style={{
|
||
position: "absolute",
|
||
width: '100%',
|
||
height: '100%',
|
||
objectFit: 'contain',
|
||
transform: "translate(-50%, 0%)",
|
||
}} />
|
||
<img
|
||
src={generateQRCodeUrl(selectedTable?.tableCode || null)}
|
||
alt="QR Code"
|
||
style={{
|
||
position: "absolute",
|
||
width: `${initialSize}%`,
|
||
left: `${initialPos.left}%`,
|
||
top: `${initialPos.top}%`,
|
||
transform: "translate(-50%, -50%)",
|
||
}} />
|
||
<div style={{
|
||
transformOrigin: 'left',
|
||
transform: `scaleX(${initialFontPos.left > 50 ? -1 : 1})`,
|
||
position: "absolute",
|
||
fontSize: `${fontsize * 3}%`,
|
||
left: `${initialFontPos.left}%`,
|
||
top: `${initialFontPos.top}%`,
|
||
textAlign: initialFontPos.left > 50 ? 'right' : 'left'
|
||
}}>
|
||
<h1 style={{
|
||
visibility: !selectedTable && isViewingQR ? 'hidden' : 'visible',
|
||
transform: `scaleX(${initialFontPos.left > 50 ? -1 : 1})`,
|
||
width: '200%',
|
||
lineHeight: 0,
|
||
fontFamily: 'Plus Jakarta Sans',
|
||
color: fontcolor
|
||
}} >{selectedTable == null ? (isConfigFont ? 'Nomor meja' : '') : selectedTable.tableNo}</h1>
|
||
</div>
|
||
<input
|
||
type="file"
|
||
accept="image/*"
|
||
ref={qrBackgroundInputRef}
|
||
style={{ display: "none" }}
|
||
onChange={handleFileChange}
|
||
/>
|
||
</div>
|
||
{!isViewingQR ?
|
||
<>
|
||
<div style={styles.uploadMessage}>
|
||
<p>Klik untuk ganti background</p>
|
||
</div>
|
||
<div style={styles.resultMessage}>
|
||
<p onClick={() => { setIsConfig(!isConfig); setIsConfigQR(!isConfigQR); setIsConfigFont(false) }}> {isConfig ? '˅' : '˃'} Konfigurasi QR</p>
|
||
<div
|
||
onClick={() => qrBackgroundInputRef.current.click()} style={styles.changeButton}>Ganti</div>
|
||
</div>
|
||
<div style={styles.switchContainer}>
|
||
{isConfig &&
|
||
<div style={{ marginLeft: '15px' }}>
|
||
{/* <p style={styles.description} onClick={() => { setIsConfigQR(!isConfigQR); setIsConfigFont(false) }}>
|
||
{isConfigQR ? '˅' : '˃'} Konfigurasi QR
|
||
</p> */}
|
||
{isConfigQR && <>
|
||
<div style={styles.sliderContainer}>
|
||
<label style={styles.label}>
|
||
QR Code Size:
|
||
<div style={styles.sliderWrapper}>
|
||
<span style={styles.labelStart}>10%</span>
|
||
<input
|
||
type="range"
|
||
step="0.25"
|
||
min="10"
|
||
max="100"
|
||
value={initialSize}
|
||
onChange={handleSizeChange}
|
||
style={styles.input}
|
||
/>
|
||
<span style={styles.value}>{initialSize}%</span>
|
||
</div>
|
||
</label>
|
||
</div>
|
||
<div style={styles.sliderContainer}>
|
||
<label style={styles.label}>
|
||
QR Code Position X:
|
||
<div style={styles.sliderWrapper}>
|
||
<span style={styles.labelStart}>0%</span>
|
||
<input
|
||
type="range"
|
||
step="0.25"
|
||
name="left"
|
||
min="0"
|
||
max="100"
|
||
value={initialPos.left}
|
||
onChange={handlePositionChange}
|
||
style={styles.input}
|
||
/>
|
||
<span style={styles.value}>{initialPos.left}%</span>
|
||
</div>
|
||
</label>
|
||
</div>
|
||
<div style={styles.sliderContainer}>
|
||
<label style={styles.label}>
|
||
QR Code Position Y:
|
||
<div style={styles.sliderWrapper}>
|
||
<span style={styles.labelStart}>0%</span>
|
||
<input
|
||
type="range"
|
||
step="0.25"
|
||
name="top"
|
||
min="0"
|
||
max="100"
|
||
value={initialPos.top}
|
||
onChange={handlePositionChange}
|
||
style={styles.input}
|
||
/>
|
||
<span style={styles.value}>{initialPos.top}%</span>
|
||
</div>
|
||
</label>
|
||
</div>
|
||
</>}
|
||
|
||
{/* <p style={styles.description} onClick={() => { setIsConfigFont(!isConfigFont); setIsConfigQR(false) }}>
|
||
{isConfigFont ? '˅' : '˃'} Konfigurasi nomor
|
||
</p> */}
|
||
{isConfigFont && (
|
||
<>
|
||
<div style={styles.sliderContainer}>
|
||
<label style={styles.label}>
|
||
Ukuran nomor meja:
|
||
<div style={styles.sliderWrapper}>
|
||
<span style={styles.labelStart}>10%</span>
|
||
<input
|
||
type="range"
|
||
step="0.25"
|
||
min="10"
|
||
max="100"
|
||
value={fontsize}
|
||
onChange={handleFontSizeChange}
|
||
style={styles.input}
|
||
/>
|
||
<span style={styles.value}>{fontsize}%</span>
|
||
</div>
|
||
</label>
|
||
</div>
|
||
<div style={styles.sliderContainer}>
|
||
<label style={styles.label}>
|
||
Posisi nomor meja - horizontal:
|
||
<div style={styles.sliderWrapper}>
|
||
<span style={styles.labelStart}>0%</span>
|
||
<input
|
||
type="range"
|
||
step="0.25"
|
||
name="left"
|
||
min="0"
|
||
max="100"
|
||
value={initialFontPos.left}
|
||
onChange={handleFontPositionChange}
|
||
style={styles.input}
|
||
/>
|
||
<span style={styles.value}>{initialFontPos.left}%</span>
|
||
</div>
|
||
</label>
|
||
</div>
|
||
<div style={styles.sliderContainer}>
|
||
<label style={styles.label}>
|
||
Posisi nomor meja - vertikal:
|
||
<div style={styles.sliderWrapper}>
|
||
<span style={styles.labelStart}>0%</span>
|
||
<input
|
||
type="range"
|
||
step="0.25"
|
||
name="top"
|
||
min="0"
|
||
max="100"
|
||
value={initialFontPos.top}
|
||
onChange={handleFontPositionChange}
|
||
style={styles.input}
|
||
/>
|
||
<span style={styles.value}>{initialFontPos.top}%</span>
|
||
</div>
|
||
</label>
|
||
</div>
|
||
<div style={styles.sliderContainer}>
|
||
<label style={styles.label}>
|
||
Warna nomor meja:
|
||
<div style={styles.sliderWrapper}>
|
||
<input
|
||
type="color"
|
||
value='#FFFFFF' // This should be the state holding the selected font color
|
||
onChange={(e) => setfontcolor(e.target.value)} // Update the font color state
|
||
style={styles.colorInput} // Add your styles for the color input if needed
|
||
/>
|
||
<span style={styles.value}>{fontcolor}</span> {/* Display the selected color value */}
|
||
</div>
|
||
</label>
|
||
</div>
|
||
</>
|
||
)}
|
||
|
||
|
||
</div>
|
||
}
|
||
{/* <p style={styles.description} onClick={() => setIsViewTables(!isViewTables)}>
|
||
{isViewTables ? '˅' : '˃'} Daftar meja
|
||
</p> */}
|
||
|
||
{isViewTables &&
|
||
<div style={{ marginTop: '34px', marginLeft: '15px' }}>
|
||
<div style={styles.resultMessage}>
|
||
<input style={{ borderRadius: '12px', paddingLeft: '13px', marginRight: '10px', width: '48%' }} placeholder="Meja A1" onChange={(e) => setTableNo(e.target.value)} value={tableNo} />
|
||
<div
|
||
onClick={handleCreate} style={styles.uploadButton}>Buat meja</div>
|
||
</div>
|
||
{tables && tables
|
||
.filter((table) => table.tableNo !== 0)
|
||
.map((table) => (
|
||
<li
|
||
key={table.tableId}
|
||
style={{
|
||
backgroundColor:
|
||
table.tableId === selectedTable?.tableId
|
||
? "lightblue"
|
||
: "white",
|
||
marginBottom: "10px",
|
||
padding: "10px",
|
||
borderRadius: "4px",
|
||
boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
|
||
cursor: "pointer",
|
||
listStyle: 'square'
|
||
}}
|
||
onClick={() => setSelectedTable(selectedTable == table ? null : table)}
|
||
>
|
||
<div style={{ marginBottom: "10px" }}>
|
||
{table.tableNo}
|
||
</div>
|
||
</li>
|
||
))
|
||
}
|
||
</div>
|
||
}
|
||
</div>
|
||
<div style={styles.buttonContainer}>
|
||
<button onClick={handleSave} style={styles.saveButton}>
|
||
Simpan
|
||
</button>
|
||
<button onClick={() => setIsViewingQR(true)} style={styles.saveButton}>
|
||
Download QR {selectedTable ? 'meja' : 'kedai'}
|
||
</button>
|
||
</div>
|
||
</> :
|
||
<>
|
||
<div style={styles.uploadMessage}>
|
||
<p>Ini adalah QR yang dapat di scan oleh tamu untuk memesan </p>
|
||
{/* <p>QR ini akan menjadi identifikasi bahwa pelanggan memesan dari {selectedTable? `(${selectedTable?.tableNo})` : 'link kafe ini. Untuk mengantarkan pelanggan ke meja yang teridentifikasi, anda perlu membuat meja.'}</p> */}
|
||
</div>
|
||
<div style={styles.buttonContainer}>
|
||
<button onClick={() => downloadQrCodeContainer({ selectedTable, shop })} style={styles.saveButton}>
|
||
Download QR {selectedTable ? 'meja' : 'kedai'}
|
||
</button>
|
||
</div>
|
||
<div style={styles.backButtonContainer}>
|
||
<p onClick={() => setIsViewingQR(false)} >
|
||
Kembali
|
||
</p>
|
||
</div>
|
||
</>
|
||
}
|
||
</div>
|
||
);
|
||
};
|
||
|
||
// Styles
|
||
const styles = {
|
||
container: {
|
||
overflowY: 'auto',
|
||
overflowX: 'hidden',
|
||
maxHeight: '80vh',
|
||
width: '100%',
|
||
backgroundColor: "white",
|
||
padding: "20px",
|
||
borderRadius: "8px",
|
||
boxShadow: "0 2px 10px rgba(0, 0, 0, 0.1)",
|
||
textAlign: "center", // Center text and children
|
||
},
|
||
title: {
|
||
marginBottom: "20px",
|
||
fontWeight: "bold",
|
||
},
|
||
qrCodeContainer: {
|
||
backgroundColor: '#999999',
|
||
borderRadius: '8px',
|
||
position: "relative",
|
||
width: "100%",
|
||
height: "200px",
|
||
backgroundSize: "contain",
|
||
overflow: "hidden",
|
||
margin: "0 auto", // Center the QR code container
|
||
},
|
||
uploadMessage: {
|
||
fontWeight: 600,
|
||
textAlign: "left",
|
||
fontSize: "15px"
|
||
},
|
||
changeButton: {
|
||
paddingRight: '10px',
|
||
backgroundColor: 'rgb(40, 167, 69)',
|
||
borderRadius: '30px',
|
||
color: 'white',
|
||
fontWeight: 700,
|
||
height: '31px',
|
||
lineHeight: '32px',
|
||
paddingLeft: '10px',
|
||
paddingHeight: '10px',
|
||
marginBottom: '22px',
|
||
width: '80px',
|
||
textAlign: 'center'
|
||
},
|
||
changeButton2: {
|
||
color: 'black',
|
||
fontWeight: 700,
|
||
textAlign: 'left'
|
||
},
|
||
uploadButton: {
|
||
paddingRight: '10px',
|
||
backgroundColor: 'green',
|
||
borderRadius: '30px',
|
||
color: 'white',
|
||
fontWeight: 700,
|
||
height: '36px',
|
||
lineHeight: '36px',
|
||
paddingLeft: '10px',
|
||
paddingHeight: '10px',
|
||
width: '40%',
|
||
textAlign: 'center'
|
||
},
|
||
resultMessage: {
|
||
marginTop: "-24px",
|
||
marginBottom: "10px",
|
||
textAlign: "left",
|
||
display: 'flex',
|
||
justifyContent: 'space-between'
|
||
},
|
||
resultMessage2: {
|
||
marginTop: "-24px",
|
||
marginBottom: "10px",
|
||
textAlign: "left",
|
||
display: 'flex',
|
||
justifyContent: 'space-evenly'
|
||
},
|
||
buttonContainer: {
|
||
marginTop: "20px",
|
||
textAlign: "left",
|
||
display: 'flex',
|
||
justifyContent: 'space-evenly'
|
||
},
|
||
backButtonContainer: {
|
||
marginTop: "2px",
|
||
marginBottom: "-10px",
|
||
textAlign: "left",
|
||
display: 'flex',
|
||
justifyContent: 'space-evenly'
|
||
},
|
||
saveButton: {
|
||
padding: '6px 15px',
|
||
fontSize: '13px',
|
||
backgroundColor: 'rgb(40, 167, 69)',
|
||
color: 'rgb(255, 255, 255)',
|
||
border: ' none',
|
||
borderRadius: '30px',
|
||
cursor: 'pointer',
|
||
transition: 'background-color 0.3s',
|
||
},
|
||
switchContainer: {
|
||
textAlign: "left",
|
||
marginTop: '-15px'
|
||
},
|
||
description: {
|
||
margin: "10px 0",
|
||
},
|
||
sliderContainer: {
|
||
marginBottom: "20px",
|
||
},
|
||
label: {
|
||
display: "block",
|
||
marginBottom: "10px",
|
||
},
|
||
sliderWrapper: {
|
||
display: "flex",
|
||
alignItems: "center",
|
||
},
|
||
input: {
|
||
flex: "1",
|
||
margin: "0 10px",
|
||
},
|
||
};
|
||
|
||
export default SetPaymentQr;
|