manage attribute form

This commit is contained in:
hamid zarghami
2026-01-26 12:04:50 +03:30
parent d7efa70023
commit 3fb908936e
6 changed files with 282 additions and 6 deletions
+20
View File
@@ -0,0 +1,20 @@
import { type FC } from 'react'
type Props = {
isActive: boolean,
value: string,
onChange: (value: string) => void
}
const Radio: FC<Props> = (props: Props) => {
return (
<div onClick={() => props.onChange(props.value)} className='size-4 cursor-pointer rounded-full bg-[#EAEDF5] flex justify-center items-center'>
{
props.isActive &&
<div className='size-2 bg-black rounded-full'></div>
}
</div>
)
}
export default Radio
+31
View File
@@ -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: Props) => {
return (
<div className='flex xl:flex-nowrap flex-wrap gap-3 xl:gap-5 items-center text-xs'>
{
props.items.map((item, index) => (
<div key={index} className='flex gap-2 items-center'>
<Radio value={item.value} onChange={props.onChange} isActive={item.value === props.selected} />
<div className='mt-0.5 whitespace-nowrap'>
{item.label}
</div>
</div>
))
}
</div>
)
}
export default RadioGroup
@@ -0,0 +1,113 @@
import { type FC } from 'react'
import type { AttributeType } from '../type/Types'
import { clx } from '@/helpers/utils'
import { FieldTypeEnum } from '../enum/OrderEnum'
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'
type Props = {
attributes?: AttributeType[]
}
const ManageAttribute: FC<Props> = (props) => {
const { attributes } = props
return (
<div className={clx(
!attributes && 'hidden'
)}>
{
attributes?.map((item) => {
if (item?.type === FieldTypeEnum.select)
return (
<div className='mt-6' key={item.id}>
<Select
placeholder={`انتخاب ${item.isRequired ? '(اجباری)' : '(اختاری)'}`}
label={item.name}
items={item.values?.map((value) => {
return {
label: value.value,
value: value.value
}
})}
/>
</div>
)
else if (item.type === FieldTypeEnum.checkbox)
return (
<div key={item.id} className='mt-6'>
<div className='text-sm mb-3'>{item.name}</div>
<div className='flex gap-5 flex-wrap'>
{
item.values?.map((value) => {
return (
<div key={value.id} className='flex gap-2 items-center'>
<div>{value.value}</div>
<Checkbox
name={item.id + ''}
value={value.value}
onCheckedChange={(c) => console.log(c)}
/>
</div>
)
})
}
</div>
</div>
)
else if (item.type === FieldTypeEnum.radio)
return (
<div key={item.id} className='mt-6'>
<div className='text-sm mb-3'>{item.name}</div>
<RadioGroup
items={item.values?.map((value) => {
return {
label: value.value,
value: value.value
}
})}
onChange={(v) => console.log(v)}
selected=''
/>
</div>
)
else if (item.type === FieldTypeEnum.date)
return (
<div key={item.id} className='mt-6'>
<DatePickerComponent
onChange={(date) => console.log(date)}
placeholder=''
label={item.name}
/>
</div>
)
else if (item.type === FieldTypeEnum.number || item.type === FieldTypeEnum.text)
return (
<div key={item.id} className='mt-6'>
<Input
label={item.name}
type={item.type}
/>
</div>
)
else if (item.type === FieldTypeEnum.textarea)
return (
<div key={item.id} className='mt-6'>
<Textarea
label={item.name}
/>
</div>
)
})
}
</div>
)
}
export default ManageAttribute
+76 -6
View File
@@ -1,4 +1,4 @@
import { type FC } from 'react'
import { useState, type ChangeEvent, type FC } from 'react'
import Button from '@/components/Button'
import Input from '@/components/Input'
import Select from '@/components/Select'
@@ -7,26 +7,96 @@ import VoiceRecorder from '@/components/VoiceRecorder'
import { COLORS } from '@/constants/colors'
import { AddSquare } from 'iconsax-react'
import ProductsSelect from './ProductsSelect'
import { useFormik } from 'formik'
import * as Yup from 'yup'
import type { OrderType, ProductType } from '../type/Types'
import { useGetProducts } from '../hooks/useOrderData'
import ManageAttribute from './ManageAttribute'
const Order: FC = () => {
const { data } = useGetProducts()
const [productSelected, setProductSelected] = useState<ProductType>()
// const [attribute, setAttribute] = useState<AttributeType>()
const formik = useFormik<OrderType>({
initialValues: {
productId: 0,
attachments: [],
quantity: undefined,
description: '',
},
validationSchema: Yup.object({
}),
onSubmit: (values) => {
}
})
const handleChange = (e: ChangeEvent<HTMLSelectElement>) => {
const productId = e.target.value
const product = data?.data?.find(o => Number(o.id) === Number(productId))
if (product) {
product.quantities.unshift(0)
setProductSelected(product)
}
}
// const handleChangeAttribute = (e: ChangeEvent<HTMLSelectElement>) => {
// const attributeId = e.target.value
// const attribute = productSelected?.attributes?.find(o => Number(o.id) === Number(attributeId))
// if (attribute) {
// setAttribute(attribute)
// }
// }
return (
<div className='bg-white rounded-3xl p-6 mt-8'>
<div className='font-light'>اطلاعات سفارش</div>
<div className='mt-6'>
<ProductsSelect />
<div className='mt-6 rowTwoInput'>
<ProductsSelect
onChange={handleChange}
/>
{/* <Select
label='ویژگی'
placeholder='انتخاب'
items={productSelected?.attributes?.map((item) => {
return {
label: item.name,
value: item.id + ''
}
}) || []}
onChange={handleChangeAttribute}
/> */}
</div>
<div>
<ManageAttribute
attributes={productSelected?.attributes}
/>
</div>
<div className='mt-6 rowTwoInput'>
<Select
items={[]}
items={productSelected?.quantities?.map((item) => {
return {
label: item === 0 ? 'انتخاب دلخواه' : item + '',
value: item + ''
}
}) || []}
label='تعداد'
placeholder='انتخاب'
{...formik.getFieldProps('quantity')}
/>
<Input
label='انتخاب دلخواه'
placeholder='100'
label='تعداد دلخواه'
readOnly={Number(formik.values.quantity) !== 0}
{...formik.getFieldProps('quantity')}
type='number'
/>
</div>
+10
View File
@@ -5,3 +5,13 @@ export const enum TabMyOrdersEnum {
DELIVERED = "delivered",
CANCELLED = "cancelled",
}
export const enum FieldTypeEnum {
text = "text",
textarea = "textarea",
number = "number",
select = "select",
radio = "radio",
checkbox = "checkbox",
date = "date",
}
+32
View File
@@ -1,4 +1,5 @@
import type { BaseResponse } from "@/shared/types/Types";
import type { FieldTypeEnum } from "../enum/OrderEnum";
export type CategoryType = {
avatarUrl?: string;
@@ -10,6 +11,36 @@ export type CategoryType = {
title: string;
};
export type OrderType = {
productId: number;
quantity?: number;
// attributesValues: [],
attachments: {
url: string;
type: string;
}[];
description?: string;
};
export type AttributeValueType = {
attribute: number;
createdAt: string;
id: number;
order: number;
value: string;
};
export type AttributeType = {
createdAt: string;
id: number;
isRequired: boolean;
name: string;
order: number;
product: number;
type: FieldTypeEnum;
values: AttributeValueType[];
};
export type ProductType = {
category: CategoryType;
createdAt: string;
@@ -21,6 +52,7 @@ export type ProductType = {
order: number;
quantities: number[];
title: string;
attributes: AttributeType[];
};
export type ProductsResponseType = BaseResponse<ProductType[]>;