2026-01-12 17:12:02 +03:00

220 lines
6.0 KiB
Vue

<template>
<div class="card location-list-card">
<div class="card-header pb-0">
<div class="d-flex align-items-center">
<h6 class="mb-0">Liste des localisations</h6>
<soft-button
class="btn btn-primary btn-sm ms-auto"
@click="locationModalIsVisible = true"
>
<i class="fas fa-plus me-1"></i>Ajouter une localisation
</soft-button>
</div>
<location-modal
:is-visible="locationModalIsVisible"
:client-id="clientId"
:location-is-loading="isLoading"
:is-modification="isModification"
:location="selectedLocation"
@close="locationModalIsVisible = false"
@location-created="handleLocationCreated"
@location-modified="handleLocationModified"
/>
</div>
<div class="card-body location-list-body p-0">
<div v-if="locations.length > 0" class="table-responsive">
<table class="table align-items-center table-flush mb-0">
<thead>
<tr>
<th
class="text-uppercase text-secondary text-xxs font-weight-bolder opacity-7"
>
Nom
</th>
<th
class="text-uppercase text-secondary text-xxs font-weight-bolder opacity-7 ps-2"
>
Adresse
</th>
<th
class="text-uppercase text-secondary text-xxs font-weight-bolder opacity-7 ps-2"
>
GPS Latitude
</th>
<th
class="text-uppercase text-secondary text-xxs font-weight-bolder opacity-7 ps-2"
>
GPS Longitude
</th>
<th
class="text-uppercase text-secondary text-xxs font-weight-bolder opacity-7 text-center"
>
Actions
</th>
</tr>
</thead>
<tbody>
<tr v-for="location in locations" :key="location.id">
<td>
<div class="d-flex px-2 py-1">
<div>
<i class="fas fa-map-marker-alt text-primary me-2"></i>
</div>
<div class="d-flex flex-column justify-content-center">
<h6 class="mb-0 text-sm">{{ location.name || "-" }}</h6>
</div>
</div>
</td>
<td>
<p class="text-xs font-weight-bold mb-0">
{{ formatAddress(location) }}
</p>
</td>
<td>
<p class="text-xs font-weight-bold mb-0">
{{
location.gps_lat ? Number(location.gps_lat).toFixed(6) : "-"
}}
</p>
</td>
<td>
<p class="text-xs font-weight-bold mb-0">
{{
location.gps_lng ? Number(location.gps_lng).toFixed(6) : "-"
}}
</p>
</td>
<td class="align-middle text-center">
<div class="d-flex justify-content-center gap-2">
<button
class="btn btn-link text-warning p-0 mb-0"
type="button"
title="Modifier"
@click="handleModifyLocation(location)"
>
<i class="fas fa-edit text-sm"></i>
</button>
<button
class="btn btn-link text-danger p-0 mb-0"
type="button"
title="Supprimer"
@click="handleRemoveLocation(location.id)"
>
<i class="fas fa-trash text-sm"></i>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div v-else class="text-center py-5">
<i
class="fas fa-map-marked-alt fa-3x text-secondary opacity-5 mb-3"
></i>
<p class="text-sm text-secondary">Aucune localisation pour ce client</p>
</div>
</div>
</div>
</template>
<script setup>
import { defineProps, defineEmits, ref } from "vue";
import LocationModal from "../location/LocationModal.vue";
import SoftButton from "@/components/SoftButton.vue";
defineProps({
locations: {
type: Array,
default: () => [],
},
clientId: {
type: Number,
required: true,
},
isLoading: {
type: Boolean,
default: false,
},
});
const locationModalIsVisible = ref(false);
const isModification = ref(false);
const selectedLocation = ref(null);
const emit = defineEmits([
"location-created",
"location-modified",
"location-removed",
]);
const handleLocationModified = (modifiedLocation) => {
locationModalIsVisible.value = false;
emit("location-modified", modifiedLocation);
};
const handleLocationCreated = (newLocation) => {
locationModalIsVisible.value = false;
emit("location-created", newLocation);
};
const handleModifyLocation = (location) => {
selectedLocation.value = location;
isModification.value = true;
locationModalIsVisible.value = true;
};
const handleRemoveLocation = (locationId) => {
if (confirm("Êtes-vous sûr de vouloir supprimer cette localisation ?")) {
emit("location-removed", locationId);
}
};
const formatAddress = (location) => {
const parts = [
location.address.line1,
location.address.line2,
location.address.postal_code,
location.address.city,
].filter(Boolean);
return parts.length > 0 ? parts.join(", ") : "-";
};
</script>
<style scoped>
.location-list-card {
min-height: 500px;
}
.location-list-body {
overflow-y: auto;
}
.table-flush {
border-spacing: 0;
border-collapse: collapse;
}
.table-flush thead th {
border-bottom: 1px solid #e9ecef;
padding: 0.75rem 1rem;
}
.table-flush tbody tr {
border-bottom: 1px solid #e9ecef;
}
.table-flush tbody td {
padding: 0.75rem 1rem;
}
.btn-link:hover {
opacity: 0.8;
}
.gap-2 {
gap: 0.5rem;
}
</style>