redhare-demo/components/forms/ProductsForm.jsx

290 lines
9.0 KiB
JavaScript

'use client'
import { useEffect, useState } from 'react'
import { SubmitHandler, useForm } from 'react-hook-form'
import { useGetDetailsQuery } from '@/store/services'
import { Tab } from '@headlessui/react'
import {
AddColors,
SelectCategories,
AddSizes,
Button,
TextField,
ImageList,
TextArea,
} from 'components'
const tabListNames = [
{ id: 0, name: '标题|介绍' },
{ id: 1, name: '图片' },
{ id: 2, name: '价格' },
{ id: 3, name: '分组' },
{ id: 4, name: '子产品' },
{ id: 5, name: '属性' },
{ id: 6, name: '规格' },
]
const initialSelectedCategories = {
levelOne: {},
levelTwo: {},
levelThree: {},
}
const ProductsForm = props => {
//? Props
const { mode, createHandler, isLoadingCreate, isLoadingUpdate, updateHandler, selectedProduct } =
props
//? States
const [isDetailsSkip, setIsDetailsSkip] = useState(true)
const [selectedCategories, setSelectedCategories] = useState(initialSelectedCategories)
//? Form Hook
const { handleSubmit, register, reset, control, getValues, watch, setValue } = useForm()
//? Queries
//* Get Details
const { data: details } = useGetDetailsQuery(
{
id: selectedCategories?.levelTwo?._id,
},
{ skip: isDetailsSkip }
)
//? Re-Renders
//* Select Category To Fetch Details
useEffect(() => {
if (selectedCategories?.levelThree?._id) {
setIsDetailsSkip(false)
}
}, [selectedCategories?.levelThree?._id])
//* Set Details
useEffect(() => {
if (details) {
setValue('info', details.data.info)
setValue('specification', details.data.specification)
setValue('optionsType', details.data.optionsType)
}
}, [details])
//* Set Product Details On Edit Mode
useEffect(() => {
if (selectedProduct && mode === 'edit') {
reset({ ...selectedProduct })
}
}, [selectedProduct])
//? Handlers
const editedCreateHandler = data => {
if (mode === 'create')
createHandler({
...data,
category: [
selectedCategories.levelOne?._id,
selectedCategories.levelTwo?._id,
selectedCategories.levelThree?._id,
],
category_levels: {
level_one: selectedCategories.levelOne?._id,
level_two: selectedCategories.levelTwo?._id,
Level_three: selectedCategories.levelThree?._id,
},
})
}
return (
<section className="p-3 md:px-3 xl:px-8 2xl:px-10">
<form
onSubmit={
mode === 'create' ? handleSubmit(editedCreateHandler) : handleSubmit(updateHandler)
}
className="space-y-10"
>
<Tab.Group>
<Tab.List className="flex space-x-1 rounded-xl bg-slate-200 p-1">
{tabListNames.map(item => (
<Tab
key={item.id}
className={({ selected }) =>
`tab
${
selected
? 'bg-white shadow'
: 'text-blue-400 hover:bg-white/[0.12] hover:text-blue-600'
}
`
}
>
{item.name}
</Tab>
))}
</Tab.List>
<Tab.Panels>
<Tab.Panel>
<TextField label="标题" name="title" control={control} />
<TextArea name="description" control={control} label="介绍" />
</Tab.Panel>
<Tab.Panel>
<ImageList control={control} />
</Tab.Panel>
<Tab.Panel>
<div className="space-y-4 md:flex md:gap-x-2 md:items-baseline md:justify-evenly">
<TextField
label="价格"
name="price"
control={control}
type="number"
inputMode="numeric"
/>
<TextField
label="存货"
name="inStock"
control={control}
type="number"
inputMode="numeric"
/>
<TextField
label="折扣百分比"
name="discount"
control={control}
type="number"
inputMode="numeric"
/>
</div>
</Tab.Panel>
<Tab.Panel>
{mode === 'create' && (
<SelectCategories
setSelectedCategories={setSelectedCategories}
selectedCategories={selectedCategories}
/>
)}
</Tab.Panel>
<Tab.Panel>
{isDetailsSkip && mode === 'create' && (
<span className="text-red-600">首先选择类别</span>
)}
{details?.data?.optionsType === 'colors' || getValues('colors')?.length > 0 ? (
<AddColors control={control} register={register} />
) : details?.data?.optionsType === 'sizes' || getValues('sizes')?.length > 0 ? (
<AddSizes control={control} register={register} />
) : details?.data?.optionsType === 'none' ? (
<span className="text-red-600">没有产品</span>
) : null}
</Tab.Panel>
<Tab.Panel>
{isDetailsSkip && mode === 'create' && (
<span className="text-red-600">首先选择类别</span>
)}
{watch('info') && (
<div className="text-sm space-y-1.5">
<span>属性</span>
<table className="w-full max-w-2xl mx-auto">
<thead className="bg-emerald-50 text-emerald-500">
<tr className="">
<th className="w-2/5 p-2.5">名称</th>
<th></th>
</tr>
</thead>
<tbody>
{watch('info').map((item, index) => (
<tr key={index} className="border-b-2 border-gray-100">
<td className="my-0.5 text-right">
<input
type="text"
className="text-field__input"
{...register(`info.${index}.title`)}
/>
</td>
<td className="p-2">
<textarea
rows={3}
className="text-field__input"
{...register(`info.${index}.value`)}
/>
</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</Tab.Panel>
<Tab.Panel>
{isDetailsSkip && mode === 'create' && (
<span className="text-red-600">首先选择类别</span>
)}
{watch('specification') && (
<div className="text-sm space-y-1.5">
<span>规格</span>
<table className="w-full max-w-2xl mx-auto">
<thead className="bg-fuchsia-50 text-fuchsia-500 ">
<tr>
<th className="w-2/5 p-2.5">名称</th>
<th></th>
</tr>
</thead>
<tbody>
{watch('specification').map((item, index) => (
<tr key={index} className="border-b-2 border-gray-100">
<td className="my-0.5 text-right">
<input
type="text"
className="text-field__input"
{...register(`specification.${index}.title`)}
/>
</td>
<td className="p-2">
<textarea
rows={3}
className="text-field__input"
{...register(`specification.${index}.value`)}
/>
</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</Tab.Panel>
</Tab.Panels>
</Tab.Group>
{mode === 'edit' ? (
<Button
className="mx-auto bg-amber-500"
isRounded
type="submit"
isLoading={isLoadingUpdate}
>
更新信息
</Button>
) : (
<Button
className="mx-auto bg-green-500"
isRounded
type="submit"
isLoading={isLoadingCreate}
>
提交信息
</Button>
)}
</form>
</section>
)
}
export default ProductsForm