diff --git a/.env b/.env index 52ebffc..5b59c6a 100644 --- a/.env +++ b/.env @@ -1,3 +1,3 @@ -VITE_API_BASE_URL = 'http://10.24.161.1:4000' +VITE_API_BASE_URL = 'http://192.168.99.221:4000' VITE_TOKEN_NAME = 'negareh_at' VITE_REFRESH_TOKEN_NAME = 'negareh_art' \ No newline at end of file diff --git a/src/components/Radio.tsx b/src/components/Radio.tsx new file mode 100644 index 0000000..6077733 --- /dev/null +++ b/src/components/Radio.tsx @@ -0,0 +1,20 @@ +import { type FC } from 'react' + +type Props = { + isActive: boolean, + value: string, + onChange: (value: string) => void +} + +const Radio: FC = (props: Props) => { + return ( +
props.onChange(props.value)} className='size-4 cursor-pointer rounded-full bg-[#EAEDF5] flex justify-center items-center'> + { + props.isActive && +
+ } +
+ ) +} + +export default Radio \ No newline at end of file diff --git a/src/components/RadioGroup.tsx b/src/components/RadioGroup.tsx new file mode 100644 index 0000000..bcb1d10 --- /dev/null +++ b/src/components/RadioGroup.tsx @@ -0,0 +1,31 @@ +import { type FC } from 'react' +import Radio from './Radio' + + +type Props = { + items: { + label: string + value: string + }[] + selected: string + onChange: (value: string) => void +} + +const RadioGroup: FC = (props: Props) => { + return ( +
+ { + props.items.map((item, index) => ( +
+ +
+ {item.label} +
+
+ )) + } +
+ ) +} + +export default RadioGroup \ No newline at end of file diff --git a/src/config/Paths.tsx b/src/config/Paths.tsx index 7b619e4..56cba94 100644 --- a/src/config/Paths.tsx +++ b/src/config/Paths.tsx @@ -28,7 +28,8 @@ export const Paths = { }, order: { list: '/order/list', - details: '/order/detail/' + details: '/order/detail/', + create: '/order/create' }, features: { list: '/features/list', diff --git a/src/pages/auth/Login.tsx b/src/pages/auth/Login.tsx index 88445cc..0ce6822 100644 --- a/src/pages/auth/Login.tsx +++ b/src/pages/auth/Login.tsx @@ -12,7 +12,7 @@ const Login: FC = () => { return (
-
+
diff --git a/src/pages/order/NewOrder.tsx b/src/pages/order/NewOrder.tsx new file mode 100644 index 0000000..07c343e --- /dev/null +++ b/src/pages/order/NewOrder.tsx @@ -0,0 +1,142 @@ +import { useState, type FC } from 'react' +import Order from './components/Order' +import Button from '@/components/Button' +import { TickSquare } from 'iconsax-react' +import { useOrderStore } from './store/OrderStore' +import { useCreateOrder } from './hooks/useOrderData' +import { toast } from '@/shared/toast' +import { useNavigate } from 'react-router-dom' +import { Paths } from '@/config/Paths' +import { extractErrorMessage } from '@/config/func' +import { useFormik } from 'formik' +import type { CreateBaseOrderType } from '../product/types/Types' +import { OrderStatusEnum } from './enum/OrderEnum' +import * as Yup from 'yup' +import Input from '@/components/Input' +import Select from '@/components/Select' +import { useGetUsers } from '../user/hooks/useUserData' + +const NewOrder: FC = () => { + + const navigate = useNavigate() + const { mutate: submitOrder, isPending } = useCreateOrder() + const { data: users } = useGetUsers() + const [showOrders, setShowOrders] = useState([0]) + const { items } = useOrderStore() + + const formik = useFormik({ + initialValues: { + enableTax: true, + estimatedDays: 0, + paymentMethod: '', + status: OrderStatusEnum.CREATED, + userId: '', + }, + validationSchema: Yup.object({ + userId: Yup.string().required('این فیلد اجباری می باشد.'), + estimatedDays: Yup.number().required('این فیلد اجباری می باشد.'), + paymentMethod: Yup.string().required('این فیلد اجباری می باشد.'), + }), + onSubmit: (values) => { + values.estimatedDays = Number(values.estimatedDays) + onSubmit(values) + } + }) + + const onSubmit = (values: CreateBaseOrderType) => { + if (items.length > 0) { + const params = { + ...values, + items: items + } + submitOrder(params, { + onSuccess: () => { + toast('سفارش با موفقیت ثبت شد', 'success') + navigate(Paths.order.list) + }, + onError: (error) => { + toast(extractErrorMessage(error), 'error') + } + }) + } else { + toast('حداقل یک سفارش باید اضافه کنید.', 'error') + } + } + + + return ( +
+
+

+ سفارش جدید +

+ +
+ +
+
اطلاعات اولیه
+ +
+ + + +
+ +
+ + { + return { + label: item, + value: item + } + })} + error_text={formik.errors.status && formik.touched.status ? formik.errors.status : ''} + /> +
+ +
+ + {showOrders.map((item) => { + return ( + setShowOrders([...showOrders, showOrders.length])} key={item} /> + ) + })} + +
+ ) +} + +export default NewOrder \ No newline at end of file diff --git a/src/pages/order/components/ManageAttribute.tsx b/src/pages/order/components/ManageAttribute.tsx new file mode 100644 index 0000000..8346d4a --- /dev/null +++ b/src/pages/order/components/ManageAttribute.tsx @@ -0,0 +1,135 @@ +import { type FC } from 'react' +import type { CreateOrderType } from '../types/Types' +import { clx } from '@/helpers/utils' +import Select from '@/components/Select' +import { Checkbox } from '@/components/ui/checkbox' +import RadioGroup from '@/components/RadioGroup' +import DatePickerComponent from '@/components/DatePicker' +import Input from '@/components/Input' +import Textarea from '@/components/Textarea' +import type { FormikProps } from 'formik' +import { FieldTypeEnum } from '@/pages/product/enum/Enum' +import type { FieldType } from '@/pages/product/types/Types' + +type Props = { + attributes?: FieldType[], + formik: FormikProps +} + +const ManageAttribute: FC = (props) => { + + const { attributes, formik } = props + + const handleChange = (attributeId: number, value: string) => { + const attribute = formik.values.attributes + const index: number = attribute.findIndex(o => o.attributeId === attributeId) + if (index > -1) { + attribute[index].value = value + } else { + attribute.push({ attributeId: attributeId, value: value }) + } + formik.setFieldValue('attributes', attribute) + } + + + return ( +
+ { + attributes?.map((item) => { + if (item?.type === FieldTypeEnum.select) + return ( +
+ handleChange(item.id, e.target.value)} + /> +
+ ) + else if (item.type === FieldTypeEnum.textarea) + return ( +
+