update
This commit is contained in:
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,10 +86,13 @@ 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)
|
||||||
|
.map(
|
||||||
|
(p: { quantity: number; price: number; active_price?: boolean }) => ({
|
||||||
quantity: parseFloat(String(p.quantity)),
|
quantity: parseFloat(String(p.quantity)),
|
||||||
price: parseFloat(String(p.price)),
|
price: parseFloat(String(p.price)),
|
||||||
|
active_price: p.active_price,
|
||||||
}),
|
}),
|
||||||
) || [],
|
) || [],
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-1
@@ -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",
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,9 +56,12 @@ export default function ProductDetailScreen() {
|
|||||||
const fixedProduct = {
|
const fixedProduct = {
|
||||||
...p,
|
...p,
|
||||||
prices:
|
prices:
|
||||||
p.prices?.map((pr: any) => ({
|
p.prices
|
||||||
|
?.filter((pr: any) => pr.active_price !== false)
|
||||||
|
.map((pr: any) => ({
|
||||||
quantity: parseFloat(String(pr.quantity)),
|
quantity: parseFloat(String(pr.quantity)),
|
||||||
price: parseFloat(String(pr.price)),
|
price: parseFloat(String(pr.price)),
|
||||||
|
active_price: pr.active_price,
|
||||||
})) || [],
|
})) || [],
|
||||||
};
|
};
|
||||||
setProduct(fixedProduct);
|
setProduct(fixedProduct);
|
||||||
|
|||||||
Reference in New Issue
Block a user