link to auth
Build and Deploy Docker Images / build_and_deploy (push) Has been cancelled

This commit is contained in:
hamid zarghami
2026-06-11 12:15:08 +03:30
parent 5976e8ea44
commit 71238dcd75
5 changed files with 87 additions and 32 deletions
+2 -2
View File
@@ -3,7 +3,7 @@
import { useCart } from "@/app/[name]/(Main)/cart/hook/useCart"; import { useCart } from "@/app/[name]/(Main)/cart/hook/useCart";
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 { toast } 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 { motion } from "framer-motion"; import { motion } from "framer-motion";
@@ -52,7 +52,7 @@ function FoodPage({}: Props) {
const token = await getToken(); const token = await getToken();
if (!token || !isSuccess) { if (!token || !isSuccess) {
toast("ابتدا لاگین کنید", "error"); toastLoginRequired(() => router.push(`/${name}/auth`), "error");
return; return;
} }
+79 -23
View File
@@ -2,11 +2,17 @@
import { CloseCircle, InfoCircle, TickCircle } from 'iconsax-react'; import { CloseCircle, InfoCircle, TickCircle } from 'iconsax-react';
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
interface ToastAction {
label: string;
onClick: () => void;
}
interface Toast { interface Toast {
id: string; id: string;
message: string; message: string;
type?: 'success' | 'error' | 'info'; type?: 'success' | 'error' | 'info';
isExiting?: boolean; isExiting?: boolean;
action?: ToastAction;
} }
let addToast: (toast: Toast) => void; let addToast: (toast: Toast) => void;
@@ -18,7 +24,8 @@ const ToastContainer: React.FC = () => {
const showToast = (toast: Toast) => { const showToast = (toast: Toast) => {
setToasts((prev) => [...prev, toast]); setToasts((prev) => [...prev, toast]);
// حذف خودکار بعد از ۳ ثانیه const dismissAfter = toast.action ? 6000 : 3000;
setTimeout(() => { setTimeout(() => {
setToasts((prev) => prev.map(t => setToasts((prev) => prev.map(t =>
t.id === toast.id ? { ...t, isExiting: true } : t t.id === toast.id ? { ...t, isExiting: true } : t
@@ -28,7 +35,16 @@ const ToastContainer: React.FC = () => {
setTimeout(() => { setTimeout(() => {
setToasts((prev) => prev.filter((t) => t.id !== toast.id)); setToasts((prev) => prev.filter((t) => t.id !== toast.id));
}, 300); // مدت زمان انیمیشن خروج }, 300); // مدت زمان انیمیشن خروج
}, 3000); }, dismissAfter);
};
const dismissToast = (id: string) => {
setToasts((prev) => prev.map((t) =>
t.id === id ? { ...t, isExiting: true } : t
));
setTimeout(() => {
setToasts((prev) => prev.filter((t) => t.id !== id));
}, 300);
}; };
// تخصیص تابع نمایش toast به متغیر سراسری // تخصیص تابع نمایش toast به متغیر سراسری
@@ -38,36 +54,76 @@ const ToastContainer: React.FC = () => {
return ( return (
<div className="fixed top-4 text-sm right-0 left-0 mx-auto w-fit z-50 flex flex-col gap-2"> <div className="fixed top-4 text-sm right-0 left-0 mx-auto w-fit z-50 flex flex-col gap-2">
{toasts.map((toast) => ( {toasts.map((toast) => {
<div const handleAction = () => {
key={toast.id} toast.action?.onClick();
className={`px-4 flex items-center gap-2 backdrop-blur-2xl h-16 min-w-[300px] rounded-2xl shadow-md dismissToast(toast.id);
};
return (
<div
key={toast.id}
role={toast.action ? 'button' : undefined}
tabIndex={toast.action ? 0 : undefined}
onClick={toast.action ? handleAction : undefined}
onKeyDown={toast.action ? (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
handleAction();
}
} : undefined}
className={`px-4 flex items-center gap-2 backdrop-blur-2xl h-16 min-w-[300px] rounded-2xl shadow-md
${toast.isExiting ? 'animate-slide-out-right' : 'animate-slide-in-right'} ${toast.type === 'success' ${toast.isExiting ? 'animate-slide-out-right' : 'animate-slide-in-right'} ${toast.type === 'success'
? 'bg-white/70 text-black' ? 'bg-white/70 text-black'
: toast.type === 'error' : toast.type === 'error'
? 'bg-white/70 text-black' ? 'bg-white/70 text-black'
: 'bg-white/70 text-black' : 'bg-white/70 text-black'
}`} } ${toast.action ? 'cursor-pointer active:scale-[0.98] transition-transform' : ''}`}
style={{ style={{
animationFillMode: 'forwards', animationFillMode: 'forwards',
animationDuration: '0.3s', animationDuration: '0.3s',
animationTimingFunction: 'ease-out' animationTimingFunction: 'ease-out'
}} }}
> >
{ <div className="flex items-center gap-2 flex-1 min-w-0">
toast.type === 'success' ? <TickCircle className='size-5' color='green' /> : {
toast.type === 'error' ? <CloseCircle className='size-5' color='red' /> : toast.type === 'success' ? <TickCircle className='size-5 shrink-0' color='green' /> :
<InfoCircle className='size-5' color='blue' /> toast.type === 'error' ? <CloseCircle className='size-5 shrink-0' color='red' /> :
} <InfoCircle className='size-5 shrink-0' color='blue' />
{toast.message} }
</div> <span className="truncate">{toast.message}</span>
))} </div>
{toast.action && (
<span className="shrink-0 rounded-xl bg-primary px-3 py-1.5 text-xs font-medium text-white pointer-events-none">
{toast.action.label}
</span>
)}
</div>
);
})}
</div> </div>
); );
}; };
export const toast = (message?: string, type: 'success' | 'error' | 'info' = 'info') => { type ToastOptions = {
addToast({ id: Date.now().toString(), message: message || '', type }); action?: ToastAction;
};
export const toast = (
message?: string,
type: 'success' | 'error' | 'info' = 'info',
options?: ToastOptions
) => {
addToast({ id: Date.now().toString(), message: message || '', type, action: options?.action });
};
export const toastLoginRequired = (
onLogin: () => void,
type: 'success' | 'error' | 'info' = 'info'
) => {
toast('ابتدا لاگین کنید', type, {
action: { label: 'ورود', onClick: onLogin },
});
}; };
export default ToastContainer; export default ToastContainer;
+2 -2
View File
@@ -18,7 +18,7 @@ import useToggle from '@/hooks/helpers/useToggle';
import { useGetAbout } from '@/app/[name]/(Main)/about/hooks/useAboutData'; import { useGetAbout } from '@/app/[name]/(Main)/about/hooks/useAboutData';
import Image from 'next/image'; import Image from 'next/image';
import { useGetProfile } from '@/app/[name]/(Profile)/profile/hooks/userProfileData'; import { useGetProfile } from '@/app/[name]/(Profile)/profile/hooks/userProfileData';
import { toast } from '../Toast'; import { toast, toastLoginRequired } from '../Toast';
type MenuItemType = { type MenuItemType = {
href: string | undefined; href: string | undefined;
@@ -203,7 +203,7 @@ function SideMenu({ menuState, toggleMenuState, nightModeState, togglenightModeS
const handleNotificationClick = (e: React.MouseEvent) => { const handleNotificationClick = (e: React.MouseEvent) => {
e.preventDefault(); e.preventDefault();
if (!isLoggedIn) { if (!isLoggedIn) {
toast('ابتدا لاگین کنید', 'info'); toastLoginRequired(() => router.push(`/${name}/auth`), 'info');
} else { } else {
router.push(`/${name}/notifications`); router.push(`/${name}/notifications`);
} }
+2 -3
View File
@@ -14,7 +14,7 @@ import { useCart } from '@/app/[name]/(Main)/cart/hook/useCart';
import { Building } from 'iconsax-react'; import { Building } from 'iconsax-react';
import clsx from 'clsx'; import clsx from 'clsx';
import { useGetProfile } from '@/app/[name]/(Profile)/profile/hooks/userProfileData'; import { useGetProfile } from '@/app/[name]/(Profile)/profile/hooks/userProfileData';
import { toast } from '../Toast'; import { toastLoginRequired } from '../Toast';
type BottomNavBarProps = { type BottomNavBarProps = {
onPagerClick?: () => void; onPagerClick?: () => void;
@@ -49,8 +49,7 @@ function BottomNavBar({ onPagerClick }: BottomNavBarProps) {
router.push(`/${name}/favorite`); router.push(`/${name}/favorite`);
} else { } else {
e.stopPropagation(); e.stopPropagation();
toast('ابتدا لاگین کنید', 'error'); toastLoginRequired(() => router.push(`/${name}/auth`), 'error');
router.replace(`/${name}/auth`);
} }
} }
+2 -2
View File
@@ -12,7 +12,7 @@ import useToggle from '@/hooks/helpers/useToggle'
import LogoutPrompt from '@/features/general/LogoutPrompt' import LogoutPrompt from '@/features/general/LogoutPrompt'
import { useGetProfile } from '@/app/[name]/(Profile)/profile/hooks/userProfileData' import { useGetProfile } from '@/app/[name]/(Profile)/profile/hooks/userProfileData'
import { useGetNotificationsCount } from '@/app/[name]/(Main)/hooks/useMenuData' import { useGetNotificationsCount } from '@/app/[name]/(Main)/hooks/useMenuData'
import { toast } from '../Toast' import { toastLoginRequired } from '../Toast'
type Props = { type Props = {
profileDropState: boolean, profileDropState: boolean,
@@ -40,7 +40,7 @@ function TopBar({ profileDropState, toggleProfileDropState, toggleMenuState }: P
const handleNotificationClick = (e: React.MouseEvent) => { const handleNotificationClick = (e: React.MouseEvent) => {
e.preventDefault(); e.preventDefault();
if (!isLoggedIn) { if (!isLoggedIn) {
toast('ابتدا لاگین کنید', 'info'); toastLoginRequired(() => router.push(`/${name}/auth`), 'info');
} else { } else {
router.push(`/${name}/notifications`); router.push(`/${name}/notifications`);
} }