From 51304d782af38a01aa8add601fc62e67160ae09c Mon Sep 17 00:00:00 2001 From: sulaimaannaasif6866 Date: Sun, 21 Jun 2026 05:50:20 +0000 Subject: [PATCH] =?UTF-8?q?feat(admin):=20=E5=95=86=E5=93=81=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E9=A1=B5=E5=A2=9E=E5=8A=A0=E4=B8=8A=E4=B8=80=E4=B8=AA?= =?UTF-8?q?/=E4=B8=8B=E4=B8=80=E4=B8=AA=E5=AF=BC=E8=88=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- admin-frontend/src/App.tsx | 15 ++++++- .../src/components/ProductDetail.tsx | 45 ++++++++++++++++--- admin-frontend/src/components/ProductList.tsx | 6 +-- 3 files changed, 55 insertions(+), 11 deletions(-) diff --git a/admin-frontend/src/App.tsx b/admin-frontend/src/App.tsx index 2b0ecfd..890f2eb 100644 --- a/admin-frontend/src/App.tsx +++ b/admin-frontend/src/App.tsx @@ -28,6 +28,7 @@ export default function App() { const [tab, setTab] = useState("products"); const [pending, setPending] = useState(null); const [view, setView] = useState({ name: "list" }); + const [navIds, setNavIds] = useState([]); useEffect(() => { if (!authed) return; @@ -190,9 +191,19 @@ export default function App() { ) : tab === "submissions" ? ( ) : view.name === "list" ? ( - setView({ name: "detail", id })} /> + { + setNavIds(ids); + setView({ name: "detail", id }); + }} + /> ) : ( - setView({ name: "list" })} /> + setView({ name: "detail", id })} + onBack={() => setView({ name: "list" })} + /> )} diff --git a/admin-frontend/src/components/ProductDetail.tsx b/admin-frontend/src/components/ProductDetail.tsx index 3066803..7075ee6 100644 --- a/admin-frontend/src/components/ProductDetail.tsx +++ b/admin-frontend/src/components/ProductDetail.tsx @@ -9,6 +9,8 @@ import { } from "../types"; import { ArrowLeft, + ChevronLeft, + ChevronRight, Plus, Save, Trash2, @@ -88,10 +90,18 @@ const inputCls = export default function ProductDetail({ id, onBack, + ids = [], + onNavigate, }: { id: string; onBack: () => void; + ids?: string[]; + onNavigate?: (id: string) => void; }) { + const navIndex = ids.indexOf(id); + const prevId = navIndex > 0 ? ids[navIndex - 1] : null; + const nextId = + navIndex >= 0 && navIndex < ids.length - 1 ? ids[navIndex + 1] : null; const [d, setD] = useState(null); const [brands, setBrands] = useState([]); const [categories, setCategories] = useState([]); @@ -226,12 +236,35 @@ export default function ProductDetail({ return (
- +
+ + {ids.length > 1 && navIndex >= 0 && ( +
+ + + {navIndex + 1} / {ids.length} + + +
+ )} +
{msg && {msg}} {error && {error}} diff --git a/admin-frontend/src/components/ProductList.tsx b/admin-frontend/src/components/ProductList.tsx index 6f50459..278148f 100644 --- a/admin-frontend/src/components/ProductList.tsx +++ b/admin-frontend/src/components/ProductList.tsx @@ -27,7 +27,7 @@ function QualityBadge({ score }: { score: number }) { export default function ProductList({ onOpen, }: { - onOpen: (id: string) => void; + onOpen: (id: string, ids: string[]) => void; }) { const [q, setQ] = useState(""); const [input, setInput] = useState(""); @@ -165,7 +165,7 @@ export default function ProductList({ onClose={() => setCreating(false)} onCreated={(id) => { setCreating(false); - onOpen(id); + onOpen(id, [id]); }} /> )} @@ -271,7 +271,7 @@ export default function ProductList({ rows.map((r) => ( onOpen(r.id)} + onClick={() => onOpen(r.id, rows.map((x) => x.id))} className={`cursor-pointer hover:bg-emerald-50/50 ${ selected.has(r.id) ? "bg-emerald-50/60" : "" }`}