feat: add Zustand store, product list and add product modal (Steps 2-3)
- Create useProductStore with Zustand for state management - Enrich client.js with all API functions (CRUD, scrape) - Connect HomePage to store with loading/error states - Add ProductCard with scrape/delete actions - Add ProductGrid component - Add AddProductModal with URL extraction - Update Header with refresh and scrape all buttons - Add comprehensive styles for cards and modal Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,17 +1,35 @@
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import { BrowserRouter, Routes, Route, NavLink } from "react-router-dom";
|
||||
import HomePage from "./pages/HomePage";
|
||||
import DebugPage from "./pages/DebugPage";
|
||||
import useProductStore from "./stores/useProductStore";
|
||||
import AddProductModal from "./components/products/AddProductModal";
|
||||
|
||||
const App = () => (
|
||||
<BrowserRouter>
|
||||
<div className="app-shell">
|
||||
const Header = () => {
|
||||
const { fetchProducts, scrapeAll, loading } = useProductStore();
|
||||
const [showAddModal, setShowAddModal] = useState(false);
|
||||
|
||||
const handleRefresh = () => {
|
||||
fetchProducts();
|
||||
};
|
||||
|
||||
const handleScrapeAll = async () => {
|
||||
if (!confirm("Lancer le scraping de tous les produits ?")) return;
|
||||
try {
|
||||
await scrapeAll();
|
||||
} catch (err) {
|
||||
console.error("Erreur scrape all:", err);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<header className="app-header">
|
||||
<div className="brand">
|
||||
<NavLink to="/">suivi_produits</NavLink>
|
||||
</div>
|
||||
<nav className="nav-links">
|
||||
<NavLink to="/" className={({ isActive }) => isActive ? "active" : ""}>
|
||||
<NavLink to="/" end className={({ isActive }) => isActive ? "active" : ""}>
|
||||
<i className="fa-solid fa-home"></i> Accueil
|
||||
</NavLink>
|
||||
<NavLink to="/debug" className={({ isActive }) => isActive ? "active" : ""}>
|
||||
@@ -19,15 +37,29 @@ const App = () => (
|
||||
</NavLink>
|
||||
</nav>
|
||||
<div className="actions">
|
||||
<button className="btn btn-primary">
|
||||
<button className="btn btn-primary" onClick={() => setShowAddModal(true)}>
|
||||
<i className="fa-solid fa-plus"></i> Add Product
|
||||
</button>
|
||||
<button className="btn">
|
||||
<i className="fa-solid fa-refresh"></i> Refresh
|
||||
<button className="btn" onClick={handleScrapeAll} disabled={loading}>
|
||||
<i className="fa-solid fa-bolt"></i> Scrape All
|
||||
</button>
|
||||
<button className="btn" onClick={handleRefresh} disabled={loading}>
|
||||
<i className={`fa-solid fa-refresh ${loading ? "fa-spin" : ""}`}></i>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{showAddModal && (
|
||||
<AddProductModal onClose={() => setShowAddModal(false)} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const App = () => (
|
||||
<BrowserRouter>
|
||||
<div className="app-shell">
|
||||
<Header />
|
||||
<Routes>
|
||||
<Route path="/" element={<HomePage />} />
|
||||
<Route path="/debug" element={<DebugPage />} />
|
||||
|
||||
Reference in New Issue
Block a user