Compare commits
No commits in common. "39bb647b5ccba8d4631aa2cf58a9a06e277b89b1" and "e50187dea1351b234f87356c83096addb09bcb01" have entirely different histories.
39bb647b5c
...
e50187dea1
@ -4,19 +4,23 @@ import { z } from 'zod';
|
|||||||
import { requestTaylor } from '@/app/api-utlities/clients/taylor.client';
|
import { requestTaylor } from '@/app/api-utlities/clients/taylor.client';
|
||||||
import { createReviewMutation } from '@/app/api-utlities/requests/common';
|
import { createReviewMutation } from '@/app/api-utlities/requests/common';
|
||||||
|
|
||||||
import { reviewSchema } from '@/features/review-form/model/review-form.schema';
|
|
||||||
|
|
||||||
export const POST = async (req: NextRequest) => {
|
export const POST = async (req: NextRequest) => {
|
||||||
const body = await req.json();
|
const body = await req.json();
|
||||||
|
|
||||||
const validatedRequest = reviewSchema.parse(body);
|
const validatedRequest = z
|
||||||
|
.object({
|
||||||
|
name: z.string(),
|
||||||
|
text: z.string(),
|
||||||
|
rating: z.number().min(0).max(5),
|
||||||
|
})
|
||||||
|
.parse(body);
|
||||||
|
|
||||||
await requestTaylor(
|
await requestTaylor(
|
||||||
{ mutation: createReviewMutation },
|
{ mutation: createReviewMutation },
|
||||||
{
|
{
|
||||||
review: {
|
review: {
|
||||||
_name: validatedRequest.name,
|
_name: validatedRequest.name,
|
||||||
_otzyv: validatedRequest.reviewMessage,
|
_otzyv: validatedRequest.text,
|
||||||
_rejting: validatedRequest.rating,
|
_rejting: validatedRequest.rating,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -5,7 +5,7 @@ export const reviewSchema = z.object({
|
|||||||
.string()
|
.string()
|
||||||
.min(2, { message: 'Имя должно содержать не менее 2 символов' }),
|
.min(2, { message: 'Имя должно содержать не менее 2 символов' }),
|
||||||
rating: z.number().min(1, { message: 'Пожалуйста, выберите рейтинг' }).max(5),
|
rating: z.number().min(1, { message: 'Пожалуйста, выберите рейтинг' }).max(5),
|
||||||
reviewMessage: z
|
text: z
|
||||||
.string()
|
.string()
|
||||||
.min(10, { message: 'Отзыв должен содержать не менее 10 символов' }),
|
.min(10, { message: 'Отзыв должен содержать не менее 10 символов' }),
|
||||||
});
|
});
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import { useState } from 'react';
|
|||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
|
|
||||||
import { useTextController } from '@/shared/language';
|
|
||||||
import { Button } from '@/shared/shadcn-ui/button';
|
import { Button } from '@/shared/shadcn-ui/button';
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
@ -33,35 +32,45 @@ import { useCreateReviewMutation } from '../api/reviews.api';
|
|||||||
import { ReviewFormValues, reviewSchema } from '../model/review-form.schema';
|
import { ReviewFormValues, reviewSchema } from '../model/review-form.schema';
|
||||||
|
|
||||||
export function ReviewForm() {
|
export function ReviewForm() {
|
||||||
const { t } = useTextController();
|
|
||||||
const [openReviewFormDialog, setOpenReviewFormDialog] = useState(false);
|
const [openReviewFormDialog, setOpenReviewFormDialog] = useState(false);
|
||||||
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||||
const [hoveredStar, setHoveredStar] = useState(0);
|
const [hoveredStar, setHoveredStar] = useState(0);
|
||||||
|
|
||||||
const [createReview, { isLoading: isSubmitting }] = useCreateReviewMutation();
|
const [createReview] = useCreateReviewMutation();
|
||||||
|
|
||||||
const form = useForm<ReviewFormValues>({
|
const form = useForm<ReviewFormValues>({
|
||||||
resolver: zodResolver(reviewSchema),
|
resolver: zodResolver(reviewSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
name: '',
|
name: '',
|
||||||
rating: 0,
|
rating: 0,
|
||||||
reviewMessage: '',
|
text: '',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const onSubmit = async (data: ReviewFormValues) => {
|
const onSubmit = async (data: ReviewFormValues) => {
|
||||||
|
setIsSubmitting(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await createReview(data);
|
await createReview(data);
|
||||||
|
|
||||||
toast.success(t('about.review-form.dialog.successResponse'), {
|
toast.success(
|
||||||
|
'Спасибо за ваш отзыв! Он будет опубликован после модерации.',
|
||||||
|
{
|
||||||
duration: 5000,
|
duration: 5000,
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
form.reset();
|
form.reset();
|
||||||
setOpenReviewFormDialog(false);
|
setOpenReviewFormDialog(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toast.error(t('about.review-form.dialog.errorResponse'), {
|
toast.error(
|
||||||
|
'Произошла ошибка при отправке отзыва. Пожалуйста, попробуйте позже.',
|
||||||
|
{
|
||||||
duration: 5000,
|
duration: 5000,
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
setIsSubmitting(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -106,17 +115,17 @@ export function ReviewForm() {
|
|||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button className='flex shadow-lg transition-all duration-300 hover:scale-105'>
|
<Button className='flex shadow-lg transition-all duration-300 hover:scale-105'>
|
||||||
<Plus />
|
<Plus />
|
||||||
<span>{t('common.buttons.addReview')}</span>
|
<span>Добавить отзыв</span>
|
||||||
</Button>
|
</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent className='overflow-hidden rounded-xl border-none bg-white/95 p-0 shadow-xl backdrop-blur-sm sm:max-w-[500px]'>
|
<DialogContent className='overflow-hidden rounded-xl border-none bg-white/95 p-0 shadow-xl backdrop-blur-sm sm:max-w-[500px]'>
|
||||||
<div className='p-6'>
|
<div className='p-6'>
|
||||||
<DialogHeader className='pb-4'>
|
<DialogHeader className='pb-4'>
|
||||||
<DialogTitle className='text-center text-2xl font-bold'>
|
<DialogTitle className='text-center text-2xl font-bold'>
|
||||||
{t('about.review-form.dialog.title')}
|
Оставьте свой отзыв
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogDescription className='pt-2 text-center'>
|
<DialogDescription className='pt-2 text-center'>
|
||||||
{t('about.review-form.dialog.description')}
|
Поделитесь своим опытом с нашей компанией
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
@ -129,15 +138,11 @@ export function ReviewForm() {
|
|||||||
control={form.control}
|
control={form.control}
|
||||||
name='name'
|
name='name'
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className='flex flex-col'>
|
<FormItem>
|
||||||
<FormLabel>
|
<FormLabel>Ваше имя</FormLabel>
|
||||||
{t('about.review-form.dialog.field.name')}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t(
|
placeholder='Введите ваше имя'
|
||||||
'about.review-form.dialog.field.name.placeholder',
|
|
||||||
)}
|
|
||||||
{...field}
|
{...field}
|
||||||
className='bg-white/50'
|
className='bg-white/50'
|
||||||
/>
|
/>
|
||||||
@ -152,9 +157,7 @@ export function ReviewForm() {
|
|||||||
name='rating'
|
name='rating'
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className='space-y-3'>
|
<FormItem className='space-y-3'>
|
||||||
<FormLabel className='block'>
|
<FormLabel className='block'>Ваша оценка</FormLabel>
|
||||||
{t('about.review-form.dialog.field.rating')}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<StarRating
|
<StarRating
|
||||||
value={field.value}
|
value={field.value}
|
||||||
@ -168,23 +171,19 @@ export function ReviewForm() {
|
|||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name='reviewMessage'
|
name='text'
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className='flex flex-col'>
|
<FormItem>
|
||||||
<FormLabel>
|
<FormLabel>Ваш отзыв</FormLabel>
|
||||||
{t('about.review-form.dialog.field.reviewMessage')}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Textarea
|
<Textarea
|
||||||
placeholder={t(
|
placeholder='Расскажите о вашем опыте...'
|
||||||
'about.review-form.dialog.field.reviewMessage.placeholder',
|
|
||||||
)}
|
|
||||||
className='min-h-[120px] resize-none bg-white/50'
|
className='min-h-[120px] resize-none bg-white/50'
|
||||||
{...field}
|
{...field}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
{t('about.review-form.dialog.noteMessage')}
|
Ваш отзыв будет опубликован после модерации.
|
||||||
</FormDescription>
|
</FormDescription>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
@ -203,7 +202,7 @@ export function ReviewForm() {
|
|||||||
Отправка...
|
Отправка...
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
t('common.buttons.sendReview')
|
'Отправить отзыв'
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user