{categories.map((category) => (
>
);
diff --git a/frontend-prep/src/pages/User/Cart.tsx b/frontend-prep/src/pages/User/Cart.tsx
index 9774e171..2374bb7b 100644
--- a/frontend-prep/src/pages/User/Cart.tsx
+++ b/frontend-prep/src/pages/User/Cart.tsx
@@ -11,7 +11,7 @@ import { useCart } from "../../context/CartContext";
import Navbar from "../../components/Navbar";
import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
-import { isUserAuthenticated, getProductById } from "../../api/api";
+import { isUserAuthenticated, getProductById, getMediaUrl } from "../../api/api";
import type { Product } from "../../api/api";
import { Trash2, ShoppingBag, AlertTriangle } from "lucide-react";
import "./Cart.css";
@@ -111,7 +111,7 @@ function Cart() {
for (let i = 0; i < product.media.length; i++) {
const mediaItem = product.media[i];
if (mediaItem && mediaItem.type === "image" && mediaItem.url) {
- return `${mediaItem.url}`;
+ return getMediaUrl(mediaItem.url);
}
}
@@ -136,7 +136,7 @@ function Cart() {
(mediaItem) => mediaItem && mediaItem.type === "video",
);
- return videoMedia?.url ? `${videoMedia.url}` : undefined;
+ return videoMedia?.url ? getMediaUrl(videoMedia.url) : undefined;
};
// ============================================
diff --git a/frontend-prep/src/pages/User/OrderDetails.tsx b/frontend-prep/src/pages/User/OrderDetails.tsx
index 283892de..50bd06de 100644
--- a/frontend-prep/src/pages/User/OrderDetails.tsx
+++ b/frontend-prep/src/pages/User/OrderDetails.tsx
@@ -14,6 +14,7 @@ import {
getCommandItemsWithDetails,
isUserAuthenticated,
getProductById,
+ getMediaUrl,
} from "../../api/api";
import type { CompletedOrder, Product } from "../../api/api_types";
import {
@@ -117,7 +118,7 @@ function OrderDetails() {
for (let i = 0; i < product.media.length; i++) {
const mediaItem = product.media[i];
if (mediaItem && mediaItem.type === "image" && mediaItem.url) {
- return `${mediaItem.url}`;
+ return getMediaUrl(mediaItem.url);
}
}
@@ -142,7 +143,7 @@ function OrderDetails() {
(mediaItem) => mediaItem && mediaItem.type === "video",
);
- return videoMedia?.url ? `${videoMedia.url}` : undefined;
+ return videoMedia?.url ? getMediaUrl(videoMedia.url) : undefined;
};
// HANDLERS VIDÉO
diff --git a/frontend-prep/src/pages/User/ProductDetail.tsx b/frontend-prep/src/pages/User/ProductDetail.tsx
index e4e9eda6..10c4d5f7 100644
--- a/frontend-prep/src/pages/User/ProductDetail.tsx
+++ b/frontend-prep/src/pages/User/ProductDetail.tsx
@@ -148,7 +148,7 @@ function ProductDetail() {
// ✅ Toast de succès
setToast({
show: true,
- message: `${product.name} (${selectedGrams}g) ajouté au panier !`,
+ message: `${product.name} (${selectedGrams}${product.unit || "g"}) ajouté au panier !`,
type: "success",
});
};
@@ -214,7 +214,7 @@ function ProductDetail() {
{selectedPrice > 0 && (
{selectedPrice.toFixed(2)} €{" "}
- {selectedGrams && `pour ${selectedGrams}g`}
+ {selectedGrams && `pour ${selectedGrams}${product.unit || "g"}`}
)}
@@ -252,7 +252,7 @@ function ProductDetail() {
key={p.quantity}
value={p.quantity}
>
- {p.quantity}g -{" "}
+ {p.quantity}{product.unit || "g"} -{" "}
{p.price.toFixed(2)} €
))}
diff --git a/frontend-prep/src/pages/User/UserAccueil.css b/frontend-prep/src/pages/User/UserAccueil.css
index 5baffd00..e7b31807 100644
--- a/frontend-prep/src/pages/User/UserAccueil.css
+++ b/frontend-prep/src/pages/User/UserAccueil.css
@@ -1,319 +1,369 @@
-.user-page-container {
- width: 100%;
- min-height: 100vh;
- padding: clamp(1rem, 3vw, 1.5rem);
- padding-top: calc(60px + clamp(1rem, 3vw, 1.5rem));
- box-sizing: border-box;
- overflow-x: hidden;
- margin-top: 0;
- background-color: #1a1a1a;
+@font-face {
+ font-family: "Reach fill & Outline";
+ src:
+ url("/fonts/reach-fill-outline.woff2") format("woff2"),
+ url("/fonts/reach-fill-outline.woff") format("woff");
+ font-weight: normal;
+ font-style: normal;
+}
+
+.user-page-container {
+ width: 100%;
+ min-height: 100vh;
+ padding: clamp(1rem, 3vw, 1.5rem);
+ padding-top: calc(60px + clamp(1rem, 3vw, 1.5rem));
+ box-sizing: border-box;
+ overflow-x: hidden;
+ margin-top: 0;
+ background-color: #1a1a1a;
+ position: relative;
+}
+
+/* ===== COMING SOON OVERLAY (Gros&Semi) ===== */
+.coming-soon-overlay {
+ position: fixed;
+ inset: 0;
+ display: flex;
+ justify-content: center;
+ align-items: flex-end;
+ padding-bottom: 12vh;
+ pointer-events: none;
+ z-index: 10;
+}
+
+.coming-soon-text {
+ font-family: "Reach fill & Outline", sans-serif;
+ font-size: clamp(1.5rem, 8vw, 0rem);
+ font-weight: 400;
+ color: #8e8fe8;
+ letter-spacing: 4px;
+ text-align: center;
+ text-transform: uppercase;
+ text-shadow:
+ 0 0 10px rgba(142, 143, 232, 0.9),
+ 0 0 25px rgba(142, 143, 232, 0.6),
+ 0 0 50px rgba(142, 143, 232, 0.3);
+ animation: pulse-scale 2s ease-in-out infinite;
+}
+
+@keyframes pulse-scale {
+ 0%,
+ 100% {
+ transform: scale(1);
+ }
+ 50% {
+ transform: scale(1.35);
+ }
}
.category-filter {
- display: flex;
- gap: clamp(0.5rem, 2vw, 0.8rem);
- overflow-x: auto;
- padding-bottom: clamp(1rem, 3vw, 1.5rem);
- margin-bottom: clamp(1rem, 3vw, 1.5rem);
- scrollbar-width: none;
- -ms-overflow-style: none;
+ display: flex;
+ gap: clamp(0.5rem, 2vw, 0.8rem);
+ overflow-x: auto;
+ padding-bottom: clamp(1rem, 3vw, 1.5rem);
+ margin-bottom: clamp(1rem, 3vw, 1.5rem);
+ scrollbar-width: none;
+ -ms-overflow-style: none;
}
.category-filter::-webkit-scrollbar {
- display: none;
+ display: none;
}
.category-button {
- background-color: transparent;
- color: white;
- border: 2px solid rgba(255, 255, 255, 0.3);
- border-radius: 25px;
- padding: clamp(0.6rem, 2vw, 0.8rem) clamp(1.2rem, 3vw, 1.5rem);
- font-size: clamp(0.9rem, 3vw, 1rem);
- font-weight: 600;
- cursor: pointer;
- transition: all 0.3s ease;
- white-space: nowrap;
- -webkit-tap-highlight-color: transparent;
- flex-shrink: 0;
+ background-color: transparent;
+ color: white;
+ border: 2px solid rgba(255, 255, 255, 0.3);
+ border-radius: 25px;
+ padding: clamp(0.6rem, 2vw, 0.8rem) clamp(1.2rem, 3vw, 1.5rem);
+ font-size: clamp(0.9rem, 3vw, 1rem);
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ white-space: nowrap;
+ -webkit-tap-highlight-color: transparent;
+ flex-shrink: 0;
}
.category-button:active {
- transform: scale(0.95);
+ transform: scale(0.95);
}
.category-button.active {
- background-color: white;
- color: black;
- border-color: white;
+ background-color: white;
+ color: black;
+ border-color: white;
}
/* Effets néon par catégorie - BOUTONS */
.category-button.active[data-category="tous"] {
- background-color: #9333ea;
- color: white;
- border-color: #9333ea;
+ background-color: #9333ea;
+ color: white;
+ border-color: #9333ea;
}
.category-button.active[data-category="weed&hash"] {
- background-color: #10b981;
- color: white;
- border-color: #10b981;
+ background-color: #10b981;
+ color: white;
+ border-color: #10b981;
}
.category-button.active[data-category="zipette&co"] {
- background-color: #F5F5F0;
- color: black;
- border-color: #F5F5F0;
+ background-color: #f5f5f0;
+ color: black;
+ border-color: #f5f5f0;
}
.category-button.active[data-category="gros&semi"] {
- background-color: #3dc2f7;
- color: white;
- border-color: #3dc2f7;
-
+ background-color: #3dc2f7;
+ color: white;
+ border-color: #3dc2f7;
}
/* ===== CATEGORY HEADER ===== */
.category-header {
- margin-bottom: clamp(2rem, 5vw, 3rem);
- animation: headerFadeIn 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ margin-bottom: clamp(2rem, 5vw, 3rem);
+ animation: headerFadeIn 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
@keyframes headerFadeIn {
- from {
- opacity: 0;
- transform: translateY(-10px);
- }
- to {
- opacity: 1;
- transform: translateY(0);
- }
+ from {
+ opacity: 0;
+ transform: translateY(-10px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
}
.category-title {
- font-size: clamp(1.8rem, 5vw, 2.8rem);
- font-weight: 700;
- color: white;
- margin: 0 0 0.8rem 0;
- letter-spacing: -0.5px;
- background: linear-gradient(135deg, #ffffff 0%, rgba(255, 255, 255, 0.8) 100%);
- -webkit-background-clip: text;
- -webkit-text-fill-color: transparent;
- background-clip: text;
+ font-size: clamp(1.8rem, 5vw, 2.8rem);
+ font-weight: 700;
+ color: white;
+ margin: 0 0 0.8rem 0;
+ letter-spacing: -0.5px;
+ background: linear-gradient(
+ 135deg,
+ #ffffff 0%,
+ rgba(255, 255, 255, 0.8) 100%
+ );
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
}
.category-subtitle {
- font-size: clamp(0.95rem, 3vw, 1.1rem);
- color: rgba(255, 255, 255, 0.65);
- margin: 0;
- font-weight: 400;
- letter-spacing: 0.3px;
- line-height: 1.5;
+ font-size: clamp(0.95rem, 3vw, 1.1rem);
+ color: rgba(255, 255, 255, 0.65);
+ margin: 0;
+ font-weight: 400;
+ letter-spacing: 0.3px;
+ line-height: 1.5;
}
/* Carrousel de produits - un produit à la fois */
.products-grid {
- display: flex;
- overflow-x: auto;
- scroll-snap-type: x mandatory;
- gap: clamp(1rem, 3vw, 1.5rem);
- width: 100%;
- max-width: 1200px;
- padding: 0 clamp(1rem, 3vw, 1.5rem);
- padding-bottom: 1rem;
- scrollbar-width: none;
- -ms-overflow-style: none;
- -webkit-overflow-scrolling: touch;
+ display: flex;
+ overflow-x: auto;
+ scroll-snap-type: x mandatory;
+ gap: clamp(1rem, 3vw, 1.5rem);
+ width: 100%;
+ max-width: 1200px;
+ padding: 0 clamp(1rem, 3vw, 1.5rem);
+ padding-bottom: 1rem;
+ scrollbar-width: none;
+ -ms-overflow-style: none;
+ -webkit-overflow-scrolling: touch;
}
.products-grid::-webkit-scrollbar {
- display: none;
+ display: none;
}
.products-grid > * {
- flex: 0 0 calc(100% - clamp(2rem, 6vw, 3rem));
- scroll-snap-align: center;
- scroll-snap-stop: always;
+ flex: 0 0 calc(100% - clamp(2rem, 6vw, 3rem));
+ scroll-snap-align: center;
+ scroll-snap-stop: always;
}
/* Effets néon par catégorie - CONTAINERS DE PRODUITS */
/* Catégorie: tous - VIOLET - Effet néon amélioré */
.products-grid > div[data-category="tous"] .product-card {
- border: 2px solid #9333ea;
- box-shadow:
- 0 0 20px rgba(147, 51, 234, 0.6),
- 0 0 40px rgba(147, 51, 234, 0.4),
- 0 0 60px rgba(147, 51, 234, 0.2),
- 0 0 80px rgba(147, 51, 234, 0.1);
+ border: 2px solid #9333ea;
+ box-shadow:
+ 0 0 20px rgba(147, 51, 234, 0.6),
+ 0 0 40px rgba(147, 51, 234, 0.4),
+ 0 0 60px rgba(147, 51, 234, 0.2),
+ 0 0 80px rgba(147, 51, 234, 0.1);
}
/* Catégorie: weed&hash - VERT - Effet néon amélioré */
.products-grid > div[data-category="weed&hash"] .product-card {
- border: 2px solid #10b981;
- box-shadow:
- 0 0 20px rgba(16, 185, 129, 0.6),
- 0 0 40px rgba(16, 185, 129, 0.4),
- 0 0 60px rgba(16, 185, 129, 0.2),
- 0 0 80px rgba(16, 185, 129, 0.1);
+ border: 2px solid #10b981;
+ box-shadow:
+ 0 0 20px rgba(16, 185, 129, 0.6),
+ 0 0 40px rgba(16, 185, 129, 0.4),
+ 0 0 60px rgba(16, 185, 129, 0.2),
+ 0 0 80px rgba(16, 185, 129, 0.1);
}
/* Catégorie: zipette&co - BLANC CASSÉ - Effet néon amélioré */
.products-grid > div[data-category="zipette&co"] .product-card {
- border: 2px solid #F5F5F0;
- box-shadow:
- 0 0 20px rgba(245, 245, 240, 0.6),
- 0 0 40px rgba(245, 245, 240, 0.4),
- 0 0 60px rgba(245, 245, 240, 0.2),
- 0 0 80px rgba(245, 245, 240, 0.1);
+ border: 2px solid #f5f5f0;
+ box-shadow:
+ 0 0 20px rgba(245, 245, 240, 0.6),
+ 0 0 40px rgba(245, 245, 240, 0.4),
+ 0 0 60px rgba(245, 245, 240, 0.2),
+ 0 0 80px rgba(245, 245, 240, 0.1);
}
/* Catégorie: gros&semi - BLEU CIEL - Effet néon amélioré */
.products-grid > div[data-category="gros&semi"] .product-card {
- border: 2px solid #3dc2f7;
- box-shadow:
- 0 0 20px rgba(61, 194, 247, 0.6),
- 0 0 40px rgba(61, 194, 247, 0.4),
- 0 0 60px rgba(61, 194, 247, 0.2),
- 0 0 80px rgba(61, 194, 247, 0.1);
+ border: 2px solid #3dc2f7;
+ box-shadow:
+ 0 0 20px rgba(61, 194, 247, 0.6),
+ 0 0 40px rgba(61, 194, 247, 0.4),
+ 0 0 60px rgba(61, 194, 247, 0.2),
+ 0 0 80px rgba(61, 194, 247, 0.1);
}
/* Petits téléphones */
@media (max-width: 360px) {
- .products-grid {
- padding: 0 0.8rem;
- padding-bottom: 1rem;
- }
-
- .products-grid > * {
- flex: 0 0 calc(100% - 1.6rem);
- }
-
- .user-page-container {
- padding: 0.8rem;
- padding-top: calc(60px + 0.8rem);
- }
+ .products-grid {
+ padding: 0 0.8rem;
+ padding-bottom: 1rem;
+ }
- .category-title {
- font-size: 1.6rem;
- }
+ .products-grid > * {
+ flex: 0 0 calc(100% - 1.6rem);
+ }
- .category-subtitle {
- font-size: 0.9rem;
- }
+ .user-page-container {
+ padding: 0.8rem;
+ padding-top: calc(60px + 0.8rem);
+ }
+
+ .category-title {
+ font-size: 1.6rem;
+ }
+
+ .category-subtitle {
+ font-size: 0.9rem;
+ }
}
/* Tablettes portrait */
@media (min-width: 600px) {
- .products-grid {
- padding: 0 2rem;
- padding-bottom: 1rem;
- }
-
- .products-grid > * {
- flex: 0 0 calc(100% - 4rem);
- }
-
- .user-page-container {
- padding: 2rem;
- padding-top: calc(60px + 2rem);
- }
+ .products-grid {
+ padding: 0 2rem;
+ padding-bottom: 1rem;
+ }
+
+ .products-grid > * {
+ flex: 0 0 calc(100% - 4rem);
+ }
+
+ .user-page-container {
+ padding: 2rem;
+ padding-top: calc(60px + 2rem);
+ }
}
/* Tablettes paysage et desktop */
@media (min-width: 900px) {
- .products-grid {
- padding: 0 2rem;
- padding-bottom: 1rem;
- }
-
- .products-grid > * {
- flex: 0 0 calc(50% - 2rem);
- }
+ .products-grid {
+ padding: 0 2rem;
+ padding-bottom: 1rem;
+ }
+
+ .products-grid > * {
+ flex: 0 0 calc(50% - 2rem);
+ }
}
/* Désactiver hover sur tactile */
@media (hover: none) {
- .category-button:hover {
- background-color: transparent;
- color: white;
- }
-
- .category-button.active:hover {
- background-color: white;
- color: black;
- }
-
- .category-button.active[data-category="tous"]:hover {
- background-color: #9333ea;
- color: white;
- }
-
- .category-button.active[data-category="weed&hash"]:hover {
- background-color: #10b981;
- color: white;
- }
-
- .category-button.active[data-category="zipette&co"]:hover {
- background-color: #F5F5F0;
- color: white;
- }
-
- .category-button.active[data-category="gros&semi"]:hover {
- background-color: #3dc2f7;
- color: white;
- }
-
- .category-button.active[data-category="festif"]:hover {
- background-color: #9333ea;
- color: white;
- }
+ .category-button:hover {
+ background-color: transparent;
+ color: white;
+ }
+
+ .category-button.active:hover {
+ background-color: white;
+ color: black;
+ }
+
+ .category-button.active[data-category="tous"]:hover {
+ background-color: #9333ea;
+ color: white;
+ }
+
+ .category-button.active[data-category="weed&hash"]:hover {
+ background-color: #10b981;
+ color: white;
+ }
+
+ .category-button.active[data-category="zipette&co"]:hover {
+ background-color: #f5f5f0;
+ color: white;
+ }
+
+ .category-button.active[data-category="gros&semi"]:hover {
+ background-color: #3dc2f7;
+ color: white;
+ }
+
+ .category-button.active[data-category="festif"]:hover {
+ background-color: #9333ea;
+ color: white;
+ }
}
.loading-container,
.error-container,
.empty-container {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- padding: 3rem;
- text-align: center;
- min-height: 300px;
- color: white;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 3rem;
+ text-align: center;
+ min-height: 300px;
+ color: white;
}
.loading-container p,
.empty-container p {
- font-size: 1.1rem;
- color: rgba(255, 255, 255, 0.8);
+ font-size: 1.1rem;
+ color: rgba(255, 255, 255, 0.8);
}
.error-message {
- color: #ff4444;
- margin-bottom: 1rem;
- font-size: 1.1rem;
- font-weight: 500;
+ color: #ff4444;
+ margin-bottom: 1rem;
+ font-size: 1.1rem;
+ font-weight: 500;
}
.error-container button {
- padding: 0.75rem 1.5rem;
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- color: white;
- border: none;
- border-radius: 8px;
- cursor: pointer;
- font-size: 1rem;
- font-weight: 600;
- transition: all 0.3s ease;
+ padding: 0.75rem 1.5rem;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: white;
+ border: none;
+ border-radius: 8px;
+ cursor: pointer;
+ font-size: 1rem;
+ font-weight: 600;
+ transition: all 0.3s ease;
}
.error-container button:hover {
- transform: translateY(-2px);
- box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
}
.error-container button:active {
- transform: translateY(0);
-}
\ No newline at end of file
+ transform: translateY(0);
+}