| Numéro du ticket | Titre du ticket | |------------------|-----------------| | | | ## Description de la PR ## Modification du .env ## Check list - [ ] Pas de régression - [ ] TU/TI/TF rédigée - [ ] TU/TI/TF OK - [ ] CHANGELOG modifié Reviewed-on: #46 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr>
318 lines
10 KiB
Vue
318 lines
10 KiB
Vue
<template>
|
|
<div class="flex justify-center">
|
|
<div class="w-[1348px]">
|
|
<div class="flex gap-3 mt-[46px]">
|
|
<MalioButtonIcon
|
|
icon="mdi:arrow-left-bold"
|
|
icon-size="24"
|
|
aria-label="Précédent"
|
|
variant="ghost"
|
|
/>
|
|
<h1 class="text-[32px] text-m-primary font-bold">Ajouter un client</h1>
|
|
</div>
|
|
<div class="mt-[48px] grid grid-cols-3 gap-x-[80px] gap-y-8">
|
|
<MalioInputText
|
|
label="Nom du client (Entreprise)"
|
|
/>
|
|
<MalioInputText
|
|
label="Nom du contact principal"
|
|
/>
|
|
<MalioInputText
|
|
label="Prénom du contact principal"
|
|
/>
|
|
<MalioSelectCheckbox
|
|
v-model="multiselectValue"
|
|
label="Catégorie"
|
|
:options="[
|
|
{label: 'Catégorie 1', value: 'Catégorie 1'},
|
|
{label: 'Catégorie 2', value: 'Catégorie 2'}
|
|
]"
|
|
/>
|
|
<MalioInputPhone
|
|
v-for="(_, index) in phones"
|
|
:key="index"
|
|
v-model="phones[index]"
|
|
label="Téléphone"
|
|
add-icon-name="mdi:plus"
|
|
:addable="phones.length === 1"
|
|
@add="addPhoneInput"
|
|
/>
|
|
<MalioInputEmail
|
|
label="Email"
|
|
/>
|
|
<MalioSelect
|
|
v-model="distributeur"
|
|
value=""
|
|
label="Distributeur / Courtier"
|
|
:options="[
|
|
{label: 'Dépend du distributeur', value: 'Dépend du distributeur'},
|
|
{label: 'Distributeur', value: 'Distributeur'},
|
|
{label: 'Courtier', value: 'Courtier'},
|
|
]"
|
|
/>
|
|
<MalioSelect
|
|
v-model="nomCourtier"
|
|
value=""
|
|
label="Nom du courtier"
|
|
:options="[
|
|
{label: 'Nom 1', value: 'Nom 1'}
|
|
]"
|
|
/>
|
|
<MalioSelect
|
|
v-model="nomDistributeur"
|
|
value=""
|
|
label="Nom du distributeur"
|
|
:options="[
|
|
{label: 'Nom 1', value: 'Nom 1'}
|
|
]"
|
|
/>
|
|
<MalioCheckbox label="Prestation de triage" groupClass="self-center"/>
|
|
</div>
|
|
|
|
<div class="mt-12 flex justify-center">
|
|
<MalioButton label="Valider" variant="primary"/>
|
|
</div>
|
|
<div class="mt-[60px]">
|
|
<MalioTabList :tabs="tabs" v-model="tabsValue">
|
|
<template #information>
|
|
<div class="grid grid-cols-3 gap-x-[80px] gap-y-8 mt-12 shadow-[0_4px_4px_0_rgba(0,0,0,0.25)] py-4 pl-[28px] pr-[60px]">
|
|
<MalioInputTextArea label="Descritpion" resize="none" groupClass="row-span-2" textInput="h-full"/>
|
|
<MalioInputText v-model="concurrent" label="Concurrent"/>
|
|
<MalioInputText label="Date création"/>
|
|
<MalioInputText label="Nombre de salariés" />
|
|
<MalioInputAmount label="CA"/>
|
|
<MalioInputText label="Dirigeant" />
|
|
<MalioInputText label="Résultat" />
|
|
</div>
|
|
<div class="mt-12 flex justify-center">
|
|
<MalioButton label="Valider" variant="primary"/>
|
|
</div>
|
|
</template>
|
|
<template #adresses>
|
|
<div class="relative grid grid-cols-3 gap-x-[80px] gap-y-8 mt-12 bg-white shadow-[0_4px_4px_0_rgba(0,0,0,0.25)] py-4 pl-[28px] pr-[60px]">
|
|
<MalioButtonIcon
|
|
icon="mdi:delete-outline"
|
|
aria-label="Supprimer l'adresse"
|
|
variant="ghost"
|
|
button-class="absolute top-3 right-3"
|
|
@click="onDeleteAdresse"
|
|
/>
|
|
<MalioCheckbox label="Prospect" groupClass="self-center"/>
|
|
<MalioCheckbox label="Adresse de livraison" groupClass="self-center"/>
|
|
<MalioCheckbox label="Facturation" groupClass="self-center"/>
|
|
<MalioSelectCheckbox
|
|
v-model="multiselectValue"
|
|
label="Catégorie"
|
|
:options="[
|
|
{label: 'Catégorie 1', value: 'Catégorie 1'},
|
|
{label: 'Catégorie 2', value: 'Catégorie 2'}
|
|
]"
|
|
/>
|
|
<MalioSelect
|
|
label="Pays"
|
|
v-model="pays"
|
|
:options="[
|
|
{label: 'France', value: 'France'},
|
|
{label: 'Espagne', value: 'Espagne'}
|
|
]"/>
|
|
<MalioInputText v-model="codePostal" label="Code postal" />
|
|
<MalioSelect
|
|
v-model="ville"
|
|
label="Ville"
|
|
:options="villeOptions"
|
|
:no-options-text="villeNoOptionsText"
|
|
/>
|
|
<MalioInputAutocomplete
|
|
v-model="adresse"
|
|
label="Adresse"
|
|
:options="adresseOptions"
|
|
:loading="adresseLoading"
|
|
:min-search-length="2"
|
|
:no-results-text="adresseNoResultsText"
|
|
:min-search-text="adresseMinSearchText"
|
|
@search="onSearchAdresse"
|
|
/>
|
|
<MalioInputText label="Adresse complémentaire"/>
|
|
<div class="flex justify-between">
|
|
<MalioCheckbox
|
|
v-for="dep in departements"
|
|
:key="dep"
|
|
v-model="departementsSelected[dep]"
|
|
:label="dep"
|
|
group-class="w-auto self-center"
|
|
/>
|
|
</div>
|
|
<MalioSelect label="Contact" :options="[]"/>
|
|
<MalioCheckbox label="Prestation de triage" groupClass="self-center"/>
|
|
</div>
|
|
<div class="mt-12 flex justify-center gap-6">
|
|
<MalioButton label="Nouvelle Adresse" variant="secondary" icon-name="mdi:add-bold" icon-position="left"/>
|
|
<MalioButton label="Valider" variant="primary"/>
|
|
</div>
|
|
</template>
|
|
</MalioTabList>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import {ref, computed, watch} from 'vue'
|
|
|
|
type Commune = {
|
|
nom: string
|
|
code: string
|
|
codesPostaux: string[]
|
|
}
|
|
|
|
type BanFeature = {
|
|
properties: {
|
|
label: string
|
|
id: string
|
|
name: string
|
|
housenumber?: string
|
|
street?: string
|
|
postcode: string
|
|
citycode: string
|
|
city: string
|
|
}
|
|
}
|
|
|
|
const multiselectValue = ref<Array<string | number>>([])
|
|
const distributeur = ref<string>('')
|
|
const phones = ref<string[]>([''])
|
|
const nomDistributeur = ref<string>('')
|
|
const nomCourtier = ref<string>('')
|
|
|
|
function addPhoneInput() {
|
|
phones.value.push('')
|
|
}
|
|
|
|
function onDeleteAdresse() {
|
|
console.log('Supprimer cette adresse')
|
|
}
|
|
|
|
const departements = ['86', '17', '82']
|
|
const departementsSelected = ref<Record<string, boolean>>({86: false, 17: false, 82: false})
|
|
|
|
const pays = ref<string>('France')
|
|
const codePostal = ref<string>('')
|
|
const ville = ref<string | number | null>(null)
|
|
const villeOptions = ref<Array<{label: string; value: string}>>([])
|
|
const villeLoading = ref(false)
|
|
|
|
const villeNoOptionsText = computed(() => {
|
|
if (villeLoading.value) return 'Chargement…'
|
|
if (!/^\d{5}$/.test(codePostal.value)) return 'Saisir un code postal (5 chiffres)'
|
|
return 'Aucune ville pour ce code postal'
|
|
})
|
|
|
|
let villeFetchId = 0
|
|
watch(codePostal, async (cp) => {
|
|
ville.value = null
|
|
villeOptions.value = []
|
|
adresse.value = null
|
|
adresseOptions.value = []
|
|
if (!/^\d{5}$/.test(cp)) {
|
|
villeLoading.value = false
|
|
return
|
|
}
|
|
const requestId = ++villeFetchId
|
|
villeLoading.value = true
|
|
try {
|
|
const response = await fetch(`https://geo.api.gouv.fr/communes?codePostal=${cp}`)
|
|
const data = await response.json() as Commune[]
|
|
if (requestId !== villeFetchId) return
|
|
villeOptions.value = data.map(c => ({label: c.nom, value: c.code}))
|
|
} catch (err) {
|
|
if (requestId !== villeFetchId) return
|
|
villeOptions.value = []
|
|
console.error('Erreur lors du chargement des villes', err)
|
|
} finally {
|
|
if (requestId === villeFetchId) villeLoading.value = false
|
|
}
|
|
})
|
|
|
|
const adresse = ref<string | number | null>(null)
|
|
const adresseOptions = ref<Array<{label: string; value: string}>>([])
|
|
const adresseLoading = ref(false)
|
|
|
|
const adresseMinSearchText = computed(() => {
|
|
if (!/^\d{5}$/.test(codePostal.value)) return 'Saisir d\'abord un code postal'
|
|
return 'Tapez au moins 3 caractères'
|
|
})
|
|
const adresseNoResultsText = computed(() => {
|
|
if (!/^\d{5}$/.test(codePostal.value)) return 'Saisir d\'abord un code postal'
|
|
return 'Aucune adresse trouvée'
|
|
})
|
|
|
|
let adresseFetchId = 0
|
|
const onSearchAdresse = async (query: string) => {
|
|
if (!/^\d{5}$/.test(codePostal.value) || query.length < 3) {
|
|
adresseOptions.value = []
|
|
adresseLoading.value = false
|
|
return
|
|
}
|
|
const requestId = ++adresseFetchId
|
|
adresseLoading.value = true
|
|
try {
|
|
const params = new URLSearchParams({
|
|
q: query,
|
|
postcode: codePostal.value,
|
|
type: 'housenumber',
|
|
})
|
|
const response = await fetch(`https://api-adresse.data.gouv.fr/search/?${params.toString()}`)
|
|
const data = await response.json() as {features: BanFeature[]}
|
|
if (requestId !== adresseFetchId) return
|
|
adresseOptions.value = data.features.map(f => ({
|
|
label: f.properties.name,
|
|
value: f.properties.name,
|
|
}))
|
|
} catch (err) {
|
|
if (requestId !== adresseFetchId) return
|
|
adresseOptions.value = []
|
|
console.error('Erreur lors du chargement des adresses', err)
|
|
} finally {
|
|
if (requestId === adresseFetchId) adresseLoading.value = false
|
|
}
|
|
}
|
|
|
|
const tabsValue = ref('information')
|
|
const concurrent = ref('')
|
|
|
|
const informationValid = computed(() => concurrent.value.trim().length > 0)
|
|
const adressesValid = computed(() => /^\d{5}$/.test(codePostal.value))
|
|
|
|
const tabs = computed(() => [
|
|
{
|
|
key: 'information',
|
|
label: 'Information',
|
|
icon: 'mdi:account-outline',
|
|
},
|
|
{
|
|
key: 'contacts',
|
|
label: 'Contacts',
|
|
icon: 'mdi:account-box-plus-outline',
|
|
disabled: !informationValid.value,
|
|
},
|
|
{
|
|
key: 'adresses',
|
|
label: 'Adresses',
|
|
icon: 'mdi:map-marker-outline',
|
|
disabled: !informationValid.value,
|
|
},
|
|
{
|
|
key: 'transport',
|
|
label: 'Transport',
|
|
icon: 'mdi:truck-delivery-outline',
|
|
disabled: !informationValid.value || !adressesValid.value,
|
|
},
|
|
{
|
|
key: 'comptabilité',
|
|
label: 'Comptabilité',
|
|
icon: 'mdi:bank-circle-outline',
|
|
disabled: !informationValid.value || !adressesValid.value,
|
|
},
|
|
])
|
|
</script>
|