Add user management endpoints and link employees to existing users through `user_id`, including API resources, validation, repository support, and database migrations. Introduce a two-step login flow that checks email first and lets users without a password create one before signing in. Update the employee detail UI with a dedicated user tab and refresh the employee and intervention side navigation to support the new account management flow.
206 lines
5.1 KiB
Vue
206 lines
5.1 KiB
Vue
<template>
|
|
<div class="ed-content">
|
|
<div v-show="activeTab === 'overview'" class="ed-pane">
|
|
<EmployeeOverview
|
|
:employee="employee"
|
|
:formatted-hire-date="formattedHireDate"
|
|
:employee-id="employeeId"
|
|
@view-info-tab="$emit('change-tab', 'info')"
|
|
/>
|
|
</div>
|
|
|
|
<div v-show="activeTab === 'info'" class="ed-pane">
|
|
<EmployeeInfoTab :employee="employee" @employee-updated="updateEmployee" />
|
|
</div>
|
|
|
|
<div v-show="activeTab === 'user'" class="ed-pane">
|
|
<EmployeeUserTab
|
|
:employee="employee"
|
|
@employee-updated="updateEmployee"
|
|
@notify-success="$emit('notify-success', $event)"
|
|
@notify-error="$emit('notify-error', $event)"
|
|
/>
|
|
</div>
|
|
|
|
<div v-show="activeTab === 'documents'" class="ed-pane">
|
|
<EmployeeDocumentsTab
|
|
:documents="practitionerDocuments"
|
|
:employee-id="employee.id"
|
|
@document-created="handleCreateDocument"
|
|
@document-modified="handleModifiedDocument"
|
|
@document-removed="handleRemoveDocument"
|
|
/>
|
|
</div>
|
|
|
|
<div v-show="activeTab === 'practitioner' && practitioner" class="ed-pane">
|
|
<div class="ed-card">
|
|
<div class="ed-card__header">
|
|
<span class="ed-card__title">Informations praticien</span>
|
|
</div>
|
|
<div class="ed-card__body">
|
|
<div class="ed-grid">
|
|
<div class="ed-data">
|
|
<span class="ed-data__label">Numero de licence</span>
|
|
<strong class="ed-data__value">{{ practitioner?.license_number || 'Non renseigne' }}</strong>
|
|
</div>
|
|
<div class="ed-data">
|
|
<span class="ed-data__label">Numero d'autorisation</span>
|
|
<strong class="ed-data__value">{{ practitioner?.authorization_number || 'Non renseigne' }}</strong>
|
|
</div>
|
|
<div class="ed-data">
|
|
<span class="ed-data__label">Validite</span>
|
|
<strong class="ed-data__value">{{ formatDate(practitioner?.authorization_valid_until) }}</strong>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div v-show="activeTab === 'activity'" class="ed-pane">
|
|
<EmployeeActivityTab :employee="employee" />
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import EmployeeOverview from "@/components/molecules/employee/EmployeeOverview.vue";
|
|
import EmployeeInfoTab from "@/components/molecules/employee/EmployeeInfoTab.vue";
|
|
import EmployeeUserTab from "@/components/molecules/employee/EmployeeUserTab.vue";
|
|
import EmployeeDocumentsTab from "@/components/molecules/employee/EmployeeDocumentsTab.vue";
|
|
import { computed, defineProps, defineEmits } from "vue";
|
|
import EmployeeActivityTab from "@/components/molecules/employee/EmployeeActivityTab.vue";
|
|
|
|
const props = defineProps({
|
|
activeTab: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
employee: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
thanatopractitionerData: {
|
|
type: Object,
|
|
default: null,
|
|
},
|
|
practitionerDocuments: {
|
|
type: Array,
|
|
default: () => [],
|
|
},
|
|
formattedHireDate: {
|
|
type: String,
|
|
default: "",
|
|
},
|
|
employeeId: {
|
|
type: [Number, String],
|
|
required: true,
|
|
},
|
|
});
|
|
|
|
const practitioner = computed(
|
|
() => props.thanatopractitionerData || props.employee?.thanatopractitioner || null
|
|
);
|
|
|
|
const emit = defineEmits([
|
|
"change-tab",
|
|
"updating-employee",
|
|
"create-practitioner-document",
|
|
"updating-practitioner-document",
|
|
"remove-practitioner-document",
|
|
"notify-success",
|
|
"notify-error",
|
|
]);
|
|
|
|
const updateEmployee = (updatedEmployee) => {
|
|
emit("updating-employee", updatedEmployee);
|
|
};
|
|
|
|
const handleCreateDocument = (newDocument) => {
|
|
emit("create-practitioner-document", newDocument);
|
|
};
|
|
|
|
const handleModifiedDocument = (modifiedDocument) => {
|
|
emit("updating-practitioner-document", modifiedDocument);
|
|
};
|
|
|
|
const handleRemoveDocument = (documentId) => {
|
|
emit("remove-practitioner-document", documentId);
|
|
};
|
|
|
|
const formatDate = (dateString) => {
|
|
if (!dateString) return "Non renseignee";
|
|
const date = new Date(dateString);
|
|
return date.toLocaleDateString("fr-FR", {
|
|
year: "numeric",
|
|
month: "long",
|
|
day: "numeric",
|
|
});
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
.ed-content {
|
|
min-width: 0;
|
|
}
|
|
|
|
.ed-pane {
|
|
min-width: 0;
|
|
}
|
|
|
|
.ed-card {
|
|
background: #fff;
|
|
border: 1px solid rgba(131, 146, 171, 0.25);
|
|
border-radius: 10px;
|
|
overflow: hidden;
|
|
box-shadow: 0 6px 18px rgba(15, 23, 42, 0.05);
|
|
}
|
|
|
|
.ed-card__header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0.875rem 1.25rem;
|
|
border-bottom: 1px solid #f3f4f6;
|
|
}
|
|
|
|
.ed-card__title {
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
color: #8392ab;
|
|
}
|
|
|
|
.ed-card__body {
|
|
padding: 1.25rem;
|
|
}
|
|
|
|
.ed-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
|
gap: 1rem;
|
|
}
|
|
|
|
.ed-data {
|
|
padding: 1rem;
|
|
border-radius: 0.85rem;
|
|
background: #f8fafc;
|
|
border: 1px solid #eef2f7;
|
|
}
|
|
|
|
.ed-data__label {
|
|
display: block;
|
|
margin-bottom: 0.35rem;
|
|
font-size: 0.72rem;
|
|
font-weight: 700;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
color: #8392ab;
|
|
}
|
|
|
|
.ed-data__value {
|
|
color: #344767;
|
|
font-size: 0.95rem;
|
|
}
|
|
</style>
|