218 lines
10 KiB
TypeScript
218 lines
10 KiB
TypeScript
'use client'
|
||
import React, { useState, useEffect } from 'react'
|
||
import { useForm } from 'react-hook-form'
|
||
import { yupResolver } from '@hookform/resolvers/yup'
|
||
import * as yup from 'yup'
|
||
import { Button } from '@/components/ui/button'
|
||
import Input from '@/components/Input'
|
||
import { Edit2 } from 'lucide-react'
|
||
import Layout from '@/hoc/Layout'
|
||
import { Heart, ShoppingCart } from 'iconsax-react'
|
||
import Menu from './components/Menu'
|
||
import { useGetProfile, useUpdateProfile } from './hooks/useProfileData'
|
||
|
||
// Schema validation
|
||
const profileSchema = yup.object({
|
||
fullName: yup.string().required('نام و نام خانوادگی الزامی است'),
|
||
phoneNumber: yup
|
||
.string()
|
||
.required('شماره تماس الزامی است')
|
||
.matches(/^09\d{9}$/, 'شماره تماس باید با 09 شروع شود و 11 رقم باشد'),
|
||
dateOfBirth: yup.string().required('تاریخ تولد الزامی است'),
|
||
nationalCode: yup
|
||
.string()
|
||
.required('کد ملی الزامی است')
|
||
.matches(/^\d{10}$/, 'کد ملی باید 10 رقم باشد'),
|
||
address: yup.string().required('آدرس الزامی است'),
|
||
})
|
||
|
||
const ProfilePage = () => {
|
||
const { data: profile, isLoading } = useGetProfile()
|
||
const updateProfileMutation = useUpdateProfile()
|
||
const [isEditing, setIsEditing] = useState(false)
|
||
|
||
const {
|
||
register,
|
||
handleSubmit,
|
||
formState: { errors, isSubmitting },
|
||
reset,
|
||
setValue,
|
||
} = useForm({
|
||
resolver: yupResolver(profileSchema),
|
||
mode: 'onChange',
|
||
defaultValues: {
|
||
fullName: '',
|
||
phoneNumber: '',
|
||
dateOfBirth: '',
|
||
nationalCode: '',
|
||
address: '',
|
||
},
|
||
})
|
||
|
||
// Set form values when profile data is loaded
|
||
useEffect(() => {
|
||
if (profile?.results?.info) {
|
||
const userInfo = profile.results.info
|
||
setValue('fullName', userInfo.fullName || '')
|
||
setValue('phoneNumber', userInfo.phoneNumber || '')
|
||
setValue('dateOfBirth', userInfo.dateOfBirth || '')
|
||
setValue('nationalCode', userInfo.nationalCode || '')
|
||
setValue('address', userInfo.userAddress?.address || '')
|
||
}
|
||
}, [profile, setValue])
|
||
|
||
const onSubmit = async (data: Record<string, unknown>) => {
|
||
await updateProfileMutation.mutateAsync(data)
|
||
setIsEditing(false)
|
||
}
|
||
|
||
const handleFormSubmit = (e: React.FormEvent) => {
|
||
e.preventDefault()
|
||
handleSubmit(onSubmit)(e)
|
||
}
|
||
|
||
const handleCancel = () => {
|
||
reset()
|
||
setIsEditing(false)
|
||
}
|
||
|
||
if (isLoading) {
|
||
return (
|
||
<div className="p-3 sm:p-4 md:p-6">
|
||
<Menu pageActive='profile' />
|
||
<div className='mt-4 sm:mt-6 md:mt-8 lg:mt-10'>
|
||
<div className="flex justify-center items-center h-64">
|
||
<div className="text-gray-500">در حال بارگذاری...</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
return (
|
||
<div className="p-3 sm:p-4 md:p-6">
|
||
<Menu pageActive='profile' />
|
||
<div className='mt-4 sm:mt-6 md:mt-8 lg:mt-10'>
|
||
<div className="flex flex-col lg:flex-row gap-4 sm:gap-6">
|
||
<div className="flex-1">
|
||
<div className="bg-[#FAFAFA] rounded-lg p-3 sm:p-4 md:p-6">
|
||
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between mb-4 sm:mb-6 gap-3 sm:gap-0">
|
||
<h1 className="text-base sm:text-lg font-bold text-gray-900">اطلاعات کاربری</h1>
|
||
<Button
|
||
onClick={() => setIsEditing(!isEditing)}
|
||
variant="outline"
|
||
className="flex items-center gap-2 text-sm sm:text-base"
|
||
>
|
||
<Edit2 size={16} />
|
||
<span className="hidden sm:inline">ویرایش</span>
|
||
</Button>
|
||
</div>
|
||
|
||
<form onSubmit={handleFormSubmit}>
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
|
||
<div>
|
||
<Input
|
||
label="نام و نام خانوادگی"
|
||
{...register('fullName')}
|
||
readOnly={!isEditing}
|
||
error_text={errors.fullName?.message}
|
||
/>
|
||
</div>
|
||
|
||
<div>
|
||
<Input
|
||
label="کد ملی"
|
||
{...register('nationalCode')}
|
||
readOnly={!isEditing}
|
||
error_text={errors.nationalCode?.message}
|
||
/>
|
||
</div>
|
||
|
||
<div>
|
||
<Input
|
||
label="شماره تماس"
|
||
{...register('phoneNumber')}
|
||
readOnly={!isEditing}
|
||
error_text={errors.phoneNumber?.message}
|
||
/>
|
||
</div>
|
||
|
||
<div>
|
||
<Input
|
||
label="تاریخ تولد"
|
||
{...register('dateOfBirth')}
|
||
readOnly={!isEditing}
|
||
error_text={errors.dateOfBirth?.message}
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="mt-3 sm:mt-4">
|
||
<Input
|
||
label="آدرس"
|
||
{...register('address')}
|
||
readOnly={!isEditing}
|
||
error_text={errors.address?.message}
|
||
/>
|
||
</div>
|
||
|
||
{isEditing && (
|
||
<div className="mt-4 sm:mt-6 flex flex-col sm:flex-row gap-3">
|
||
<Button
|
||
type="submit"
|
||
disabled={isSubmitting || updateProfileMutation.isPending}
|
||
className="px-6 sm:px-8 bg-blue-600 hover:bg-blue-700 text-sm sm:text-base"
|
||
>
|
||
{isSubmitting || updateProfileMutation.isPending ? 'در حال ذخیره...' : 'ذخیره تغییرات'}
|
||
</Button>
|
||
<Button
|
||
type="button"
|
||
onClick={handleCancel}
|
||
variant="outline"
|
||
className="text-sm sm:text-base"
|
||
>
|
||
انصراف
|
||
</Button>
|
||
</div>
|
||
)}
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<div className='flex-1 flex lg:flex-row flex-col gap-6'>
|
||
<div className='flex flex-row lg:flex-col gap-3 sm:gap-4 lg:gap-6 flex-1'>
|
||
<div className='flex-1 lg:w-full bg-[#FAFAFA] rounded-[10px] flex flex-col gap-3 sm:gap-4 lg:gap-6 justify-center items-center h-[100px] sm:h-[120px] lg:h-[160px] xl:h-[200px]'>
|
||
<div className='size-10 sm:size-12 lg:size-16 xl:size-20 bg-[#F2F2F2] rounded-full flex justify-center items-center'>
|
||
<ShoppingCart size={20} color='#000' className='sm:w-6 sm:h-6 lg:w-8 lg:h-8 xl:w-10 xl:h-10' />
|
||
</div>
|
||
<div className='text-xs sm:text-sm lg:text-base text-center'>
|
||
سفارشات
|
||
</div>
|
||
</div>
|
||
<div className='flex-1 lg:w-full bg-[#FAFAFA] rounded-[10px] flex flex-col gap-3 sm:gap-4 lg:gap-6 justify-center items-center h-[100px] sm:h-[120px] lg:h-[160px] xl:h-[200px]'>
|
||
<div className='size-10 sm:size-12 lg:size-16 xl:size-20 bg-[#F2F2F2] rounded-full flex justify-center items-center'>
|
||
<Heart size={20} color='#000' className='sm:w-6 sm:h-6 lg:w-8 lg:h-8 xl:w-10 xl:h-10' />
|
||
</div>
|
||
<div className='text-xs sm:text-sm lg:text-base text-center'>
|
||
علاقه مندی ها
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className='flex-1 bg-red-50 '>
|
||
{/* محتوای اضافی */}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
export default function ProfilePageWithLayout() {
|
||
return (
|
||
<Layout>
|
||
<ProfilePage />
|
||
</Layout>
|
||
)
|
||
} |