- Wire ThrottlerModule to a Redis-backed storage (shared across API
instances) using @nest-lab/throttler-storage-redis.
- Add FeatureListingThrottlerGuard that tracks per-user when JWT is
present, falling back to the real client IP behind the reverse proxy —
keeps per-user and per-IP buckets independent.
- Apply @Throttle({ default: { limit: 10, ttl: 60_000 } }) + the guard
to POST /listings/:id/feature and document 429 in Swagger.
- Integration test (feature-listing-throttle.integration.spec.ts)
verifies: 10 reqs pass / 11th returns 429 with Retry-After, separate
IPs keep their own quotas, and the tracker key logic.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add RedisIoAdapter (shared/infra) for multi-instance Socket.IO fan-out
with graceful fallback to the in-memory IoAdapter when Redis is
unreachable.
- Pin Socket.IO heartbeat (pingInterval/pingTimeout/connectTimeout)
via env-tunable gateway options for reconnect stability.
- Expose Prometheus metrics on /notifications: goodgo_ws_connected_clients
(Gauge) and goodgo_ws_messages_total (Counter) with namespace/event/
direction labels. Wired through MetricsService and tracked across
connect/disconnect + emits.
- Unit tests: RedisIoAdapter connect/fallback/close, new MetricsService
WS helpers, and gateway metric increments/decrements on auth paths.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The "Nhắn tin" button's inquiry modal now shows a success toast via
sonner after submission instead of an in-dialog success state, and
closes the modal automatically. Added sonner as a dependency and
mounted <Toaster> in the root locale layout.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Add three new NestJS modules following DDD/CQRS architecture:
- Industrial: KCN (industrial park) management with PostGIS geo queries, Typesense search, and market statistics
- Transfer: Furniture/premises transfer listings with AI-powered price estimation and depreciation modeling
- Reports: Async AI report generation via BullMQ with Claude narrative service, PDF generation, and macro data integration
Includes Prisma schema models, migrations, seed scripts, and app.module wiring with BullMQ Redis config.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Implements the frontend notification client for TEC-2217:
1. notifications-api.ts — API client for list, unread-count,
markAsRead, markAllAsRead endpoints
2. notifications-store.ts — Zustand store for notification state
(recent list, unread count, dropdown open state)
3. use-socket-notifications.ts — Socket.IO hook that connects with
httpOnly cookie auth, listens for notification:new events,
auto-reconnects, and syncs unread count on (re)connect
4. notification-bell.tsx — Bell icon with unread badge + dropdown
showing 10 most recent notifications with time-ago formatting,
mark-as-read on click, mark-all-as-read, and "Xem tất cả" link
5. notifications-provider.tsx — Provider wired into locale layout
(inside AuthProvider) to initialize Socket.IO connection
6. Dashboard header — NotificationBell placed before LanguageSwitcher
Added socket.io-client dependency.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
@nestjs/config is used at runtime (ConfigModule in shared.module)
but was incorrectly in devDependencies, causing MODULE_NOT_FOUND
when running with --prod install.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update root, API, and web package.json files with latest dependencies.
Refresh pnpm-lock.yaml and update Playwright configuration.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Add missing auth and search translation namespaces to vi.json and en.json
that are required by login/register pages and search filter-bar component.
Update filter-bar with useTranslations('search'), aria-labels, and
role="search" for WCAG 2.1 AA compliance.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add AiServiceClient HTTP client for Python FastAPI AI service with timeout and fallback
- Add HttpAVMService that calls Python AVM endpoint, falls back to PrismaAVMService on failure
- Add ListingCreatedModerationHandler: auto-flags suspicious listings via AI moderation on create
- Add MarketIndexCronService: daily cron job aggregating market stats per district/city/type
- Wire ScheduleModule and new providers into AnalyticsModule and AppModule
- Add unit tests for AiServiceClient, HttpAVMService, and moderation handler (all passing)
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Add HealthModule with /health (liveness) and /ready (readiness) probes.
Readiness checks DB (Prisma) and Redis connectivity.
Replaces the basic /health endpoint in AppController.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Install @tanstack/react-query with exponential backoff retry config
- Create QueryClientProvider and custom hooks for listings, analytics,
payments, and subscription API calls
- Migrate 5 dashboard pages from useState/useEffect to React Query hooks
- Add dark mode CSS variables and ThemeProvider with localStorage persistence
- Add theme toggle button in dashboard header (sun/moon icon)
- Enhance error boundaries with auto-retry, retry count, and loading state
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Remove hardcoded minioadmin/minioadmin_secret fallback from docker-compose.yml,
require MINIO_ACCESS_KEY/MINIO_SECRET_KEY env vars (fail-fast with :? syntax)
- Align docker-compose.yml env var names with .env.example (MINIO_ACCESS_KEY/SECRET_KEY)
- Update CI e2e workflow to use GitHub vars with non-default fallbacks
- Update .env.test to use non-default test credentials
- Add @aws-sdk/s3-request-presigner and getPresignedUploadUrl() method to
MinioMediaStorageService for properly signed client-side uploads
- Remove hardcoded credentials from dev-environment docs
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add vitest config and test script to web app
- Auth validation tests: phone format, password rules, registration flow
- Listing validation tests: all schema steps, constants, merged schema
- Utils tests: cn() class merging with Tailwind conflict resolution
- 36 tests across 3 test files
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Add complete OAuth2 authentication flow for Google and Zalo providers:
- OAuthService: handles account linking (by email/phone), new user
creation for OAuth-only accounts, and JWT token generation
- GoogleOAuthStrategy: passport-google-oauth20 integration
- ZaloOAuthStrategy: custom OAuth2 implementation using Zalo's API
(authorization URL generation, code exchange, user info fetch)
- OAuthController: redirect and callback endpoints for both providers
with httpOnly cookie-based token management
- Unit tests for OAuthService (7 tests), GoogleOAuthStrategy (4 tests),
and ZaloOAuthStrategy (7 tests)
- OAuth env vars added to .env.example and env-validation warnings
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Dashboard overview: stats cards (listings, views, inquiries, market avg price), Recharts bar chart for district pricing, recent listings feed with engagement metrics
- Analytics page: tabbed layout (overview/trends/districts), interactive bar chart for district comparison, line chart for price trend over quarters with dual Y-axis, clickable heatmap cards
- Listings management: grid/table view toggle, status filter, stats summary cards, table view with thumbnails and engagement data
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Add CSRF middleware with double-submit cookie pattern for all
state-changing requests. Integrate cookie-parser, update CORS
headers, and add client-side CSRF token handling.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Install @nestjs/swagger, configure Swagger UI at /api/docs with JWT bearer
auth, and add ApiTags/ApiOperation/ApiResponse/ApiProperty decorators to
all 8 controllers (50+ endpoints) and 31 DTOs across auth, listings,
search, payments, subscriptions, admin, notifications, and analytics modules.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Setup code quality tooling for the monorepo:
- ESLint 9 flat config with TypeScript, import ordering, and NestJS rules
- Prettier with consistent formatting across all files
- dependency-cruiser enforcing module boundary rules (no cross-module internals, no circular deps)
- Husky + lint-staged for pre-commit hooks
- Auto-fixed existing files for type imports and import ordering
Co-Authored-By: Paperclip <noreply@paperclip.ing>