2026-01-28 14:26:20 +03:00

263 lines
7.0 KiB
Vue

<template>
<div class="card mt-4">
<div class="table-responsive">
<table id="commande-list" class="table table-flush">
<thead class="thead-light">
<tr>
<th>N° Commande</th>
<th>Date</th>
<th>Fournisseur</th>
<th>Statut</th>
<th>Montant TTC</th>
<th>Articles</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="commande in data" :key="commande.id">
<!-- N° Commande -->
<td>
<div class="d-flex align-items-center">
<soft-checkbox class="me-2" />
<p class="text-xs font-weight-bold ms-2 mb-0">
{{ commande.po_number || commande.number }}
</p>
</div>
</td>
<!-- Date -->
<td class="font-weight-bold">
<span class="my-2 text-xs">{{
formatDate(commande.order_date || commande.date)
}}</span>
</td>
<!-- Supplier -->
<td class="text-xs font-weight-bold">
<div class="d-flex align-items-center">
<soft-avatar
:img="getRandomAvatar()"
class="me-2"
size="xs"
alt="supplier image"
circular
/>
<span>{{ commande.fournisseur?.name || commande.supplier }}</span>
</div>
</td>
<!-- Status -->
<td class="text-xs font-weight-bold">
<div class="d-flex align-items-center">
<soft-button
:color="getStatusColor(commande.status)"
variant="outline"
class="btn-icon-only btn-rounded mb-0 me-2 btn-sm d-flex align-items-center justify-content-center"
>
<i
:class="getStatusIcon(commande.status)"
aria-hidden="true"
></i>
</soft-button>
<span>{{ getStatusLabel(commande.status) }}</span>
</div>
</td>
<!-- Amount -->
<td class="text-xs font-weight-bold">
<span class="my-2 text-xs">{{
formatCurrency(commande.total_ttc || commande.amount)
}}</span>
</td>
<!-- Items Count -->
<td class="text-xs font-weight-bold">
<span class="badge bg-secondary">{{ commande.lines?.length || commande.items_count || 0 }}</span>
</td>
<!-- Actions -->
<td class="text-xs font-weight-bold">
<div class="d-flex align-items-center">
<button
class="btn btn-link text-secondary mb-0 px-2"
:data-id="commande.id"
data-action="view"
title="Voir la commande"
>
<i class="fas fa-eye text-xs" aria-hidden="true"></i>
</button>
<button
class="btn btn-link text-danger mb-0 px-2"
:data-id="commande.id"
data-action="delete"
title="Supprimer la commande"
>
<i class="fas fa-trash text-xs" aria-hidden="true"></i>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script setup>
import {
ref,
onMounted,
watch,
onUnmounted,
defineProps,
defineEmits,
} from "vue";
import { DataTable } from "simple-datatables";
import SoftButton from "@/components/SoftButton.vue";
import SoftAvatar from "@/components/SoftAvatar.vue";
import SoftCheckbox from "@/components/SoftCheckbox.vue";
// Sample avatar images
import img1 from "@/assets/img/team-2.jpg";
import img2 from "@/assets/img/team-1.jpg";
import img3 from "@/assets/img/team-3.jpg";
import img4 from "@/assets/img/team-4.jpg";
import img5 from "@/assets/img/team-5.jpg";
import img6 from "@/assets/img/ivana-squares.jpg";
const avatarImages = [img1, img2, img3, img4, img5, img6];
const emit = defineEmits(["view", "delete"]);
const props = defineProps({
data: {
type: Array,
default: () => [],
},
loading: {
type: Boolean,
default: false,
},
});
const dataTableInstance = ref(null);
const getRandomAvatar = () => {
const randomIndex = Math.floor(Math.random() * avatarImages.length);
return avatarImages[randomIndex];
};
const formatDate = (dateString) => {
if (!dateString) return "-";
const options = {
day: "numeric",
month: "short",
year: "numeric",
};
return new Date(dateString).toLocaleDateString("fr-FR", options);
};
const formatCurrency = (value) => {
return new Intl.NumberFormat("fr-FR", {
style: "currency",
currency: "EUR",
}).format(value);
};
// Map status to colors and icons
const getStatusColor = (status) => {
const map = {
brouillon: "secondary",
confirmee: "info",
livree: "success",
facturee: "warning",
annulee: "danger",
};
return map[status] || "secondary";
};
const getStatusIcon = (status) => {
const map = {
brouillon: "fas fa-pen",
confirmee: "fas fa-check-circle",
livree: "fas fa-truck",
facturee: "fas fa-file-invoice-dollar",
annulee: "fas fa-ban",
};
return map[status] || "fas fa-info";
};
const getStatusLabel = (status) => {
const labels = {
brouillon: "Brouillon",
confirmee: "Confirmée",
livree: "Livrée",
facturee: "Facturée",
annulee: "Annulée",
};
return labels[status] || status;
};
const initializeDataTable = () => {
if (dataTableInstance.value) {
dataTableInstance.value.destroy();
dataTableInstance.value = null;
}
const dataTableEl = document.getElementById("commande-list");
if (dataTableEl) {
dataTableInstance.value = new DataTable(dataTableEl, {
searchable: true,
fixedHeight: false,
perPageSelect: false,
});
}
};
onMounted(() => {
if (!props.loading && props.data.length > 0) {
initializeDataTable();
}
// Event delegation
const table = document.getElementById("commande-list");
if (table) {
table.addEventListener("click", (event) => {
const btn = event.target.closest("button");
if (!btn) return;
const id = btn.getAttribute("data-id");
const action = btn.getAttribute("data-action");
if (id && action) {
if (action === "view") {
console.log("View commande:", id);
emit("view", parseInt(id));
} else if (action === "delete") {
console.log("Delete commande:", id);
emit("delete", parseInt(id));
}
}
});
}
});
watch(
() => props.data,
() => {
if (!props.loading) {
setTimeout(() => {
initializeDataTable();
}, 100);
}
},
{ deep: true }
);
onUnmounted(() => {
if (dataTableInstance.value) {
dataTableInstance.value.destroy();
}
});
</script>