remodifier productDetails

This commit is contained in:
Nyavokevin 2025-11-03 14:57:45 +03:00
parent cfdbc11b1a
commit 18f9d83e5a
3 changed files with 1062 additions and 282 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,167 +1,12 @@
<template>
<div class="product-details-page">
<!-- Breadcrumbs -->
<div class="page-header">
<nav aria-label="breadcrumb" class="breadcrumbs-nav">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<router-link to="/stock">Stock</router-link>
</li>
<li class="breadcrumb-item">
<router-link to="/stock/produits">Produits</router-link>
</li>
<li class="breadcrumb-item active" aria-current="page">
{{ productData?.nom || "Chargement..." }}
</li>
</ol>
</nav>
<!-- Actions header -->
<div class="page-actions">
<soft-button type="outline" color="secondary" size="sm" @click="goBack">
<i class="fas fa-arrow-left me-2"></i>
Retour
</soft-button>
<soft-button
type="outline"
color="primary"
size="sm"
@click="editProduct"
>
<i class="fas fa-edit me-2"></i>
Modifier
</soft-button>
<soft-button
type="outline"
color="danger"
size="sm"
@click="deleteProduct"
:disabled="loading"
>
<i class="fas fa-trash me-2"></i>
Supprimer
</soft-button>
</div>
</div>
<!-- Loading state -->
<div v-if="loading" class="loading-container">
<div class="loading-spinner">
<i class="fas fa-spinner fa-spin fa-2x"></i>
<p>Chargement des informations du produit...</p>
</div>
</div>
<!-- Error state -->
<div v-else-if="error" class="error-container">
<div class="error-message">
<i class="fas fa-exclamation-triangle fa-2x text-danger mb-3"></i>
<h5>Erreur de chargement</h5>
<p>{{ error }}</p>
<soft-button
type="outline"
color="primary"
size="sm"
@click="loadProduct"
>
Réessayer
</soft-button>
</div>
</div>
<!-- Product details -->
<div v-else-if="productData" class="product-details-content">
<product-details-section
:product-data="productData"
@view-supplier="handleViewSupplier"
/>
</div>
<!-- Empty state -->
<div v-else class="empty-container">
<div class="empty-message">
<i class="fas fa-box fa-3x text-muted mb-3"></i>
<h5>Produit non trouvé</h5>
<p>Le produit demandé n'existe pas ou a été supprimé.</p>
<soft-button type="outline" color="primary" size="sm" @click="goBack">
Retour à la liste
</soft-button>
</div>
</div>
</div>
<product-details-presentation @view-supplier="handleViewSupplier" />
</template>
<script setup>
import { ref, onMounted, computed } from "vue";
import { useRoute, useRouter } from "vue-router";
import ProductDetailsSection from "@/components/Organism/Product/ProductDetailsSection.vue";
import SoftButton from "@/components/SoftButton.vue";
import ProductService from "@/services/product";
import { useProductStore } from "@/stores/productStore";
import ProductDetailsPresentation from "@/components/Organism/Stock/ProductDetailsPresentation.vue";
import { useRouter } from "vue-router";
const route = useRoute();
const router = useRouter();
const productStore = useProductStore();
const loading = ref(true);
const error = ref(null);
const productData = ref(null);
const productId = computed(() => {
return parseInt(route.params.id);
});
const loadProduct = async () => {
if (!productId.value) {
error.value = "ID de produit invalide";
loading.value = false;
return;
}
loading.value = true;
error.value = null;
try {
const response = await productStore.fetchProduct(productId.value);
productData.value = response;
} catch (err) {
console.error("Error loading product:", err);
error.value =
err.response?.data?.message || "Erreur lors du chargement du produit";
} finally {
loading.value = false;
}
};
const goBack = () => {
router.push("/stock/produits");
};
const editProduct = () => {
router.push({
name: "Modification produit",
params: {
id: productId.value,
},
});
};
const deleteProduct = async () => {
if (!confirm("Êtes-vous sûr de vouloir supprimer ce produit ?")) {
return;
}
try {
await ProductService.deleteProduct(productId.value);
// Show success message
router.push("/stock/produits");
} catch (err) {
console.error("Error deleting product:", err);
// Show error message
}
};
const handleViewSupplier = (supplier) => {
if (supplier && supplier.id) {
@ -173,128 +18,4 @@ const handleViewSupplier = (supplier) => {
});
}
};
onMounted(() => {
loadProduct();
});
</script>
<style scoped>
.product-details-page {
padding: 1.5rem;
background-color: #f8fafc;
min-height: calc(100vh - 60px);
}
.page-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 2rem;
padding: 1.5rem;
background-color: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 8px;
}
@media (max-width: 768px) {
.page-header {
flex-direction: column;
gap: 1rem;
align-items: stretch;
}
}
.breadcrumbs-nav {
margin-bottom: 0;
}
.breadcrumb {
list-style: none;
padding: 0;
margin: 0;
display: flex;
align-items: center;
gap: 0.5rem;
}
.breadcrumb-item {
color: #6b7280;
font-size: 0.875rem;
}
.breadcrumb-item:not(:last-child)::after {
content: "/";
margin-left: 0.5rem;
color: #d1d5db;
}
.breadcrumb-item a {
color: #3b82f6;
text-decoration: none;
}
.breadcrumb-item a:hover {
text-decoration: underline;
}
.breadcrumb-item.active {
color: #1f2937;
font-weight: 500;
}
.page-actions {
display: flex;
gap: 0.75rem;
flex-wrap: wrap;
}
.product-details-content {
background-color: transparent;
}
.loading-container,
.error-container,
.empty-container {
display: flex;
justify-content: center;
align-items: center;
min-height: 400px;
background-color: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 8px;
}
.loading-spinner,
.error-message,
.empty-message {
text-align: center;
padding: 2rem;
}
.loading-spinner i {
color: #3b82f6;
margin-bottom: 1rem;
}
.error-message i {
margin-bottom: 1rem;
}
.empty-message i {
color: #6b7280;
margin-bottom: 1rem;
}
.error-message h5,
.empty-message h5 {
color: #1f2937;
margin-bottom: 0.5rem;
}
.error-message p,
.empty-message p {
color: #6b7280;
margin-bottom: 1rem;
}
</style>