Files
dmenu-plus-front/src/app/[name]/(Profile)/profile/address/page.tsx
T
hamid zarghami d3ef8e1a98 load pattern
2026-06-21 11:08:11 +03:30

181 lines
8.3 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import Button from '@/components/button/PrimaryButton';
import { ef } from '@/lib/helpers/utfNumbers';
import { ArrowLeft, Edit2, TickCircle, Trash } from 'iconsax-react';
import Link from 'next/link';
import { useRouter, useSearchParams } from 'next/navigation';
import React, { useState } from 'react';
import { useGetAddresses, useSetDefaultAddress, useDeleteAddress } from './hooks/useAddressData';
import { Address } from './types/Types';
import Prompt from '@/components/utils/Prompt';
import { toast } from '@/components/Toast';
import useToggle from '@/hooks/helpers/useToggle';
type Props = object
function UserAddressesPage({ }: Props) {
const { data: addressesResponse, isLoading } = useGetAddresses();
const router = useRouter();
const searchParams = useSearchParams();
const redirect = searchParams.get('redirect');
const { mutate: setDefault, isPending: isSettingDefault } = useSetDefaultAddress();
const { mutate: deleteAddressMutation, isPending: isDeleting } = useDeleteAddress();
const { state: deleteModalVisible, set: setDeleteModal } = useToggle();
const [selectedAddressId, setSelectedAddressId] = useState<string | null>(null);
const addresses = addressesResponse?.data || [];
const handleSetDefault = (addressId: string) => {
setDefault(addressId, {
onSuccess: () => {
toast('آدرس به عنوان پیش‌فرض تنظیم شد', 'success');
if (redirect) {
router.replace(redirect);
}
},
onError: (error) => {
const errorMessage = error instanceof Error ? error.message : 'خطا در تنظیم آدرس پیش‌فرض';
toast(errorMessage, 'error');
},
});
};
const handleDeleteClick = (addressId: string) => {
setSelectedAddressId(addressId);
setDeleteModal(true);
};
const handleDeleteConfirm = () => {
if (!selectedAddressId) return;
deleteAddressMutation(selectedAddressId, {
onSuccess: () => {
toast('آدرس با موفقیت حذف شد', 'success');
setDeleteModal(false);
setSelectedAddressId(null);
},
onError: (error) => {
const errorMessage = error instanceof Error ? error.message : 'خطا در حذف آدرس';
toast(errorMessage, 'error');
},
});
};
const handleDeleteCancel = () => {
setDeleteModal(false);
setSelectedAddressId(null);
};
const formatAddress = (address: Address) => {
return `${address.address}، ${address.city}، ${address.province}`;
};
const getEditHref = (addressId: string) => {
const base = `address/new?id=${addressId}`;
return redirect ? `${base}&redirect=${encodeURIComponent(redirect)}` : base;
};
return (
<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'>افزودن و انتخاب آدرس</h1>
<ArrowLeft
className='cursor-pointer place-self-end'
size='24'
color='currentColor'
onClick={() => { router.back() }}
/>
</div>
<div className="mt-8 flex-1 w-full py-0 flex flex-col gap-4">
{isLoading ? (
<div className='flex-1 flex flex-col items-center justify-center gap-4'>
<p className='text-center text-sm2 text-disabled-text'>
در حال بارگذاری...
</p>
</div>
) : addresses.length === 0 ? (
<div className='flex-1 flex flex-col items-center justify-center gap-4'>
<p className='text-center text-sm2 text-disabled-text'>
شما هیچ آدرسی ثبت نکرده اید. برای ثبت آدرس دکمه افزودن را بزنید
</p>
</div>
) : (
addresses.map((address) => (
<div
key={address.id}
className={`bg-container rounded-container w-full shadow-xl px-4 py-4 flex flex-col justify-between ${address.isDefault ? 'border border-primary' : ''}`}
>
<div className="flex justify-between items-start mb-2">
<h2 className='text-sm font-medium'>{address.title}</h2>
{address.isDefault && (
<span className='text-xs bg-primary/10 text-primary px-2 py-1 rounded-full'>
پیشفرض
</span>
)}
</div>
<p className='text-sm2 mt-2'>
{formatAddress(address)}
</p>
<p className='text-xs mt-2 text-disabled-text'>
کد پستی: {ef(address.postalCode || 'ثبت نشده')}
</p>
<p className='text-xs mt-2 text-disabled-text'>
تلفن: {ef(address.phone)}
</p>
<div className="flex justify-between items-center mt-4 gap-2">
{!address.isDefault && (
<Button
onClick={() => handleSetDefault(address.id)}
disabled={isSettingDefault}
pending={isSettingDefault}
className='bg-background! pattern-secondary-bg text-foreground! flex items-center gap-2 text-xs h-8 flex-1'
>
<TickCircle variant='Bold' className='fill-foreground stroke-background size-4.5 mb-0.5' />
تنظیم به عنوان فعال
</Button>
)}
<div className="flex gap-2">
<Link href={getEditHref(address.id)}>
<Button className='bg-background! pattern-secondary-bg text-foreground! flex justify-center items-center gap-2 text-xs p-0! size-8!'>
<Edit2 className='stroke-foreground size-5 mb-0.5' />
</Button>
</Link>
<Button
onClick={() => handleDeleteClick(address.id)}
disabled={isDeleting}
className='bg-background! pattern-secondary-bg text-foreground! flex justify-center items-center gap-2 text-xs p-0! size-8!'
>
<Trash className='stroke-foreground size-5 mb-0.5' />
</Button>
</div>
</div>
</div>
))
)}
</div>
<div className='w-full text-center mt-6'>
<Link href={'address/new'}>
<Button>افزودن آدرس</Button>
</Link>
</div>
<Prompt
title='حذف آدرس'
description='آیا از حذف این آدرس اطمینان دارید؟'
textConfirm='بله، حذف کن'
textCancel='انصراف'
visible={deleteModalVisible}
onConfirm={handleDeleteConfirm}
onCancel={handleDeleteCancel}
onClick={handleDeleteCancel}
/>
</div>
)
}
export default UserAddressesPage