Tổng hợpCập nhật 2026-06-30 · REUSABLE-MATRIX.md
Reusable Matrix
Which Guest-portal building blocks carry forward to the other portals. ✅ reuse as-is · 🔁 reuse with props/variant · — not applicable.
Foundation (reused everywhere)
| Layer | Guest | Partner | Admin | Customer | Affiliate |
|---|---|---|---|---|---|
lib/domain/models (Listing, Inventory, Reservation, Review...) | ✅ | ✅ | ✅ | ✅ | ✅ |
lib/domain/ports (repositories) | ✅ | ✅ | ✅ | ✅ | ✅ |
lib/services + lib/mock/repositories | ✅ | ✅ | ✅ | ✅ | ✅ |
theme/* (5 brand themes, tokens) | ✅ | ✅ | ✅ | ✅ | ✅ |
components/ui/* (shadcn) | ✅ | ✅ | ✅ | ✅ | ✅ |
lib/format, lib/images | ✅ | ✅ | ✅ | ✅ | ✅ |
Components
| Component | Guest | Partner | Admin | Customer | Affiliate | Note |
|---|---|---|---|---|---|---|
ListingCard | ✅ | 🔁 | 🔁 | ✅ | 🔁 | Partner/Admin: add manage actions; Affiliate: add referral link |
ListingGallery | ✅ | 🔁 | — | ✅ | — | Partner: upload/reorder variant |
UnitRow | ✅ | 🔁 | 🔁 | — | — | Partner/Admin: editable inventory rows |
Price, RatingBadge, Stars | ✅ | ✅ | ✅ | ✅ | ✅ | atoms |
ReviewList / ReviewCard | ✅ | 🔁 | 🔁 | 🔁 | — | Partner: reply; Customer: my reviews |
RatingBreakdown | ✅ | ✅ | ✅ | — | — | analytics |
SearchFiltersPanel | ✅ | 🔁 | 🔁 | — | — | reused as table filters |
DateRangePicker, GuestSelector | ✅ | 🔁 | 🔁 | — | — | Partner: calendar/availability editor |
OrderSummary / PriceSummary | ✅ | ✅ | ✅ | ✅ | 🔁 | reservation/payout summaries |
PromoCard | ✅ | 🔁 | 🔁 | ✅ | — | Admin: campaign mgmt |
EmptyState, SectionHeading, MapPlaceholder, Reveal | ✅ | ✅ | ✅ | ✅ | ✅ | shared |
SiteHeader / SiteFooter | ✅ | 🔁 | 🔁 | ✅ | 🔁 | Partner/Admin: app shell with sidebar variant |
ReservationFlow | ✅ | — | — | 🔁 | — | Customer: rebook |
DestinationCard | ✅ | — | 🔁 | ✅ | 🔁 | Admin: destination mgmt |
New per portal (to build later)
- Partner: PMS dashboard, availability/rate calendar editor, booking management table, revenue charts.
- Admin: tenant/partner/customer tables, CMS, platform analytics.
- Customer: profile, booking history, wishlist, voucher wallet.
- Affiliate: referral link generator, commission ledger, payout requests.
Backend swap: replace Mock*Repository in lib/services/index.ts with Http*Repository implementing the same ports. No component, view-model, or feature changes required.
Realized in Partner phase
- New shared layer
components/admin/*(AppShell, SidebarNav, PageHeader, StatCard, StatusBadge, DataTable, BarChart, DonutChart) built generic so Platform Admin / Customer / Affiliate reuse them next with zero changes. - Reused as-is from Guest/shared: ThemeToggle, BrandSwitcher, EmptyState, Price atoms, format + images helpers, full ui/* set, theme tokens, domain/ports/services seam.
- No duplication: Partner adds only genuinely-new admin UI (dashboard shell, data grid, rate calendar, charts) + a new
PartnerRepository/partnerServiceover the existing port pattern.
Realized in Platform Admin phase
- Reused with zero changes: AppShell, SidebarNav, PageHeader, StatCard, StatusBadge, DataTable, BarChart, DonutChart, EmptyState, Sheet/Tabs/Select/Input/Card/Button/Skeleton, format + images helpers, theme tokens, domain/ports/services seam.
- Shared improvement (not duplication): AppShell got optional
brandName/brandHrefprops so Partner and Platform share one shell. - New only where unavoidable:
PlatformRepository/platformService+ platform mock data +features/admin/*views. No new generic primitive needed (the Partner-era components/admin set covered every surface). - Tie-out: platform GMV = sum(BOOKINGS revenue-statuses) = the exact figure the Partner portal shows; partner GMV partitions the 18 listings so per-partner GMV sums to platform GMV.
Realized in Customer phase
- Reused with zero changes: AppShell + SidebarNav (account nav), PageHeader, StatCard, StatusBadge, DataTable, EmptyState, Tabs/Select/Checkbox/Input/Label/Card/Button/Skeleton,
ListingCard(wishlist),ReviewCard(đã viết),PriceSummary(payment),photo/avatar/formatVnd,toListingCardVM, theme tokens, domain/ports/services seam. - New generic primitives (shared, reusable by other portals):
components/shared/reservation-timeline.tsx,components/shared/star-rating-input.tsx,components/shared/voucher-card.tsx. Each is new because no equivalent existed; built generic (not customer-specific). - No duplication: Customer adds only
CustomerRepository/customerService+ customer mock projections +features/customer/*views. - Tie-out:
CURRENT_CUSTOMER= the most-frequent guestName in BOOKINGS (Hồ Quang Vinh, 6 bookings); every customer KPI/list = BOOKINGS filtered by that name. Vouchers reuse PROMOTIONS, wishlist a deterministic LISTINGS subset, written/pending reviews split this customer's past stays.
Affiliate Portal — realized reuse
| Component | Reused? |
|---|---|
| AppShell + SidebarNav | ✅ (brandName "BNG Affiliate") |
| StatCard / DataTable / StatusBadge / BarChart / PageHeader / EmptyState | ✅ |
| photo() resolver, formatVnd | ✅ |
| QrCode | 🆕 new shared primitive (no prior equivalent) |
| AffiliateRepository/Service seam | 🆕 follows Partner/Platform/Customer pattern |