The verification review page was rendering hardcoded mock documents and
mock profile data instead of the real API response, so admins never saw
what customers actually submitted. Wires it to the real documents/payload
fields. Also replaces raw UUID displays with the new human-readable
reference_number across verification, support, orders, and users.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Pairs with the backend's new POST /api/admin/auth/refresh (nxtgauge-backend-rust).
While the admin is active (mouse/keyboard/scroll/touch), silently exchange
the refresh-token cookie for a new access token every 3 minutes so the
15-minute access token never actually expires mid-work. Once idle for 15
minutes, the refresh loop stops on its own and the token expires naturally,
triggering the existing session-expired dialog - "logged out on inactivity,
not on a fixed timer" as intended.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Admin access tokens expire after 15 minutes with no refresh flow. Until now,
once the token expired, every subsequent action (approve, save, etc.) just
403/401'd with no visible feedback, or an error banner easy to miss inside a
modal — it looked like the button "didn't work."
Add a global window.fetch wrapper (installSessionExpiryWatcher, installed
once from AdminShell) that flips a shared signal whenever an authenticated
request comes back 401. AdminShell renders a "You have been logged out"
dialog on top of everything when that fires, with a button that clears the
stale session and sends the admin back to /login?from=<current path>.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Every action branch (reject, request-documents, request-revision, notes)
set common.body to a JSON payload, but the isApprove branch never did,
leaving body: undefined. axum's Json<ActionPayload> extractor rejects a
body-less POST before approve_verification even runs, so clicking Approve
in the queue-list modal silently failed (the error banner renders at the
top of the page, easy to miss behind the open modal).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Backend's AuthUser extractor only reads the Authorization header — it never
looks at cookies. The verification queue list (index.tsx load()) and every
call in the verification detail page (via the shared adminFetch helper) sent
credentials: 'include' but no Authorization header, so they 401'd right after
a successful login even though the access token was already in sessionStorage.
Matches the pattern already used by the approve/reject actions further down
in index.tsx.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Server-side gateway proxy (login, forgot-password, reset-password, all
/api/admin/* and /api/gateway/* calls) was reading import.meta.env.VITE_GATEWAY_URL,
which Vite only inlines at build time. The Dockerfile wrote GATEWAY_URL (no VITE_
prefix, and localhost besides) to .env at build time, so the var was never picked
up and the fallback http://localhost:9100 got baked into the server bundle
permanently — unreachable inside the pod, causing every admin auth call to 502
regardless of the correct GATEWAY_URL already set in the k8s ConfigMap.
Switch to process.env.GATEWAY_URL, read at runtime like the rest of the server
config already is.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The previous fix routed through /api/gateway/auth/* (the users-table
forgot-password), which succeeds but changes the wrong account entirely —
admin.nxtgauge.com authenticates against a separate employees table.
Backend now exposes /api/admin/auth/forgot-password and
/api/admin/auth/reset-password against EmployeeRepository; route there.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
/api/auth/forgot-password and /api/auth/reset-password aren't routes this
app serves itself — admin.nxtgauge.com only proxies specific prefixes
(/api/admin/*, /api/gateway/*, /api/me/*), so calling the bare path 404'd
at the SolidStart routing layer before ever reaching the backend. The
existing /api/gateway/[...path] proxy already rewrites /auth/* to
/api/auth/* on the real backend — route through that instead.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The reset-password flow called /api/auth/internal/forgot-password/request-code
and /verify-code with a challengeId-based two-step contract — neither route
exists anywhere in the backend, so every reset attempt failed with "Failed to
send reset code." The real backend only exposes /api/auth/forgot-password
(sends a one-time code, always 200 to avoid account enumeration) and
/api/auth/reset-password (consumes the code + new password, no challengeId
involved). Rewrites both request/verify handlers to match that contract.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Each of these profession admin list pages (makeup artist, tutor, developer,
video editor, graphic designer, social media manager, fitness trainer,
catering services) linked "View Profile" to /admin/{role}/{id}, but only
Photographer and Company had a real [id].tsx route — every other role fell
through to the legacy catch-all module and showed a placeholder instead of
the applicant's actual profile. Converts each flat list route into a
folder (index.tsx + [id].tsx) and adds a shared ProfessionDetailPage
component, modeled on the working Photographer detail page.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- users: wire suspend/block buttons to PATCH /api/admin/users/:id/status
(previously only mutated local state, reverted on refresh); add
load/action error banners instead of silently emptying the table
- [...module]: stop rendering a dead localhost:9201 iframe for legacy
modules when VITE_LEGACY_ADMIN_ORIGIN isn't configured (it never is
in production); show a clear "not available" message instead
- dashboard: surface a banner when /api/admin/dashboard/metrics fails
instead of silently showing "No Data" on every widget
- credit: fix stray extra closing </Show> tag that broke the whole
file's JSX parse; restore missing API/authHeaders module helpers
dropped in a previous refactor (AI Credits handlers referenced them
but they were undefined); replace a dead, broken exportLedgerCsv/
filteredLedger implementation with one matching actual call sites;
fix activeTab type/tab keys so the Balance & Ledger and Platform
Ledger tabs were actually reachable (they compared against 'balance'
/'platform' but the tab buttons only ever set 'ledger')
- roles: surface errors when fetching a role's permissions for edit
fails, instead of silently swallowing them
- runtime-roles: surface fetch/delete errors instead of silently
swallowing them or presenting fallback sample data as if real
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- verification/[id].tsx: "Add Note" in the Reviewer Notes panel had no
onClick — wired to the existing POST /api/admin/verifications/:id/notes
endpoint.
- approval/index.tsx: Decision Notes textarea was uncontrolled and its
"Add Note" button was a no-op; there's no standalone notes endpoint
for approval_requests, so the textarea is now bound to state and its
value is sent as the rejection reason when the reviewer rejects
(the only channel the backend currently supports).
- support.tsx: removed a no-op onClick={() => {}} on the case row —
the row isn't actually clickable, only the adjacent "View" link is
(though that link's target route doesn't exist yet — flagged
separately, out of scope here).
- Fix nested tag structure: AI Credits tab was incorrectly nested inside Platform Ledger section
- Close Platform Ledger section before starting AI Credits tab
- Move AI Credits tab to be a sibling of Platform Ledger tab, not a child
- Wrap AI Credits content in proper section element for consistent styling
Fixes build errors in admin-solid
- Fix nested tag structure: AI Credits tab was incorrectly nested inside Platform Ledger section
- Close Platform Ledger section before starting AI Credits tab
- Move AI Credits tab to be a sibling of Platform Ledger tab, not a child
- Wrap AI Credits content in proper section element for consistent styling
- Inject Bearer token from sessionStorage into all API requests
- Add typed API helpers for invoices, credits, discounts, ledger, orders, pricing, tax
- Overhaul invoice, credit, pricing, tax admin routes with full CRUD UI
- Remove committed log files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New AI Management page (/admin/ai-management):
- Overview tab: AI users, daily/monthly generations, active plans
- User Usage tab: searchable table with plan, usage, addon balance
- Plans tab: grid of available AI plans
Sidebar:
- Added AI Management nav item with Sparkles icon
Dashboard:
- Added kpi_ai_users widget
- Added kpi_ai_generations_today widget
Files:
- src/routes/admin/ai-management.tsx (new)
- Redesign SMTP management page with two-column layout
- Add SMTP connection test functionality
- Add link to email templates page
- Show current SMTP status
- Add quick help section
- All 4 pages now send Bearer token from sessionStorage on every fetch
- Pricing: fixed endpoint from /api/admin/packages → /api/admin/tracecoin-packages;
added search, role filter, status filter, and sort (name/price/coins)
- Coupon: added search by code/title and status filter; fixed refetch to use load()
- Invoice: refactored from createResource to onMount+signals for consistent auth
- Credit: authenticated balance, ledger, adjust, and reconcile fetch calls
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace all /api/gateway/* with /api/* to match gateway routing
- Fix AdminShell.tsx: update UGC route to singular and fix logout URL
- Remove Applications and Responses from sidebar (unused)
- Move conflicting route files into folders (company, approval, verification, users, jobs, kb, leads, photographer) as index.tsx to avoid catch-all interference
- Upgrade ProfessionAdminListPage to match Department Management UI:
• Dark headers with white text
• Icons on Sort/Filters/Export buttons
• Pagination UI
• Improved empty state with Create button
• Hover effects and consistent spacing
- Update all pages using ProfessionAdminListPage to benefit from new UI
- Fix jobs admin endpoint to use /api/admin/companies/jobs with auth
- Add authentication headers to jobs and leads fetch calls
These changes unify the API architecture and bring a consistent, professional look to all management tables.
When roles API fails to load or roleId doesn't match a loaded role,
selectedRoleKey() returns empty string. Fall back to formRoleKey() in
all three DashboardDesignPreview instances (compact, full_preview tab,
fullscreen overlay) so the role-specific preview always renders correctly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Create ProfessionAdminListPage component for admin list views
- Update all 9 profession pages to use /api/admin/<profession> endpoints
- Remove unused FALLBACK_* constants from onboarding-schemas
- Improves performance and data accuracy for admin profession management
- Added full CRUD UI for categories (create/edit/delete)
- Category form with name, slug, description, display order, active toggle
- Categories displayed as editable tags with delete icons
- Removed duplicate second implementation entirely
- Fixed file structure to have single component
- Updated package.json with solid-markdown dependency
- Integrated Markdown component into article detail page for proper rendering
- AdminShell: added notification bell polling every 30s
- KB page: added createCategory, updateCategory, deleteCategory API helpers
- KB page: added category management state and handlers
- KB page: removed duplicate second implementation (partial)
- KB page: need to insert category UI in next step
- verification/[id].tsx: approve, reject, request-documents, request-revision
all wired to real API endpoints with loading states and feedback banners
- Delete onboarding-management/ (flow moved to dashboard My Profile/Portfolio)
- kb.tsx: remove stray closing brace (TS1128 syntax error)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace runtime storage CRUD with real /api/admin/kb endpoints
- Add proper error handling and state management
- Support seed functionality via API
- Align data mapping with backend Article and Category structs
- Improves data persistence and admin UX
Closes #KB-API-Migration
- Wire dashboard home to live /api/admin/dashboard/metrics with 8 KPI widgets
- Add pending_approvals and total_revenue widget definitions
- Fix JSX syntax errors in [...module].tsx and modules.tsx
- Fix '>' character in DashboardDesignPreview.tsx
- AdminShell: add PAGE_TITLES and ROUTE_MODULE_KEYS entries for
/admin/ugc-content-creators with UGC_CONTENT_CREATOR_MANAGEMENT keys
- DashboardDesignPreview: fix portfolioMediaConfig to include DEVELOPER and
FITNESS_TRAINER as visual portfolio roles
- DashboardDesignPreview: add missing customerViewFor handlers for
'applications', 'shortlisted candidates', 'my applications', 'saved jobs'
- external-dashboard-management: add 'Settings' to CUSTOMER sidebar array
- Fix launch.json PATH so npm is found in sh shell
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>