This commit is contained in:
2025-10-24 06:12:58 +03:00
parent 3aeaa0a9f3
commit 3a827a8f69
7 changed files with 90 additions and 52 deletions

View File

@@ -18,6 +18,7 @@
"cart": "السلة", "cart": "السلة",
"checkout": "الدفع", "checkout": "الدفع",
"login": "تسجيل الدخول", "login": "تسجيل الدخول",
"logout": "تسجيل الخروج",
"contact": "اتصل بنا", "contact": "اتصل بنا",
"admin": "لوحة الإدارة", "admin": "لوحة الإدارة",
"search": "البحث عن المنتجات...", "search": "البحث عن المنتجات...",
@@ -231,7 +232,8 @@
"useLoyaltyPoints": "استخدام نقاط الولاء", "useLoyaltyPoints": "استخدام نقاط الولاء",
"noLoyaltyItemsInCart": "لا توجد عناصر ولاء في سلة المشتريات", "noLoyaltyItemsInCart": "لا توجد عناصر ولاء في سلة المشتريات",
"pleaseAddLoyaltyItems": "يرجى إضافة عناصر ولاء إلى سلة المشتريات لاستخدام نقاط الولاء", "pleaseAddLoyaltyItems": "يرجى إضافة عناصر ولاء إلى سلة المشتريات لاستخدام نقاط الولاء",
"loyaltyDiscountApplied": "تم تطبيق خصم الولاء: {{itemName}} (خصم {{amount}})" "loyaltyDiscountApplied": "تم تطبيق خصم الولاء: {{itemName}} (خصم {{amount}})",
"joinToEarn": "انضم إلى الولاء لتحصل على هدية مجانية"
}, },
"checkout": { "checkout": {
"title": "الدفع", "title": "الدفع",

View File

@@ -18,6 +18,7 @@
"cart": "Cart", "cart": "Cart",
"checkout": "Checkout", "checkout": "Checkout",
"login": "Login", "login": "Login",
"logout": "Logout",
"contact": "Contact Us", "contact": "Contact Us",
"admin": "Admin Panel", "admin": "Admin Panel",
"search": "Search products...", "search": "Search products...",
@@ -159,7 +160,8 @@
"search": "Search", "search": "Search",
"searchPlaceholder": "Search for products...", "searchPlaceholder": "Search for products...",
"noResultsFound": "No results found", "noResultsFound": "No results found",
"cart": "Cart" "cart": "Cart",
"joinToEarn": "Join us to earn loyalty points"
}, },
"cart": { "cart": {
"title": "Cart", "title": "Cart",
@@ -314,7 +316,7 @@
"gotIt": "Got It", "gotIt": "Got It",
"howItWorksDescription": "The gifted amount will be credited directly to your friend's wallet in the app. The recipient can use the amount to book a session of their choice within the app. The gifted amount is non-refundable and can only be used for booking sessions.", "howItWorksDescription": "The gifted amount will be credited directly to your friend's wallet in the app. The recipient can use the amount to book a session of their choice within the app. The gifted amount is non-refundable and can only be used for booking sessions.",
"senderEmail": "Sender Email", "senderEmail": "Sender Email",
"save":"Save" "save": "Save"
}, },
"login": { "login": {
"singup/Login": "Sing up / Login", "singup/Login": "Sing up / Login",

View File

@@ -2,14 +2,18 @@ import { Button, Card, Col, Image, Row } from "antd";
import LoyaltyIcon from "components/Icons/cart/LoyaltyIcons"; import LoyaltyIcon from "components/Icons/cart/LoyaltyIcons";
import PresentIcon from "components/Icons/cart/PresentIcon"; import PresentIcon from "components/Icons/cart/PresentIcon";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useParams } from "react-router-dom";
import { useGetRestaurantDetailsQuery } from "redux/api/others"; import { useGetRestaurantDetailsQuery } from "redux/api/others";
import { ACCESS_TOKEN } from "utils/constants";
import { colors } from "../../ThemeConstants"; import { colors } from "../../ThemeConstants";
import ProText from "../ProText"; import ProText from "../ProText";
import styles from "./LoyaltyCard.module.css"; import styles from "./LoyaltyCard.module.css";
const LoyaltyCard = () => { const LoyaltyCard = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { id } = useParams();
const { data: restaurant } = useGetRestaurantDetailsQuery("595"); const { data: restaurant } = useGetRestaurantDetailsQuery("595");
const token = localStorage.getItem(ACCESS_TOKEN);
const isHasLoyaltyGift = const isHasLoyaltyGift =
(restaurant?.loyalty_stamps ?? 0) - (restaurant?.loyalty_stamps ?? 0) -
(restaurant?.customer_loyalty_points ?? 0) <= (restaurant?.customer_loyalty_points ?? 0) <=
@@ -57,57 +61,68 @@ const LoyaltyCard = () => {
top: -2, top: -2,
}} }}
> >
{t("menu.loyaltyDescription", { {token &&
value: restaurant?.loyalty_stamps, t("menu.loyaltyDescription", {
})} value: restaurant?.loyalty_stamps ?? 0,
})}
{!token && (
<Link
to={`/${id}/login`}
style={{ color: colors.primary, marginTop: 4 }}
>
{t("menu.joinToEarn")}
</Link>
)}
</ProText> </ProText>
</Col> </Col>
<Col> <Col>
<PresentIcon /> <PresentIcon />
</Col> </Col>
</Row> </Row>
<Row justify="space-between" align="middle"> {token && (
<Col> <Row justify="space-between" align="middle">
<div className={styles.presentIcon}> <Col>
<div style={{ display: "flex" }}> <div className={styles.presentIcon}>
<Image <div style={{ display: "flex" }}>
className={styles.presentIconItem} <Image
preview={false} className={styles.presentIconItem}
width={32} preview={false}
height={32} width={32}
src={restaurant?.loyalty_stamp_image} height={32}
/> src={restaurant?.loyalty_stamp_image}
<ProText />
type="secondary" <ProText
strong type="secondary"
style={{ strong
fontSize: "1rem", style={{
fontWeight: 400, fontSize: "1rem",
position: "relative", fontWeight: 400,
top: 3, position: "relative",
margin: "0 2px", top: 3,
}} margin: "0 2px",
> }}
x >
{(restaurant?.loyalty_stamps ?? 0) - x
(restaurant?.customer_loyalty_points ?? 0)} {(restaurant?.loyalty_stamps ?? 0) -
</ProText>{" "} (restaurant?.customer_loyalty_points ?? 0)}
</ProText>{" "}
</div>
</div> </div>
</div> </Col>
</Col> <Col>
<Col> <Button
<Button style={{
style={{ backgroundColor: colors.primary,
backgroundColor: colors.primary, color: "white",
color: "white", border: 0,
border: 0, height: 32,
height: 32, }}
}} >
> {t("menu.claim")}
{t("menu.claim")} </Button>
</Button> </Col>
</Col> </Row>
</Row> )}
</Card> </Card>
</div> </div>
); );

View File

@@ -2,15 +2,18 @@ import {
BgColorsOutlined, BgColorsOutlined,
HomeOutlined, HomeOutlined,
LoginOutlined, LoginOutlined,
LogoutOutlined,
MenuOutlined, MenuOutlined,
TranslationOutlined, TranslationOutlined,
} from "@ant-design/icons"; } from "@ant-design/icons";
import { logoutThunk } from "features/auth/authSlice";
import { setLocale, setLocalesThunk } from "features/locale/localeSlice"; import { setLocale, setLocalesThunk } from "features/locale/localeSlice";
import { toggleTheme } from "features/theme/themeSlice"; import { toggleTheme } from "features/theme/themeSlice";
import i18n from "i18n/i18n"; import i18n from "i18n/i18n";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate, useParams } from "react-router-dom"; import { Link, useNavigate, useParams } from "react-router-dom";
import { useAppDispatch, useAppSelector } from "redux/hooks"; import { useAppDispatch, useAppSelector } from "redux/hooks";
import { ACCESS_TOKEN } from "utils/constants";
export default function useHeaderMenu() { export default function useHeaderMenu() {
const { id } = useParams(); const { id } = useParams();
@@ -19,6 +22,7 @@ export default function useHeaderMenu() {
const { isRTL } = useAppSelector((state) => state.locale); const { isRTL } = useAppSelector((state) => state.locale);
const { themeName } = useAppSelector((state) => state.theme); const { themeName } = useAppSelector((state) => state.theme);
const navigate = useNavigate(); const navigate = useNavigate();
const token = localStorage.getItem(ACCESS_TOKEN);
const menuItems = [ const menuItems = [
{ {
@@ -73,7 +77,7 @@ export default function useHeaderMenu() {
), ),
label: <Link to={`/${id}/menu`}>{t("common.branches")}</Link>, label: <Link to={`/${id}/menu`}>{t("common.branches")}</Link>,
}, },
{ ...(!token ? [{
key: "login", key: "login",
icon: ( icon: (
<LoginOutlined <LoginOutlined
@@ -84,7 +88,19 @@ export default function useHeaderMenu() {
onClick: () => { onClick: () => {
navigate(`/${id}/login`); navigate(`/${id}/login`);
}, },
}, }] : []),
...(token ? [{
key: "logout",
icon: (
<LogoutOutlined
style={{ color: themeName === "dark" ? "white" : "#1f2937" }}
/>
),
label: <div>{t("common.logout")}</div>,
onClick: () => {
dispatch(logoutThunk());
},
}] : []),
]; ];
return { menuItems }; return { menuItems };
} }

View File

@@ -117,7 +117,8 @@ function MenuPage() {
<Space direction="vertical" style={{ width: "100%", gap: 16 }}> <Space direction="vertical" style={{ width: "100%", gap: 16 }}>
<div> <div>
{restaurant?.loyalty_stamps && {restaurant?.loyalty_stamps &&
restaurant?.is_loyalty_enabled && <LoyaltyCard />} restaurant?.is_loyalty_enabled &&
<LoyaltyCard />}
<CategoriesList categories={menuData?.categories || []} /> <CategoriesList categories={menuData?.categories || []} />
</div> </div>

View File

@@ -24,6 +24,7 @@ export const loginApi = baseApi.injectEndpoints({
method: "POST", method: "POST",
body, body,
}), }),
invalidatesTags: ["Restaurant"],
}), }),
}), }),
}); });

View File

@@ -26,6 +26,7 @@ export const branchApi = baseApi.injectEndpoints({
transformResponse: (response: any) => { transformResponse: (response: any) => {
return response?.result?.restaurants?.[0]; return response?.result?.restaurants?.[0];
}, },
providesTags: ["Restaurant"],
}), }),
getMenu: builder.query<any, string | void>({ getMenu: builder.query<any, string | void>({
query: (restaurantId: string) => query: (restaurantId: string) =>
@@ -50,7 +51,7 @@ export const branchApi = baseApi.injectEndpoints({
method: "POST", method: "POST",
body, body,
}), }),
invalidatesTags: ["Orders"], invalidatesTags: ["Orders", "Restaurant"],
}), }),
cancelOrder: builder.mutation({ cancelOrder: builder.mutation({
query: (body: any) => ({ query: (body: any) => ({
@@ -58,7 +59,7 @@ export const branchApi = baseApi.injectEndpoints({
method: "POST", method: "POST",
body, body,
}), }),
invalidatesTags: ["Orders"], invalidatesTags: ["Orders", "Restaurant"],
}), }),
getTables: builder.query<any, { restaurantID: string; tableType: string }>({ getTables: builder.query<any, { restaurantID: string; tableType: string }>({
query: ({ query: ({