Task #19: Donation cart (سلة تبرعاتك) for EHSAN POC
Built a real donation cart matching ehsan.sa: - CartContext provider (localStorage-persisted, defensive parsing) wired into App.tsx - OpportunityCard: cart icon now adds the case with its typed amount and swaps the action row to an added state («مضاف لسلة تبرعاتك» + «إزالة») - Header cart button: live count badge + navigates to /cart - New /cart page + route: breadcrumb, item list (delete icon, category, name, editable «قيمة المبلغ» amount, image+progress%), summary panel «الإجمالي» + green «للمتابعة للدفع», decorative leaf SVG background, empty state - translations.ts: parallel AR+EN `cart` section - donate.tsx: removes the donated case from the cart on successful donation (cart reconciliation), preventing stale added-state/badge Notes/deviations: - Checkout handoff routes the first cart item into the existing single-case donate flow (the POC backend has no multi-item payment). Reconciliation keeps remaining items coherent. A true multi-item checkout backend was out of scope. - Verified with passing e2e test (add → badge → cart page → remove → empty) and clean tsc; architect review addressed (reconciliation + defensive parsing).
This commit is contained in:
@@ -3,6 +3,7 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { Toaster } from "@/components/ui/toaster";
|
||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||
import { LanguageProvider } from "./contexts/LanguageContext";
|
||||
import { CartProvider } from "./contexts/CartContext";
|
||||
import { AuthProvider, useAuth } from "./contexts/AuthContext";
|
||||
import { AppLayout } from "./components/layout/AppLayout";
|
||||
import NotFound from "@/pages/not-found";
|
||||
@@ -19,6 +20,7 @@ import Track from "./pages/track";
|
||||
import ThankYou from "./pages/thank-you";
|
||||
import WhatsappLog from "./pages/whatsapp-log";
|
||||
import Login from "./pages/login";
|
||||
import Cart from "./pages/cart";
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
@@ -39,6 +41,7 @@ function Router() {
|
||||
<Route path="/request" component={RequestSupport} />
|
||||
<Route path="/opportunities" component={Opportunities} />
|
||||
<Route path="/donate/:id" component={Donate} />
|
||||
<Route path="/cart" component={Cart} />
|
||||
<Route path="/login" component={Login} />
|
||||
<Route path="/admin">
|
||||
<Protected component={Admin} />
|
||||
@@ -59,12 +62,14 @@ function App() {
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<LanguageProvider>
|
||||
<AuthProvider>
|
||||
<TooltipProvider>
|
||||
<WouterRouter base={import.meta.env.BASE_URL.replace(/\/$/, "")}>
|
||||
<Router />
|
||||
</WouterRouter>
|
||||
<Toaster />
|
||||
</TooltipProvider>
|
||||
<CartProvider>
|
||||
<TooltipProvider>
|
||||
<WouterRouter base={import.meta.env.BASE_URL.replace(/\/$/, "")}>
|
||||
<Router />
|
||||
</WouterRouter>
|
||||
<Toaster />
|
||||
</TooltipProvider>
|
||||
</CartProvider>
|
||||
</AuthProvider>
|
||||
</LanguageProvider>
|
||||
</QueryClientProvider>
|
||||
|
||||
Reference in New Issue
Block a user