This repository has been archived on 2026-08-11. You can view files and clone it, but cannot push or open issues or pull requests.
Gishen-B2B/docs/features/portal-layout.md
kirukib 3778801ef5 Ship Gishen B2B institutional portal with polished layout and mock-backed flows.
Deliver role-aware shell (sidebar, breadcrumbs, quick search, tables, detail/create layouts), locale-ready pages, shared backend/feature docs, and Vercel project config so HR, finance, and members can demo against typed mocks.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-06 21:18:23 +03:00

106 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Portal layout conventions (Yimaru / Fortune)
Shared shell patterns for list, detail, and create pages.
**Workspace:** `/Users/kirukib/Desktop/Yaltopia Project/Gishen-B2B`
## Components
| Piece | Path | Role |
|-------|------|------|
| `PageShell` | `src/components/layout/page-shell.tsx` | Full-width page header + content; optional `breadcrumb` |
| `DetailPageLayout` | `src/components/layout/detail-layout.tsx` | Detail wrapper; **breadcrumbs on by default** |
| `Breadcrumbs` / `Bc` | `src/components/layout/breadcrumbs.tsx` | Fortune-style trail; locale links via `@/i18n/routing` |
| `StatCard` / `StatCardGrid` | `src/components/layout/stat-card.tsx` | Flat MakerSys metrics (thin border, brand mint icon well) |
| `TablePanel` | `src/components/table/table-panel.tsx` | Flat white panel (`rounded-xl`, thin border, no shadow) wrapping toolbar + table |
| `TableToolbar` | `src/components/table/table-toolbar.tsx` | In-panel search / filter strip (hairline bottom) |
| `DataTable` | `src/components/table/data-table.tsx` | Column-driven table inside `TablePanel` |
| Table primitives | `src/components/ui/table.tsx` | Yimaru / Fortune density: muted uppercase headers, `px-4` cells, mint hover |
## Breadcrumbs API
```tsx
import { Breadcrumbs, Bc } from "@/components/layout/breadcrumbs";
import { PageShell } from "@/components/layout/page-shell";
import { DetailPageLayout } from "@/components/layout/detail-layout";
// Detail — breadcrumbs default true
<DetailPageLayout title="…">…</DetailPageLayout>
// Create / nested — opt in
<PageShell title="…" breadcrumb>…</PageShell>
// Custom trail (tests / one-offs)
<Breadcrumbs items={[{ href: "/", label: "Dashboard" }, { label: "Custom" }]} />
```
### Labels
- Static paths and dynamic parents map to `bc.*` keys in `src/messages/en.json` + `am.json`.
- Path map lives in `PATH_LABEL_KEYS` / `DYNAMIC_PARENT_KEYS` inside `breadcrumbs.tsx`.
- To extend: add a path key → `bc` message key, then Amharic/English strings.
## When to use what
| Surface | Stats | Tabs | Breadcrumbs | Width |
|---------|:-----:|:----:|:-----------:|-------|
| List dashboards | ✓ metric strip | — | off | full |
| Detail | metrics + sections | shadcn `Tabs` (line) | on | full |
| Create / import / nested settings | — | optional | on | full-width form card (no `max-w-*` unless interaction needs it) |
## List tables
Use the shared panel pattern so every list matches MakerSys / Yimaru:
```tsx
import { TablePanel } from "@/components/table/table-panel";
import { TableToolbar } from "@/components/table/table-toolbar";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
<TablePanel
loading={isLoading}
loadingLabel={t("common.loading")}
toolbar={
<TableToolbar
search={search}
onSearchChange={setSearch}
resultCount={filtered.length}
resultLabel={t("common.results")}
/>
}
>
<Table>…</Table>
</TablePanel>
```
Conventions:
- **Panel:** `rounded-xl`, `border-border`, white `bg-card`, **no shadow** — do not wrap tables in padded `Card` / `CardContent`.
- **Header row:** muted background, compact uppercase labels (`text-[11px]`, tracking), `px-4`.
- **Body:** comfortable `py-4` rows, mint-tinted hover, last row border removed.
- **Empty / loading:** centered `h-28` empty cell or `TablePanel` `loading` state.
- **Mobile:** horizontal scroll via the table container (`overflow-x-auto`).
- **Detail embeds:** prefer `DetailTableSection` (same panel chrome) with flush table primitives.
## Tabs
Use `@/components/ui/tabs`. Default `TabsList` variant is **line** (Yimaru/Fortune underline). Keep 2–4 sections max.
```tsx
const tTabs = useTranslations("tabs");
<Tabs defaultValue="profile" className="w-full">
<TabsList>
<TabsTrigger value="profile">{tTabs("profile")}</TabsTrigger>
</TabsList>
<TabsContent value="profile" className="space-y-4 pt-1">…</TabsContent>
</Tabs>
```
Labels live under root `tabs.*` in `en.json` / `am.json` (`profile`, `entitlement`, `dependants`, `clinical`, `rules`, `perks`, `summary`, `errors`, `breakdown`, `contract`, `people`, `spend`, `info`, `basics`). Prefer `useTranslations("tabs")` so missing keys never render as nested `tabs.tabs.*`.
## Related docs
- [i18n.md](i18n.md) — message files
- [INDEX.md](INDEX.md) — feature → route map