Création du composant MovieCommentForm, début de mise en place de la lofgique, a…
…vec rules de validation.
Showing
4 changed files
with
166 additions
and
3 deletions
components/form/MovieCommentForm.vue
0 → 100644
1 | +<script lang="ts" setup> | ||
2 | +import { useVuelidate } from "@vuelidate/core"; | ||
3 | +import { helpers, maxLength, minLength, required, minValue, maxValue } from "@vuelidate/validators"; | ||
4 | + | ||
5 | +// type FormData = { | ||
6 | +// username: string | ||
7 | +// message: string | ||
8 | +// rating: number | ||
9 | +// }; | ||
10 | + | ||
11 | +type FormData = { [key: string]: string|number }; | ||
12 | + | ||
13 | +//#region --Data/ref--. | ||
14 | +const initialState = { | ||
15 | + username: "", | ||
16 | + message: "", | ||
17 | + rating: 5, | ||
18 | +}; | ||
19 | + | ||
20 | +// Validation rules | ||
21 | +const rules = { | ||
22 | + username: { | ||
23 | + required: helpers.withMessage("Le nom d'utilisateur est requis", required), | ||
24 | + minLength: helpers.withMessage("Le nom d'utilisateur doit contenir au moins 3 caractères", minLength(3)), | ||
25 | + maxLength: helpers.withMessage("Le nom d'utilisateur ne peut pas dépasser 50 caractères", maxLength(50)), | ||
26 | + alpha: helpers.withMessage( | ||
27 | + "Le nom d'utilisateur ne peut contenir que des lettres", | ||
28 | + helpers.regex(/^[a-zA-ZÀ-ÿ\s]+$/), | ||
29 | + ), | ||
30 | + }, | ||
31 | + message: { | ||
32 | + required: helpers.withMessage("Le message est requis", required), | ||
33 | + minLength: helpers.withMessage("Le message doit contenir au moins 3 caractères", minLength(3)), | ||
34 | + maxLength: helpers.withMessage("Le message ne peut pas dépasser 500 caractères", maxLength(500)), | ||
35 | + }, | ||
36 | + rating:{ | ||
37 | + required: helpers.withMessage("La notation est requise", required), | ||
38 | + minValue: helpers.withMessage("Le message ne être inférieure à 0", minValue(0)), | ||
39 | + maxValue: helpers.withMessage("Le message ne être suppérieur à 10", maxValue(10)), | ||
40 | + } | ||
41 | +}; | ||
42 | + | ||
43 | +const formData = reactive({ | ||
44 | + ...initialState, | ||
45 | +}); | ||
46 | +const v$ = useVuelidate(rules, formData); | ||
47 | +//#endregion | ||
48 | + | ||
49 | +function submitComment() { | ||
50 | + console.log("Submit !") | ||
51 | +} | ||
52 | + | ||
53 | +function clear () { | ||
54 | + v$.value.$reset(); | ||
55 | + formData.username = initialState.username; | ||
56 | + formData.message = initialState.message; | ||
57 | + formData.rating = initialState.rating; | ||
58 | +} | ||
59 | + | ||
60 | +// :error-messages="getErrors('username', $v.username)" :counter="10" label="username" | ||
61 | +// :error-messages="getErrors('message', $v.message)" | ||
62 | +</script> | ||
63 | + | ||
64 | +<template> | ||
65 | + <section> | ||
66 | + movie comment form | ||
67 | + <VForm @submit.prevent="submitComment"> | ||
68 | + <v-text-field | ||
69 | + v-model="formData.username" | ||
70 | + :error-messages="v$.username.$errors.map(e => e.$message)" | ||
71 | + label="nom d'utilisateur" | ||
72 | + placeholder="nom d'utilisateur" | ||
73 | + required | ||
74 | + @blur="v$.username.$touch()" | ||
75 | + @input="v$.username.$touch()" | ||
76 | + /> | ||
77 | + <v-textarea | ||
78 | + v-model="formData.message" | ||
79 | + :error-messages="v$.message.$errors.map(e => e.$message)" | ||
80 | + label="message" | ||
81 | + placeholder="Saisissez votre commentaire" | ||
82 | + required | ||
83 | + @blur="v$.message.$touch" | ||
84 | + @input="v$.message.$touch" | ||
85 | + /> | ||
86 | + <v-text-field | ||
87 | + v-model="formData.rating" | ||
88 | + :error-messages="v$.rating.$errors.map(e => e.$message)" | ||
89 | + label="Note (1-10)" | ||
90 | + placeholder="" | ||
91 | + required | ||
92 | + type="number" | ||
93 | + @blur="v$.rating.$touch" | ||
94 | + @input="v$.rating.$touch" | ||
95 | + /> | ||
96 | + <v-btn class="mr-4">submit</v-btn> | ||
97 | + </VForm> | ||
98 | + </section> | ||
99 | +</template> | ||
100 | + | ||
101 | +<style scoped></style> |
@@ -17,6 +17,7 @@ | @@ -17,6 +17,7 @@ | ||
17 | "@nuxt/ui": "^2.22.0", | 17 | "@nuxt/ui": "^2.22.0", |
18 | "@pinia-orm/nuxt": "^1.10.2", | 18 | "@pinia-orm/nuxt": "^1.10.2", |
19 | "@pinia/nuxt": "^0.9.0", | 19 | "@pinia/nuxt": "^0.9.0", |
20 | + "@types/vuelidate": "^0.7.22", | ||
20 | "@unhead/vue": "^2.0.8", | 21 | "@unhead/vue": "^2.0.8", |
21 | "@vuelidate/core": "^2.0.3", | 22 | "@vuelidate/core": "^2.0.3", |
22 | "@vuelidate/validators": "^2.0.4", | 23 | "@vuelidate/validators": "^2.0.4", |
@@ -4636,6 +4637,64 @@ | @@ -4636,6 +4637,64 @@ | ||
4636 | "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", | 4637 | "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", |
4637 | "license": "MIT" | 4638 | "license": "MIT" |
4638 | }, | 4639 | }, |
4640 | + "node_modules/@types/vuelidate": { | ||
4641 | + "version": "0.7.22", | ||
4642 | + "resolved": "https://registry.npmjs.org/@types/vuelidate/-/vuelidate-0.7.22.tgz", | ||
4643 | + "integrity": "sha512-bD3pP9FgL3pxMVQ9NJ3d8BbV8Ij6xsrDKdCO4l1Wq/AksXxRRmQ9lmYjRJwn/hLMcgWO/k0QdULfZWpRz13adw==", | ||
4644 | + "license": "MIT", | ||
4645 | + "dependencies": { | ||
4646 | + "vue": "^2.7.15" | ||
4647 | + } | ||
4648 | + }, | ||
4649 | + "node_modules/@types/vuelidate/node_modules/@vue/compiler-sfc": { | ||
4650 | + "version": "2.7.16", | ||
4651 | + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.16.tgz", | ||
4652 | + "integrity": "sha512-KWhJ9k5nXuNtygPU7+t1rX6baZeqOYLEforUPjgNDBnLicfHCoi48H87Q8XyLZOrNNsmhuwKqtpDQWjEFe6Ekg==", | ||
4653 | + "dependencies": { | ||
4654 | + "@babel/parser": "^7.23.5", | ||
4655 | + "postcss": "^8.4.14", | ||
4656 | + "source-map": "^0.6.1" | ||
4657 | + }, | ||
4658 | + "optionalDependencies": { | ||
4659 | + "prettier": "^1.18.2 || ^2.0.0" | ||
4660 | + } | ||
4661 | + }, | ||
4662 | + "node_modules/@types/vuelidate/node_modules/prettier": { | ||
4663 | + "version": "2.8.8", | ||
4664 | + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", | ||
4665 | + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", | ||
4666 | + "license": "MIT", | ||
4667 | + "optional": true, | ||
4668 | + "bin": { | ||
4669 | + "prettier": "bin-prettier.js" | ||
4670 | + }, | ||
4671 | + "engines": { | ||
4672 | + "node": ">=10.13.0" | ||
4673 | + }, | ||
4674 | + "funding": { | ||
4675 | + "url": "https://github.com/prettier/prettier?sponsor=1" | ||
4676 | + } | ||
4677 | + }, | ||
4678 | + "node_modules/@types/vuelidate/node_modules/source-map": { | ||
4679 | + "version": "0.6.1", | ||
4680 | + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", | ||
4681 | + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", | ||
4682 | + "license": "BSD-3-Clause", | ||
4683 | + "engines": { | ||
4684 | + "node": ">=0.10.0" | ||
4685 | + } | ||
4686 | + }, | ||
4687 | + "node_modules/@types/vuelidate/node_modules/vue": { | ||
4688 | + "version": "2.7.16", | ||
4689 | + "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.16.tgz", | ||
4690 | + "integrity": "sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==", | ||
4691 | + "deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.", | ||
4692 | + "license": "MIT", | ||
4693 | + "dependencies": { | ||
4694 | + "@vue/compiler-sfc": "2.7.16", | ||
4695 | + "csstype": "^3.1.0" | ||
4696 | + } | ||
4697 | + }, | ||
4639 | "node_modules/@types/web-bluetooth": { | 4698 | "node_modules/@types/web-bluetooth": { |
4640 | "version": "0.0.21", | 4699 | "version": "0.0.21", |
4641 | "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", | 4700 | "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", |
@@ -23,6 +23,7 @@ | @@ -23,6 +23,7 @@ | ||
23 | "@nuxt/ui": "^2.22.0", | 23 | "@nuxt/ui": "^2.22.0", |
24 | "@pinia-orm/nuxt": "^1.10.2", | 24 | "@pinia-orm/nuxt": "^1.10.2", |
25 | "@pinia/nuxt": "^0.9.0", | 25 | "@pinia/nuxt": "^0.9.0", |
26 | + "@types/vuelidate": "^0.7.22", | ||
26 | "@unhead/vue": "^2.0.8", | 27 | "@unhead/vue": "^2.0.8", |
27 | "@vuelidate/core": "^2.0.3", | 28 | "@vuelidate/core": "^2.0.3", |
28 | "@vuelidate/validators": "^2.0.4", | 29 | "@vuelidate/validators": "^2.0.4", |
1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
2 | //#region --import--. | 2 | //#region --import--. |
3 | -import { ArrowLeftIcon, FilmIcon } from "lucide-vue-next"; | 3 | +import { ArrowLeftIcon } from "lucide-vue-next"; |
4 | import { useTMDB } from "~/composables/tMDB"; | 4 | import { useTMDB } from "~/composables/tMDB"; |
5 | import { computed, onMounted, ref } from "vue"; | 5 | import { computed, onMounted, ref } from "vue"; |
6 | import { Movie } from "~/models/movie"; | 6 | import { Movie } from "~/models/movie"; |
@@ -125,7 +125,7 @@ onMounted(() => { | @@ -125,7 +125,7 @@ onMounted(() => { | ||
125 | <!-- Contenu du film --> | 125 | <!-- Contenu du film --> |
126 | <div v-else-if="movie" class="relative"> | 126 | <div v-else-if="movie" class="relative"> |
127 | <!-- Backdrop image --> | 127 | <!-- Backdrop image --> |
128 | - <ui-components-backdrop-image v-if="movie.backdrop_path" :src="movie.poster_path" :title="movie.title" /> | 128 | + <ui-components-backdrop-image v-if="movie.backdrop_path" :src="movie.backdrop_path" :title="movie.title" /> |
129 | 129 | ||
130 | <!-- Contenu principal --> | 130 | <!-- Contenu principal --> |
131 | <div class="container mx-auto px-4 py-8 relative z-10 pt-20"> | 131 | <div class="container mx-auto px-4 py-8 relative z-10 pt-20"> |
@@ -170,12 +170,14 @@ onMounted(() => { | @@ -170,12 +170,14 @@ onMounted(() => { | ||
170 | <span class="font-semibold">Têtes d'affiche:</span> | 170 | <span class="font-semibold">Têtes d'affiche:</span> |
171 | {{ | 171 | {{ |
172 | movie.credit.cast | 172 | movie.credit.cast |
173 | - .slice(0, 5) | 173 | + .slice(0, 10) |
174 | .map((person) => person.name) | 174 | .map((person) => person.name) |
175 | .join(", ") | 175 | .join(", ") |
176 | }} | 176 | }} |
177 | </div> | 177 | </div> |
178 | </div> | 178 | </div> |
179 | + <!-- Comments form. --> | ||
180 | + <form-movie-comment-form /> | ||
179 | </section> | 181 | </section> |
180 | </div> | 182 | </div> |
181 | </div> | 183 | </div> |
-
Please register or login to post a comment