Files
mercadodevida/work/artifacts/F-076/architect.md
2026-08-19 19:31:46 +02:00

2.6 KiB

F-076 — Architect: Link to frontend product + archive separate listing

Current state

Admin products listing (/products) shows all products (active, archived, draft) in one table. No link to the frontend product page. No way to filter by state.

Goal

  1. Frontend link: Add a column with an external link icon that opens the product on the frontend (http://192.168.18.93:3003/productos/[slug]). Only shown for state === 'active' products.
  2. Archive listing: Add a status filter (Todos / Activos / Archivados) to separate active from archived products.

Scope IN

  • project/apps/admin/src/app/(dashboard)/products/page.tsx:
    • Add statusFilter state: 'all' | 'active' | 'archived'
    • Add filter buttons (Todos / Activos / Archivados) below the search bar
    • Add a new column "Tienda" (Frontend) with an external link icon for active products only
    • Filter products by p.state when statusFilter !== 'all'
    • Update total count to reflect filtered products
    • Use external link URL: http://192.168.18.93:3003/productos/[slug]

Scope OUT

  • No backend changes
  • No new pages (filter is inline in the same page)
  • No change to the product editor

Design

Status filter buttons:

<div className="flex gap-2 mb-4">
  {(['all', 'active', 'archived'] as const).map(f => (
    <button key={f} onClick={() => setStatusFilter(f)}
      className={`px-3 py-1.5 rounded-lg text-xs font-medium ${
        statusFilter === f ? 'bg-[#2D6A4F] text-white' : 'bg-white border border-gray-300 text-gray-600 hover:bg-gray-50'
      }`}>
      {f === 'all' ? 'Todos' : f === 'active' ? 'Activos' : 'Archivados'}
    </button>
  ))}
</div>

Frontend link column:

{p.state === 'active' ? (
  <a
    href={`http://192.168.18.93:3003/productos/${p.slug}`}
    target="_blank"
    rel="noopener noreferrer"
    title="Ver en la tienda"
    className="inline-flex items-center justify-center w-8 h-8 rounded-lg bg-green-50 text-green-600 hover:bg-green-100 transition-colors"
    onClick={e => e.stopPropagation()}
  >
    <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
    </svg>
  </a>
) : (
  <span className="w-8 h-8" />
)}

Risk

  • Low risk: purely frontend UX changes, no backend or DB changes
  • URL is hardcoded to local dev URL (acceptable for admin panel)

Verification

  • npx tsc --noEmit admin
  • npx eslint on changed file
  • ./scripts/verify.sh green