update address

This commit is contained in:
hamid zarghami
2026-06-06 11:48:22 +03:30
parent 347017f1be
commit 931cc76a47
7 changed files with 70 additions and 20 deletions
@@ -6,6 +6,7 @@ import Modal from '@/components/utils/Modal';
import Link from 'next/link'; import Link from 'next/link';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { ef } from '@/lib/helpers/utfNumbers'; import { ef } from '@/lib/helpers/utfNumbers';
import { Edit2 } from 'iconsax-react';
const formatAddress = (address: Address) => { const formatAddress = (address: Address) => {
return `${address.address}، ${address.city}، ${address.province}`; return `${address.address}، ${address.city}، ${address.province}`;
@@ -78,6 +79,20 @@ export const AddressSelectionModal = ({
<p className='text-xs mt-2 text-disabled-text'> <p className='text-xs mt-2 text-disabled-text'>
تلفن: {ef(address.phone)} تلفن: {ef(address.phone)}
</p> </p>
<div className='mt-3 flex justify-end'>
<Link
href={`/${name}/profile/address/new?id=${address.id}&redirect=${encodeURIComponent(redirectUrl)}`}
onClick={(e) => e.stopPropagation()}
>
<button
type='button'
className='text-xs text-primary dark:text-foreground flex items-center gap-1'
>
<Edit2 className='size-4 stroke-primary dark:stroke-foreground' />
ویرایش
</button>
</Link>
</div>
</div> </div>
))} ))}
</div> </div>
@@ -29,8 +29,9 @@ export const useUpdateAddress = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: updateAddress, mutationFn: updateAddress,
onSuccess: () => { onSuccess: (_data, variables) => {
queryClient.invalidateQueries({ queryKey: ["addresses"] }); queryClient.invalidateQueries({ queryKey: ["addresses"] });
queryClient.invalidateQueries({ queryKey: ["address", variables.id] });
}, },
}); });
}; };
@@ -2,12 +2,13 @@ import AnimatedBottomSheet from '@/components/bottomsheet/AnimatedBottomSheet';
import Button from '@/components/button/PrimaryButton'; import Button from '@/components/button/PrimaryButton';
import { AddressDisplay } from './AddressDisplay'; import { AddressDisplay } from './AddressDisplay';
import { AddressForm } from './AddressForm'; import { AddressForm } from './AddressForm';
import { NominatimReverseGeocodingResponse } from '../../types/Types'; import { Address, NominatimReverseGeocodingResponse } from '../../types/Types';
import { Location } from 'iconsax-react'; import { Location } from 'iconsax-react';
interface AddressDetailsModalProps { interface AddressDetailsModalProps {
visible: boolean; visible: boolean;
selectedAddress: NominatimReverseGeocodingResponse | null; selectedAddress: NominatimReverseGeocodingResponse | null;
existingAddress?: Address | null;
formData: { formData: {
title: string; title: string;
addressDetails: string; addressDetails: string;
@@ -26,6 +27,7 @@ interface AddressDetailsModalProps {
export const AddressDetailsModal = ({ export const AddressDetailsModal = ({
visible, visible,
selectedAddress, selectedAddress,
existingAddress,
formData, formData,
isPending, isPending,
editMode = false, editMode = false,
@@ -41,13 +43,13 @@ export const AddressDetailsModal = ({
blurOpacity={null} blurOpacity={null}
noBlur noBlur
visible={visible} visible={visible}
title='آدرس' title={editMode ? 'ویرایش آدرس' : 'آدرس'}
onClick={onClose} onClick={onClose}
overrideClassName='bg-container!' overrideClassName='bg-container!'
> >
<form onSubmit={onSubmit}> <form onSubmit={onSubmit}>
<div className='px-4'> <div className='px-4'>
<AddressDisplay selectedAddress={selectedAddress} /> <AddressDisplay selectedAddress={selectedAddress} existingAddress={existingAddress} />
{editMode && onChangePosition && ( {editMode && onChangePosition && (
<div className='mt-4 mb-6 flex justify-end'> <div className='mt-4 mb-6 flex justify-end'>
<Button <Button
@@ -1,19 +1,22 @@
import { NominatimReverseGeocodingResponse } from '../../types/Types'; import { Address, NominatimReverseGeocodingResponse } from '../../types/Types';
import { formatSelectedAddress } from '../utils/formatAddress'; import { formatAddress, formatSelectedAddress } from '../utils/formatAddress';
interface AddressDisplayProps { interface AddressDisplayProps {
selectedAddress: NominatimReverseGeocodingResponse | null; selectedAddress: NominatimReverseGeocodingResponse | null;
existingAddress?: Address | null;
} }
export const AddressDisplay = ({ selectedAddress }: AddressDisplayProps) => { export const AddressDisplay = ({ selectedAddress, existingAddress }: AddressDisplayProps) => {
const displayText = selectedAddress
? formatSelectedAddress(selectedAddress)
: existingAddress
? formatAddress(existingAddress)
: 'آدرس را به صورت دستی وارد کنید';
return ( return (
<div className='px-4 mt-2 bg-container'> <div className='px-4 mt-2 bg-container'>
<span className='text-sm'> <span className='text-sm'>
{!selectedAddress ? ( {displayText}
'آدرس را به صورت دستی وارد کنید'
) : (
formatSelectedAddress(selectedAddress)
)}
</span> </span>
<hr className='border border-border mt-3 mb-10' /> <hr className='border border-border mt-3 mb-10' />
</div> </div>
@@ -6,7 +6,7 @@ import { ArrowLeft } from 'iconsax-react';
import { useAuthStore } from '@/zustand/authStore'; import { useAuthStore } from '@/zustand/authStore';
import { AddressDetailsModal } from './components/AddressDetailsModal'; import { AddressDetailsModal } from './components/AddressDetailsModal';
import { useAddressForm } from './hooks/useAddressForm'; import { useAddressForm } from './hooks/useAddressForm';
import { useGetAddressById } from '../hooks/useAddressData'; import { useGetAddresses } from '../hooks/useAddressData';
import { useGetAbout } from '@/app/[name]/(Main)/about/hooks/useAboutData'; import { useGetAbout } from '@/app/[name]/(Main)/about/hooks/useAboutData';
function OrderTrackingPage() { function OrderTrackingPage() {
@@ -15,9 +15,14 @@ function OrderTrackingPage() {
const id = params.get('id'); const id = params.get('id');
const editMode = !!id; const editMode = !!id;
const { data: addressResponse, isLoading: isLoadingAddress } = useGetAddressById(id); const { data: addressesResponse, isLoading: isLoadingAddresses } = useGetAddresses();
const { data: aboutData } = useGetAbout(); const { data: aboutData } = useGetAbout();
const address = addressResponse?.data;
const address = useMemo(() => {
if (!editMode || !id) return null;
return addressesResponse?.data?.find((item) => item.id === id) ?? null;
}, [editMode, id, addressesResponse?.data]);
const user = useAuthStore((state) => state.user); const user = useAuthStore((state) => state.user);
const restaurant = aboutData?.data; const restaurant = aboutData?.data;
@@ -55,7 +60,7 @@ function OrderTrackingPage() {
addressData: address || null, addressData: address || null,
}); });
if (editMode && isLoadingAddress) { if (editMode && isLoadingAddresses) {
return ( return (
<div className="fixed inset-0 bg-gray-50 flex items-center justify-center"> <div className="fixed inset-0 bg-gray-50 flex items-center justify-center">
<p className="text-sm2 text-disabled-text">در حال بارگذاری...</p> <p className="text-sm2 text-disabled-text">در حال بارگذاری...</p>
@@ -63,8 +68,22 @@ function OrderTrackingPage() {
); );
} }
if (editMode && !address) {
return (
<div className="fixed inset-0 bg-gray-50 flex flex-col items-center justify-center gap-4 px-4">
<p className="text-sm2 text-disabled-text text-center">آدرس مورد نظر یافت نشد</p>
<button
onClick={() => router.back()}
className="p-2 rounded-full bg-container shadow-sm"
>
<ArrowLeft size={24} className="stroke-foreground" />
</button>
</div>
);
}
if (!restaurant) { if (!restaurant) {
return null return null;
} }
return ( return (
@@ -82,6 +101,7 @@ function OrderTrackingPage() {
<AddressDetailsModal <AddressDetailsModal
visible visible
selectedAddress={null} selectedAddress={null}
existingAddress={address}
formData={formData} formData={formData}
isPending={isPending} isPending={isPending}
editMode={editMode} editMode={editMode}
@@ -1,4 +1,8 @@
import { NominatimReverseGeocodingResponse } from '../../types/Types'; import { Address, NominatimReverseGeocodingResponse } from '../../types/Types';
export const formatAddress = (address: Address): string => {
return `${address.address}، ${address.city}، ${address.province}`;
};
export const formatSelectedAddress = (selectedAddress: NominatimReverseGeocodingResponse | null): string => { export const formatSelectedAddress = (selectedAddress: NominatimReverseGeocodingResponse | null): string => {
if (!selectedAddress) { if (!selectedAddress) {
@@ -72,6 +72,11 @@ function UserAddressesPage({ }: Props) {
return `${address.address}، ${address.city}، ${address.province}`; 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 ( return (
<div className='overflow-y-auto h-full noscrollbar flex flex-col'> <div className='overflow-y-auto h-full noscrollbar flex flex-col'>
<div className='grid grid-cols-3 items-center'> <div className='grid grid-cols-3 items-center'>
@@ -134,7 +139,7 @@ function UserAddressesPage({ }: Props) {
</Button> </Button>
)} )}
<div className="flex gap-2"> <div className="flex gap-2">
<Link href={`address/new?id=${address.id}`}> <Link href={getEditHref(address.id)}>
<Button className='bg-background! text-foreground! flex justify-center items-center gap-2 text-xs p-0! size-8!'> <Button className='bg-background! text-foreground! flex justify-center items-center gap-2 text-xs p-0! size-8!'>
<Edit2 className='stroke-foreground size-5 mb-0.5' /> <Edit2 className='stroke-foreground size-5 mb-0.5' />
</Button> </Button>