|
|
@@ -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()
|
|
|
}
|
|
|
}
|