From 3e7cc74d5755db0a948b2e5784aedcce608774ec Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Sat, 27 Jun 2026 15:24:50 +0330 Subject: [PATCH] create customer --- src/components/DatePicker.tsx | 10 +- src/components/Select.tsx | 12 +- src/components/UploadBox.tsx | 8 +- src/pages/customers/Create.tsx | 328 ++++++++++++--------- src/pages/customers/types/Types.ts | 4 + src/shared/components/CustomersSubMenu.tsx | 4 +- 6 files changed, 225 insertions(+), 141 deletions(-) diff --git a/src/components/DatePicker.tsx b/src/components/DatePicker.tsx index 6c10758..ea3c14a 100644 --- a/src/components/DatePicker.tsx +++ b/src/components/DatePicker.tsx @@ -14,7 +14,8 @@ type Props = { reset?: boolean; isDateTime?: boolean; className?: string; - label?: string + label?: string; + isNotRequired?: boolean; }; const DatePickerComponent: FC = (props: Props) => { @@ -85,8 +86,11 @@ const DatePickerComponent: FC = (props: Props) => { return (
{props.label && -
- {props.label} +
+
{props.label}
+ {props.isNotRequired && ( + (اختیاری) + )}
}
const Select: FC = (props: Props) => { @@ -20,9 +21,14 @@ const Select: FC = (props: Props) => {
{ props.label && - +
+ + {props.isNotRequired && ( + (اختیاری) + )} +
} diff --git a/src/pages/customers/Create.tsx b/src/pages/customers/Create.tsx index 208171e..0f9fc64 100644 --- a/src/pages/customers/Create.tsx +++ b/src/pages/customers/Create.tsx @@ -1,155 +1,219 @@ +import { type FC, useEffect, useState } from 'react' +import { useFormik } from 'formik' +import * as Yup from 'yup' +import { TickCircle } from 'iconsax-react' +import { toast } from 'react-toastify' +import { useNavigate } from 'react-router-dom' import Button from '@/components/Button' import Input from '@/components/Input' import Select from '@/components/Select' import DatePicker from '@/components/DatePicker' -import Textarea from '@/components/Textarea' -import CustomerStats from '@/components/CustomerStats' -import { TickCircle, Wallet2, TicketDiscount } from 'iconsax-react' -import { type FC } from 'react' +import UploadBox from '@/components/UploadBox' +import { useCreateUser } from './hooks/useUsersData' +import { useSingleUpload } from '@/pages/uploader/hooks/useUploaderData' +import type { CreateUserType } from './types/Types' +import { Pages } from '@/config/Pages' +import type { ErrorType } from '@/helpers/types' +import { extractErrorMessage } from '@/config/func' + +type CreateCustomerFormValues = { + phone: string + firstName: string + lastName: string + birthDate: string + marriageDate: string + gender: string +} + +const buildCreateUserPayload = ( + values: CreateCustomerFormValues, + avatarUrl?: string, +): CreateUserType => { + const payload: CreateUserType = { + phone: values.phone.trim(), + firstName: values.firstName.trim(), + lastName: values.lastName.trim(), + } + + if (values.birthDate) payload.birthDate = values.birthDate + if (values.marriageDate) payload.marriageDate = values.marriageDate + if (values.gender !== '') payload.gender = values.gender === 'true' + if (avatarUrl) payload.avatarUrl = avatarUrl + + return payload +} const CreateCustomer: FC = () => { + const navigate = useNavigate() + const { mutate: createUser, isPending } = useCreateUser() + const { mutate: singleUpload, isPending: isUploading } = useSingleUpload() + const [avatarFile, setAvatarFile] = useState([]) + const [avatarPreviewUrl, setAvatarPreviewUrl] = useState('') + + useEffect(() => { + if (avatarFile.length > 0) { + const url = URL.createObjectURL(avatarFile[0]) + setAvatarPreviewUrl(url) + return () => URL.revokeObjectURL(url) + } + setAvatarPreviewUrl('') + }, [avatarFile]) + + const formik = useFormik({ + initialValues: { + phone: '', + firstName: '', + lastName: '', + birthDate: '', + marriageDate: '', + gender: '', + }, + validationSchema: Yup.object().shape({ + phone: Yup.string().required('شماره تلفن الزامی است'), + firstName: Yup.string().required('نام الزامی است'), + lastName: Yup.string().required('نام خانوادگی الزامی است'), + birthDate: Yup.string(), + marriageDate: Yup.string(), + gender: Yup.string(), + }), + onSubmit: (values) => { + const submitCustomer = (avatarUrl?: string) => { + createUser(buildCreateUserPayload(values, avatarUrl), { + onSuccess: (response) => { + toast.success('مشتری با موفقیت ایجاد شد') + const userId = response.data.user.id + navigate(Pages.customers.detail + userId) + }, + onError: (error: ErrorType) => { + toast.error(extractErrorMessage(error)) + }, + }) + } + + if (avatarFile.length > 0) { + singleUpload(avatarFile[0], { + onSuccess: (response) => { + const avatarUrl = response?.data?.url || '' + submitCustomer(avatarUrl) + }, + onError: (error: ErrorType) => { + toast.error(extractErrorMessage(error, 'خطا در آپلود تصویر')) + }, + }) + } else { + submitCustomer() + } + }, + }) + return (

افزودن مشتری

-
-
-
-
-
- اطلاعات مشتری -
+
+
+
اطلاعات مشتری
-
- - -
+
+ + - -
+
+ + +
-
-
- { }} +
+ formik.setFieldValue('birthDate', date)} + /> + formik.setFieldValue('marriageDate', date)} + /> +
+ +
+ setAvatarFile(files)} + isReset={avatarFile.length === 0} + /> + + {avatarPreviewUrl && ( +
+ avatar preview
- { }} - /> -
-
- -
-
- آدرس -
- -
- -
- -
- -
- -
-