remodifier productDetails
This commit is contained in:
parent
cfdbc11b1a
commit
18f9d83e5a
File diff suppressed because it is too large
Load Diff
@ -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>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user