refactor: modals

This commit is contained in:
Mahyar Khanbolooki
2025-08-10 17:54:21 +03:30
parent ac30ac1ecf
commit 389ac492c2
9 changed files with 214 additions and 129 deletions
+46 -92
View File
@@ -1,18 +1,20 @@
'use client';
import React, { useMemo, useRef, useState } from 'react';
import React, { useMemo, useRef } from 'react';
import { motion, PanInfo, Variants } from 'framer-motion';
import SideMenuItem from './SideMenuItem';
import NoteBoardIcon from '../icons/NoteBoardIcon';
import BlurredOverlayContainer from '../overlays/BlurredOverlayContainer';
import NightModeSwitch from '../button/NightModeSwitch';
import Button from '../button/PrimaryButton';
import { useAuthStore } from '@/zustand/authStore';
import { useParams, usePathname, useRouter } from 'next/navigation';
import { useParams, usePathname } from 'next/navigation';
import clsx from 'clsx';
import { useTranslation } from 'react-i18next';
import { CalendarSearch, Cup, DirectboxReceive, DocumentCopy, Game, Icon, Instagram, Like1, LogoutCurve, Notification, Receipt1, Setting2, Share, TicketDiscount, Whatsapp } from 'iconsax-react';
import TelegramIcon from '../icons/TelegramIcon';
import Modal from '../utils/Modal';
import LogoutPrompt from '@/features/general/LogoutPrompt';
import useToggle from '@/hooks/helpers/useToggle';
type MenuItemType = {
href: string | undefined;
@@ -49,21 +51,17 @@ type Props = {
function SideMenu({ menuState, toggleMenuState, nightModeState, togglenightModeState }: Props) {
const menuStateMemo = useMemo(() => menuState, [menuState]);
const [logoutModalVisible, setLogoutModalVisible] = useState(false);
const [shareModalVisible, setShareModalVisible] = useState(false);
const closeRef = useRef<HTMLDivElement>(null);
const userIsAuthenticated = true; // useAuthStore((state) => state.isAuthenticated);
const authLogout = useAuthStore((state) => state.logout);
const router = useRouter();
const { active: logoutModal, onToggle: onToggleLogoutModal } = useToggle();
const { active: shareModal, onToggle: onToggleShareModal } = useToggle();
const params = useParams();
const { name } = params;
const pathname = usePathname();
const { t: tMenu } = useTranslation('common', {
keyPrefix: 'SideMenu'
});
const { t: tLogoutModal } = useTranslation('common', {
keyPrefix: 'LogoutModal'
});
const { t: tShareModal } = useTranslation('common', {
keyPrefix: 'ShareModal'
});
@@ -79,29 +77,9 @@ function SideMenu({ menuState, toggleMenuState, nightModeState, togglenightModeS
}
};
const toggleLogoutModalVisiblity = (e?: React.MouseEvent) => {
e?.preventDefault();
e?.stopPropagation();
setLogoutModalVisible((state) => !state);
};
const toggleShareModalVisiblity = (e?: React.MouseEvent) => {
e?.preventDefault();
e?.stopPropagation();
setShareModalVisible((state) => !state);
};
const onLogout = (e: React.MouseEvent<HTMLButtonElement> | null) => {
if (!e) return;
if (userIsAuthenticated) {
authLogout();
router.replace('/');
}
};
const hrefOnClicks = [
{ href: '?logout', handler: toggleLogoutModalVisiblity },
{ href: '?share', handler: toggleShareModalVisiblity }
{ href: '?logout', handler: onToggleLogoutModal },
{ href: '?share', handler: onToggleShareModal }
];
const renderMenu = () => {
@@ -210,80 +188,56 @@ function SideMenu({ menuState, toggleMenuState, nightModeState, togglenightModeS
className="fixed top-0 bottom-0 right-0 bg-white w-[200px] h-dvh flex flex-col z-40 overflow-clip not-xl:!rounded-s-none"
>
{renderMenu()}
{String(logoutModal)}
</motion.nav>
</BlurredOverlayContainer>
<nav
<nav
className="hidden fixed top-4 bottom-4 right-4 bg-white xl:w-[250px] xl:flex flex-col z-40 overflow-clip xl:rounded-4xl"
>
>
{renderMenu()}
</nav>
</aside>
</div>
{/* Logout Modal */}
<BlurredOverlayContainer visible={logoutModalVisible} onClick={toggleLogoutModalVisiblity} inDuration={100} outDuration={100} outDelay={75}>
<div className="absolute top-1/2 left-6 right-6 px-6">
<motion.div
animate={{ y: logoutModalVisible ? [10, 0] : [0, 10] }}
transition={{ duration: 0.1, ease: 'easeInOut' }}
className="top-1/2 absolute left-1/2 min-w-xs w-full max-w-sm text-center -translate-1/2 px-6 pt-8 pb-9 drop-shadow-container bg-white/63 rounded-4xl"
>
<h2 className="text-base font-medium">
{tLogoutModal('Heading')}
</h2>
<p className="text-xs font-medium mt-6">
{tLogoutModal('Description')}
</p>
<div className="grid grid-cols-2 gap-5.5 mt-8">
<Button onClick={onLogout} className="text-sm font-normal">
{tLogoutModal('ButtonOk')}
</Button>
<Button onClick={toggleLogoutModalVisiblity} className="bg-disabled! text-disabled2! text-sm font-normal">
{tLogoutModal('ButtonCancel')}
</Button>
</div>
</motion.div>
</div>
</BlurredOverlayContainer>
<LogoutPrompt
visible={logoutModal}
onClick={onToggleLogoutModal}
/>
{/* Share modal */}
<BlurredOverlayContainer visible={shareModalVisible} onClick={toggleShareModalVisiblity} inDuration={100} outDuration={100} outDelay={75}>
<div className="absolute top-1/2 left-6 right-6 px-6">
<motion.div
animate={{ y: shareModalVisible ? [10, 0] : [0, 10] }}
transition={{ duration: 0.1, ease: 'easeInOut' }}
className="top-1/2 absolute left-1/2 min-w-xs w-full max-w-sm text-center -translate-1/2 px-6 pt-8 pb-9 drop-shadow-container bg-white/63 rounded-4xl"
>
<h2 className="text-base font-medium">
<Share className="inline-block ml-2 mb-1.5 stroke-primary" size={24} />
{tShareModal('Heading')}
</h2>
<p className="text-xs font-medium mt-6">
{tShareModal('Description')}
</p>
<Modal
visible={shareModal}
onClick={onToggleShareModal}
>
<h2 className="text-base font-medium">
<Share className="inline-block ml-2 mb-1.5 stroke-primary" size={24} />
{tShareModal('Heading')}
</h2>
<p className="text-xs font-medium mt-6">
{tShareModal('Description')}
</p>
<Button onClick={onLogout} className="text-sm mt-8">
<DocumentCopy className="inline-block ml-2 mb-0.5 stroke-white" size={20} />
<span className="font-light">{tShareModal('ButtonCopy')}</span>
</Button>
<Button onClick={() => { }} className="text-sm mt-8">
<DocumentCopy className="inline-block ml-2 mb-0.5 stroke-white" size={20} />
<span className="font-light">{tShareModal('ButtonCopy')}</span>
</Button>
<div className="grid grid-cols-3 gap-5.5 mt-6 px-12">
<div className="place-items-center">
<TelegramIcon width={24} height={24} className="mb-1.5 stroke-primary" />
<span className='text-xs2 font-medium'>Telegram</span>
</div>
<div className="place-items-center">
<Whatsapp size={24} className="mb-1.5 stroke-primary" />
<span className='text-xs2 font-medium'>WhatsApp</span>
</div>
<div className="place-items-center">
<Instagram size={24} className="mb-1.5 stroke-primary" />
<span className='text-xs2 font-medium'>Instagram</span>
</div>
</div>
</motion.div>
<div className="grid grid-cols-3 gap-5.5 mt-6 px-12">
<div className="place-items-center">
<TelegramIcon width={24} height={24} className="mb-1.5 stroke-primary" />
<span className='text-xs2 font-medium'>Telegram</span>
</div>
<div className="place-items-center">
<Whatsapp size={24} className="mb-1.5 stroke-primary" />
<span className='text-xs2 font-medium'>WhatsApp</span>
</div>
<div className="place-items-center">
<Instagram size={24} className="mb-1.5 stroke-primary" />
<span className='text-xs2 font-medium'>Instagram</span>
</div>
</div>
</BlurredOverlayContainer>
</Modal>
</>
);
}