update
This commit is contained in:
@@ -456,7 +456,7 @@ func GetAllProducts(c *gin.Context) {
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
products = filterActivePrices(products)
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"data": products,
|
||||
@@ -493,17 +493,16 @@ func GetProductsByCategory(c *gin.Context) {
|
||||
media, _ := database.GetMediaByProductID(products[i].ID)
|
||||
products[i].Media = media
|
||||
}
|
||||
|
||||
filteredProducts := filterActivePrices(products)
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"data": products,
|
||||
"count": len(products),
|
||||
"data": filteredProducts,
|
||||
"count": len(filteredProducts),
|
||||
})
|
||||
}
|
||||
|
||||
func GetProductByID(c *gin.Context) {
|
||||
database := c.MustGet("database").(*db.Database)
|
||||
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil || id <= 0 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
@@ -512,7 +511,6 @@ func GetProductByID(c *gin.Context) {
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
product, err := database.GetProductByID(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
@@ -521,11 +519,13 @@ func GetProductByID(c *gin.Context) {
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// ✅ Charger les médias
|
||||
media, _ := database.GetMediaByProductID(product.ID)
|
||||
product.Media = media
|
||||
|
||||
// ✅ Filtrer les prix désactivés
|
||||
filterActivepricesSingle(&product)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"data": product,
|
||||
@@ -563,6 +563,7 @@ func UpdateProduct(c *gin.Context) {
|
||||
Description string `json:"description"`
|
||||
Unit string `json:"unit"`
|
||||
Prices []models.ProductPrice `json:"prices"`
|
||||
Stock *float64 `json:"stock"`
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
updatedProduct, _ := database.GetProductByID(id)
|
||||
media, _ := database.GetMediaByProductID(id)
|
||||
@@ -1013,3 +1027,26 @@ func cleanFileName(name string) string {
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -366,6 +366,7 @@ export interface TrackingResponse {
|
||||
export interface ProductPrice {
|
||||
quantity: number;
|
||||
price: number;
|
||||
active_price?: boolean;
|
||||
}
|
||||
export interface Product {
|
||||
id: number;
|
||||
|
||||
@@ -70,10 +70,9 @@ function UserAccueil() {
|
||||
};
|
||||
|
||||
const getProductPrice = (product: Product): number => {
|
||||
if (!product.prices || product.prices.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
return product.prices[0]?.price || 0;
|
||||
const activePrices = product.prices?.filter(p => p.active_price !== false);
|
||||
if (!activePrices || activePrices.length === 0) return 0;
|
||||
return activePrices[0].price;
|
||||
};
|
||||
const hasProductVideo = (product: Product): boolean => {
|
||||
if (!product.media || product.media.length === 0) {
|
||||
@@ -210,7 +209,7 @@ function UserAccueil() {
|
||||
image={getProductImage(product)}
|
||||
stock={product.stock}
|
||||
category={product.category}
|
||||
prices={product.prices}
|
||||
prices={product.prices?.filter(p => p.active_price !== false)}
|
||||
hasVideo={hasProductVideo(product)}
|
||||
videoUrl={getProductVideoUrl(product)}
|
||||
categoryColor={
|
||||
|
||||
@@ -86,12 +86,15 @@ function ProductDetail() {
|
||||
const fixedProduct = {
|
||||
...response.data,
|
||||
prices:
|
||||
response.data.prices?.map(
|
||||
(p: { quantity: number; price: number }) => ({
|
||||
quantity: parseFloat(String(p.quantity)),
|
||||
price: parseFloat(String(p.price)),
|
||||
}),
|
||||
) || [],
|
||||
response.data.prices
|
||||
?.filter((p: { quantity: number; price: number; active_price?: boolean }) => p.active_price !== false)
|
||||
.map(
|
||||
(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);
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"expo": {
|
||||
"name": "Milieu Nantais",
|
||||
"slug": "frontend-client",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.2",
|
||||
"orientation": "portrait",
|
||||
"icon": "./assets/icon.png",
|
||||
"userInterfaceStyle": "dark",
|
||||
|
||||
@@ -356,6 +356,7 @@ export interface TrackingResponse {
|
||||
export interface ProductPrice {
|
||||
quantity: number;
|
||||
price: number;
|
||||
active_price?: boolean;
|
||||
}
|
||||
export interface Product {
|
||||
id: number;
|
||||
|
||||
@@ -48,7 +48,8 @@ export default function ProductCard({ product, onPress, categoryColor }: Product
|
||||
const { addToCart } = useCart();
|
||||
const catColor = categoryColor ?? colors.accent;
|
||||
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 videoMedia = product.media?.find((m) => m.type === "video");
|
||||
@@ -267,7 +268,7 @@ export default function ProductCard({ product, onPress, categoryColor }: Product
|
||||
style={styles.pickerScroll}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
{product.prices?.map((p) => (
|
||||
{activePrices.map((p) => (
|
||||
<TouchableOpacity
|
||||
key={p.quantity}
|
||||
style={[
|
||||
|
||||
@@ -56,10 +56,13 @@ export default function ProductDetailScreen() {
|
||||
const fixedProduct = {
|
||||
...p,
|
||||
prices:
|
||||
p.prices?.map((pr: any) => ({
|
||||
quantity: parseFloat(String(pr.quantity)),
|
||||
price: parseFloat(String(pr.price)),
|
||||
})) || [],
|
||||
p.prices
|
||||
?.filter((pr: any) => pr.active_price !== false)
|
||||
.map((pr: any) => ({
|
||||
quantity: parseFloat(String(pr.quantity)),
|
||||
price: parseFloat(String(pr.price)),
|
||||
active_price: pr.active_price,
|
||||
})) || [],
|
||||
};
|
||||
setProduct(fixedProduct);
|
||||
if (fixedProduct.prices.length > 0) {
|
||||
|
||||
Reference in New Issue
Block a user