atelier-du-sac-web
- Dominant language
- Python
- Stars
- 3.2k
- Forks
- 459
- Avg merge
- 27d 1h
- Merged PRs (30d)
- 1
Description
Import React, { useState, useMemo, useEffect } from "react";
Import {
Search, ShoppingBag, Home, Phone, Info, X, Plus, Minus,
MessageCircle, Star, Trash2, ChevronLeft, Check, Sparkles,
Tag, Truck, ShieldCheck, LayoutDashboard
} from "lucide-react";
Const WHATSAPP_NUMBER = "237691630724";
Const CATEGORIES = ["Tous", "Sacs à main", "Sacs de voyage", "Portefeuilles"];
Const INITIAL_PRODUCTS = [
{ id: 1, name: "Sac Aurore", cat: "Sacs à main", price: 28000, promo: null, popular: true, new: true, colors: ["Noir", "Doré", "Beige"], rating: 4.8, reviews: 12, desc: "Sac à main en cuir texturé, fermoir doré et anse chaîne amovible." },
{ id: 2, name: "Sac Voyageur Prestige", cat: "Sacs de voyage", price: 45000, promo: 39000, popular: true, new: false, colors: ["Noir", "Brun"], rating: 4.6, reviews: 9, desc: "Grand sac de voyage rigide, compartiment chaussures dédié." },
{ id: 3, name: "Portefeuille Élégance", cat: "Portefeuilles", price: 12000, promo: null, popular: false, new: true, colors: ["Noir", "Beige"], rating: 4.9, reviews: 21, desc: "Portefeuille compact en cuir grainé, 8 compartiments cartes." },
{ id: 4, name: "Sac Baobab", cat: "Sacs à main", price: 32000, promo: 27000, popular: true, new: false, colors: ["Beige", "Doré"], rating: 4.7, reviews: 15, desc: "Sac cabas structuré, doublure intérieure poche zippée." },
{ id: 5, name: "Sac Weekend Nomade", cat: "Sacs de voyage", price: 38000, promo: null, popular: false, new: false, colors: ["Noir"], rating: 4.5, reviews: 6, desc: "Sac week-end souple, format cabine, poignées matelassées." },
{ id: 6, name: "Portefeuille Héritage", cat: "Portefeuilles", price: 15000, promo: null, popular: false, new: false, colors: ["Brun", "Noir"], rating: 4.4, reviews: 8, desc: "Portefeuille long à rabat, porte-monnaie pressionné." },
{ id: 7, name: "Sac Étoile du Soir", cat: "Sacs à main", price: 34000, promo: null, popular: false, new: true, colors: ["Doré", "Noir"], rating: 5.0, reviews: 4, desc: "Pochette de soirée à chaîne fine dorée." },
{ id: 8, name: "Sac Trotteur Beige", cat: "Sacs à main", price: 24000, promo: 21000, popular: true, new: false, colors: ["Beige"], rating: 4.6, reviews: 18, desc: "Sac bandoulière léger du quotidien, poche avant zippée." },
];
Function formatFCFA(n) {
Return n.toLocaleString("fr-FR") + " FCFA";
}
Function Logo({ size = "text-xl" }) {
Return (
L'Atelier du Sac
BY AS
);
}
Function TagCard({ children, className = "" }) {
Return (
{children}
);
}
Export default function App() {
Const [page, setPage] = useState("accueil");
Const [activeCat, setActiveCat] = useState("Tous");
Const [query, setQuery] = useState("");
Const [selectedProduct, setSelectedProduct] = useState(null);
Const [selectedColor, setSelectedColor] = useState(null);
// Persistance du panier dans localStorage
Const [cart, setCart] = useState(() => {
Const saved = localStorage.getItem("atelier_cart");
Return saved ? JSON.parse(saved) : [];
});
useEffect(() => {
LocalStorage.setItem("atelier_cart", JSON.stringify(cart));
}, [cart]);
Const [products, setProducts] = useState(INITIAL_PRODUCTS);
Const [paymentMethod, setPaymentMethod] = useState("orange");
Const [orderConfirmed, setOrderConfirmed] = useState(false);
Const [adminOpen, setAdminOpen] = useState(false);
// Formulaire Admin
Const [newProduct, setNewProduct] = useState({ name: "", price: "", cat: "Sacs à main" });
// Formulaire Contact
Const [contactForm, setContactForm] = useState({ name: "", phone: "", message: "" });
Const filteredProducts = useMemo(() => {
Return products.filter((p) => {
Const matchCat = activeCat === "Tous" || p.cat === activeCat;
Const matchQuery = p.name.toLowerCase().includes(query.toLowerCase());
Return matchCat && matchQuery;
});
}, [products, activeCat, query]);
Const cartTotal = cart.reduce((sum, item) => sum + (item.promo || item.price) * item.qty, 0);
Const cartCount = cart.reduce((sum, item) => sum + item.qty, 0);
Function addToCart(p, color) {
SetCart((prev) => {
Const existing = prev.find((i) => i.id === p.id && i.color === color);
If (existing) {
Return prev.map((i) => i.id === p.id && i.color === color ? { ...i, qty: i.qty + 1 } : i);
}
Return [...prev, { ...p, color, qty: 1 }];
});
}
Function handleAddProductAdmin() {
If (!newProduct.name.trim() || !newProduct.price) return;
Const newEntry = {
Id: Date.now(),
Name: newProduct.name,
Cat: newProduct.cat,
Price: Number(newProduct.price),
Promo: null,
Popular: false,
New: true,
Colors: ["Noir"],
Rating: 5,
Reviews: 0,
Desc: "Produit récemment ajouté.",
};
SetProducts((prev) => [newEntry, ...prev]);
SetNewProduct({ name: "", price: "", cat: "Sacs à main" });
}
Function handleContactSubmit(e) {
E.preventDefault();
Const text = `Bonjour, je suis ${contactForm.name} (${contactForm.phone}). Message : ${contactForm.message}`;
Window.open(`https://wa.me/${WHATSAPP_NUMBER}?text=${encodeURIComponent(text)}`, "_blank");
}
Return (
{/* Navigation Header */}
{page !== "accueil" ? (
setPage("accueil")} className="p-1">
) :
setPage("panier")} className="relative p-1">
{cartCount > 0 && (
{cartCount}
)}
{/* Vue dynamique basée sur la variable 'page' */}
{/* ... [Rendu du reste de la page identique avec l'intégration des handlers] */}
{/* Bottom Navigation */}
{[
{ id: "accueil", icon: Home, label: "Accueil" },
{ id: "boutique", icon: ShoppingBag, label: "Boutique" },
{ id: "panier", icon: ShoppingBag, label: "Panier", badge: cartCount },
{ id: "contact", icon: Phone, label: "Contact" },
{ id: "apropos", icon: Info, label: "À propos" },
].map((t) => (
setPage(t.id)}
className={`flex flex-col items-center gap-0.5 px-2 relative ${page === t.id ? "text-[#1B1712]" : "text-[#c2b7a3]"}`}
>
{t.label}
))}
Contributor guide
No contributing guide indexed for this repository
Research direction
The issue contains an inline React application but does not identify a repository file, test, entry point, or requested change. First clarify the intended scope and locate where this application belongs in the repository; completion criteria cannot be established until the expected change is specified.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, react, tailwindcss
- Domain
- frontend, web-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100