210 lines
5.2 KiB
Vue
210 lines
5.2 KiB
Vue
<template>
|
|
<div class="card position-sticky top-1">
|
|
<!-- Defunt Profile Card -->
|
|
<div class="card-body text-center">
|
|
<div
|
|
class="avatar avatar-xl bg-gradient-dark border-radius-md d-flex align-items-center justify-content-center mx-auto mb-3"
|
|
>
|
|
<i class="fa fa-user text-white fa-2x"></i>
|
|
</div>
|
|
<h5 class="mb-1">{{ getFullName }}</h5>
|
|
<p class="text-xs text-secondary mb-2">
|
|
Âge au décès: {{ calculateAgeAtDeath }}
|
|
</p>
|
|
<div class="row text-center">
|
|
<div class="col-4">
|
|
<h6 class="mb-0 text-sm">{{ deceased?.documents_count || 0 }}</h6>
|
|
<p class="mb-0 text-xs text-secondary">Documents</p>
|
|
</div>
|
|
<div class="col-4">
|
|
<h6 class="mb-0 text-sm">{{ deceased?.interventions_count || 0 }}</h6>
|
|
<p class="mb-0 text-xs text-secondary">Interventions</p>
|
|
</div>
|
|
<div class="col-4">
|
|
<h6 class="mb-0 text-sm">{{ formatDate(deceased?.created_at) }}</h6>
|
|
<p class="mb-0 text-xs text-secondary">Créé le</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<hr class="horizontal dark my-3 mx-3" />
|
|
|
|
<!-- Quick Actions -->
|
|
<div class="card-body pt-0">
|
|
<h6 class="text-uppercase text-secondary text-xs font-weight-bolder mb-3">
|
|
Actions rapides
|
|
</h6>
|
|
<div class="d-grid gap-2">
|
|
<soft-button
|
|
color="primary"
|
|
variant="gradient"
|
|
class="btn-sm"
|
|
@click="$emit('create-intervention')"
|
|
>
|
|
<i class="fas fa-plus me-2"></i>
|
|
Nouvelle intervention
|
|
</soft-button>
|
|
<soft-button
|
|
color="secondary"
|
|
variant="outline"
|
|
class="btn-sm"
|
|
@click="$emit('edit-deceased')"
|
|
>
|
|
<i class="fas fa-edit me-2"></i>
|
|
Modifier
|
|
</soft-button>
|
|
</div>
|
|
</div>
|
|
|
|
<hr class="horizontal dark my-3 mx-3" />
|
|
|
|
<!-- Key Dates -->
|
|
<div class="card-body pt-0">
|
|
<h6 class="text-uppercase text-secondary text-xs font-weight-bolder mb-3">
|
|
Dates importantes
|
|
</h6>
|
|
<div class="timeline timeline-one-side">
|
|
<div class="timeline-block mb-3">
|
|
<span class="timeline-step">
|
|
<i class="fas fa-calendar-alt text-primary"></i>
|
|
</span>
|
|
<div class="timeline-content">
|
|
<h6 class="text-dark text-sm font-weight-bold mb-0">Naissance</h6>
|
|
<p class="text-secondary text-xs mb-0">
|
|
{{ formatDate(deceased?.birth_date) }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="timeline-block mb-0">
|
|
<span class="timeline-step">
|
|
<i class="fas fa-cross text-dark"></i>
|
|
</span>
|
|
<div class="timeline-content">
|
|
<h6 class="text-dark text-sm font-weight-bold mb-0">Décès</h6>
|
|
<p class="text-secondary text-xs mb-0">
|
|
{{ formatDate(deceased?.death_date) }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed } from "vue";
|
|
import { defineProps, defineEmits } from "vue";
|
|
import SoftButton from "@/components/SoftButton.vue";
|
|
|
|
const props = defineProps({
|
|
deceased: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
isLoading: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
});
|
|
|
|
defineEmits(["create-intervention", "edit-deceased"]);
|
|
|
|
const getFullName = computed(() => {
|
|
if (!props.deceased) return "Nom non renseigné";
|
|
const parts = [props.deceased.first_name, props.deceased.last_name].filter(
|
|
Boolean
|
|
);
|
|
return parts.join(" ") || "Nom non renseigné";
|
|
});
|
|
|
|
const calculateAgeAtDeath = computed(() => {
|
|
if (
|
|
!props.deceased ||
|
|
!props.deceased.birth_date ||
|
|
!props.deceased.death_date
|
|
) {
|
|
return "N/A";
|
|
}
|
|
|
|
const birthDate = new Date(props.deceased.birth_date);
|
|
const deathDate = new Date(props.deceased.death_date);
|
|
const age = deathDate.getFullYear() - birthDate.getFullYear();
|
|
|
|
// Adjust if birthday hasn't occurred yet in the year of death
|
|
const monthDiff = deathDate.getMonth() - birthDate.getMonth();
|
|
if (
|
|
monthDiff < 0 ||
|
|
(monthDiff === 0 && deathDate.getDate() < birthDate.getDate())
|
|
) {
|
|
return age - 1;
|
|
}
|
|
|
|
return age;
|
|
});
|
|
|
|
const formatDate = (dateString) => {
|
|
if (!dateString) return "Non renseignée";
|
|
|
|
const date = new Date(dateString);
|
|
return date.toLocaleDateString("fr-FR", {
|
|
day: "2-digit",
|
|
month: "2-digit",
|
|
year: "numeric",
|
|
});
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
.position-sticky {
|
|
top: 1rem;
|
|
}
|
|
|
|
.card {
|
|
border: 0;
|
|
box-shadow: 0 0 2rem 0 rgba(136, 152, 170, 0.15);
|
|
}
|
|
|
|
.avatar {
|
|
min-width: 80px;
|
|
min-height: 80px;
|
|
}
|
|
|
|
.timeline-one-side {
|
|
position: relative;
|
|
}
|
|
|
|
.timeline-block {
|
|
position: relative;
|
|
padding-left: 2.5rem;
|
|
}
|
|
|
|
.timeline-step {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0.25rem;
|
|
width: 1.5rem;
|
|
height: 1.5rem;
|
|
border-radius: 50%;
|
|
background: #fff;
|
|
border: 2px solid #dee2e6;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 0.75rem;
|
|
}
|
|
|
|
.timeline-content {
|
|
position: relative;
|
|
}
|
|
|
|
.timeline-block:not(:last-child)::before {
|
|
content: "";
|
|
position: absolute;
|
|
left: 0.75rem;
|
|
top: 2rem;
|
|
width: 2px;
|
|
height: calc(100% - 2rem);
|
|
background: #dee2e6;
|
|
}
|
|
</style>
|