-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFormFeedback.tsx
130 lines (121 loc) · 4.05 KB
/
FormFeedback.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import React, { useState } from 'react';
import { useMediaQuery } from '@mantine/hooks';
import { Button, Center, Title, Textarea, Text } from '@mantine/core';
import { useForm } from '@mantine/form';
import { zodResolver } from 'mantine-form-zod-resolver';
import { z } from 'zod';
import { StarLikeComponent } from '../starComponent/StarLikeComponent';
import useNotify, { NotifyDto } from '../../hooks/useNotify';
import { AuthStore, useAuthStore } from '../../store/useAuthStore';
import { TestimonialsController } from '../../services/BaseApi';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { AddTestimonialDto } from '@FullStackMap/from-a2b';
export const FormFeedback = () => {
const MAX_CHARS = 500;
const [charCount, setCharCount] = useState(0);
const isMobile = useMediaQuery('(max-width: 768px)');
const { SuccessNotify } = useNotify();
const queryClient = useQueryClient();
const userId: string | undefined = useAuthStore((s: AuthStore) => s.user?.Id);
const feedbackSchema = z.object({
feedBack: z
.string()
.min(10, 'Le commentaire doit contenir au moins 10 caractères')
.refine(
(value) => {
return !/\s{6,}/.test(value);
},
{
message:
'Le commentaire ne peut pas contenir plus de 5 espaces de suite',
path: ['feedBack'],
}
)
.refine((value) => /\S/.test(value), {
message:
'Le commentaire ne peut pas être vide ou contenir uniquement des espaces',
path: ['feedBack'],
}),
rate: z
.number()
.min(1, 'La note minimale est de 1')
.max(5, 'La note maximale est de 5'),
});
const feedbackForm = useForm({
validateInputOnChange: true,
initialValues: {
feedBack: '',
rate: 0,
testimonialDate: new Date().toISOString().split('T')[0],
},
validate: zodResolver(feedbackSchema),
});
const sendTestimonialMutation = useMutation({
mutationFn: async ([id, dto]: [string, AddTestimonialDto]) =>
await TestimonialsController.createTestimonialAsyncPOST(id, dto),
onSuccess: () => {
SuccessNotify({
title: 'Avis envoyé',
message: 'Votre avis a bien été envoyé, merci !',
autoClose: 5000,
} as NotifyDto);
feedbackForm.reset();
queryClient.invalidateQueries({ queryKey: ['testimonials'] });
},
});
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
if (!feedbackForm.isValid()) return;
sendTestimonialMutation.mutate([userId!, feedbackForm.values]);
};
const handleChangeRating = (rate: number) => {
feedbackForm.setValues({ ...feedbackForm.values, rate });
};
const handleCommentChange = (
event: React.ChangeEvent<HTMLTextAreaElement>
) => {
const feedBack = event.target.value;
setCharCount(feedBack.length);
if (feedBack.length > MAX_CHARS) {
event.target.value = feedBack.slice(0, MAX_CHARS);
setCharCount(MAX_CHARS);
}
feedbackForm.setFieldValue('feedBack', feedBack.slice(0, MAX_CHARS));
};
return (
<form onSubmit={handleSubmit}>
<Title order={2} mt={50} ta="center">
Laissez votre avis
</Title>
<Textarea
label="Votre commentaire"
minRows={4}
resize={!isMobile ? 'vertical' : 'none'}
required
placeholder='Ex: "J’ai adoré mon séjour, je recommande vivement !"'
{...feedbackForm.getInputProps('feedBack')}
onChange={handleCommentChange}
/>
<Text
size="sm"
mt="sm"
ta="end"
c={charCount > MAX_CHARS ? 'red' : undefined}>
{charCount} / {MAX_CHARS} caractères
</Text>
<Center mt="sm">
<StarLikeComponent ChangeRating={handleChangeRating} />
</Center>
<Center mt="xl">
<Button
type="submit"
loading={sendTestimonialMutation.isPending}
disabled={!feedbackForm.isValid()}
variant="filled"
mb="lg">
Envoyer
</Button>
</Center>
</form>
);
};