Files
bewell-in-ua/components/(protected)/admin/product/create-edit-form.tsx
2025-02-07 08:34:42 +02:00

434 lines
13 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client'
import {zodResolver} from '@hookform/resolvers/zod'
import dynamic from 'next/dynamic'
import React, {useEffect, useMemo, useRef, useState} from 'react'
import {useFieldArray, useForm} from 'react-hook-form'
import toast from 'react-hot-toast'
import {z} from 'zod'
import {onProductCreateAction} from '@/actions/admin/product'
import {i18nDefaultLocale, i18nLocales} from '@/i18n-config'
import {BaseEditorConfig} from '@/lib/config/editor'
import {createProductFormSchema} from '@/lib/schemas/admin/product'
import {toEmptyParams} from '@/lib/utils'
import {Button} from '@/ui/button'
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage
} from '@/ui/form'
import {Input} from '@/ui/input'
import {Switch} from '@/ui/switch'
import {Tabs, TabsContent, TabsList, TabsTrigger} from '@/ui/tabs'
const JoditEditor = dynamic(() => import('jodit-react'), {ssr: false})
let localesValues = {
title: '',
shortTitle: '',
headingTitle: '',
description: '',
content: '',
instruction: ''
}
let metaValues = {
title: '',
description: '',
keywords: '',
author: ''
}
export default function ProductCreateEditForm({data}: {data?: any}) {
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
const [success, setSuccess] = useState('')
const [description0, setDescription0] = useState(
data?.locales[0].description || ''
)
const [description1, setDescription1] = useState(
data?.locales[1].description || ''
)
const [content0, setContent0] = useState(data?.locales[0].content || '')
const [content1, setContent1] = useState(data?.locales[1].content || '')
const [instruction0, setInstruction0] = useState(
data?.locales[0].instruction || ''
)
const [instruction1, setInstruction1] = useState(
data?.locales[1].instruction || ''
)
const editor = useRef(null) //declared a null value
const config = useMemo(() => BaseEditorConfig, [])
const form = useForm<z.infer<typeof createProductFormSchema>>({
resolver: zodResolver(createProductFormSchema),
mode: 'onBlur',
defaultValues: data
? (data => {
const {locales, meta} = data
return {
published: data.toStore[0].published,
price: data.toStore[0].price,
pricePromotional: data.toStore[0].pricePromotional,
image: data.image,
locales: toEmptyParams(locales) as any,
meta: meta
? (toEmptyParams(meta) as any)
: [{...metaValues}, {...metaValues}]
}
})(data)
: {
published: false,
price: '0',
pricePromotional: '0',
image: '',
locales: [
{lang: 'uk', ...localesValues},
{lang: 'ru', ...localesValues}
],
meta: [{...metaValues}, {...metaValues}]
}
})
const {register, setValue} = form
useEffect(() => {
register('locales.0.description')
register('locales.0.content')
register('locales.0.instruction')
register('locales.1.description')
register('locales.1.content')
register('locales.1.instruction')
}, [register])
const {fields: localeFields} = useFieldArray({
name: 'locales',
control: form.control
})
const {fields: metaFields} = useFieldArray({
name: 'meta',
control: form.control
})
console.log(form.formState.errors)
const onSubmit = async (values: z.infer<typeof createProductFormSchema>) => {
setLoading(true)
onProductCreateAction(values).then((res: any) => {
if (res?.error) {
setError(res?.error)
setSuccess('')
setLoading(false)
toast.error(res?.error)
} else {
setSuccess(res?.success as string)
setError('')
setLoading(false)
toast.success(res?.success)
}
})
}
return (
<Form {...form}>
<form
action=''
onSubmit={form.handleSubmit(onSubmit)}
className='bgs-grasy-50/50 mx-auto mb-8 min-w-[640px] max-w-[992px] flex-1 space-y-5 rounded-lg border p-4'
>
<div className='mx-auto my-4 w-full space-y-4'>
<h1 className='mb-6 text-center text-2xl font-bold text-brand-violet'>
ДОДАВАННЯ ТОВАРУ ДО БАЗИ
</h1>
<div className='my-4 space-y-4'>
<FormField
control={form.control}
name='published'
render={({field}) => (
<FormItem className='flex flex-row items-center justify-between rounded-lg border bg-gray-50 p-4'>
<div className='space-y-0.5'>
<FormLabel className='text-base'>Опублікувати</FormLabel>
<FormDescription>
Відразу після збереження буде розміщено на сайті
</FormDescription>
</div>
<FormControl>
<Switch
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
</FormItem>
)}
/>
<div className='flex flex-row items-center justify-between gap-4 rounded-lg border bg-gray-50 p-4'>
<div className='w-1/2'>
<FormField
control={form.control}
name='price'
render={({field}) => (
<FormItem className={'w-full'}>
<FormLabel>Ціна за одиницю товару</FormLabel>
<FormControl>
<Input type='text' placeholder='' {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<div className='w-1/2'>
<FormField
control={form.control}
name='pricePromotional'
render={({field}) => (
<FormItem className={'w-full'}>
<FormLabel>Акційна Ціна</FormLabel>
<FormControl>
<Input type='text' placeholder='' {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
</div>
<fieldset className='flex gap-4 rounded-lg border bg-gray-50 p-4'>
<FormField
control={form.control}
name='image'
render={({field}) => (
<FormItem className={'w-full'}>
<FormLabel>Головне зображення</FormLabel>
<FormControl>
<Input type='text' placeholder='' {...field} />
</FormControl>
<FormDescription>
Вкажіть шліх до зображення відносно публічної папки
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</fieldset>
</div>
<Tabs
defaultValue={i18nDefaultLocale}
className='min-h-[560px] rounded-lg border p-4'
>
<TabsList className='grid w-full grid-cols-2'>
{i18nLocales.map(locale => (
<TabsTrigger key={locale.icon} value={locale.code}>
{locale.nameUkr}
</TabsTrigger>
))}
</TabsList>
{localeFields.map((_, index) => (
<TabsContent
id={`form-tab-${form.getValues(`locales.${index}.lang`)}`}
value={form.getValues(`locales.${index}.lang`)}
key={index}
className='space-y-4'
>
<FormField
control={form.control}
key={index}
name={`locales.${index}.lang`}
render={({field}) => (
<FormItem className={'w-full'}>
{/*<FormLabel>Мова</FormLabel>*/}
<FormControl>
<Input type='hidden' placeholder='' {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<fieldset className='flex gap-4 rounded-lg border bg-gray-50 p-4'>
<div className='w-1/2'>
<FormField
control={form.control}
key={index + 1}
name={`locales.${index}.title`}
render={({field}) => (
<FormItem className={'w-full'}>
<FormLabel>Назва товару</FormLabel>
<FormControl>
<Input placeholder='' {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<div className='w-1/2'>
<FormField
control={form.control}
key={index + 2}
name={`locales.${index}.shortTitle`}
render={({field}) => (
<FormItem className={'w-full'}>
<FormLabel>Скорочена назва товару</FormLabel>
<FormControl>
<Input placeholder='' {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
</fieldset>
<fieldset className='rounded-lg border bg-gray-50 p-4'>
<FormField
control={form.control}
key={index + 3}
name={`locales.${index}.headingTitle`}
render={({field}) => (
<FormItem className={'w-full'}>
<FormLabel>
Назва товару у описі та коротка анотація
</FormLabel>
<FormControl>
<Input placeholder='' {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<JoditEditor
key={index + 4}
ref={editor}
config={config}
value={index === 0 ? description0 : description1}
className='mt-4 w-full'
onBlur={value => {
index === 0
? setDescription0(value)
: setDescription1(value)
setValue(`locales.${index}.description`, value)
}}
/>
</fieldset>
<fieldset className='rounded-lg border bg-gray-50 p-4'>
<FormLabel>Опис товару</FormLabel>
<JoditEditor
key={index + 5}
ref={editor}
config={config}
value={index === 0 ? content0 : content1}
className='mt-4 w-full'
onBlur={value => {
index === 0 ? setContent0(value) : setContent1(value)
setValue(`locales.${index}.content`, value)
}}
/>
</fieldset>
<fieldset className='rounded-lg border bg-gray-50 p-4'>
<FormLabel>Інструкція до товару</FormLabel>
<JoditEditor
key={index + 2125}
ref={editor}
config={config}
value={index === 0 ? instruction0 : instruction1}
className='mt-4 w-full'
onBlur={value => {
index === 0
? setInstruction0(value)
: setInstruction1(value)
setValue(`locales.${index}.instruction`, value)
}}
/>
</fieldset>
</TabsContent>
))}
{metaFields.map((_, index) => (
<TabsContent
id={`form-tab-${form.getValues(`locales.${index}.lang`)}`}
value={form.getValues(`locales.${index}.lang`)}
key={index}
className='space-y-4'
>
<fieldset className='rounded-lg border bg-gray-50 p-4'>
<legend className='rounded-lg border bg-gray-200 px-16 py-1 text-xl font-bold'>
META ДАНІ
</legend>
<FormField
control={form.control}
key={index + 'meta.title'}
name={`meta.${index}.title`}
render={({field}) => (
<FormItem className={'w-full'}>
<FormLabel>Назва</FormLabel>
<FormControl>
<Input type='text' placeholder='' {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
key={index + 'meta.description'}
name={`meta.${index}.description`}
render={({field}) => (
<FormItem className={'w-full'}>
<FormLabel>Опис</FormLabel>
<FormControl>
<Input type='text' placeholder='' {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
key={index + 'meta.keywords'}
name={`meta.${index}.keywords`}
render={({field}) => (
<FormItem className={'w-full'}>
<FormLabel>Ключові слова</FormLabel>
<FormControl>
<Input type='text' placeholder='' {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
key={index + 'meta.author'}
name={`meta.${index}.author`}
render={({field}) => (
<FormItem className={'w-full'}>
<FormLabel>Автор</FormLabel>
<FormControl>
<Input type='text' placeholder='' {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</fieldset>
</TabsContent>
))}
</Tabs>
</div>
<Button type='submit' className='!mt-0 w-full'>
Створити
</Button>
</form>
</Form>
)
}