implemt QRBottomSheet

This commit is contained in:
2025-12-25 00:35:44 +03:00
parent f35cf0bd3a
commit 90e729cdce
4 changed files with 517 additions and 514 deletions

View File

@@ -10,7 +10,6 @@ import { CustomAmountChoiceBottomSheet } from "./splitBill/CustomAmountChoiceBot
import { EqualltyChoiceBottomSheet } from "./splitBill/EqualltyChoiceBottomSheet"; import { EqualltyChoiceBottomSheet } from "./splitBill/EqualltyChoiceBottomSheet";
import { PayForYourItemsChoiceBottomSheet } from "./splitBill/PayForYourItemsChoiceBottomSheet"; import { PayForYourItemsChoiceBottomSheet } from "./splitBill/PayForYourItemsChoiceBottomSheet";
import { SplitBillChoiceBottomSheet } from "./splitBill/SplitBillChoiceBottomSheet"; import { SplitBillChoiceBottomSheet } from "./splitBill/SplitBillChoiceBottomSheet";
import { QRBottomSheet } from "./splitBill/QRBottomSheet";
type SplitWay = "customAmount" | "equality" | "payForItems" | null; type SplitWay = "customAmount" | "equality" | "payForItems" | null;
@@ -27,7 +26,6 @@ export default function PayButton({ form }: { form: FormInstance }) {
const [isCustomAmountOpen, setIsCustomAmountOpen] = useState(false); const [isCustomAmountOpen, setIsCustomAmountOpen] = useState(false);
const [isEqualityOpen, setIsEqualityOpen] = useState(false); const [isEqualityOpen, setIsEqualityOpen] = useState(false);
const [isPayForItemsOpen, setIsPayForItemsOpen] = useState(false); const [isPayForItemsOpen, setIsPayForItemsOpen] = useState(false);
const [isQROpen, setIsQROpen] = useState(false);
const handleSplitBillClick = useCallback(() => { const handleSplitBillClick = useCallback(() => {
if (selectedSplitWay === "customAmount") { if (selectedSplitWay === "customAmount") {
@@ -105,9 +103,6 @@ export default function PayButton({ form }: { form: FormInstance }) {
setIsCustomAmountOpen(false); setIsCustomAmountOpen(false);
}} }}
onRemoveSplitWay={handleRemoveSplitWay} onRemoveSplitWay={handleRemoveSplitWay}
onSave={() => {
setIsQROpen(true);
}}
/> />
<EqualltyChoiceBottomSheet <EqualltyChoiceBottomSheet
@@ -116,21 +111,15 @@ export default function PayButton({ form }: { form: FormInstance }) {
setIsEqualityOpen(false); setIsEqualityOpen(false);
}} }}
onRemoveSplitWay={handleRemoveSplitWay} onRemoveSplitWay={handleRemoveSplitWay}
onSave={() => {
setIsQROpen(true);
}}
/> />
<PayForYourItemsChoiceBottomSheet <PayForYourItemsChoiceBottomSheet
isOpen={isPayForItemsOpen} isOpen={isPayForItemsOpen}
onClose={() => { onClose={() => {
setIsPayForItemsOpen(false); setIsPayForItemsOpen(false);
setIsQROpen(true);
}} }}
onRemoveSplitWay={handleRemoveSplitWay} onRemoveSplitWay={handleRemoveSplitWay}
/> />
<QRBottomSheet isOpen={isQROpen} onClose={() => setIsQROpen(false)} />
</> </>
); );
} }

View File

@@ -12,11 +12,11 @@ import { useAppDispatch, useAppSelector } from "redux/hooks";
import ProText from "components/ProText"; import ProText from "components/ProText";
import ArabicPrice from "components/ArabicPrice"; import ArabicPrice from "components/ArabicPrice";
import styles from "./SplitBill.module.css"; import styles from "./SplitBill.module.css";
import { QRBottomSheet } from "./QRBottomSheet";
interface SplitBillChoiceBottomSheetProps { interface SplitBillChoiceBottomSheetProps {
isOpen: boolean; isOpen: boolean;
onClose: () => void; onClose: () => void;
onSave?: (value: string) => void;
onRemoveSplitWay?: () => void; onRemoveSplitWay?: () => void;
} }
@@ -32,7 +32,7 @@ export function CustomAmountChoiceBottomSheet({
const [amount, setAmount] = useState<string>( const [amount, setAmount] = useState<string>(
splitBillAmount > 0 ? splitBillAmount.toString() : "", splitBillAmount > 0 ? splitBillAmount.toString() : "",
); );
const [isQROpen, setIsQROpen] = useState(false);
useEffect(() => { useEffect(() => {
if (isOpen && splitBillAmount > 0) { if (isOpen && splitBillAmount > 0) {
setAmount(splitBillAmount.toString()); setAmount(splitBillAmount.toString());
@@ -42,6 +42,7 @@ export function CustomAmountChoiceBottomSheet({
const handleSave = () => { const handleSave = () => {
const numAmount = parseFloat(amount) || 0; const numAmount = parseFloat(amount) || 0;
dispatch(updateSplitBillAmount(numAmount)); dispatch(updateSplitBillAmount(numAmount));
setIsQROpen(true);
onClose(); onClose();
}; };
@@ -61,135 +62,138 @@ export function CustomAmountChoiceBottomSheet({
const previewRemaining = originalTotalBill - currentAmount; const previewRemaining = originalTotalBill - currentAmount;
return ( return (
<ProBottomSheet <>
isOpen={isOpen} <ProBottomSheet
onClose={onClose} isOpen={isOpen}
title={t("splitBill.payAsCustomAmount")} onClose={onClose}
showCloseButton={true} title={t("splitBill.payAsCustomAmount")}
initialSnap={1} showCloseButton={true}
height={430} initialSnap={1}
snapPoints={[430]} height={430}
contentStyle={{ snapPoints={[430]}
padding: 0, contentStyle={{
}} padding: 0,
>
<div
style={{
padding: "20px",
display: "flex",
flexDirection: "column",
gap: 20,
}} }}
> >
<div> <div
<ProText style={{
style={{ padding: "20px",
fontWeight: 400, display: "flex",
fontStyle: "Regular", flexDirection: "column",
fontSize: 16, gap: 20,
lineHeight: "140%", }}
letterSpacing: "0%", >
}} <div>
> <ProText
{t("splitBill.howMuchWouldYouLikeToPay")} style={{
</ProText> fontWeight: 400,
<Form.Item fontStyle: "Regular",
label={t("splitBill.amount")} fontSize: 16,
name="amount" lineHeight: "140%",
style={{ position: "relative", top: -5 }} letterSpacing: "0%",
>
<InputNumber
value={amount}
onChange={(value) => {
setAmount(value?.toString() || "");
dispatch(updateSplitBillAmount(Number(value) || 0));
}} }}
placeholder={t("splitBill.amount")} >
max={(grandTotal + splitBillAmount).toString()} {t("splitBill.howMuchWouldYouLikeToPay")}
min={"0"} </ProText>
style={{ width: "100%", fontSize: "1rem" }} <Form.Item
/> label={t("splitBill.amount")}
</Form.Item> name="amount"
style={{ position: "relative", top: -5 }}
>
<InputNumber
value={amount}
onChange={(value) => {
setAmount(value?.toString() || "");
dispatch(updateSplitBillAmount(Number(value) || 0));
}}
placeholder={t("splitBill.amount")}
max={(grandTotal + splitBillAmount).toString()}
min={"0"}
style={{ width: "100%", fontSize: "1rem" }}
/>
</Form.Item>
</div>
</div> </div>
</div>
<div <div
style={{ style={{
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
backgroundColor: "var(--background)", backgroundColor: "var(--background)",
padding: "20px", padding: "20px",
opacity: 1, opacity: 1,
gap: 8, gap: 8,
borderTopLeftRadius: 24, borderTopLeftRadius: 24,
borderTopRightRadius: 24, borderTopRightRadius: 24,
paddingTop: 12, paddingTop: 12,
paddingRight: 24, paddingRight: 24,
paddingBottom: 24, paddingBottom: 24,
paddingLeft: 24, paddingLeft: 24,
}} }}
> >
<div className={styles.summaryRow}> <div className={styles.summaryRow}>
<ProText <ProText
style={{ style={{
fontWeight: 400, fontWeight: 400,
fontStyle: "Regular", fontStyle: "Regular",
fontSize: 14, fontSize: 14,
lineHeight: "140%", lineHeight: "140%",
letterSpacing: "0%", letterSpacing: "0%",
}} }}
> >
{t("splitBill.totalBill")} {t("splitBill.totalBill")}
</ProText> </ProText>
<ArabicPrice price={previewTotalBill} /> <ArabicPrice price={previewTotalBill} />
</div>
<div className={styles.summaryRow}>
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 14,
lineHeight: "140%",
letterSpacing: "0%",
}}
>
{t("splitBill.remainingToPay")}
</ProText>
<ArabicPrice price={Math.max(0, previewRemaining)} />
</div>
</div> </div>
<div className={styles.summaryRow}>
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 14,
lineHeight: "140%",
letterSpacing: "0%",
}}
>
{t("splitBill.remainingToPay")}
</ProText>
<ArabicPrice price={Math.max(0, previewRemaining)} />
</div>
</div>
<div <div
style={{
display: "flex",
gap: 12,
margin: 20,
}}
>
<Button
style={{ style={{
flex: 1, display: "flex",
backgroundColor: "#FEEDED", gap: 12,
color: "#DD4143", margin: 20,
boxShadow: "none",
border: "none",
}} }}
onClick={handleRemoveSplitWay}
> >
{t("splitBill.removeSplit")} <Button
</Button> style={{
<Button flex: 1,
type="primary" backgroundColor: "#FEEDED",
style={{ color: "#DD4143",
flex: 1, boxShadow: "none",
boxShadow: "none", border: "none",
}} }}
onClick={handleSave} onClick={handleRemoveSplitWay}
disabled={!amount || parseFloat(amount) <= 0} >
> {t("splitBill.removeSplit")}
{t("splitBill.confirm")} </Button>
</Button> <Button
</div> type="primary"
</ProBottomSheet> style={{
flex: 1,
boxShadow: "none",
}}
onClick={handleSave}
disabled={!amount || parseFloat(amount) <= 0}
>
{t("splitBill.confirm")}
</Button>
</div>
</ProBottomSheet>
<QRBottomSheet isOpen={isQROpen} onClose={() => setIsQROpen(false)} />
</>
); );
} }

View File

@@ -1,6 +1,6 @@
import { Button } from "antd"; import { Button } from "antd";
import { ProBottomSheet } from "components/ProBottomSheet/ProBottomSheet.tsx"; import { ProBottomSheet } from "components/ProBottomSheet/ProBottomSheet.tsx";
import { useMemo } from "react"; import { useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import ProText from "components/ProText"; import ProText from "components/ProText";
@@ -15,6 +15,7 @@ import { ProGray1 } from "ThemeConstants";
import PayForActions from "../../../split-bill/components/PayForActions"; import PayForActions from "../../../split-bill/components/PayForActions";
import TotalPeopleActions from "../../../split-bill/components/TotalPeopleActions"; import TotalPeopleActions from "../../../split-bill/components/TotalPeopleActions";
import styles from "./SplitBill.module.css"; import styles from "./SplitBill.module.css";
import { QRBottomSheet } from "./QRBottomSheet";
interface SplitBillChoiceBottomSheetProps { interface SplitBillChoiceBottomSheetProps {
isOpen: boolean; isOpen: boolean;
@@ -37,7 +38,7 @@ export function EqualltyChoiceBottomSheet({
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { tmp, splitBillAmount } = useAppSelector(selectCart); const { tmp, splitBillAmount } = useAppSelector(selectCart);
const grandTotal = useAppSelector(selectGrandTotal); const grandTotal = useAppSelector(selectGrandTotal);
const [isQROpen, setIsQROpen] = useState(false);
const splitBillTmp = tmp as SplitBillTmp; const splitBillTmp = tmp as SplitBillTmp;
const totalPeople = splitBillTmp?.totalPeople || 2; const totalPeople = splitBillTmp?.totalPeople || 2;
const payFor = splitBillTmp?.payFor || 1; const payFor = splitBillTmp?.payFor || 1;
@@ -55,6 +56,7 @@ export function EqualltyChoiceBottomSheet({
const handleSave = () => { const handleSave = () => {
dispatch(updateSplitBillAmount(splitAmount)); dispatch(updateSplitBillAmount(splitAmount));
setIsQROpen(true);
onClose(); onClose();
}; };
@@ -65,281 +67,284 @@ export function EqualltyChoiceBottomSheet({
}; };
return ( return (
<ProBottomSheet <>
isOpen={isOpen} <ProBottomSheet
onClose={onClose} isOpen={isOpen}
title={t("splitBill.divideTheBillEqually")} onClose={onClose}
showCloseButton={true} title={t("splitBill.divideTheBillEqually")}
initialSnap={1} showCloseButton={true}
height={630} initialSnap={1}
snapPoints={[630]} height={630}
contentStyle={{ snapPoints={[630]}
padding: 0, contentStyle={{
}} padding: 0,
>
<div
style={{
display: "flex",
flexDirection: "column",
marginTop: 20,
}} }}
> >
{/* Spinner Visualization - Blank Spin Wheel */} <div
{totalPeople > 0 && ( style={{
display: "flex",
flexDirection: "column",
marginTop: 20,
}}
>
{/* Spinner Visualization - Blank Spin Wheel */}
{totalPeople > 0 && (
<div
style={{
display: "flex",
flexDirection: "column",
gap: 12,
alignItems: "center",
}}
>
<div
style={{
position: "relative",
width: 200,
height: 200,
margin: "0 auto",
}}
>
<svg
width="200"
height="200"
viewBox="0 0 200 200"
style={{
transform: "rotate(-90deg)",
}}
>
{Array.from({ length: totalPeople }).map((_, index) => {
const anglePerSlice = 360 / totalPeople;
const startAngle = index * anglePerSlice;
const endAngle = (index + 1) * anglePerSlice;
const isSelected = index < payFor;
// Convert angles to radians
const startAngleRad = (startAngle * Math.PI) / 180;
const endAngleRad = (endAngle * Math.PI) / 180;
// Calculate path for pie slice (fit 200x200 viewBox)
const radius = 90;
const centerX = 100;
const centerY = 100;
const x1 = centerX + radius * Math.cos(startAngleRad);
const y1 = centerY + radius * Math.sin(startAngleRad);
const x2 = centerX + radius * Math.cos(endAngleRad);
const y2 = centerY + radius * Math.sin(endAngleRad);
const largeArcFlag = anglePerSlice > 180 ? 1 : 0;
const pathData = [
`M ${centerX} ${centerY}`,
`L ${x1} ${y1}`,
`A ${radius} ${radius} 0 ${largeArcFlag} 1 ${x2} ${y2}`,
"Z",
].join(" ");
return (
<path
key={index}
d={pathData}
fill={
isSelected ? "var(--primary)" : "rgba(0, 0, 0, 0.1)"
}
stroke="#fff"
strokeWidth="5"
/>
);
})}
</svg>
{/* Center circle with total bill amount */}
<div
style={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
// Keep the SVG at 200x200, but make the center content smaller
// so the wheel remains visible around it.
width: 160,
height: 160,
borderRadius: "50%",
backgroundColor: "var(--secondary-background)",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
zIndex: 10,
padding: 10,
}}
>
<div
style={{
fontSize: 20,
fontWeight: 600,
color: "var(--primary)",
lineHeight: 1.1,
textAlign: "center",
}}
>
<ArabicPrice
price={originalTotalBill}
style={{
fontSize: 20,
fontWeight: 600,
}}
/>
</div>
<ProText
style={{
fontSize: 11,
color: ProGray1,
marginTop: 6,
textAlign: "center",
lineHeight: 1.2,
fontWeight: 400,
}}
>
{t("splitBill.totalBill")}
</ProText>
</div>
</div>
</div>
)}
<div <div
style={{ style={{
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
gap: 12, gap: "1rem",
alignItems: "center", padding: 20,
}} }}
> >
<div <div
style={{ style={{
position: "relative", display: "flex",
width: 200, flexDirection: "row",
height: 200, justifyContent: "space-between",
margin: "0 auto", gap: "1rem",
padding: 8,
}} }}
> >
<svg <ProText
width="200"
height="200"
viewBox="0 0 200 200"
style={{ style={{
transform: "rotate(-90deg)", fontSize: "1rem",
marginTop: 3,
color: ProGray1,
}} }}
> >
{Array.from({ length: totalPeople }).map((_, index) => { {t("checkout.totalPeople")}
const anglePerSlice = 360 / totalPeople; </ProText>
const startAngle = index * anglePerSlice;
const endAngle = (index + 1) * anglePerSlice;
const isSelected = index < payFor;
// Convert angles to radians <TotalPeopleActions />
const startAngleRad = (startAngle * Math.PI) / 180;
const endAngleRad = (endAngle * Math.PI) / 180;
// Calculate path for pie slice (fit 200x200 viewBox) <ProText
const radius = 90;
const centerX = 100;
const centerY = 100;
const x1 = centerX + radius * Math.cos(startAngleRad);
const y1 = centerY + radius * Math.sin(startAngleRad);
const x2 = centerX + radius * Math.cos(endAngleRad);
const y2 = centerY + radius * Math.sin(endAngleRad);
const largeArcFlag = anglePerSlice > 180 ? 1 : 0;
const pathData = [
`M ${centerX} ${centerY}`,
`L ${x1} ${y1}`,
`A ${radius} ${radius} 0 ${largeArcFlag} 1 ${x2} ${y2}`,
"Z",
].join(" ");
return (
<path
key={index}
d={pathData}
fill={
isSelected ? "var(--primary)" : "rgba(0, 0, 0, 0.1)"
}
stroke="#fff"
strokeWidth="5"
/>
);
})}
</svg>
{/* Center circle with total bill amount */}
<div
style={{ style={{
position: "absolute", fontSize: "1rem",
top: "50%", marginTop: 3,
left: "50%", color: ProGray1,
transform: "translate(-50%, -50%)",
// Keep the SVG at 200x200, but make the center content smaller
// so the wheel remains visible around it.
width: 160,
height: 160,
borderRadius: "50%",
backgroundColor: "var(--secondary-background)",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
zIndex: 10,
padding: 10,
}} }}
> >
<div {t("checkout.totalPeople")}
style={{ </ProText>
fontSize: 20, </div>
fontWeight: 600,
color: "var(--primary)", <div
lineHeight: 1.1, style={{
textAlign: "center", display: "flex",
}} flexDirection: "row",
> justifyContent: "space-between",
<ArabicPrice gap: "1rem",
price={originalTotalBill} padding: 8,
style={{ }}
fontSize: 20, >
fontWeight: 600, <ProText
}} style={{
/> fontSize: "1rem",
</div> marginTop: 2,
<ProText color: ProGray1,
style={{ }}
fontSize: 11, >
color: ProGray1, {t("checkout.payFor")}
marginTop: 6, </ProText>
textAlign: "center",
lineHeight: 1.2, <PayForActions />
fontWeight: 400,
}} <ProText
> style={{
{t("splitBill.totalBill")} fontSize: "1rem",
</ProText> marginTop: 2,
</div> color: ProGray1,
}}
>
{t("checkout.payFor")}
</ProText>
</div> </div>
</div> </div>
)}
<div
style={{
display: "flex",
flexDirection: "column",
gap: "1rem",
padding: 20,
}}
>
<div <div
style={{ style={{
display: "flex", display: "flex",
flexDirection: "row", flexDirection: "column",
justifyContent: "space-between", backgroundColor: "var(--background)",
gap: "1rem", padding: 20,
padding: 8, opacity: 1,
gap: 8,
borderTopLeftRadius: 24,
borderTopRightRadius: 24,
paddingTop: 12,
paddingRight: 24,
paddingBottom: 24,
paddingLeft: 24,
}} }}
> >
<ProText <div className={styles.summaryRow}>
style={{ <ProText
fontSize: "1rem", style={{
marginTop: 3, fontWeight: 400,
color: ProGray1, fontStyle: "Regular",
}} fontSize: 14,
> lineHeight: "140%",
{t("checkout.totalPeople")} letterSpacing: "0%",
</ProText> }}
>
<TotalPeopleActions /> {t("splitBill.yourShare")}
</ProText>
<ProText <ArabicPrice price={splitAmount} />
style={{ </div>
fontSize: "1rem",
marginTop: 3,
color: ProGray1,
}}
>
{t("checkout.totalPeople")}
</ProText>
</div> </div>
<div <div
style={{ style={{
display: "flex", display: "flex",
flexDirection: "row", gap: 12,
justifyContent: "space-between", margin: 20,
gap: "1rem",
padding: 8,
}} }}
> >
<ProText <Button
style={{ style={{
fontSize: "1rem", flex: 1,
marginTop: 2, backgroundColor: "#FEEDED",
color: ProGray1, color: "#DD4143",
boxShadow: "none",
border: "none",
}} }}
onClick={handleRemoveSplitWay}
> >
{t("checkout.payFor")} {t("splitBill.removeSplit")}
</ProText> </Button>
<Button
<PayForActions /> type="primary"
style={{ flex: 1, boxShadow: "none" }}
<ProText onClick={handleSave}
style={{
fontSize: "1rem",
marginTop: 2,
color: ProGray1,
}}
> >
{t("checkout.payFor")} {t("cart.save")}
</ProText> </Button>
</div> </div>
</div> </div>
</ProBottomSheet>
<div <QRBottomSheet isOpen={isQROpen} onClose={() => setIsQROpen(false)} />
style={{ </>
display: "flex",
flexDirection: "column",
backgroundColor: "var(--background)",
padding: 20,
opacity: 1,
gap: 8,
borderTopLeftRadius: 24,
borderTopRightRadius: 24,
paddingTop: 12,
paddingRight: 24,
paddingBottom: 24,
paddingLeft: 24,
}}
>
<div className={styles.summaryRow}>
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 14,
lineHeight: "140%",
letterSpacing: "0%",
}}
>
{t("splitBill.yourShare")}
</ProText>
<ArabicPrice price={splitAmount} />
</div>
</div>
<div
style={{
display: "flex",
gap: 12,
margin: 20,
}}
>
<Button
style={{
flex: 1,
backgroundColor: "#FEEDED",
color: "#DD4143",
boxShadow: "none",
border: "none",
}}
onClick={handleRemoveSplitWay}
>
{t("splitBill.removeSplit")}
</Button>
<Button
type="primary"
style={{ flex: 1, boxShadow: "none" }}
onClick={handleSave}
>
{t("cart.save")}
</Button>
</div>
</div>
</ProBottomSheet>
); );
} }

View File

@@ -8,6 +8,7 @@ import ProText from "components/ProText";
import { selectCart, updateSplitBillAmount } from "features/order/orderSlice"; import { selectCart, updateSplitBillAmount } from "features/order/orderSlice";
import { useAppDispatch, useAppSelector } from "redux/hooks"; import { useAppDispatch, useAppSelector } from "redux/hooks";
import styles from "./SplitBill.module.css"; import styles from "./SplitBill.module.css";
import { QRBottomSheet } from "./QRBottomSheet";
interface SplitBillChoiceBottomSheetProps { interface SplitBillChoiceBottomSheetProps {
isOpen: boolean; isOpen: boolean;
@@ -25,7 +26,7 @@ export function PayForYourItemsChoiceBottomSheet({
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { items } = useAppSelector(selectCart); const { items } = useAppSelector(selectCart);
const [selectedItems, setSelectedItems] = useState<Set<string>>(new Set()); const [selectedItems, setSelectedItems] = useState<Set<string>>(new Set());
const [isQROpen, setIsQROpen] = useState(false);
// Calculate total for selected items // Calculate total for selected items
const selectedTotal = items const selectedTotal = items
.filter((item) => selectedItems.has(item.uniqueId || item.id.toString())) .filter((item) => selectedItems.has(item.uniqueId || item.id.toString()))
@@ -56,6 +57,7 @@ export function PayForYourItemsChoiceBottomSheet({
const handleSave = () => { const handleSave = () => {
dispatch(updateSplitBillAmount(selectedTotal)); dispatch(updateSplitBillAmount(selectedTotal));
setIsQROpen(true);
onClose(); onClose();
}; };
@@ -67,159 +69,162 @@ export function PayForYourItemsChoiceBottomSheet({
}; };
return ( return (
<ProBottomSheet <>
isOpen={isOpen} <ProBottomSheet
onClose={onClose} isOpen={isOpen}
title={t("splitBill.payForYourItems")} onClose={onClose}
showCloseButton={true} title={t("splitBill.payForYourItems")}
initialSnap={1} showCloseButton={true}
height={720} initialSnap={1}
snapPoints={[720]} height={720}
contentStyle={{ padding: 0 }} snapPoints={[720]}
> contentStyle={{ padding: 0 }}
<div
style={{
padding: 20,
display: "flex",
flexDirection: "column",
gap: 12,
maxHeight: "455px",
minHeight: "455px",
overflowY: "auto",
}}
>
{items.length === 0 ? (
<ProText
type="secondary"
style={{ textAlign: "center", padding: 20 }}
>
{t("cart.emptyCart")}
</ProText>
) : (
items.map((item) => {
const itemId = item.uniqueId || item.id.toString();
const isSelected = selectedItems.has(itemId);
const itemTotal = item.price * item.quantity;
return (
<>
<Card
key={itemId}
style={{
border: "none",
cursor: "pointer",
padding: 0,
}}
onClick={() => handleItemToggle(itemId)}
>
<div
style={{
display: "flex",
flexDirection: "row",
gap: 12,
alignItems: "center",
}}
>
<Image
src={item.image}
alt={item.name}
width={60}
height={60}
preview={false}
style={{
borderRadius: 8,
objectFit: "cover",
}}
/>
<div
style={{
flex: 1,
display: "flex",
flexDirection: "column",
gap: 4,
}}
>
<ProText style={{ fontSize: 14, fontWeight: 500 }}>
{item.name}
</ProText>
<ArabicPrice price={itemTotal} />
</div>
<div
style={{
width: 32,
height: 32,
minWidth: 32,
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
onClick={(e) => e.stopPropagation()}
>
<Checkbox
className={styles.circleCheckbox}
checked={isSelected}
onChange={() => handleItemToggle(itemId)}
/>
</div>
</div>
</Card>
{item !== items[items.length - 1] && (
<Divider style={{ margin: "0" }} />
)}
</>
);
})
)}
</div>
<div
style={{
padding: 16,
backgroundColor: "rgba(255, 183, 0, 0.08)",
borderRadius: 8,
marginTop: 8,
}}
> >
<div <div
style={{ style={{
padding: 20,
display: "flex", display: "flex",
justifyContent: "space-between", flexDirection: "column",
alignItems: "center", gap: 12,
maxHeight: "455px",
minHeight: "455px",
overflowY: "auto",
}} }}
> >
<ProText style={{ fontSize: 16, fontWeight: 600 }}> {items.length === 0 ? (
{t("splitBill.selectedTotal")}: <ProText
</ProText> type="secondary"
<ArabicPrice price={selectedTotal} /> style={{ textAlign: "center", padding: 20 }}
>
{t("cart.emptyCart")}
</ProText>
) : (
items.map((item) => {
const itemId = item.uniqueId || item.id.toString();
const isSelected = selectedItems.has(itemId);
const itemTotal = item.price * item.quantity;
return (
<>
<Card
key={itemId}
style={{
border: "none",
cursor: "pointer",
padding: 0,
}}
onClick={() => handleItemToggle(itemId)}
>
<div
style={{
display: "flex",
flexDirection: "row",
gap: 12,
alignItems: "center",
}}
>
<Image
src={item.image}
alt={item.name}
width={60}
height={60}
preview={false}
style={{
borderRadius: 8,
objectFit: "cover",
}}
/>
<div
style={{
flex: 1,
display: "flex",
flexDirection: "column",
gap: 4,
}}
>
<ProText style={{ fontSize: 14, fontWeight: 500 }}>
{item.name}
</ProText>
<ArabicPrice price={itemTotal} />
</div>
<div
style={{
width: 32,
height: 32,
minWidth: 32,
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
onClick={(e) => e.stopPropagation()}
>
<Checkbox
className={styles.circleCheckbox}
checked={isSelected}
onChange={() => handleItemToggle(itemId)}
/>
</div>
</div>
</Card>
{item !== items[items.length - 1] && (
<Divider style={{ margin: "0" }} />
)}
</>
);
})
)}
</div> </div>
</div> <div
<div
style={{
display: "flex",
gap: 12,
margin: 20,
}}
>
<Button
style={{ style={{
flex: 1, padding: 16,
backgroundColor: "#FEEDED", backgroundColor: "rgba(255, 183, 0, 0.08)",
color: "#DD4143", borderRadius: 8,
boxShadow: "none", marginTop: 8,
border: "none",
}} }}
onClick={handleRemoveSplitWay}
> >
{t("splitBill.removeSplit")} <div
</Button> style={{
<Button display: "flex",
type="primary" justifyContent: "space-between",
style={{ flex: 1, boxShadow: "none" }} alignItems: "center",
onClick={handleSave} }}
disabled={selectedTotal === 0} >
<ProText style={{ fontSize: 16, fontWeight: 600 }}>
{t("splitBill.selectedTotal")}:
</ProText>
<ArabicPrice price={selectedTotal} />
</div>
</div>
<div
style={{
display: "flex",
gap: 12,
margin: 20,
}}
> >
{t("cart.save")} <Button
</Button> style={{
</div> flex: 1,
</ProBottomSheet> backgroundColor: "#FEEDED",
color: "#DD4143",
boxShadow: "none",
border: "none",
}}
onClick={handleRemoveSplitWay}
>
{t("splitBill.removeSplit")}
</Button>
<Button
type="primary"
style={{ flex: 1, boxShadow: "none" }}
onClick={handleSave}
disabled={selectedTotal === 0}
>
{t("cart.save")}
</Button>
</div>
</ProBottomSheet>
<QRBottomSheet isOpen={isQROpen} onClose={() => setIsQROpen(false)} />
</>
); );
} }