empty data
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 55 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
@@ -59,6 +59,8 @@ const CartSummary = () => {
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{!isCartEmpty && (
|
||||
<>
|
||||
<div className='mt-2'>
|
||||
<div className='relative'>
|
||||
@@ -75,11 +77,8 @@ const CartSummary = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={`fixed bottom-0 left-0 right-0 z-50 bg-white border-t border-border p-4 w-full ${isCartEmpty ? 'pointer-events-none opacity-60' : ''}`}
|
||||
>
|
||||
<div className='fixed bottom-0 left-0 right-0 z-50 bg-white border-t border-border p-4 w-full'>
|
||||
<div className='flex justify-between items-center gap-4'>
|
||||
|
||||
<div className='flex flex-col'>
|
||||
<div className='text-xs text-gray-400'>{t('PayableAmountLabel')}</div>
|
||||
<div className='text-sm mt-2 font-semibold'>{formatPrice(totalPrice)} تومان</div>
|
||||
@@ -88,10 +87,6 @@ const CartSummary = () => {
|
||||
<Link
|
||||
href={'order/checkout/0'}
|
||||
onClick={(event) => {
|
||||
if (isCartEmpty) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
if (!isSuccess) {
|
||||
event.preventDefault();
|
||||
const redirectUrl = encodeURIComponent(pathname);
|
||||
@@ -100,11 +95,12 @@ const CartSummary = () => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Button className='w-fit! px-10' disabled={isCartEmpty}>{t('ButtonCheckout')}</Button>
|
||||
<Button className='w-fit! px-10'>{t('ButtonCheckout')}</Button>
|
||||
</Link>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* {!isCartEmpty && (
|
||||
<div className='flex items-center justify-between rounded-xl border border-border px-4 py-3 text-xs text-muted-foreground'>
|
||||
|
||||
@@ -4,22 +4,37 @@ import React from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ArrowLeft, Trash } from 'iconsax-react';
|
||||
import Image from 'next/image';
|
||||
import { useCart } from './hook/useCart';
|
||||
import CartItemsList from './components/CartItemsList';
|
||||
import CartSummary from './components/CartSummary';
|
||||
import Prompt from '@/components/utils/Prompt';
|
||||
import { useGetFoods } from '@/app/[name]/(Main)/hooks/useMenuData';
|
||||
import { CartSummarySkeleton } from './components/CartSkeleton';
|
||||
import VerticalScrollView from '@/components/listview/VerticalScrollView';
|
||||
import MenuItem from '@/components/listview/MenuItem';
|
||||
import MenuItemRenderer from '@/components/listview/MenuItemRenderer';
|
||||
import type { Food } from '@/app/[name]/(Main)/types/Types';
|
||||
|
||||
const CartIndex = () => {
|
||||
const { t } = useTranslation('parallels', { keyPrefix: 'Cart' });
|
||||
const router = useRouter();
|
||||
const { clearCart } = useCart();
|
||||
const { clearCart, items } = useCart();
|
||||
const [showClearConfirm, setShowClearConfirm] = React.useState(false);
|
||||
const { data: foodsResponse, isFetching } = useGetFoods();
|
||||
const foods = React.useMemo(() => foodsResponse?.data ?? [], [foodsResponse?.data]);
|
||||
const isLoading = isFetching && !foods.length;
|
||||
|
||||
const cartFoods = React.useMemo(() => {
|
||||
if (!foods.length) return [];
|
||||
return Object.entries(items)
|
||||
.filter(([, detail]) => detail?.quantity && detail.quantity > 0)
|
||||
.map(([id]) =>
|
||||
foods.find((foodItem) => String(foodItem.id) === String(id))
|
||||
)
|
||||
.filter((food): food is Food => Boolean(food));
|
||||
}, [foods, items]);
|
||||
|
||||
const isCartEmpty = cartFoods.length === 0;
|
||||
|
||||
const handleClearCart = (e: React.MouseEvent) => {
|
||||
e?.preventDefault();
|
||||
e?.stopPropagation();
|
||||
@@ -34,14 +49,18 @@ const CartIndex = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='bg-inherit flex flex-col h-full'>
|
||||
<div className='grid grid-cols-3 items-center py-4'>
|
||||
<div className='overflow-y-auto h-full noscrollbar flex flex-col'>
|
||||
<div className='grid grid-cols-3 items-center'>
|
||||
{isCartEmpty ? (
|
||||
<span></span>
|
||||
) : (
|
||||
<Trash
|
||||
className='cursor-pointer place-self-start'
|
||||
size='24'
|
||||
color='currentColor'
|
||||
onClick={() => setShowClearConfirm(true)}
|
||||
/>
|
||||
)}
|
||||
<h1 className='text-sm2 place-self-center font-medium'>{t('Heading')}</h1>
|
||||
<ArrowLeft
|
||||
className='cursor-pointer place-self-end'
|
||||
@@ -51,9 +70,40 @@ const CartIndex = () => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='flex overflow-y-auto noscrollbar flex-col h-full pt-4 gap-4 pb-24' dir='rtl'>
|
||||
<CartItemsList />
|
||||
{isLoading ? <CartSummarySkeleton /> : <CartSummary />}
|
||||
<div className="mt-8 flex-1 h-full">
|
||||
{isLoading ? (
|
||||
<div className='flex flex-col items-center justify-center gap-2 py-12 text-sm2 text-muted-foreground'>
|
||||
<span className='h-4 w-4 animate-spin rounded-full border border-dashed border-foreground border-t-transparent'></span>
|
||||
<p>در حال دریافت سبد خرید...</p>
|
||||
</div>
|
||||
) : isCartEmpty ? (
|
||||
<div className='flex flex-col items-center justify-center gap-4 h-full'>
|
||||
<Image
|
||||
src='/assets/images/cart.png'
|
||||
alt='cart'
|
||||
width={120}
|
||||
height={120}
|
||||
className='object-contain'
|
||||
/>
|
||||
<div className='flex flex-col items-center gap-2 text-sm2 text-muted-foreground'>
|
||||
<p>{t('EmptyStateTitle', { defaultValue: 'سبد خرید شما خالی است' })}</p>
|
||||
<p className='text-xs'>
|
||||
{t('EmptyStateDescription', {
|
||||
defaultValue: 'برای افزودن غذا، به منوی رستوران برگردید.',
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<VerticalScrollView className="overflow-y-auto h-full pb-24">
|
||||
{cartFoods.map((food) => (
|
||||
<MenuItemRenderer key={food.id}>
|
||||
<MenuItem food={food} />
|
||||
</MenuItemRenderer>
|
||||
))}
|
||||
<CartSummary />
|
||||
</VerticalScrollView>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className={showClearConfirm ? 'fixed inset-0 z-1001' : 'pointer-events-none fixed inset-0 z-1001'}>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { ef } from '@/lib/helpers/utfNumbers';
|
||||
import { ArrowLeft, Trash } from 'iconsax-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import React from 'react'
|
||||
import Image from 'next/image';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useGetNotifications, useDeleteNotification } from './hooks/useNotificationData';
|
||||
import type { Notification } from './types/Types';
|
||||
@@ -30,7 +31,7 @@ const formatTime = (dateString: string): string => {
|
||||
export default function NotificationsIndex({ }: Props) {
|
||||
const { t } = useTranslation('notifications')
|
||||
const router = useRouter();
|
||||
const { data, isLoading, isError } = useGetNotifications();
|
||||
const { data, isLoading } = useGetNotifications();
|
||||
const { mutate: deleteNotification } = useDeleteNotification();
|
||||
|
||||
const notifications = React.useMemo(() => {
|
||||
@@ -41,10 +42,9 @@ export default function NotificationsIndex({ }: Props) {
|
||||
deleteNotification(id);
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className='h-full bg-inherit relative flex flex-col lg:gap-4'>
|
||||
<div className='grid grid-cols-3 items-center py-4 '>
|
||||
<div className='overflow-y-auto h-full noscrollbar flex flex-col'>
|
||||
<div className='grid grid-cols-3 items-center'>
|
||||
<span></span>
|
||||
<h1 className='text-sm2 place-self-center font-medium'>{t("Heading")}</h1>
|
||||
<ArrowLeft
|
||||
@@ -54,47 +54,27 @@ export default function NotificationsIndex({ }: Props) {
|
||||
onClick={() => { router.back() }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mt-8 flex-1 h-full">
|
||||
{isLoading ? (
|
||||
<div className='flex flex-col items-center justify-center gap-2 py-12 text-sm2 text-muted-foreground'>
|
||||
<span className='h-4 w-4 animate-spin rounded-full border border-dashed border-foreground border-t-transparent'></span>
|
||||
<p>در حال دریافت اعلانها...</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (isError || !notifications.length) {
|
||||
return (
|
||||
<div className='h-full bg-inherit relative flex flex-col lg:gap-4'>
|
||||
<div className='grid grid-cols-3 items-center py-4 '>
|
||||
<span></span>
|
||||
<h1 className='text-sm2 place-self-center font-medium'>{t("Heading")}</h1>
|
||||
<ArrowLeft
|
||||
className='cursor-pointer place-self-end'
|
||||
size='24'
|
||||
color='currentColor'
|
||||
onClick={() => { router.back() }}
|
||||
) : notifications.length === 0 ? (
|
||||
<div className='flex flex-col items-center justify-center gap-4 h-full'>
|
||||
<Image
|
||||
src='/assets/images/notification.png'
|
||||
alt='notification'
|
||||
width={120}
|
||||
height={120}
|
||||
className='object-contain'
|
||||
/>
|
||||
</div>
|
||||
<div className='flex flex-col items-center justify-center gap-2 py-12 text-sm2 text-muted-foreground'>
|
||||
<div className='flex flex-col items-center gap-2 text-sm2 text-muted-foreground'>
|
||||
<p>اعلانی وجود ندارد</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='h-full bg-inherit relative flex flex-col lg:gap-4'>
|
||||
<div className='grid grid-cols-3 items-center py-4 '>
|
||||
<span></span>
|
||||
<h1 className='text-sm2 place-self-center font-medium'>{t("Heading")}</h1>
|
||||
<ArrowLeft
|
||||
className='cursor-pointer place-self-end'
|
||||
size='24'
|
||||
color='currentColor'
|
||||
onClick={() => { router.back() }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
) : (
|
||||
<ul className='flex flex-col gap-4 pb-20'>
|
||||
{notifications.map((notification: Notification) => {
|
||||
const isNew = !notification.sentAt;
|
||||
@@ -131,6 +111,8 @@ export default function NotificationsIndex({ }: Props) {
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
import React, { useMemo } from 'react'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { ArrowLeft } from 'iconsax-react'
|
||||
import Image from 'next/image'
|
||||
import { useGetFavorites } from './hooks/useFavoriteData'
|
||||
import MenuItem from '@/components/listview/MenuItem'
|
||||
import MenuItemRenderer from '@/components/listview/MenuItemRenderer'
|
||||
@@ -74,12 +75,21 @@ function FavoritePage() {
|
||||
<p>در حال دریافت علاقهمندیها...</p>
|
||||
</div>
|
||||
) : foodItems.length === 0 ? (
|
||||
<div className='flex flex-col items-center justify-center gap-2 py-12 text-sm2 text-muted-foreground'>
|
||||
<div className='flex flex-col items-center justify-center gap-4 h-full'>
|
||||
<Image
|
||||
src='/assets/images/favorite.png'
|
||||
alt='favorite'
|
||||
width={120}
|
||||
height={120}
|
||||
className='object-contain'
|
||||
/>
|
||||
<div className='flex flex-col items-center gap-2 text-sm2 text-muted-foreground'>
|
||||
<p>شما هیچ مورد علاقهمندی ثبت نکردهاید</p>
|
||||
<p className='text-xs'>
|
||||
برای افزودن غذا به علاقهمندیها، به صفحه جزئیات غذا بروید
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<VerticalScrollView className="overflow-y-auto h-full">
|
||||
{foodItems.map((food) => (
|
||||
|
||||
Reference in New Issue
Block a user