249 lines
7.4 KiB
TypeScript
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>
|
|
</>
|
|
);
|
|
}
|