This commit is contained in:
@@ -6,6 +6,7 @@ import PlusIcon from "@/components/icons/PlusIcon";
|
|||||||
import { toast, toastLoginRequired } from "@/components/Toast";
|
import { toast, toastLoginRequired } from "@/components/Toast";
|
||||||
import { getToken } from "@/lib/api/func";
|
import { getToken } from "@/lib/api/func";
|
||||||
import { ef } from "@/lib/helpers/utfNumbers";
|
import { ef } from "@/lib/helpers/utfNumbers";
|
||||||
|
import clsx from "clsx";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { ArrowLeft, Clock, Cup, Heart, TruckTick } from "iconsax-react";
|
import { ArrowLeft, Clock, Cup, Heart, TruckTick } from "iconsax-react";
|
||||||
import { useParams, useRouter } from "next/navigation";
|
import { useParams, useRouter } from "next/navigation";
|
||||||
@@ -36,9 +37,8 @@ function FoodPage({}: Props) {
|
|||||||
}, [items, foodId]);
|
}, [items, foodId]);
|
||||||
|
|
||||||
const handleAddToCart = () => {
|
const handleAddToCart = () => {
|
||||||
if (foodId) {
|
if (!foodId || food?.data?.isAvailable === false) return;
|
||||||
addToCart(foodId);
|
addToCart(foodId);
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRemoveFromCart = () => {
|
const handleRemoveFromCart = () => {
|
||||||
@@ -97,6 +97,7 @@ function FoodPage({}: Props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const foodData = food.data;
|
const foodData = food.data;
|
||||||
|
const isAvailable = foodData.isAvailable !== false;
|
||||||
const foodName = foodData.title || foodData.name || foodData.foodName || "";
|
const foodName = foodData.title || foodData.name || foodData.foodName || "";
|
||||||
const foodImage =
|
const foodImage =
|
||||||
typeof foodData.image === "string"
|
typeof foodData.image === "string"
|
||||||
@@ -128,7 +129,12 @@ function FoodPage({}: Props) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="not-lg:max-w-lg not-lg:place-self-center not-lg:w-full not-lg:mb-10 pt-6 not-lg:flex not-lg:flex-col lg:fixed lg:z-10 lg:top-20 xl:top-22 lg:bottom-24 lg:left-5 lg:right-4 xl:right-[285px] lg:grid lg:grid-cols-2 lg:min-h-0 lg:overflow-hidden lg:rounded-2xl">
|
<div
|
||||||
|
className={clsx(
|
||||||
|
"not-lg:max-w-lg not-lg:place-self-center not-lg:w-full not-lg:mb-10 pt-6 not-lg:flex not-lg:flex-col lg:fixed lg:z-10 lg:top-20 xl:top-22 lg:bottom-24 lg:left-5 lg:right-4 xl:right-[285px] lg:grid lg:grid-cols-2 lg:min-h-0 lg:overflow-hidden lg:rounded-2xl",
|
||||||
|
!isAvailable && "opacity-50",
|
||||||
|
)}
|
||||||
|
>
|
||||||
<div className="relative w-full lg:h-full min-h-0 not-lg:bg-container rounded-2xl overflow-hidden lg:rounded-r-none lg:order-1">
|
<div className="relative w-full lg:h-full min-h-0 not-lg:bg-container rounded-2xl overflow-hidden lg:rounded-r-none lg:order-1">
|
||||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||||
<img
|
<img
|
||||||
@@ -224,13 +230,14 @@ function FoodPage({}: Props) {
|
|||||||
<div className="mt-12 lg:mt-0 shrink-0 flex justify-between items-center">
|
<div className="mt-12 lg:mt-0 shrink-0 flex justify-between items-center">
|
||||||
<span dir="ltr">{ef(price.toLocaleString("en-US"))} T</span>
|
<span dir="ltr">{ef(price.toLocaleString("en-US"))} T</span>
|
||||||
<motion.div
|
<motion.div
|
||||||
whileTap={{ scale: 1.05 }}
|
whileTap={isAvailable ? { scale: 1.05 } : undefined}
|
||||||
className="bg-background active:drop-shadow-xs max-w-[115px] rounded-md w-full h-8 inline-flex p-1 justify-between items-center gap-2 relative overflow-hidden"
|
className="bg-background active:drop-shadow-xs max-w-[115px] rounded-md w-full h-8 inline-flex p-1 justify-between items-center gap-2 relative overflow-hidden"
|
||||||
>
|
>
|
||||||
{quantity <= 0 ? (
|
{quantity <= 0 ? (
|
||||||
<button
|
<button
|
||||||
onClick={handleAddToCart}
|
onClick={handleAddToCart}
|
||||||
className="inline-flex w-full justify-center items-center gap-2"
|
disabled={!isAvailable}
|
||||||
|
className="inline-flex w-full justify-center items-center gap-2 disabled:pointer-events-none disabled:opacity-40"
|
||||||
>
|
>
|
||||||
<PlusIcon />
|
<PlusIcon />
|
||||||
<div className="text-sm2 pt-0.5 font-normal text-foreground">
|
<div className="text-sm2 pt-0.5 font-normal text-foreground">
|
||||||
@@ -241,7 +248,8 @@ function FoodPage({}: Props) {
|
|||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
onClick={handleAddToCart}
|
onClick={handleAddToCart}
|
||||||
className="bg-container hover:bg-container/60 active:bg-container/30 rounded-sm p-2 transition-colors"
|
disabled={!isAvailable}
|
||||||
|
className="bg-container hover:bg-container/60 active:bg-container/30 rounded-sm p-2 transition-colors disabled:opacity-40 disabled:pointer-events-none"
|
||||||
>
|
>
|
||||||
<PlusIcon className="text-foreground" />
|
<PlusIcon className="text-foreground" />
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ export interface Food {
|
|||||||
pickupServe: boolean;
|
pickupServe: boolean;
|
||||||
discount: number;
|
discount: number;
|
||||||
isSpecialOffer: boolean;
|
isSpecialOffer: boolean;
|
||||||
|
isAvailable: boolean;
|
||||||
|
unavailabilityMessage: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** جزئیات کامل یک غذا (endpoint تکی) */
|
/** جزئیات کامل یک غذا (endpoint تکی) */
|
||||||
@@ -71,6 +73,8 @@ export interface FoodDetail {
|
|||||||
score: number;
|
score: number;
|
||||||
discount: number;
|
discount: number;
|
||||||
isSpecialOffer: boolean;
|
isSpecialOffer: boolean;
|
||||||
|
isAvailable: boolean;
|
||||||
|
unavailabilityMessage: string | null;
|
||||||
reviews: unknown[];
|
reviews: unknown[];
|
||||||
favorites: unknown[];
|
favorites: unknown[];
|
||||||
isFavorite: boolean;
|
isFavorite: boolean;
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ function FavoritePage() {
|
|||||||
pickupServe: favoriteFood.pickupServe,
|
pickupServe: favoriteFood.pickupServe,
|
||||||
discount: favoriteFood.discount,
|
discount: favoriteFood.discount,
|
||||||
isSpecialOffer: favoriteFood.isSpecialOffer,
|
isSpecialOffer: favoriteFood.isSpecialOffer,
|
||||||
|
isAvailable: true,
|
||||||
|
unavailabilityMessage: null,
|
||||||
}
|
}
|
||||||
return food
|
return food
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { useCart } from "@/app/[name]/(Main)/cart/hook/useCart";
|
|||||||
import type { Food, FoodImage } from "@/app/[name]/(Main)/types/Types";
|
import type { Food, FoodImage } from "@/app/[name]/(Main)/types/Types";
|
||||||
import MinusIcon from "@/components/icons/MinusIcon";
|
import MinusIcon from "@/components/icons/MinusIcon";
|
||||||
import PlusIcon from "@/components/icons/PlusIcon";
|
import PlusIcon from "@/components/icons/PlusIcon";
|
||||||
|
import clsx from "clsx";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
@@ -86,7 +87,10 @@ const MenuItem = ({ food }: MenuItemProps) => {
|
|||||||
|
|
||||||
const hasDiscount = useMemo(() => (food.discount || 0) > 0, [food.discount]);
|
const hasDiscount = useMemo(() => (food.discount || 0) > 0, [food.discount]);
|
||||||
|
|
||||||
|
const isAvailable = food.isAvailable !== false;
|
||||||
|
|
||||||
const handleAddToCart = () => {
|
const handleAddToCart = () => {
|
||||||
|
if (!isAvailable) return;
|
||||||
addToCart(food.id);
|
addToCart(food.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -97,7 +101,12 @@ const MenuItem = ({ food }: MenuItemProps) => {
|
|||||||
const foodDetailUrl = `/${name}/${food.id}?category=${food.category}`;
|
const foodDetailUrl = `/${name}/${food.id}?category=${food.category}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex gap-4 w-full h-full items-center">
|
<div
|
||||||
|
className={clsx(
|
||||||
|
"flex gap-4 w-full h-full items-center",
|
||||||
|
!isAvailable && "opacity-50",
|
||||||
|
)}
|
||||||
|
>
|
||||||
<Link href={foodDetailUrl} className="cursor-pointer">
|
<Link href={foodDetailUrl} className="cursor-pointer">
|
||||||
<img
|
<img
|
||||||
className="rounded-xl bg-[#F2F2F9] min-w-28 w-28 max-h-28 object-cover"
|
className="rounded-xl bg-[#F2F2F9] min-w-28 w-28 max-h-28 object-cover"
|
||||||
@@ -140,13 +149,14 @@ const MenuItem = ({ food }: MenuItemProps) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<motion.div
|
<motion.div
|
||||||
whileTap={{ scale: 1.05 }}
|
whileTap={isAvailable ? { scale: 1.05 } : undefined}
|
||||||
className="bg-background active:drop-shadow-xs max-w-[115px] rounded-md w-full h-8 inline-flex p-1 justify-between items-center gap-2 relative overflow-hidden"
|
className="bg-background active:drop-shadow-xs max-w-[115px] rounded-md w-full h-8 inline-flex p-1 justify-between items-center gap-2 relative overflow-hidden"
|
||||||
>
|
>
|
||||||
{quantity <= 0 ? (
|
{quantity <= 0 ? (
|
||||||
<button
|
<button
|
||||||
onClick={handleAddToCart}
|
onClick={handleAddToCart}
|
||||||
className="inline-flex w-full justify-center items-center gap-2"
|
disabled={!isAvailable}
|
||||||
|
className="inline-flex w-full justify-center items-center gap-2 disabled:pointer-events-none disabled:opacity-40"
|
||||||
>
|
>
|
||||||
<PlusIcon />
|
<PlusIcon />
|
||||||
<div className="text-sm2 pt-0.5 font-normal text-foreground">
|
<div className="text-sm2 pt-0.5 font-normal text-foreground">
|
||||||
@@ -157,7 +167,8 @@ const MenuItem = ({ food }: MenuItemProps) => {
|
|||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
onClick={handleAddToCart}
|
onClick={handleAddToCart}
|
||||||
className="bg-container hover:bg-container/60 active:bg-container/30 rounded-sm p-2 transition-colors"
|
disabled={!isAvailable}
|
||||||
|
className="bg-container hover:bg-container/60 active:bg-container/30 rounded-sm p-2 transition-colors disabled:opacity-40 disabled:pointer-events-none"
|
||||||
>
|
>
|
||||||
<PlusIcon className="text-foreground" />
|
<PlusIcon className="text-foreground" />
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user