Files
web-menu-react-version-/src/components/CustomBottomSheet/RateBottomSheet.tsx

249 lines
7.4 KiB
TypeScript

// import { useGlobals } from "../../hooks/useGlobals";
import { Button, Card, message } from "antd";
import RateIcon from "components/Icons/order/RateIcon";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { useParams } from "react-router-dom";
import { useGetUserDetailsQuery, useRateOrderMutation } from "redux/api/others";
import { useAppSelector } from "redux/hooks";
import { ProBottomSheet } from "../ProBottomSheet/ProBottomSheet";
import ProText from "../ProText";
import ProTitle from "../ProTitle";
import styles from "./CustomBottomSheet.module.css";
import { colors } from "ThemeConstants";
export function RateBottomSheet() {
const { t } = useTranslation();
const [isOpen, setIsOpen] = useState(false);
const [rating, setRating] = useState<number>(0);
const { isRTL } = useAppSelector((state) => state.locale);
const { orderId } = useParams();
const [rateOrder] = useRateOrderMutation();
const { data: getUserDetails } = useGetUserDetailsQuery(undefined, {
skip: !isOpen,
});
const handleSubmitRating = () => {
setIsOpen(false);
if (getUserDetails?.id) {
rateOrder({
orderID: orderId || "",
rating: rating,
comment: "This is a test comment",
userID: getUserDetails?.id.toString() || "",
}).then((res: any) => {
if (res.error) {
message.error(res.error.data.message);
} else {
message.success(res.data.message);
}
});
} else {
message.error(t("order.pleaseLoginToAllowRating"));
}
};
const handleStarClick = (
starIndex: number,
event: React.MouseEvent<HTMLDivElement>,
) => {
const starElement = event.currentTarget;
const rect = starElement.getBoundingClientRect();
const clickX = event.clientX - rect.left;
const starWidth = rect.width;
// Calculate which part of the star was clicked
// Divide star into 4 parts: 0-25% = 0.25, 25-50% = 0.5, 50-75% = 0.75, 75-100% = 1.0
let clickPercentage = clickX / starWidth;
// In RTL mode, invert the click percentage since stars are displayed in reverse
if (isRTL) {
clickPercentage = 1 - clickPercentage;
}
let starValue = 0;
if (clickPercentage <= 0.25) {
starValue = 0.25;
} else if (clickPercentage <= 0.5) {
starValue = 0.5;
} else if (clickPercentage <= 0.75) {
starValue = 0.75;
} else {
starValue = 1.0;
}
const newRating = starIndex + starValue;
setRating(Math.min(newRating, 5)); // Cap at 5
};
return (
<>
<Card className={styles.rateServiceCard} onClick={() => setIsOpen(true)}>
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "center",
marginTop: 1,
}}
>
<div style={{ display: "flex", flexDirection: "row", gap: 10 }}>
<ProTitle
level={5}
style={{
marginTop: 1,
fontSize: 14,
}}
>
{t("order.rateOrder")}
</ProTitle>
</div>
</div>
</Card>
<ProBottomSheet
isOpen={isOpen}
onClose={() => setIsOpen(false)}
title={t("order.rateOrder")}
showCloseButton={false}
initialSnap={1}
height={450}
snapPoints={[450]}
>
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
gap: 16,
marginTop: 15,
}}
>
<RateIcon />
<ProText
style={{
fontSize: 14,
}}
>
{t("order.howWasYourExperienceWithFascanoRestaurant")}
</ProText>
<div
style={{
display: "flex",
flexDirection: "row",
gap: 8,
marginTop: 10,
marginBottom: 10,
}}
>
{[0, 1, 2, 3, 4].map((starIndex) => {
const starValue = starIndex + 1;
const isFilled = rating >= starValue;
const isPartialFilled = rating > starIndex && rating < starValue;
const fillPercentage = isPartialFilled
? ((rating - starIndex) * 100) / 1
: isFilled
? 100
: 0;
return (
<div
key={starIndex}
onClick={(e) => handleStarClick(starIndex, e)}
style={{
position: "relative",
cursor: "pointer",
width: 40,
height: 40,
display: "inline-block",
}}
>
{/* Gray star background */}
<svg
width="40"
height="40"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
style={{
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%",
}}
>
<path
d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"
fill="#d3d3d3"
/>
</svg>
{/* Golden star overlay with overflow for partial fill */}
<div
style={{
position: "absolute",
top: 0,
...(isRTL ? { right: 0 } : { left: 0 }),
width: `${fillPercentage}%`,
height: "100%",
overflow: "hidden",
}}
>
<svg
width="40"
height="40"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
style={{
position: "absolute",
top: 0,
...(isRTL ? { right: 0 } : { left: 0 }),
width: 40,
height: 40,
}}
>
<path
d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"
fill={colors.primary}
/>
</svg>
</div>
</div>
);
})}
</div>
<div
style={{
display: "flex",
flexDirection: "row",
gap: 10,
width: "100%",
}}
>
<Button
type="primary"
style={{
width: "100%",
height: 48,
color: colors.primary,
borderColor: colors.primary,
backgroundColor: "#fff",
}}
onClick={handleSubmitRating}
>
{t("order.submitRating")}
</Button>
</div>
</div>
</ProBottomSheet>
</>
);
}