311 lines
9.0 KiB
Vue

<template>
<div class="multisteps-form__panel" :class="isActive ? activeClass : ''">
<h6 class="mb-3 text-dark font-weight-bold">Informations du Défunt</h6>
<div class="row mb-4">
<div class="col-12 d-flex justify-content-center">
<div class="btn-group" role="group">
<input
id="modeNew"
type="radio"
class="btn-check"
name="deceasedMode"
autocomplete="off"
:checked="!formData.is_existing"
@change="
formData.is_existing = false;
formData.id = null;
"
/>
<label class="btn btn-outline-primary" for="modeNew"
>Nouveau Défunt</label
>
<input
id="modeSearch"
type="radio"
class="btn-check"
name="deceasedMode"
autocomplete="off"
:checked="formData.is_existing"
@change="formData.is_existing = true"
/>
<label class="btn btn-outline-primary" for="modeSearch"
>Rechercher</label
>
</div>
</div>
</div>
<!-- SEARCH MODE -->
<div v-if="formData.is_existing" class="row">
<div class="col-12 mb-3 position-relative">
<label class="form-label">Rechercher un défunt (Nom, Prénom)</label>
<div class="input-group">
<span class="input-group-text"><i class="fas fa-search"></i></span>
<input
v-model="searchQuery"
type="text"
class="form-control"
:class="{ 'is-invalid': hasError('deceased_id') }"
placeholder="Tapez pour rechercher..."
@input="handleSearchInput"
/>
<button
v-if="formData.id"
class="btn btn-outline-secondary"
type="button"
@click="clearSelection"
>
<i class="fas fa-times"></i>
</button>
</div>
<div
v-if="getFieldError('deceased_id')"
class="invalid-feedback d-block"
>
{{ getFieldError("deceased_id") }}
</div>
<!-- Dropdown Results -->
<div
v-if="showResults && searchResults.length"
class="list-group position-absolute w-100 shadow"
style="z-index: 1000; max-height: 200px; overflow-y: auto"
>
<button
v-for="deceased in searchResults"
:key="deceased.id"
type="button"
class="list-group-item list-group-item-action"
@click="selectDeceased(deceased)"
>
<div class="d-flex w-100 justify-content-between">
<h6 class="mb-1">
{{ deceased.first_name }} {{ deceased.last_name }}
</h6>
<small
>{{ deceased.birth_date }} - {{ deceased.death_date }}</small
>
</div>
</button>
</div>
<div
v-if="
showResults &&
searchResults.length === 0 &&
searchQuery.length >= 2 &&
!isSearching
"
class="list-group position-absolute w-100 shadow"
style="z-index: 1000"
>
<div class="list-group-item text-muted">Aucun résultat trouvé.</div>
</div>
</div>
<div v-if="formData.id" class="col-12">
<div class="alert alert-info">
<strong>Défunt sélectionné:</strong> {{ formData.first_name }}
{{ formData.last_name }}
</div>
</div>
</div>
<!-- CREATE MODE -->
<div v-else class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Prénom</label>
<input
v-model="formData.first_name"
type="text"
class="form-control"
:class="{ 'is-invalid': hasError('first_name') }"
placeholder="Prénom du défunt"
maxlength="191"
/>
<div v-if="getFieldError('first_name')" class="invalid-feedback">
{{ getFieldError("first_name") }}
</div>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Nom *</label>
<input
v-model="formData.last_name"
type="text"
class="form-control"
:class="{ 'is-invalid': hasError('last_name') }"
placeholder="Nom du défunt"
required
maxlength="191"
/>
<div v-if="getFieldError('last_name')" class="invalid-feedback">
{{ getFieldError("last_name") }}
</div>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Date de naissance</label>
<input
v-model="formData.birth_date"
type="date"
class="form-control"
:class="{ 'is-invalid': hasError('birth_date') }"
/>
<div v-if="getFieldError('birth_date')" class="invalid-feedback">
{{ getFieldError("birth_date") }}
</div>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Date de décès</label>
<input
v-model="formData.death_date"
type="date"
class="form-control"
:class="{ 'is-invalid': hasError('death_date') }"
/>
<div v-if="getFieldError('death_date')" class="invalid-feedback">
{{ getFieldError("death_date") }}
</div>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Lieu de décès</label>
<input
v-model="formData.place_of_death"
type="text"
class="form-control"
:class="{ 'is-invalid': hasError('place_of_death') }"
placeholder="Lieu de décès"
maxlength="255"
/>
<div v-if="getFieldError('place_of_death')" class="invalid-feedback">
{{ getFieldError("place_of_death") }}
</div>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Genre</label>
<select v-model="formData.gender" class="form-select">
<option value="">Sélectionner</option>
<option value="male">Homme</option>
<option value="female">Femme</option>
<option value="other">Autre</option>
</select>
</div>
<div class="col-md-12 mb-3">
<label class="form-label">Notes</label>
<textarea
v-model="formData.notes"
class="form-control"
:class="{ 'is-invalid': hasError('notes') }"
rows="3"
placeholder="Notes supplémentaires..."
></textarea>
<div v-if="getFieldError('notes')" class="invalid-feedback">
{{ getFieldError("notes") }}
</div>
</div>
</div>
<div class="d-flex justify-content-end mt-3">
<button
type="button"
class="btn bg-gradient-primary"
:disabled="validating"
@click="$emit('next')"
>
<span v-if="validating">
<i class="fas fa-spinner fa-spin me-2"></i>
Validation...
</span>
<span v-else>
Suivant
<i class="fas fa-arrow-right ms-2"></i>
</span>
</button>
</div>
</div>
</template>
<script setup>
import { defineProps, defineEmits, ref, watch } from "vue";
import DeceasedService from "@/services/deceased";
const props = defineProps({
formData: {
type: Object,
required: true,
},
isActive: {
type: Boolean,
default: false,
},
activeClass: {
type: String,
default: "js-active",
},
errors: {
type: Array,
default: () => [],
},
validating: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(["next"]);
// Search state
const searchQuery = ref("");
const searchResults = ref([]);
const isSearching = ref(false);
const showResults = ref(false);
// Debounce search
let searchTimeout;
const handleSearchInput = () => {
if (searchTimeout) clearTimeout(searchTimeout);
if (searchQuery.value.length < 2) {
searchResults.value = [];
showResults.value = false;
return;
}
isSearching.value = true;
searchTimeout = setTimeout(async () => {
try {
const results = await DeceasedService.searchDeceased(searchQuery.value);
searchResults.value = results;
showResults.value = true;
} catch (e) {
console.error("Search failed", e);
} finally {
isSearching.value = false;
}
}, 300);
};
const selectDeceased = (deceased) => {
props.formData.id = deceased.id;
props.formData.first_name = deceased.first_name;
props.formData.last_name = deceased.last_name;
searchQuery.value = `${deceased.first_name || ""} ${deceased.last_name}`;
showResults.value = false;
};
const clearSelection = () => {
props.formData.id = null;
searchQuery.value = "";
searchResults.value = [];
};
// Error helpers using props
const getFieldError = (field) => {
const error = props.errors.find((err) => err.field === field);
return error ? error.message : "";
};
const hasError = (field) => {
return props.errors.some((err) => err.field === field);
};
</script>