MovieCommentForm.vue 4.15 KB
<script lang="ts" setup>
import type { Comment } from "~/type/commentForm";
// #region --Import--.
import { useVuelidate } from "@vuelidate/core";
import { helpers, maxLength, maxValue, minLength, minValue, required } from "@vuelidate/validators";
// #endregion

// #region --Props--.
withDefaults(defineProps<{
  isSubmitting?: boolean;
}>(), {
  isSubmitting: false,
});
// #endregion

// #region --Emit--.
const emit = defineEmits<{
  eventSubmit: [formData: any];
}>();
// #endregion

// #region --Data/ref--.
const initialState: Comment = {
  username: "",
  message: "",
  rating: 5,
};

// Validation rules
const rules = {
  username: {
    required: helpers.withMessage("Le nom d'utilisateur est requis", required),
    minLength: helpers.withMessage("Le nom d'utilisateur doit contenir au moins 3 caractères", minLength(3)),
    maxLength: helpers.withMessage("Le nom d'utilisateur ne peut pas dépasser 50 caractères", maxLength(50)),
    alpha: helpers.withMessage(
      "Le nom d'utilisateur ne peut contenir que des lettres",
      // eslint-disable-next-line regexp/no-obscure-range
      helpers.regex(/^[a-zA-ZÀ-ÿ\s]+$/),
    ),
  },
  message: {
    required: helpers.withMessage("Le message est requis", required),
    minLength: helpers.withMessage("Le message doit contenir au moins 3 caractères", minLength(3)),
    maxLength: helpers.withMessage("Le message ne peut pas dépasser 500 caractères", maxLength(500)),
  },
  rating: {
    required: helpers.withMessage("La notation est requise", required),
    minValue: helpers.withMessage("Le message ne être inférieure à 0", minValue(0)),
    maxValue: helpers.withMessage("Le message ne être suppérieur à 10", maxValue(10)),
  },
};

const formData = reactive({
  ...initialState,
});
const v$ = useVuelidate(rules, formData);
// #endregion

// const errormessages = computed(() => {
//   return v$.value.message.$errors.map((e) => e.$message);
// });

// #region --Function--.
async function submitComment() {
  emit("eventSubmit", formData);
}

function clear() {
  v$.value.$reset();
  formData.username = initialState.username;
  formData.message = initialState.message;
  formData.rating = initialState.rating;
}

function handleMessageEvent(event: string) {
  formData.message = event;
  // todo : revoir ici la validation manquante (dû au retour de TinyMCE).
  v$.value.message.$touch();
  // console.log(formData.message.replace(/<[^>]*>/g, ''));
  // console.log(formData.message.replace(/(&lt;([^&gt;]+)&gt;)/ig, ''));
}

// #endregion
</script>

<template>
  <section>
    <VForm>
      <v-text-field
        v-model="formData.username"
        :error-messages="v$.username.$errors.map((e) => e.$message) as readonly string[]"
        label="nom d'utilisateur"
        placeholder="nom d'utilisateur"
        required
        @blur="v$.username.$touch()"
        @input="v$.username.$touch()"
      />
      <v-text-field
        v-model="formData.rating"
        :error-messages="v$.rating.$errors.map((e) => e.$message) as readonly string[]"
        label="Note (1-10)"
        placeholder=""
        required
        type="number"
        @blur="v$.rating.$touch"
        @input="v$.rating.$touch"
      />
      <!--      <pre>{{ errormessages }}</pre> -->
      <ui-components-tiny-mce-field-editor
        :error-message="v$?.message?.$errors[0]?.$message ? (v$.message.$errors[0].$message as string) : ''"
        :model-value="formData.message"
        @update-model-value="handleMessageEvent"
      />
      <v-btn
        class="mt-6 mr-4"
        color="primary"
        @click="
          async () => {
            const validForm = await v$.$validate();
            if (validForm) submitComment();
          }
        "
      >
        <span
          v-if="isSubmitting"
          class="flex items-center justify-center"
        >
          <span class="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin mr-2" />
          Envoi en cours...
        </span>
        <span v-else>Publier le commentaire</span>
      </v-btn>
      <v-btn
        class="mt-6 mr-4"
        color="primary"
        @click="clear"
      >
        effacer
      </v-btn>
    </VForm>
  </section>
</template>

<style scoped></style>