Commit Graph

10 Commits

Author SHA1 Message Date
Ho Ngoc Hai
5848c2b386 perf(web): optimize bundle size — dynamic import Mapbox GL and code split Recharts
- Dynamic import ListingMap with next/dynamic (ssr: false) in /listings/[id] and /search pages
- Extract Recharts into lazy-loaded DistrictBarChart and PriceTrendChart components
- /listings/[id] first-load JS: 618KB → 149KB (-76%)
- /search first-load JS: 619KB → 150KB (-76%)
- Both pages now well under 300KB target

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 13:10:24 +07:00
Ho Ngoc Hai
585fdc6ab6 fix(web): XSS in Mapbox popup, add CSP header, CSRF on media upload
- Replace innerHTML/setHTML with DOM API (createElement/textContent/setDOMContent)
  to prevent XSS via user-controlled listing titles, URLs, and prices
- Add Content-Security-Policy header to next.config.js with proper directives
  for Mapbox, API, images, workers, and frame-ancestors
- Add X-CSRF-Token header to media upload fetch call, matching apiClient behavior

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 13:08:10 +07:00
Ho Ngoc Hai
2502aa69b7 fix: production readiness — resolve build, lint, and code quality issues
- Fix Next.js build failure: remove duplicate route at (dashboard)/listings/[id]
  that conflicted with (public)/listings/[id] (same URL path in two route groups)
- Fix 772 ESLint errors: auto-fix import ordering (import-x/order), remove unused
  imports/variables, convert empty interfaces to type aliases, replace require()
  with ESM imports, fix consistent-type-imports violations
- Add CLAUDE.md for developer onboarding documentation
- All checks pass: 0 lint errors, typecheck clean, 230 tests passing, build success

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 07:15:06 +07:00
Ho Ngoc Hai
afa70320f5 fix(web): frontend quality — XSS, error states, a11y, image optimization, security headers
- Whitelist OAuth error codes; never render raw URL params (XSS fix)
- Add error state UI with retry button for API failures on homepage and search
- Use <article> for property cards with ARIA labels and semantic list markup
- Replace raw <img> with Next.js <Image> across all listing/gallery/KYC pages
- Add security headers (X-Content-Type-Options, X-Frame-Options, etc.) in next.config.js
- Gate console.error behind NODE_ENV check in global error boundary
- Mapbox confirmed npm-bundled (SRI N/A)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 06:32:08 +07:00
Ho Ngoc Hai
6389dcf78e fix(auth): migrate tokens from localStorage to httpOnly cookies + CSRF hardening
Backend:
- Auth controller sets httpOnly secure cookies (access_token, refresh_token, goodgo_authenticated) on login/register/refresh
- JWT strategy reads token from cookie first, falls back to Authorization header
- Added POST /auth/logout to clear auth cookies
- Added POST /auth/exchange-token for OAuth callback token-to-cookie exchange
- Refresh endpoint reads refresh_token from cookie (body fallback for backwards compat)
- CSRF middleware excludes auth endpoints (login, register, refresh, exchange-token, logout)

Frontend:
- Removed all localStorage token storage (goodgo_tokens key)
- Removed authGet/authPost/authPatch helpers from api-client (tokens sent via cookies)
- All API calls use credentials:'include' for cookie-based auth
- Updated auth-store: no more token state, uses isAuthenticated flag from cookie
- Updated admin-api, listings-api to remove explicit token parameters
- Updated all pages (admin dashboard, users, KYC, moderation, listings) to remove token passing
- OAuth callbacks use exchange-token endpoint to convert URL tokens to cookies
- Auth provider simplified (no client-side cookie management needed)

Security improvements:
- JWT no longer accessible via JavaScript (XSS-safe)
- Refresh token scoped to /auth path only
- Server-side goodgo_authenticated cookie with SameSite=Lax
- Access token cookie with SameSite=Strict

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 06:25:11 +07:00
Ho Ngoc Hai
b6bb422d33 feat(web): add listing detail page and Mapbox GL JS map integration
- Create public listing detail page at /listings/[id] with image gallery,
  property specs, contact card, and embedded map
- Rewrite ListingMap component to use Mapbox GL JS with interactive markers,
  price labels, and listing popups
- Add selectedListingId prop to search page map views for marker highlighting
- Install mapbox-gl dependency

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 05:12:48 +07:00
Ho Ngoc Hai
6123fc427d feat(web): add Admin module frontend — dashboard, users, moderation, KYC
Build the complete admin panel UI at apps/web/app/(admin)/:
- Admin layout with sidebar navigation and ADMIN role guard
- Dashboard page with stats cards and revenue chart
- User management with search, filters, pagination, detail panel, ban/unban
- Listings moderation queue with approve/reject/bulk actions
- KYC review page with document viewer and approve/reject flow
- New reusable UI components: Dialog, Table

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 02:29:21 +07:00
Ho Ngoc Hai
5e44456d11 feat(search-frontend): add public landing page, search page with map view, filters, and property cards
- Create (public) route group with landing page (hero, featured listings, district links, stats, CTA)
- Create search page with filter sidebar, list/map/split view modes, URL-synced filters, pagination
- Build ListingMap component with CSS-based marker visualization and popup details
- Build FilterBar with transaction type, property type, city, price range, area, bedrooms filters
- Build PropertyCard and SearchResults components with responsive grid layout
- Update middleware to allow public access to / and /search routes
- Move dashboard home to /dashboard to avoid route conflict
- All content in Vietnamese, mobile responsive

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 02:02:42 +07:00
Ho Ngoc Hai
207a2013f3 feat(listings-frontend): add create/edit form, detail page, and listing components
- Multi-step wizard for listing creation (basic info, location, details, pricing, images)
- Listing detail page with image gallery, property specs, seller/agent info, stats
- Listings index page with filters (transaction type, property type) and pagination
- Edit page with tab-based form (read-only until backend PATCH endpoint available)
- Drag & drop image upload component with preview and multi-file support
- Dashboard layout with navigation bar
- New UI primitives: textarea, select, badge, tabs
- Listings API client with typed endpoints matching backend contract
- Zod validation schemas for all form steps
- Status badges with Vietnamese labels for all listing states
- Responsive design across all pages

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 01:54:08 +07:00
Ho Ngoc Hai
0b29fac35e feat(notifications): add multi-channel notification module with Email, FCM, templates, and event listeners
- Domain: NotificationLog/NotificationPreference entities, repositories, channel value object
- Infrastructure: EmailService (nodemailer/SMTP), FcmService (firebase-admin), TemplateService (Handlebars)
- Application: SendNotification CQRS command, UserRegistered + AgentVerified event listeners
- Presentation: NotificationsController with history, preferences, and templates endpoints
- Prisma: NotificationLog and NotificationPreference models with proper indexes
- Templates: Vietnamese notification templates for user.registered, agent.verified, listing.approved, inquiry.received, password.reset

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 01:42:17 +07:00