P1 Bug Fixes:
- Fix Finance stat spacing (0₫ → 0 ₫)
- Replace 3 empty catch blocks with error state UI + logging
- Make POS button functional (navigate to /pos)
- Add @implements IDisposable to AdminLayout
P2 Code Quality:
- Create ShopVerticalHelper.cs (DRY icon/label/normalize)
- Remove dead overview case from ShopPage.razor
- Delete 15 orphaned admin pages (moved to shop-scope)
- ShopSidebarConfig delegates to ShopVerticalHelper
P3 UX Enhancement:
- Add CTA buttons to all empty states
- Real KPIs in ShopOverview (orders, products, revenue)
- User role from auth token (Admin/Khách)
- Responsive CSS for stat cards, tables, mobile sidebar
- AdminLayout: removed Sản phẩm, Kho hàng, Tài chính, Nhân sự, Khách hàng from admin sidebar
- ShopSidebarConfig: added Finance to all 4 verticals (Café, Restaurant, Karaoke, Spa)
- ShopPage: rewritten with real API data for menu/inventory/finance/staff/customers sections
- Each section filtered by shopId, loads only required data
- Rewrite StoreList.razor with real data from PosDataService
- Rewrite StoreDetail.razor with real shop data from BFF
- Rewrite StoreSettings.razor with editable form bound to real data
- Add GetShopByIdAsync to PosDataService and BFF endpoint
- Add UpdateShopAsync to MerchantApiService
- Add ShopUpdateDto to MerchantDtos
- Fix BFF DB connection: configurable via env vars (BFF_DB_HOST)
- Add BFF_DB env vars to docker-compose.yml
- Changed repository LINQ queries to use EF.Property<T>() for backing fields
- Expression-bodied properties cannot be auto-mapped by EF Core
- Fixed StatusId comparison in CreateShopCommandHandler (Status nav is null)
- Updated EntityTypeConfiguration comments explaining Ignore pattern
- Created ResourceOwnerPasswordValidator using UserManager.CheckPasswordAsync
- Registered with .AddResourceOwnerValidator<ResourceOwnerPasswordValidator>()
- Added comments explaining EF.Property pattern for DDD backing fields
- Landing Page at /home renders correctly (GoodGo POS branding)
- Server middleware redirects / → /home (302)
- Login Type Selector at /login with 4 role cards
- All navbar links point to /login
- Simplified Home.razor (removed @layout override that caused routing issue)
- Fixed /auth/login route conflict
Co-authored-by: Velik <hongochai10@users.noreply.github.com>
Mobile Apps CI / dotnet-client-apps (apps/web-client-eggymon-landipage-net/src/EggymonLandingPage.Server/EggymonLandingPage.Server.csproj) (push) Failing after 9s
Mobile Apps CI / dotnet-client-app-tests (apps/app-client-base-net/tests/AppClientBase.UnitTests/AppClientBase.UnitTests.csproj) (push) Failing after 7s
Mobile Apps CI / dotnet-client-app-tests (apps/web-client-base-net/tests/WebClientBase.SmokeTests/WebClientBase.SmokeTests.csproj) (push) Failing after 11s
Mobile Apps CI / dotnet-client-app-tests (apps/web-client-eggymon-landipage-net/tests/EggymonLandingPage.SmokeTests/EggymonLandingPage.SmokeTests.csproj) (push) Failing after 9s
Mobile Apps CI / dotnet-client-app-tests (apps/web-client-tpos-net/tests/WebClientTpos.SmokeTests/WebClientTpos.SmokeTests.csproj) (push) Failing after 5s
Phase 1 fixes:
- Fixed Customer Login route (/auth/login/customer now renders correctly)
- Fixed YARP proxy ports for all microservices
- Fixed login links across all auth pages (/login → /auth/login)
- Created AuthStateService for role-based portal redirects
- Dashboard loads real shop data from BFF API
- Reverted UseBlazorFrameworkFiles (breaks .NET 10 MapStaticAssets)
- Created Home.razor landing page and LoginSelect.razor (compiled in DLL,
Blazor client routing needs investigation for / and /auth/login routes)
Verified working:
- Customer Login: phone/OTP with social login
- Staff Login: green theme with role hints
- Admin Login: blue theme with security warning
- Branch Login: orange theme with stats
- Registration: form + API via YARP proxy
- Store Onboarding: 5 types (Café/Nhà hàng/Karaoke/Spa/Bán lẻ)
Co-authored-by: Velik <hongochai10@users.noreply.github.com>
- Inject PosDataService and load shops in OnInitializedAsync
- Show 'Welcome! Tạo cửa hàng đầu tiên' with onboarding link when no shops
- Render dynamic shop cards from DB data when shops exist
- Keep existing KPI cards and alerts/activity panels unchanged
Co-authored-by: Velik <hongochai10@users.noreply.github.com>
- Create Services/AuthStateService.cs with Login/Logout/GetPortalUrl
- Register as singleton in Program.cs
Co-authored-by: Velik <hongochai10@users.noreply.github.com>
- Created Home.razor landing page at / with GoodGo POS branding
- Created LoginSelect.razor role selector at /auth/login
- Created AuthLayout.razor for auth/marketing pages
- Fixed YARP proxy ports: IAM→5001, Merchant→5005, Catalog→5016, Order→5017
- Added Spa & Beauty store type to onboarding (5th option)
- Registration API now works through YARP proxy
Co-authored-by: Velik <hongochai10@users.noreply.github.com>
- Create Layout/AuthLayout.razor with nav bar for auth pages
- Replace Pages/Home.razor with branded landing page (hero + 4 feature cards)
- Create Pages/Auth/LoginSelect.razor with 4 role-based login cards
- Add Spa & Beauty store type to OnboardingStore.razor onboarding flow
Co-authored-by: Velik <hongochai10@users.noreply.github.com>
Add bilingual comment to mark files that use static/demo data:
- TableDetail.razor, Reservation.razor, EodReport.razor
- RestaurantJourney.razor, AllergenWarning.razor
- CourseTiming.razor, OrderNote.razor
Comment: 'Static UI configuration — does not require DB data'
Co-authored-by: Velik <hongochai10@users.noreply.github.com>
- RestaurantTablet.razor: load tables from DB via GetTablesAsync
- RestaurantMobile.razor: load tables from DB via GetTablesAsync
- TableMap.razor: load tables from DB with shape inference
- TableSelect.razor: load available tables from DB
- TableMergeSplit.razor: load tables for merge/split from DB
- KitchenDisplay.razor: inject DataService, keep demo tickets (needs API)
- WaiterPad.razor: load products/categories from DB
- RestaurantMenuManagement.razor: load products from DB
- OrderHistory.razor: inject DataService, keep demo orders (needs API)
All files follow the RestaurantDesktop pattern with loading/error states.
Co-authored-by: Velik <hongochai10@users.noreply.github.com>
Add bilingual (EN/VI) documentation comments to @code blocks explaining
the intended real data sources for each group:
- Payment (11 files): order context workflow state
- Operations (5 files): shift/cash management API
- Dialogs (8 files): current order/product context
Also add @using WebClientTpos.Client.Services to all 24 files for
future service integration pattern, plus @inject PosDataService
DataService to PendingOrders.razor specifically.
No UI template, CSS, or demo data changes — comments only.
Co-authored-by: Velik <hongochai10@users.noreply.github.com>
- Created BffDataController with 6 read-only endpoints using Dapper
- Created PosDataService client with snake_case JSON deserialization
- Refactored CafeDesktop to load products from catalog_service DB
- Refactored RestaurantDesktop to load tables from fnb_engine DB
- Refactored SpaDesktop to load services from catalog_service DB
- Added Npgsql + Dapper packages to Server project
- Seeded: 4 merchants, 4 shops, 26 products, 12 tables, 4 sessions,
4 resources, 3 appointments across all 4 verticals
Co-authored-by: Velik <hongochai10@users.noreply.github.com>
- CafeDesktop: load products & categories from DataService.GetProductsAsync
and GetCategoriesAsync with cafe shop ID
- RestaurantDesktop: load tables from DataService.GetTablesAsync with
restaurant shop ID, map zones from API data
- KaraokeDesktop: keep mock data, add TODO comment for future FnB engine
rooms endpoint integration
- SpaDesktop: load spa services from DataService.GetProductsAsync with
spa shop ID, map duration from product attributes
- All refactored pages show loading state and error handling
Co-authored-by: Velik <hongochai10@users.noreply.github.com>
- Create PosDataService with typed record DTOs for shops, products,
categories, tables, and appointments
- Register PosDataService as scoped service in Client Program.cs
Co-authored-by: Velik <hongochai10@users.noreply.github.com>
- Add Npgsql 9.0.3 and Dapper 2.1.66 packages to Server project
- Create BffDataController with read-only endpoints:
GET /api/bff/shops
GET /api/bff/shops/{shopId}/products
GET /api/bff/shops/{shopId}/categories
GET /api/bff/shops/{shopId}/tables
GET /api/bff/shops/{shopId}/appointments
GET /api/bff/shops/{shopId}/resources
- Register MVC controllers in Program.cs (AddControllers + MapControllers)
Co-authored-by: Velik <hongochai10@users.noreply.github.com>
Replace manual SymmetricSecurityKey validation with Authority-based OIDC
discovery so tokens are validated against RSA keys published by the IAM
IdentityServer's discovery endpoint.
Services updated:
- CatalogService.API
- OrderService.API
- InventoryService.API
- FnbEngine.API
- BookingService.API
Co-authored-by: Velik <hongochai10@users.noreply.github.com>
Add AddAuthentication(JwtBearerDefaults.AuthenticationScheme) and
AddJwtBearer() service registration before CORS configuration in:
- CatalogService.API
- OrderService.API
- InventoryService.API
- FnbEngine.API
- BookingService.API
Also add Microsoft.AspNetCore.Authentication.JwtBearer v10.0.1 NuGet
package reference to each service's .csproj file.
This fixes the runtime error caused by UseAuthentication() being called
without a registered authentication scheme.
Co-authored-by: Velik <hongochai10@users.noreply.github.com>
Added app.UseAuthentication() and app.UseAuthorization() after
app.UseRouting() in the middleware pipeline for:
- CatalogService.API
- OrderService.API
- InventoryService.API
- FnbEngine.API
- BookingService.API
Co-authored-by: Velik <hongochai10@users.noreply.github.com>
Add POS dialog components in Shared/Dialogs/:
- VoidRefund.razor: Void/refund dialog with order lookup, type selection, reason, manager PIN
- OrderEdit.razor: Edit existing order with qty controls, add items, discount, notes
- OrderCancel.razor: Cancel order confirmation with reason dropdown, refund warning
- SplitBill.razor: Split bill with equal/by-item/custom modes
- StockIn.razor: Quick stock-in with supplier, lot, expiry, recent log
- StockOut.razor: Stock-out with current stock display, reason selection
- StockTransfer.razor: Transfer between branches with product list
- PriceCheck.razor: Price check with hero price, promotions, price history
All files use @layout PosLayout, @inherits PosBase, bilingual comments,
CSS variables, Vietnamese demo data with VND prices.
Co-authored-by: Velik <hongochai10@users.noreply.github.com>