浏览代码

Moves structure identifier and adds password fields

Introduces structure identifier and password fields to the trial request form.

This allows users to set up their initial login credentials during the trial request process.
It also includes validation for both fields and displays related helper text.
Olivier Massot 5 月之前
父节点
当前提交
3a76d62380
共有 2 个文件被更改,包括 114 次插入39 次删除
  1. 113 39
      pages/shop/try/artist-premium.vue
  2. 1 0
      types/interface.d.ts

+ 113 - 39
pages/shop/try/artist-premium.vue

@@ -185,44 +185,6 @@
                   </v-col>
                 </v-row>
 
-                <!-- Structure identifier -->
-                <v-row>
-                  <v-col cols="12" md="6" class="mx-auto">
-                    <v-text-field
-                      v-model="trialRequest.structureIdentifier"
-                      :rules="[
-                        validateRequired,
-                        validateSubdomain,
-                        validateSubdomainAvailability,
-                      ]"
-                      label="Identifiant de la structure*"
-                      required
-                      class="text-center"
-                      @input="onStructureIdentifierUpdated"
-                    />
-                    <div class="validationMessage">
-                      <span v-if="validationPending">
-                        <v-progress-circular size="16" indeterminate />
-                        <i class="ml-2">Vérification en cours</i>
-                      </span>
-                      <span
-                        v-else-if="subdomainAvailable === true"
-                        class="text-success"
-                      >
-                        <v-icon>fa fa-check</v-icon>
-                        <i class="ml-2"> Cet identifiant est disponible</i>
-                      </span>
-                      <span
-                        v-else-if="subdomainAvailable === false"
-                        class="text-error"
-                      >
-                        <v-icon>fa fa-x</v-icon>
-                        <i class="ml-2">Cet identifiant n'est pas disponible</i>
-                      </span>
-                    </div>
-                  </v-col>
-                </v-row>
-
                 <h2 class="section-title">Représentée par</h2>
 
                 <!-- Representative function -->
@@ -280,6 +242,83 @@
                   </v-col>
                 </v-row>
 
+                <h2 class="section-title mb-6">Informations de connexion</h2>
+
+                <!-- Structure identifier -->
+                <v-row>
+                  <v-col cols="12" md="6" class="mx-auto">
+                    <v-text-field
+                      v-model="trialRequest.structureIdentifier"
+                      :rules="[
+                        validateRequired,
+                        validateSubdomain,
+                        validateSubdomainAvailability,
+                      ]"
+                      label="Identifiant de la structure*"
+                      required
+                      class="text-center"
+                      @input="onStructureIdentifierUpdated"
+                    />
+                    <div class="validationMessage">
+                      <span v-if="validationPending">
+                        <v-progress-circular size="16" indeterminate />
+                        <i class="ml-2">Vérification en cours</i>
+                      </span>
+                      <span
+                        v-else-if="subdomainAvailable === true"
+                        class="text-success"
+                      >
+                        <v-icon>fa fa-check</v-icon>
+                        <i class="ml-2"> Cet identifiant est disponible</i>
+                      </span>
+                      <span
+                        v-else-if="subdomainAvailable === false"
+                        class="text-error"
+                      >
+                        <v-icon>fa fa-x</v-icon>
+                        <i class="ml-2">Cet identifiant n'est pas disponible</i>
+                      </span>
+                    </div>
+                    <div class="mt-2">
+                      <i v-if="trialRequest.structureIdentifier">
+                        Le compte administrateur de la structure sera
+                        <strong>
+                          admin{{ trialRequest.structureIdentifier }}
+                        </strong>
+                      </i>
+                    </div>
+                    <div>
+                      <i>
+                        Veuillez renseigner un mot de passe pour ce compte :
+                      </i>
+                    </div>
+                  </v-col>
+                </v-row>
+
+                <!-- Password field -->
+                <v-row>
+                  <v-col cols="12" md="6" class="mx-auto">
+                    <v-text-field
+                      v-model="trialRequest.password"
+                      :rules="[validateRequired, validatePassword]"
+                      label="Mot de passe*"
+                      required
+                      :type="showPassword ? 'text' : 'password'"
+                      :append-inner-icon="
+                        showPassword ? 'fa fa-eye-slash' : 'fa fa-eye'
+                      "
+                      @click:append-inner="showPassword = !showPassword"
+                    />
+                    <div class="mt-1">
+                      <i>
+                        Le mot de passe doit contenir au moins 8 caractères, une
+                        minuscule, une majuscule, un chiffre et un caractère
+                        spécial.
+                      </i>
+                    </div>
+                  </v-col>
+                </v-row>
+
                 <h2 class="section-title">Accord de termes et conditions</h2>
 
                 <!-- Terms checkboxes -->
@@ -455,6 +494,7 @@ const trialRequest = reactive<TrialRequest>({
   representativeFunction: '',
   representativeEmail: '',
   representativePhone: '',
+  password: '',
   termsAccepted: false,
   legalRepresentative: false,
   newsletterSubscription: false,
@@ -480,6 +520,7 @@ const fillWithDummyData = () => {
   trialRequest.representativeFunction = 'Directeur Artistique'
   trialRequest.representativeEmail = 'jean.dupont@compagnie-test.fr'
   trialRequest.representativePhone = '0612345678'
+  trialRequest.password = 'Test1234!'
   trialRequest.termsAccepted = true
   trialRequest.legalRepresentative = true
   trialRequest.newsletterSubscription = true
@@ -547,6 +588,34 @@ const validateSiren = (siren: string) =>
 const validateCheckbox = (value: boolean) =>
   value || 'Vous devez accepter cette condition'
 
+const validatePassword = (password: string) => {
+  if (!password) return 'Ce champ est obligatoire'
+
+  const minLength = password.length >= 8
+  const hasLowercase = /[a-z]/.test(password)
+  const hasUppercase = /[A-Z]/.test(password)
+  const hasNumber = /[0-9]/.test(password)
+  const hasSpecial = /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(password)
+
+  if (!minLength) {
+    return 'Le mot de passe doit contenir au moins 8 caractères'
+  }
+  if (!hasLowercase) {
+    return 'Le mot de passe doit contenir au moins une lettre minuscule'
+  }
+  if (!hasUppercase) {
+    return 'Le mot de passe doit contenir au moins une lettre majuscule'
+  }
+  if (!hasNumber) {
+    return 'Le mot de passe doit contenir au moins un chiffre'
+  }
+  if (!hasSpecial) {
+    return 'Le mot de passe doit contenir au moins un caractère spécial'
+  }
+
+  return true
+}
+
 const validateSubdomain = (value: string) => {
   if (!value) return 'Ce champ est obligatoire'
 
@@ -566,6 +635,9 @@ const validateSubdomainAvailability = (value: string) => {
   )
 }
 
+// Password visibility toggle
+const showPassword = ref(false)
+
 // Form state
 const trialRequestSent: Ref<boolean> = ref(false)
 const errorMsg: Ref<string | null> = ref(null)
@@ -637,7 +709,9 @@ const submit = async (): Promise<void> => {
 // Event handler for structureName updates
 const onStructureNameUpdated = (newName: string) => {
   if (!structureIdentifierModified.value && newName) {
-    trialRequest.structureIdentifier = slugify(trialRequest.structureName)
+    trialRequest.structureIdentifier = slugify(
+      trialRequest.structureName
+    ).replace('-', '')
     checkSubdomainAvailabilityDebounced()
   }
 }

+ 1 - 0
types/interface.d.ts

@@ -200,6 +200,7 @@ interface TrialRequest {
   representativeFunction: string
   representativeEmail: string
   representativePhone: string
+  password: string
   termsAccepted: boolean
   legalRepresentative: boolean
   newsletterSubscription: boolean