This commit is contained in:
2026-05-15 16:45:56 +02:00
parent 921c861311
commit 04671637d2
8 changed files with 70 additions and 25 deletions
+44 -7
View File
@@ -456,7 +456,7 @@ func GetAllProducts(c *gin.Context) {
}) })
return return
} }
products = filterActivePrices(products)
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"success": true, "success": true,
"data": products, "data": products,
@@ -493,17 +493,16 @@ func GetProductsByCategory(c *gin.Context) {
media, _ := database.GetMediaByProductID(products[i].ID) media, _ := database.GetMediaByProductID(products[i].ID)
products[i].Media = media products[i].Media = media
} }
filteredProducts := filterActivePrices(products)
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"success": true, "success": true,
"data": products, "data": filteredProducts,
"count": len(products), "count": len(filteredProducts),
}) })
} }
func GetProductByID(c *gin.Context) { func GetProductByID(c *gin.Context) {
database := c.MustGet("database").(*db.Database) database := c.MustGet("database").(*db.Database)
id, err := strconv.Atoi(c.Param("id")) id, err := strconv.Atoi(c.Param("id"))
if err != nil || id <= 0 { if err != nil || id <= 0 {
c.JSON(http.StatusBadRequest, gin.H{ c.JSON(http.StatusBadRequest, gin.H{
@@ -512,7 +511,6 @@ func GetProductByID(c *gin.Context) {
}) })
return return
} }
product, err := database.GetProductByID(id) product, err := database.GetProductByID(id)
if err != nil { if err != nil {
c.JSON(http.StatusNotFound, gin.H{ c.JSON(http.StatusNotFound, gin.H{
@@ -521,11 +519,13 @@ func GetProductByID(c *gin.Context) {
}) })
return return
} }
// ✅ Charger les médias // ✅ Charger les médias
media, _ := database.GetMediaByProductID(product.ID) media, _ := database.GetMediaByProductID(product.ID)
product.Media = media product.Media = media
// ✅ Filtrer les prix désactivés
filterActivepricesSingle(&product)
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"success": true, "success": true,
"data": product, "data": product,
@@ -563,6 +563,7 @@ func UpdateProduct(c *gin.Context) {
Description string `json:"description"` Description string `json:"description"`
Unit string `json:"unit"` Unit string `json:"unit"`
Prices []models.ProductPrice `json:"prices"` Prices []models.ProductPrice `json:"prices"`
Stock *float64 `json:"stock"`
} }
if err := c.ShouldBindJSON(&updateData); err != nil { if err := c.ShouldBindJSON(&updateData); err != nil {
@@ -607,6 +608,13 @@ func UpdateProduct(c *gin.Context) {
} }
} }
if updateData.Stock != nil {
if err := validateStock(*updateData.Stock); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
}
log.Printf("🔄 [UpdateProduct] %s met à jour produit #%d", username, id) log.Printf("🔄 [UpdateProduct] %s met à jour produit #%d", username, id)
if err := database.UpdateProduct(id, updateData.Name, updateData.Category, updateData.Description, updateData.Unit, updateData.Prices); err != nil { if err := database.UpdateProduct(id, updateData.Name, updateData.Category, updateData.Description, updateData.Unit, updateData.Prices); err != nil {
@@ -615,6 +623,12 @@ func UpdateProduct(c *gin.Context) {
return return
} }
if updateData.Stock != nil {
if err := database.SetProductStock(id, *updateData.Stock); err != nil {
log.Printf("⚠️ [UpdateProduct] Erreur mise à jour stock: %v", err)
}
}
// ✅ RÉCUPÉRER LE PRODUIT MIS À JOUR // ✅ RÉCUPÉRER LE PRODUIT MIS À JOUR
updatedProduct, _ := database.GetProductByID(id) updatedProduct, _ := database.GetProductByID(id)
media, _ := database.GetMediaByProductID(id) media, _ := database.GetMediaByProductID(id)
@@ -1013,3 +1027,26 @@ func cleanFileName(name string) string {
return result return result
} }
func filterActivePrices(products []models.Product) []models.Product {
for i := range products {
activePrices := []models.ProductPrice{}
for _, p := range products[i].Prices {
if p.ActivePrice {
activePrices = append(activePrices, p)
}
}
products[i].Prices = activePrices
}
return products
}
func filterActivepricesSingle(product *models.Product) {
activePrices := []models.ProductPrice{}
for _, p := range product.Prices {
if p.ActivePrice {
activePrices = append(activePrices, p)
}
}
product.Prices = activePrices
}
+1
View File
@@ -366,6 +366,7 @@ export interface TrackingResponse {
export interface ProductPrice { export interface ProductPrice {
quantity: number; quantity: number;
price: number; price: number;
active_price?: boolean;
} }
export interface Product { export interface Product {
id: number; id: number;
+4 -5
View File
@@ -70,10 +70,9 @@ function UserAccueil() {
}; };
const getProductPrice = (product: Product): number => { const getProductPrice = (product: Product): number => {
if (!product.prices || product.prices.length === 0) { const activePrices = product.prices?.filter(p => p.active_price !== false);
return 0; if (!activePrices || activePrices.length === 0) return 0;
} return activePrices[0].price;
return product.prices[0]?.price || 0;
}; };
const hasProductVideo = (product: Product): boolean => { const hasProductVideo = (product: Product): boolean => {
if (!product.media || product.media.length === 0) { if (!product.media || product.media.length === 0) {
@@ -210,7 +209,7 @@ function UserAccueil() {
image={getProductImage(product)} image={getProductImage(product)}
stock={product.stock} stock={product.stock}
category={product.category} category={product.category}
prices={product.prices} prices={product.prices?.filter(p => p.active_price !== false)}
hasVideo={hasProductVideo(product)} hasVideo={hasProductVideo(product)}
videoUrl={getProductVideoUrl(product)} videoUrl={getProductVideoUrl(product)}
categoryColor={ categoryColor={
@@ -86,12 +86,15 @@ function ProductDetail() {
const fixedProduct = { const fixedProduct = {
...response.data, ...response.data,
prices: prices:
response.data.prices?.map( response.data.prices
(p: { quantity: number; price: number }) => ({ ?.filter((p: { quantity: number; price: number; active_price?: boolean }) => p.active_price !== false)
quantity: parseFloat(String(p.quantity)), .map(
price: parseFloat(String(p.price)), (p: { quantity: number; price: number; active_price?: boolean }) => ({
}), quantity: parseFloat(String(p.quantity)),
) || [], price: parseFloat(String(p.price)),
active_price: p.active_price,
}),
) || [],
}; };
setProduct(fixedProduct); setProduct(fixedProduct);
+1 -1
View File
@@ -2,7 +2,7 @@
"expo": { "expo": {
"name": "Milieu Nantais", "name": "Milieu Nantais",
"slug": "frontend-client", "slug": "frontend-client",
"version": "1.0.1", "version": "1.0.2",
"orientation": "portrait", "orientation": "portrait",
"icon": "./assets/icon.png", "icon": "./assets/icon.png",
"userInterfaceStyle": "dark", "userInterfaceStyle": "dark",
+1
View File
@@ -356,6 +356,7 @@ export interface TrackingResponse {
export interface ProductPrice { export interface ProductPrice {
quantity: number; quantity: number;
price: number; price: number;
active_price?: boolean;
} }
export interface Product { export interface Product {
id: number; id: number;
+3 -2
View File
@@ -48,7 +48,8 @@ export default function ProductCard({ product, onPress, categoryColor }: Product
const { addToCart } = useCart(); const { addToCart } = useCart();
const catColor = categoryColor ?? colors.accent; const catColor = categoryColor ?? colors.accent;
const isSoldOut = product.stock <= 0; const isSoldOut = product.stock <= 0;
const firstPrice = product.prices?.[0]?.price ?? null; const activePrices = product.prices?.filter((p) => p.active_price !== false) ?? [];
const firstPrice = activePrices[0]?.price ?? null;
const imageMedia = product.media?.find((m) => m.type === "image"); const imageMedia = product.media?.find((m) => m.type === "image");
const videoMedia = product.media?.find((m) => m.type === "video"); const videoMedia = product.media?.find((m) => m.type === "video");
@@ -267,7 +268,7 @@ export default function ProductCard({ product, onPress, categoryColor }: Product
style={styles.pickerScroll} style={styles.pickerScroll}
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
> >
{product.prices?.map((p) => ( {activePrices.map((p) => (
<TouchableOpacity <TouchableOpacity
key={p.quantity} key={p.quantity}
style={[ style={[
@@ -56,10 +56,13 @@ export default function ProductDetailScreen() {
const fixedProduct = { const fixedProduct = {
...p, ...p,
prices: prices:
p.prices?.map((pr: any) => ({ p.prices
quantity: parseFloat(String(pr.quantity)), ?.filter((pr: any) => pr.active_price !== false)
price: parseFloat(String(pr.price)), .map((pr: any) => ({
})) || [], quantity: parseFloat(String(pr.quantity)),
price: parseFloat(String(pr.price)),
active_price: pr.active_price,
})) || [],
}; };
setProduct(fixedProduct); setProduct(fixedProduct);
if (fixedProduct.prices.length > 0) { if (fixedProduct.prices.length > 0) {