F
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)

LayerGuestPartnerAdminCustomerAffiliate
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

ComponentGuestPartnerAdminCustomerAffiliateNote
ListingCard🔁🔁🔁Partner/Admin: add manage actions; Affiliate: add referral link
ListingGallery🔁Partner: upload/reorder variant
UnitRow🔁🔁Partner/Admin: editable inventory rows
Price, RatingBadge, Starsatoms
ReviewList / ReviewCard🔁🔁🔁Partner: reply; Customer: my reviews
RatingBreakdownanalytics
SearchFiltersPanel🔁🔁reused as table filters
DateRangePicker, GuestSelector🔁🔁Partner: calendar/availability editor
OrderSummary / PriceSummary🔁reservation/payout summaries
PromoCard🔁🔁Admin: campaign mgmt
EmptyState, SectionHeading, MapPlaceholder, Revealshared
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/partnerService over 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/brandHref props 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

ComponentReused?
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