diff --git a/src/app/profile/hooks/useProfileData.ts b/src/app/profile/hooks/useProfileData.ts index ddbad18..8caae0c 100644 --- a/src/app/profile/hooks/useProfileData.ts +++ b/src/app/profile/hooks/useProfileData.ts @@ -1,6 +1,7 @@ -import { useQuery } from "@tanstack/react-query"; +import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import * as api from "../service/Service"; import { useSharedStore } from "@/share/store/sharedStore"; +import { UpdateProfileRequest } from "../types/ProfileTypes"; export const useGetProfile = () => { const { isLogin } = useSharedStore(); @@ -10,3 +11,18 @@ export const useGetProfile = () => { enabled: isLogin, }); }; + +export const useUpdateProfile = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: (profileData: UpdateProfileRequest) => + api.updateProfile(profileData), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ["profile"] }); + }, + onError: (error: any) => { + console.error("خطا در به‌روزرسانی پروفایل:", error); + }, + }); +}; diff --git a/src/app/profile/page.tsx b/src/app/profile/page.tsx index 8992f7c..af22111 100644 --- a/src/app/profile/page.tsx +++ b/src/app/profile/page.tsx @@ -1,40 +1,94 @@ 'use client' -import React, { useState } from 'react' +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 [userInfo, setUserInfo] = useState({ - name: 'حسین دهقانی', - email: 'sondos@gmail.com', - phone: '09010901789', - nationalCode: '052093452', - birthDate: '1365/5/8', - postalCode: '1235478951', - province: 'مرکزی', - city: 'اراک', - address: 'خیابان دانشگاه رودوی بیمارستان خوانساری ساختمان مهر طبقه سوم واحد2', - district: '58' - }) - + const { data: profile, isLoading } = useGetProfile() + const updateProfileMutation = useUpdateProfile() const [isEditing, setIsEditing] = useState(false) - const handleInputChange = (field: string, value: string) => { - setUserInfo(prev => ({ - ...prev, - [field]: value - })) + 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) => { + await updateProfileMutation.mutateAsync(data) + setIsEditing(false) } - const handleSubmit = () => { - // Handle form submission + const handleFormSubmit = (e: React.FormEvent) => { + e.preventDefault() + handleSubmit(onSubmit)(e) + } + + const handleCancel = () => { + reset() setIsEditing(false) } + if (isLoading) { + return ( +
+ +
+
+
در حال بارگذاری...
+
+
+
+ ) + } + return (
@@ -54,98 +108,74 @@ const ProfilePage = () => {
-
- handleInputChange('name', e.target.value)} - readOnly={!isEditing} - /> +
+
+
+ +
- handleInputChange('nationalCode', e.target.value)} - readOnly={!isEditing} - /> +
+ +
- handleInputChange('email', e.target.value)} - readOnly={!isEditing} - type="email" - /> +
+ +
- handleInputChange('phone', e.target.value)} - readOnly={!isEditing} - /> - - handleInputChange('birthDate', e.target.value)} - readOnly={!isEditing} - /> - - handleInputChange('province', e.target.value)} - readOnly={!isEditing} - /> - - handleInputChange('city', e.target.value)} - readOnly={!isEditing} - /> - - handleInputChange('postalCode', e.target.value)} - readOnly={!isEditing} - /> - - handleInputChange('district', e.target.value)} - readOnly={!isEditing} - /> -
- -
- handleInputChange('address', e.target.value)} - readOnly={!isEditing} - /> -
- - {isEditing && ( -
- - +
+ +
- )} + +
+ +
+ + {isEditing && ( +
+ + +
+ )} +
@@ -170,11 +200,9 @@ const ProfilePage = () => {
- + {/* محتوای اضافی */}
- - diff --git a/src/app/profile/service/Service.ts b/src/app/profile/service/Service.ts index d5a513a..28c0e18 100644 --- a/src/app/profile/service/Service.ts +++ b/src/app/profile/service/Service.ts @@ -1,7 +1,19 @@ import axios from "@/config/axios"; import { UserMeResponseType } from "@/share/types/SharedTypes"; +import { + UpdateProfileRequest, + UpdateProfileResponse, +} from "../types/ProfileTypes"; export const getProfile = async () => { const { data } = await axios.get("/user/profile"); return data; }; + +export const updateProfile = async (profileData: UpdateProfileRequest) => { + const { data } = await axios.patch( + "/user/profile", + profileData + ); + return data; +}; diff --git a/src/app/profile/types/ProfileTypes.ts b/src/app/profile/types/ProfileTypes.ts new file mode 100644 index 0000000..7af482e --- /dev/null +++ b/src/app/profile/types/ProfileTypes.ts @@ -0,0 +1,60 @@ +export interface ProfileFormData { + fullName: string; + phoneNumber: string; + dateOfBirth: string; + nationalCode: string; + address: string; +} + +export interface UpdateProfileRequest { + fullName?: string; + phoneNumber?: string; + dateOfBirth?: string; + nationalCode?: string; + address?: string; +} + +export interface UpdateProfileResponse { + status: number; + success: boolean; + results: { + info: { + _id: string; + fullName: string; + phoneNumber: string; + dateOfBirth: string | null; + address: string; + nationalCode: string | null; + homeNumber: string | null; + createdAt: string; + updatedAt: string; + userAddress: { + _id: string; + address: string; + city: { + _id: number; + name: string; + province: number; + createdAt: string; + updatedAt: string; + __v: number; + }; + province: { + _id: number; + name: string; + createdAt: string; + updatedAt: string; + __v: number; + }; + postalCode: string; + plaque: string; + lat: string; + lon: string; + createdAt: string; + updatedAt: string; + __v: number; + }; + isSeller: boolean; + }; + }; +}