Fixed issue where password form fields (especially "New Password")
were being pre-filled with values, either from browser autocomplete
or residual form state.
Changes:
1. Added explicit empty defaultValues to password form
- currentPassword: ''
- newPassword: ''
- confirmPassword: ''
2. Added autoComplete attributes to prevent browser pre-fill:
- currentPassword: autoComplete="current-password"
- newPassword: autoComplete="new-password"
- confirmPassword: autoComplete="new-password"
3. Added useEffect to reset password form when switching tabs:
- Ensures clean state when navigating to "Change Password" tab
- Prevents stale values from persisting
4. Explicit reset values on successful password change:
- Previously used passwordForm.reset() without values
- Now explicitly sets all fields to empty strings
This ensures password fields are always empty and never pre-filled
by the browser or by residual form state.
Refs: apps/frontend/app/dashboard/profile/page.tsx:64-70,85-95
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed critical issues with the profile page (/dashboard/profile):
1. **Form data not persisting on page refresh**:
- Added useEffect to update form values when user data loads
- Forms now properly populate after auth context loads user data
2. **Blank page on refresh**:
- Added loading and error states for better UX
- Handle case where user is not loaded yet (loading spinner)
- Handle case where user fails to load (retry button)
3. **Password change API endpoint correction**:
- Fixed: POST /api/v1/users/change-password (incorrect)
- Corrected to: PATCH /api/v1/users/me/password (matches backend)
- Updated return type to include { message: string }
The root cause was that useForm defaultValues were set once at
component mount when user was still null. The form never updated
when user data was subsequently loaded by the auth context.
Now the form properly resets with user data via useEffect, and
proper loading/error states prevent showing a blank page.
Refs: apps/frontend/app/dashboard/profile/page.tsx:68-78
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fix password change feature that was previously non-functional:
- Add changePassword function in frontend API (src/lib/api/users.ts)
- Update API endpoint to match backend: PATCH /api/v1/users/me/password
- Connect profile page to real API instead of mock implementation
- Export changePassword function from API index
The backend endpoint was already implemented but frontend was using
a placeholder Promise.resolve(). Now properly calls the backend API.
Refs: apps/frontend/app/dashboard/profile/page.tsx:87-105
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Replace full logo (1875x1699) with simplified icon (512x512) optimized for favicon display
- Implement CSS media queries for automatic theme adaptation:
* Dark mode: white X (#FFFFFF) with cyan dot (#34CCCD)
* Light mode: dark blue X and dot (#1D3865)
- Remove old logo files (xpeditis-icon.svg, xpeditis-logo.svg)
- Simplified design with clean X shape and accent dot for better visibility at small sizes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Replace the icon with the full Xpeditis logo (logo-black.svg) as requested.
Updated references in:
- app/icon.svg (favicon)
- app/layout.tsx (metadata and social cards)
- public/manifest.json (PWA icon)
Note: The full logo (1875x1699px) will be scaled down in browser tabs.
Consider creating a square optimized version for better display in small sizes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add site favicon and enhance metadata for better SEO and social sharing:
- Added app/icon.svg from existing logo for browser tab icon
- Enhanced metadata with Open Graph and Twitter card support
- Created manifest.json for PWA support
- Added metadataBase for proper social image resolution
- Updated .env.example with NEXT_PUBLIC_APP_URL
The Xpeditis logo (blue background with cyan X) now appears in:
- Browser tabs (favicon)
- Bookmarks
- Mobile home screen (PWA)
- Social media shares (Open Graph)
Configuration for different environments:
- Dev: NEXT_PUBLIC_APP_URL=http://localhost:3000
- Preprod: NEXT_PUBLIC_APP_URL=https://app.preprod.xpeditis.com
- Prod: NEXT_PUBLIC_APP_URL=https://xpeditis.com🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Replace hardcoded localhost:4000 URLs with NEXT_PUBLIC_API_URL environment variable
in carrier portal pages to support different environments (dev/staging/production).
Pages updated:
- app/carrier/accept/[token]/page.tsx
- app/carrier/reject/[token]/page.tsx
This fixes the issue where preprod environment (app.preprod.xpeditis.com) was calling
localhost:4000 instead of the correct API endpoint (api.preprod.xpeditis.com).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Problems Fixed:
1. **User Creation (Invite)**
- ❌ Missing password field (required by API)
- ❌ Hardcoded organizationId 'default-org-id'
- ❌ Wrong role format (lowercase instead of ADMIN/USER/MANAGER)
- ✅ Now uses currentUser.organizationId from auth context
- ✅ Added password field with validation (min 8 chars)
- ✅ Fixed role enum to match backend (ADMIN, USER, MANAGER, VIEWER)
2. **Role Change (PATCH)**
- ❌ Used 'as any' masking type errors
- ❌ Lowercase role values
- ✅ Proper typing with uppercase roles
- ✅ Added success/error feedback
- ✅ Disabled state during mutation
3. **Toggle Active (PATCH)**
- ✅ Was working but added better feedback
- ✅ Added disabled state during mutation
4. **Delete User (DELETE)**
- ✅ Was working but added better feedback
- ✅ Added disabled state during mutation
5. **UI Improvements**
- Added success messages with auto-dismiss (3s)
- Added error messages with auto-dismiss (5s)
- Added loading states on all action buttons
- Fixed role badge colors to use uppercase keys
- Better form validation before API call
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Problem:
- CSV files uploaded to MinIO via admin panel
- But getAvailableCsvFiles() only listed local filesystem
- Result: rate search returned 0 results even though files exist in MinIO
Solution:
- Modified getAvailableCsvFiles() to check MinIO first
- Lists files from csv_rate_configs table with minioObjectKey
- Falls back to local filesystem if MinIO not configured
- Logs clearly which source is being used
This ensures rate search uses the uploaded CSV files from MinIO storage.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changes:
- Moved all Traefik labels from root level to deploy.labels for Swarm compatibility
- Added deploy.restart_policy to backend, frontend, and MinIO services
- Removed restart: unless-stopped (incompatible with Swarm mode)
- Keeps depends_on for startup ordering
This fixes Gateway Timeout errors by ensuring Traefik can properly discover
and route to services when running in Docker Swarm mode.
Services updated:
- xpeditis-backend: Deploy labels + restart policy
- xpeditis-frontend: Deploy labels + restart policy
- xpeditis-minio: Deploy labels + restart policy
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fixed test user migration to use real Argon2id hash for Password123!
- Replaced random uuidv4() with fixed UUIDs in organization seeds
- Updated auth.service.ts to use DEFAULT_ORG_ID constant
- Added ON CONFLICT DO UPDATE to migration for existing users
- Ensures consistent UUIDs across environments (dev/preprod/prod)
Fixes:
- Registration 500 error (foreign key constraint violation)
- Login 401 error (invalid password hash)
- Organization ID mismatch between migrations and application code
Test users (Password: Password123!):
- admin@xpeditis.com (ADMIN)
- manager@xpeditis.com (MANAGER)
- user@xpeditis.com (USER)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
CRITICAL FIX: Frontend was serving raw CSS with uncompiled @tailwind directives,
resulting in completely unstyled pages (plain text without any CSS).
Root cause:
- postcss.config.js and tailwind.config.js/ts were excluded in .dockerignore
- This prevented PostCSS/Tailwind from compiling CSS during Docker builds
- Local builds worked because config files were present
Changes:
1. apps/frontend/.dockerignore:
- Commented out postcss.config.js exclusion
- Commented out tailwind.config.js/ts exclusions
- Added explanatory comments about why these files are needed
2. apps/backend/Dockerfile:
- Copy src/ directory to production stage for CSV upload paths
- Create csv-storage/rates directory with proper permissions
- Fix EACCES errors when uploading CSV files
3. apps/backend/src/application/controllers/admin/csv-rates.controller.ts:
- Add getCsvUploadPath() helper function
- Support both local dev and Docker environments
- Use absolute paths instead of relative paths
4. docker-compose.dev.yml:
- Change backend port mapping to 4001:4000 (avoid local dev conflicts)
- Change frontend port mapping to 3001:3000
- Update CORS_ORIGIN and NEXT_PUBLIC_API_URL accordingly
Impact:
- ✅ Fixes completely broken frontend CSS in Docker/production
- ✅ Applies to CI/CD builds (uses apps/frontend/.dockerignore)
- ✅ Applies to Portainer deployments (pulls from CI/CD images)
- ✅ Fixes CSV upload permission errors in backend
- ✅ Enables local Docker testing on Mac ARM64
Testing:
- Local Docker build now shows compiled Tailwind CSS (60KB+)
- Frontend displays properly styled pages at http://localhost:3001
- Backend CSV uploads work without permission errors
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>