Conversation
feat: enhance PayHere payment object with additional fields and logging
chore: trigger GitOps pipeline
…and enhance error handling
Style/lightmode
Style toast messages
style: remove demo user information from login page
…rror handling to `authService` login.
- Updated VehicleCard component to use theme classes for color and button styles. - Refactored AIChatWidget to streamline state management and improve UI consistency with theme variables. - Modified AdminDashboard, CustomerDashboard, EmployeeDashboard, and SuperAdminDashboard to replace hardcoded styles with theme classes. - Enhanced AppointmentDetailPage and layout components to improve toast handling and navigation styles. - Updated VehiclesPage and ProfilePhotoUpload components to utilize theme classes for loading indicators and alerts. - Added new CSS classes for navigation items and progress bars to maintain design consistency across the application.
…nd optimize loading time
…ent classes in VehicleDetailsPage and Home components
…ading features, and update ReportResponse interface for improved data handling
…nd user experience
…s across all dashboard pages
…r better debugging
…s for improved reliability
…oved clarity and user feedback
… improved clarity and security
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughThis PR implements a centralized theming system with design tokens to replace hardcoded Tailwind colors, introduces a toast notification system across the dashboard, refactors the AI chat component to use a centralized API client, and adds validation scripts to enforce theme compliance. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant Theme as Theme Init Script
participant React
participant LocalStorage
participant CSS as CSS Variables
User->>Browser: Load page
Theme->>LocalStorage: Check theme preference
Theme->>CSS: Apply theme tokens to document
Theme->>React: Hydrate (no FOUC)
React->>CSS: Apply semantic classes
CSS-->>User: Render with theme
User->>React: Toggle theme
React->>LocalStorage: Save preference
React->>CSS: Update CSS variables
CSS-->>User: Re-render with new theme
sequenceDiagram
actor User
participant Chat as Floating Chat Button
participant AIChatWidget as Chat Widget
participant apiClient as API Client
participant Backend as Backend
User->>Chat: Click chat button
Chat->>AIChatWidget: Open chat panel
User->>AIChatWidget: Type message
AIChatWidget->>apiClient: post(/ai/chat)
apiClient->>Backend: Send message + token
Backend-->>apiClient: ChatResponse
apiClient->>AIChatWidget: Typed response
AIChatWidget->>AIChatWidget: Handle session_id
AIChatWidget->>AIChatWidget: Display message
Note over AIChatWidget: On error: extract<br/>status-driven message<br/>show system message
AIChatWidget-->>User: Render in chat
sequenceDiagram
actor User
participant Component as Page Component
participant useToast as useToast Hook
participant Toast as Toast Component
participant Display as DOM
Component->>useToast: Call success(msg)
useToast->>useToast: Generate toast id
useToast->>useToast: Append to toasts array
useToast-->>Component: Updated toasts
Component->>Toast: Render ToastContainer
Toast->>Display: Show toast at top-right
Toast->>Toast: Auto-dismiss after 5s
Toast->>useToast: Call closeToast(id)
useToast->>useToast: Remove from array
Display->>Display: Remove from DOM
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Areas requiring close attention:
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 10
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (6)
src/services/payhereService.ts (1)
124-134: Critical: Remove or redact sensitive data from logs.Logging the payment
hash(line 130) and the full payment object (line 134) exposes sensitive security tokens and PII that create serious risks:
- Security risk: The hash is a cryptographic token for payment verification; exposing it in logs could enable replay attacks or tampering if logs are compromised.
- Compliance violation: Logging customer PII (email, phone, address, names) violates GDPR, CCPA, and other privacy regulations, potentially resulting in significant fines.
- Data breach exposure: Logs often flow to monitoring services, log aggregators, or filesystem storage with broader access than production databases.
Apply this diff to remove sensitive fields from logs:
console.log('Starting PayHere payment:', { sandbox: payment.sandbox, orderId: payment.order_id, amount: payment.amount, - merchantId: payment.merchant_id, currency: payment.currency, - hash: payment.hash, - customerEmail: payment.email }); - console.log('Full PayHere payment object:', payment);If detailed logging is required for debugging, consider:
- Using a debug flag to conditionally log (disabled in production)
- Redacting sensitive fields before logging
- Logging only to secure, access-controlled destinations
Example with conditional logging:
if (process.env.NODE_ENV === 'development') { console.log('Starting PayHere payment:', { sandbox: payment.sandbox, orderId: payment.order_id, amount: payment.amount, currency: payment.currency, }); }src/app/dashboard/appointments/book/page.tsx (1)
108-151: Inconsistent service type payload format.Lines 110 and 148 send different formats for
serviceType:
- Line 110 (
checkAvailability): sendsform.serviceTypeId(ID)- Line 148 (
bookAppointment): sendsselectedServiceType?.name || ''(name string)The AI summary indicates both should use IDs for consistency. This mismatch could cause issues if the backend expects uniform data types.
Apply this diff to use IDs consistently:
await appointmentService.bookAppointment({ vehicleId: form.vehicleId, - serviceType: selectedServiceType?.name || '', + serviceType: form.serviceTypeId, requestedDateTime: requestedDateTime, specialInstructions: form.notes || undefined, })src/app/contexts/NotificationContext.tsx (1)
198-227: Align toast notification styling with centralized theming system.The toast notification uses hardcoded Tailwind color classes (
bg-green-50,border-green-200, etc.), which is inconsistent with the PR's objective to implement a centralized theming system. Other components in this PR usetheme-alert-*classes.Consider updating to use theme classes:
- <div className={` - max-w-sm p-4 rounded-lg shadow-lg border - ${toastNotification.type === 'SUCCESS' ? 'bg-green-50 border-green-200' : ''} - ${toastNotification.type === 'INFO' ? 'bg-blue-50 border-blue-200' : ''} - ${toastNotification.type === 'WARNING' ? 'bg-yellow-50 border-yellow-200' : ''} - ${toastNotification.type === 'ERROR' ? 'bg-red-50 border-red-200' : ''} - `}> + <div className={` + max-w-sm p-4 rounded-lg shadow-lg + ${toastNotification.type === 'SUCCESS' ? 'theme-alert-success' : ''} + ${toastNotification.type === 'INFO' ? 'theme-alert-info' : ''} + ${toastNotification.type === 'WARNING' ? 'theme-alert-warning' : ''} + ${toastNotification.type === 'ERROR' ? 'theme-alert-danger' : ''} + `}>src/components/TimeTracker.tsx (1)
102-179: ToastContainer missing in active timer state.The
ToastContaineris only rendered in the non-active state (Line 105) but not in the active timer state (lines 125-179). This means the success toast triggered on clock-out (Line 84) won't be visible to users. The component should renderToastContainerin both states.Apply this fix to ensure toasts display in all states:
return ( <div className="space-y-4"> + <ToastContainer toasts={toasts} onClose={closeToast} /> {error && ( <div className="theme-alert-danger text-sm">src/app/components/dashboards/CustomerDashboard.tsx (1)
183-212: Fix invalid Tailwind syntax for CSS variable usage.The hover border styling uses invalid syntax:
hover:border-(--accent-primary). This is not valid Tailwind CSS and will not work. Tailwind doesn't support this syntax for CSS variables.Apply this diff to fix the syntax:
<Link href="/dashboard/vehicles" - className="p-4 border theme-border rounded-lg hover:border-(--accent-primary) transition-colors text-center" + className="p-4 border theme-border rounded-lg hover:border-blue-500 dark:hover:border-blue-400 transition-colors text-center" > - <svg className="mx-auto w-12 h-12 mb-2 theme-text-muted" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"> + <svg className="mx-auto w-12 h-12 mb-2 theme-text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M3 12l1.5-4.5A2 2 0 0 1 6.4 6h11.2a2 2 0 0 1 1.9 1.5L21 12" /> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M5 18a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM19 18a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z" /> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M3 12h18v2H3v-2z" /> </svg> <p className="theme-text-primary font-medium">Vehicles</p> </Link> <Link href="/dashboard/appointments" - className="p-4 border theme-border rounded-lg hover:border-(--accent-primary) transition-colors text-center" + className="p-4 border theme-border rounded-lg hover:border-blue-500 dark:hover:border-blue-400 transition-colors text-center" > <svg className="mx-auto w-12 h-12 mb-2 theme-text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" /> </svg> <p className="theme-text-primary font-medium">Appointments</p> </Link> <Link href="/dashboard/projects" - className="p-4 border theme-border rounded-lg hover:border-(--accent-primary) transition-colors text-center" + className="p-4 border theme-border rounded-lg hover:border-blue-500 dark:hover:border-blue-400 transition-colors text-center" > <svg className="mx-auto w-12 h-12 mb-2 theme-text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M3 7h18M3 12h18M3 17h18" /> </svg> <p className="theme-text-primary font-medium">Projects</p> </Link> <Link href="/profile" - className="p-4 border theme-border rounded-lg hover:border-(--accent-primary) transition-colors text-center" + className="p-4 border theme-border rounded-lg hover:border-blue-500 dark:hover:border-blue-400 transition-colors text-center" > <svg className="mx-auto w-12 h-12 mb-2 theme-text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" /> </svg> <p className="theme-text-primary font-medium">Profile</p> </Link>Note: If you want to use CSS variables for theming, you'll need to use arbitrary values like
hover:border-[var(--accent-primary)], but ensure the variable is defined in your CSS.src/app/dashboard/time-logs/page.tsx (1)
181-213: Watch for NaN inhoursstate and consider tightening table empty-state logic
- For the “Hours Worked” field,
onChangedoesparseFloat(e.target.value)and stores it directly, while the value prop isformData.hours || ''. If the user clears the field,parseFloat('')becomesNaN, which then lives in state (even though the displayed value falls back to''). That could result inNaNbeing submitted if HTML validation is bypassed. A small guard like:const value = parseFloat(e.target.value); setFormData({ ...formData, hours: Number.isNaN(value) ? 0 : value, });would keep the state consistent.
- In the table body, there’s a nested
filteredLogs.length === 0check inside a branch that only renders whenfilteredLogs.length !== 0(outer ternary at Lines 314–327), so that inner branch is effectively dead code. It’s harmless but can be removed to simplify the JSX.Also applies to: 235-261, 341-372
🧹 Nitpick comments (24)
src/services/appointmentService.ts (1)
31-33: Response normalization is reasonable; consider centralizing itThe
listAppointmentsandgetAppointmentDetailsguards (res.data.data || res.data, plusArray.isArrayanddata.contentfallback) should handle the common response wrappers safely and always return an array / DTO as promised.Given similar patterns exist in other services, consider extracting a small helper (e.g.,
normalizeListResponse(res)/unwrapData(res)) to avoid copy‑pasting these checks in multiple places.Also applies to: 37-38
src/app/auth/otp-verify/page.tsx (1)
7-8: OTP header branding matches the new pattern; consider minor readability tweakThe new “TT” automotive-accent logo and “TechTorque” brand text align nicely with the other auth pages. The entire
<Link>tree on Line 42 is inlined, which is a bit dense—splitting the inner<div>and<h1>onto separate lines would improve readability, but it’s not required.Also applies to: 42-43
src/lib/apiClient.ts (1)
57-141: LGTM! Robust error handling improvements.The changes significantly improve error handling:
- Login redirect guard (lines 57-64): Prevents redirect loops by detecting login requests before removing tokens
- Message extraction (lines 67-110): Comprehensive helper handles various API response shapes (detail, message, error, msg) with proper fallbacks
- Sanitization (lines 116-121): Single-line, 300-char limit ensures safe display in UI/logs
- Enhanced error object (lines 126-141): Preserves axios metadata (status, response, config) for better debugging
These improvements align well with the PR's toast notification system by providing clean, actionable error messages.
Minor note: Line 58 uses
.includes('/auth/login')which will match any URL containing that substring. If you have endpoints like/auth/login/refreshor/api/auth/login/verify, they'll also bypass the redirect. This is likely acceptable, but consider using exact matching (=== '/auth/login'orendsWith('/auth/login')) if you need stricter control.src/app/profile/page.tsx (1)
281-291: Theming updates applied, minor inconsistency noted.The error and success alerts now use
theme-alert-dangerandtheme-alert-successwrappers, aligning with the centralized theming system. However, the success alert still contains hardcoded color classes on line 288 (text-green-600 dark:text-green-400), which could be replaced with a theme utility class for full consistency.Optional improvement:
- <p className="text-sm text-green-600 dark:text-green-400"> + <p className="text-sm"> {success} </p>The theme-alert-success wrapper should already handle text color styling.
src/app/auth/login/page.tsx (1)
102-102: Minor: Extraneous empty line.Line 102 contains an empty line that doesn't appear to serve a formatting purpose in this context. Consider removing it for cleaner code.
src/services/projectService.ts (1)
69-73: Approve normalization, but consider consistency across all methods.The response normalization in
listCustomerProjectsis good defensive coding that handles varying API response shapes. However, this normalization pattern is inconsistent with other methods in the same service (e.g.,listCustomerServicesat line 20,getServiceDetailsat line 30) that directly returnres.datawithout normalization.Consider applying consistent response normalization across all service methods to prevent potential runtime errors if the API response shape varies:
async listCustomerServices(status?: string): Promise<ServiceResponseDto[]> { const res = await api.get('/services', { params: { status } }); const data = res.data.data || res.data; return Array.isArray(data) ? data : []; },src/hooks/useToast.ts (1)
9-13: Consider more robust ID generation.Using
Math.random().toString(36).substring(7)for ID generation has a small collision risk. While acceptable for toast notifications with short lifetimes, consider using a more robust approach for production code.Alternative approaches:
Option 1: Use crypto.randomUUID() (modern browsers):
const id = crypto.randomUUID();Option 2: Use a counter (simpler, guaranteed unique):
let toastIdCounter = 0; const id = `toast-${++toastIdCounter}`;Option 3: Timestamp + random (hybrid):
const id = `${Date.now()}-${Math.random().toString(36).substring(7)}`;src/app/admin/page.tsx (1)
117-121: Remove redundant color classes inside theme wrapper.Line 118 contains explicit color classes (
text-green-600 dark:text-green-400) inside thetheme-alert-successwrapper. The semantic theme class should handle all styling to maintain centralized theme control.Apply this diff to remove the redundant classes:
{success && ( <div className="mb-6 theme-alert-success"> - <p className="text-sm text-green-600 dark:text-green-400"> + <p className="text-sm"> {success} </p> </div>src/app/dashboard/projects/[projectId]/page.tsx (1)
41-55: Minor syntax issue in finally block.Line 52 has
} finally{without a space before the opening brace. While this works, it's inconsistent with the codebase style where spaces are used (see lines 67, 84, 105).- } finally{ + } finally { setActionLoading(false); }src/app/dashboard/invoices/page.tsx (1)
206-206: Consider performance impact of transition-all.The hover effect uses
transition-allwhich animates all properties. While this works, it can be less performant than specifying exact properties.Apply this diff for better performance:
- className="block rounded-xl border border-gray-200 dark:border-gray-800 hover:border-blue-400 dark:hover:border-blue-500 hover:shadow-lg transition-all" + className="block rounded-xl border border-gray-200 dark:border-gray-800 hover:border-blue-400 dark:hover:border-blue-500 hover:shadow-lg transition-[border-color,box-shadow] duration-200"src/components/Toast.tsx (1)
21-27: Potential issue with useEffect dependencies.The timer depends on the entire
toastobject, which could cause the timer to reset unnecessarily if the toast reference changes (even if the content is the same). Consider extracting only the necessary properties.Apply this diff to optimize the effect:
useEffect(() => { const timer = setTimeout(() => { onClose(toast.id); - }, toast.duration || 5000); + }, toast.duration ?? 5000); return () => clearTimeout(timer); - }, [toast, onClose]); + }, [toast.id, toast.duration, onClose]);src/app/dashboard/services/page.tsx (1)
141-141: Consider specifying transition properties.Similar to the invoices page,
transition-allcan be less performant than specifying exact properties.Apply this diff for better performance:
- className="block rounded-xl border border-gray-200 dark:border-gray-800 hover:border-blue-400 dark:hover:border-blue-500 hover:shadow-lg transition-all" + className="block rounded-xl border border-gray-200 dark:border-gray-800 hover:border-blue-400 dark:hover:border-blue-500 hover:shadow-lg transition-[border-color,box-shadow] duration-200"src/app/dashboard/vehicles/page.tsx (1)
8-9: Toast integration is sound; consider unifying error UX.
useToastis wired correctly (aliasingerrorasshowError), and wiringToastContainerat the page level cleanly scopes vehicle toasts. You might optionally route the initial load error (setError) through a toast as well for a more consistent feedback pattern between fetch, delete, and other actions.Also applies to: 12-13, 37-45, 65-68
src/app/dashboard/layout.tsx (1)
152-186: Customer chat toggle works; consider tightening role gating and responsiveness.The fixed chat launcher/panel wiring with
chatOpenand AIChatWidget is straightforward and correctly gated on customer presence. If you want stricter behavior, you might gate purely onactiveRole === 'CUSTOMER', and for very small viewports consider making the panel width/height responsive (e.g.,max-w-[480px] w-full h-[60vh] max-h-[600px]) to avoid overflow.src/app/components/dashboards/AdminDashboard.tsx (1)
59-63: Theming updates are consistent; inline accent override is reasonable.Swapping to
theme-alert-danger,theme-border,theme-text-info, andtheme-bg-*/theme-bg-accentkeeps the existing UX while aligning with the token system. The extrabackgroundColor: 'var(--accent-primary)'on the revenue bar is slightly redundant withtheme-bg-accentbut fine if you want to guarantee the CSS variable accent; you could centralize that in the class later if desired.Also applies to: 140-151, 176-180
src/app/dashboard/admin/users/page.tsx (3)
9-15: Toast-based feedback is well integrated; consider centralizing error parsing.
useToastis wired cleanly (success +showError) and you now surface meaningful messages for create, role edits, validation, and status toggles, which is a solid UX improvement. The custom extraction of API error messages inhandleCreateUser(and the simpler patterns in other handlers) could eventually be pulled into a small shared helper (e.g.,getApiErrorMessage(err, defaultMessage)) to avoid duplicating error-shape checks across pages.Also applies to: 58-63, 69-80, 85-99, 112-129, 132-137, 145-163, 557-558
296-308: Table header still uses raw color utilities; optional future tokenization.Header background, borders, and text colors remain on concrete
bg-slate-*/border-gray-*/text-slate-*classes. That’s perfectly fine functionally; if the long‑term goal is full token usage, this would be a good future candidate fortheme-*header tokens.
473-477: Modal content/forms now use shared tokens; consider reusing the overlay helper too.Using
modal-contentandform-inputgreatly simplifies the create-user modal and keeps it consistent with other forms. If you’ve standardized a.modal-overlayclass elsewhere (e.g., vehicles page), you might optionally swap thebg-black/50wrapper to that for cross-page consistency.Also applies to: 480-537
src/app/dashboard/notifications/page.tsx (1)
123-137: Filter tab theming is clean; consider avoiding new raw color utilities on the unread badgeThe refactor to
filter-tabs-container+filter-tab/filter-tab-active/filter-tab-inactivekeeps the filter logic readable and aligns with the new design tokens.The unread badge at Line 136 still introduces raw color utilities (
bg-white,dark:bg-gray-800,bg-opacity-30, etc.). If the goal is to centralize colors behind tokens, consider a small wrapper class (e.g., afilter-tab-unread-badgeor theme badge token) instead of additional hardcoded colors.src/app/dashboard/admin/service-types/page.tsx (1)
7-13: Toast integration is solid; consider also surfacing load/toggle feedback and trimming debug logsUsing
useToastwithsuccess/showErrorfor create, update, and delete paths is wired correctly, andToastContainerplacement at the page root is appropriate.Two small follow‑ups you might consider:
loadServiceTypesfailures currently only hitconsole.errorand clear the list; adding ashowError('Failed to load service types...')there would make the issue visible to admins.handleToggleActivesurfaces an error toast but no success toast; if the intent is toast‑based feedback for all state‑changing operations, a short “Service status updated” success toast would keep UX consistent.Also, there are still several
console.logstatements left inloadServiceTypes/handleSubmit; worth removing or guarding them behind a debug flag before merging.Also applies to: 70-114, 116-129, 132-147, 396-397
src/app/dashboard/time-logs/page.tsx (1)
7-13: Toast-based error feedback is wired correctly; you may want to surface load failures tooThe
useToastintegration (erroraliased asshowError) is correctly used in both the create and delete error paths, andToastContainerplacement at the bottom of the page is appropriate.You might also consider calling
showErrorinloadTimeLogs’s catch block so initial load failures don’t silently degrade to an empty table.Also applies to: 56-78, 80-89, 392-393
src/app/dashboard/projects/page.tsx (1)
13-20: Status chip colors and new stat/filter/card theming are consistent; just keep an eye on future statusesThe updated
statusStylesmappings and the move tostat-card,filter-tabs-container/filter-tab(-active|‑inactive), and themed empty-state/icon styles all look coherent with the new design tokens and don’t change behavior.Because
statusStylesis aRecord<string, string>and the render uses a fallback for unknown statuses, this will degrade gracefully if new statuses are introduced later; just remember to add explicit mappings for any new status values so chips don’t all fall back to the gray default.Also applies to: 115-119, 121-137, 140-152, 160-161, 183-187
src/app/components/chatbot/AIChatWidget.tsx (1)
18-38: Core chat flow and session handling viaapiClientlook solid; consider a message when no token is presentUsing
Cookies.get('tt_access_token')plussessionIdin the payload and centralizing the call throughapiClient.post<ChatResponse>('/ai/chat', payload)is a good cleanup; the guard on blank messages andisLoadingprevents overlapping requests.One UX improvement to consider: when
currentTokenis missing,sendMessagecurrently just returns, so the user gets no feedback if they’ve been logged out. You could append a small'system'message (similar to the 401 branch) explaining that they need to sign in again instead of silently ignoring the input.Also applies to: 44-64
src/app/dashboard/admin/reports/page.tsx (1)
118-275: Reports UI, theming, and toast integration look solid.The overall layout (2‑column grid, standardized
dashboard-content-card/form controls), use of theme tokens, and integration of toasts for generate/load/download flows are coherent and readable. I don’t see functional issues in the main render path; just consider the hook-dependency tweak noted separately.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (62)
README.md(1 hunks)package.json(1 hunks)scripts/check-hardcoded-colors.js(1 hunks)scripts/check-theme-setup.js(1 hunks)src/app/admin/page.tsx(2 hunks)src/app/auth/forgot-password/page.tsx(3 hunks)src/app/auth/login/page.tsx(4 hunks)src/app/auth/otp-verify/page.tsx(2 hunks)src/app/auth/register/page.tsx(3 hunks)src/app/auth/resend-verification/page.tsx(3 hunks)src/app/auth/reset-password/ResetPasswordForm.tsx(1 hunks)src/app/auth/reset-password/page.tsx(2 hunks)src/app/auth/verify-email/page.tsx(2 hunks)src/app/components/AddVehicleForm.tsx(1 hunks)src/app/components/EditVehicleForm.tsx(5 hunks)src/app/components/NotificationBell.tsx(7 hunks)src/app/components/PaymentGateway.tsx(2 hunks)src/app/components/RoleSwitcher.tsx(5 hunks)src/app/components/VehicleCard.tsx(3 hunks)src/app/components/chatbot/AIChatWidget.tsx(1 hunks)src/app/components/dashboards/AdminDashboard.tsx(4 hunks)src/app/components/dashboards/CustomerDashboard.tsx(8 hunks)src/app/components/dashboards/EmployeeDashboard.tsx(4 hunks)src/app/components/dashboards/SuperAdminDashboard.tsx(3 hunks)src/app/contexts/NotificationContext.tsx(7 hunks)src/app/dashboard/admin/audit-logs/page.tsx(4 hunks)src/app/dashboard/admin/page.tsx(6 hunks)src/app/dashboard/admin/reports/page.tsx(4 hunks)src/app/dashboard/admin/service-types/page.tsx(16 hunks)src/app/dashboard/admin/users/page.tsx(15 hunks)src/app/dashboard/appointments/[appointmentId]/page.tsx(9 hunks)src/app/dashboard/appointments/availability/page.tsx(1 hunks)src/app/dashboard/appointments/book/page.tsx(3 hunks)src/app/dashboard/appointments/page.tsx(4 hunks)src/app/dashboard/invoices/page.tsx(2 hunks)src/app/dashboard/layout.tsx(7 hunks)src/app/dashboard/notifications/page.tsx(5 hunks)src/app/dashboard/payments/page.tsx(1 hunks)src/app/dashboard/projects/[projectId]/page.tsx(10 hunks)src/app/dashboard/projects/page.tsx(4 hunks)src/app/dashboard/projects/request/page.tsx(3 hunks)src/app/dashboard/schedule/page.tsx(5 hunks)src/app/dashboard/services/page.tsx(2 hunks)src/app/dashboard/time-logs/page.tsx(16 hunks)src/app/dashboard/vehicles/[vehicleId]/page.tsx(6 hunks)src/app/dashboard/vehicles/page.tsx(6 hunks)src/app/globals.css(7 hunks)src/app/layout.tsx(1 hunks)src/app/page.tsx(7 hunks)src/app/payment-gateway/page.tsx(1 hunks)src/app/profile/page.tsx(1 hunks)src/components/ProfilePhotoUpload.tsx(3 hunks)src/components/TimeTracker.tsx(5 hunks)src/components/Toast.tsx(1 hunks)src/hooks/useToast.ts(1 hunks)src/lib/apiClient.ts(1 hunks)src/services/adminService.ts(2 hunks)src/services/appointmentService.ts(1 hunks)src/services/authService.ts(2 hunks)src/services/payhereService.ts(1 hunks)src/services/projectService.ts(2 hunks)src/types/admin.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (15)
scripts/check-hardcoded-colors.js (1)
eslint.config.mjs (1)
__dirname(6-6)
src/app/dashboard/admin/service-types/page.tsx (3)
src/app/contexts/DashboardContext.tsx (1)
useDashboard(65-71)src/hooks/useToast.ts (1)
useToast(6-44)src/components/Toast.tsx (1)
ToastContainer(65-75)
src/hooks/useToast.ts (1)
src/components/Toast.tsx (2)
ToastMessage(8-13)ToastType(6-6)
src/components/TimeTracker.tsx (2)
src/hooks/useToast.ts (1)
useToast(6-44)src/components/Toast.tsx (1)
ToastContainer(65-75)
src/app/dashboard/projects/[projectId]/page.tsx (3)
src/app/contexts/DashboardContext.tsx (1)
useDashboard(65-71)src/hooks/useToast.ts (1)
useToast(6-44)src/components/Toast.tsx (1)
ToastContainer(65-75)
src/app/dashboard/admin/reports/page.tsx (5)
src/app/contexts/DashboardContext.tsx (1)
useDashboard(65-71)src/hooks/useToast.ts (1)
useToast(6-44)src/types/admin.ts (1)
ReportResponse(123-139)src/services/adminService.ts (1)
adminService(17-192)src/components/Toast.tsx (1)
ToastContainer(65-75)
src/app/components/NotificationBell.tsx (3)
src/app/contexts/NotificationContext.tsx (1)
useNotifications(23-29)src/services/notificationService.ts (2)
markAsRead(28-33)markAllAsRead(54-59)src/services/websocketService.ts (1)
isConnected(125-127)
src/services/appointmentService.ts (1)
src/types/appointment.ts (1)
AppointmentResponseDto(15-30)
src/app/dashboard/vehicles/[vehicleId]/page.tsx (2)
src/hooks/useToast.ts (1)
useToast(6-44)src/components/Toast.tsx (1)
ToastContainer(65-75)
src/app/contexts/NotificationContext.tsx (2)
src/types/notification.ts (1)
NotificationResponse(3-14)src/services/notificationService.ts (1)
notificationService(12-60)
scripts/check-theme-setup.js (1)
eslint.config.mjs (1)
__dirname(6-6)
src/app/dashboard/appointments/[appointmentId]/page.tsx (2)
src/hooks/useToast.ts (1)
useToast(6-44)src/components/Toast.tsx (1)
ToastContainer(65-75)
src/app/dashboard/vehicles/page.tsx (2)
src/hooks/useToast.ts (1)
useToast(6-44)src/components/Toast.tsx (1)
ToastContainer(65-75)
src/app/dashboard/admin/users/page.tsx (3)
src/app/contexts/DashboardContext.tsx (1)
useDashboard(65-71)src/hooks/useToast.ts (1)
useToast(6-44)src/components/Toast.tsx (1)
ToastContainer(65-75)
src/app/dashboard/time-logs/page.tsx (3)
src/app/contexts/DashboardContext.tsx (1)
useDashboard(65-71)src/hooks/useToast.ts (1)
useToast(6-44)src/components/Toast.tsx (1)
ToastContainer(65-75)
🪛 GitHub Check: Install, Lint and Build
src/app/dashboard/admin/reports/page.tsx
[warning] 28-28:
React Hook useEffect has missing dependencies: 'hasAccess' and 'loadReports'. Either include them or remove the dependency array
🪛 markdownlint-cli2 (0.18.1)
README.md
63-63: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
64-64: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
65-65: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
70-70: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
71-71: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
🔇 Additional comments (80)
src/app/auth/register/page.tsx (1)
9-10: Branding and copy updates align with the new theme systemThe simplified “TT” logo, updated “TechTorque” text, and success message copy all look consistent with the new automotive-accent/themed branding and don’t affect behavior.
Also applies to: 122-127, 168-169
src/app/components/AddVehicleForm.tsx (1)
62-66: Error banner switch totheme-alert-dangerlooks goodUsing
theme-alert-dangerhere matches the new tokenized alert styles and keeps the same error semantics.src/app/payment-gateway/page.tsx (1)
80-82: Header logo theming change is consistent with the new automotive accentSwitching the logo container to use
automotive-accentmatches the rest of the app’s updated branding without impacting behavior.src/app/components/VehicleCard.tsx (1)
13-14: VehicleCard theming/token updates look consistent and non-breakingUsing
theme-alert-infofor the color badge,theme-text-danger/hover:theme-bg-hoverfor Delete, and addinghover:shadow-lg transition-allto the card all fit the new tokenized theme system without changing behavior.Also applies to: 22-25, 54-55
src/app/dashboard/admin/audit-logs/page.tsx (1)
55-126: LGTM! Consistent theme token adoption.The styling updates consistently use the new theme tokens (
theme-bg-tertiary,theme-text-muted,dashboard-content-card,hover:theme-bg-hover) to replace hardcoded color classes. This aligns with the PR's centralized theming objective.src/app/components/EditVehicleForm.tsx (2)
62-118: LGTM! Clean theme token migration.The form styling has been successfully migrated to use semantic theme classes (
theme-alert-danger,theme-input,theme-button-*), aligning with the centralized theming approach.
95-103: License plate validation logic is in external backend—manual verification required.The form calls
vehicleService.updateVehicle()which delegates to an external backend API (PUT /vehicles/{vehicleId}). No backend routes exist in this codebase, so server-side validation cannot be verified here. While the form has error handling for backend responses, you must verify that your backend enforces unique license plate constraints before allowing this change to production.src/app/dashboard/appointments/book/page.tsx (1)
184-245: LGTM! Theme alert wrappers applied consistently.The error, success, and info messages now use semantic theme classes (
theme-alert-danger,theme-alert-success,theme-alert-info), improving consistency with the global theming system.src/components/ProfilePhotoUpload.tsx (1)
128-186: LGTM! Comprehensive theme token migration.All UI elements have been successfully migrated to use semantic theme classes for borders, backgrounds, text colors, and alert states. The changes maintain the component's functionality while ensuring consistency with the centralized theming system.
src/app/page.tsx (1)
2-230: LGTM! Clean refactor and theme token adoption.The changes successfully:
- Extract
ThemeToggleinto a reusable component (improving modularity)- Apply new theme tokens (
automotive-accent,accent-badge,text-gradient-accent,bg-linear-to-br) consistently across hero, features, and footer sectionsThe refactoring maintains the existing layout and functionality while aligning with the centralized theming approach.
src/app/dashboard/schedule/page.tsx (1)
102-222: LGTM! Standardized theme tokens and semantic containers.The updates consistently apply:
- Semantic alert wrappers (
theme-alert-danger)- Standardized card containers (
dashboard-content-card,stat-card)- Theme utility classes (
form-input,hover:theme-bg-hover,empty-state)The stat blocks are now uniformly structured with
stat-card-labelandstat-card-value, improving maintainability.src/types/admin.ts (1)
125-136: LGTM! Enhanced report response type.The additions to
ReportResponseimprove tracking and flexibility:
- New
GENERATINGstatus provides better progress visibility- Optional metadata fields (
downloadUrl,fileSize,data, etc.) support various report formats and states- Field naming is clear and consistent
src/app/auth/reset-password/ResetPasswordForm.tsx (1)
146-146: LGTM! Theming update applied.The error message styling has been updated to use
theme-text-danger, aligning with the centralized theming system introduced in this PR.src/services/adminService.ts (1)
26-27: LGTM! Robust response normalization.The array normalization pattern handles multiple potential response structures (
data.data,data.content, or direct array), ensuring consistent return types and preventing runtime errors from API response variations.Also applies to: 56-57
src/app/dashboard/appointments/availability/page.tsx (1)
158-158: LGTM! Simplified error styling with theme classes.The error alert now uses
theme-alert-dangerinstead of multiple Tailwind utility classes, improving maintainability and consistency with the centralized theming system.src/app/layout.tsx (1)
28-28: LGTM! Proper hydration warning suppression and theme initialization.The additions correctly handle theme initialization before React hydration:
suppressHydrationWarningon the<html>element prevents React 19 from warning about server/client mismatches caused by the pre-hydration theme script- The inline
beforeInteractivescript applies the theme from localStorage or system preference, preventing FOUC (Flash of Unstyled Content)- Try/catch wrapper ensures errors don't break the page load
This is the recommended pattern for theme initialization in Next.js with React 19.
Also applies to: 35-36
src/app/auth/verify-email/page.tsx (1)
17-21: LGTM! Simplified branding and cleanup.The changes remove unused icon components and standardize the branding to "TechTorque" with a simple "TT" badge, consistent with branding updates across other auth pages in this PR.
src/app/auth/reset-password/page.tsx (1)
6-7: LGTM! Clean branding consolidation.The removal of unused icon helpers and the introduction of the
automotive-accentstyling with updated branding ("TechTorque") aligns well with the centralized theming system. The implementation is clean and consistent with the broader PR objectives.Also applies to: 16-21
src/app/auth/forgot-password/page.tsx (1)
9-9: LGTM! Consistent theming applied.The changes successfully replace hardcoded color classes with semantic theme tokens (
theme-text-danger), and the header branding matches the consolidated approach across auth pages. The implementation maintains the existing functionality while improving theme consistency.Also applies to: 49-49, 77-77
src/app/auth/login/page.tsx (1)
11-11: LGTM! Theming consistency achieved.The updates successfully implement the centralized theming system with
automotive-accentbranding andtheme-text-dangerfor error messages. The changes are consistent with the broader PR goals.Also applies to: 72-76, 150-150
src/services/projectService.ts (1)
80-83: LGTM! Response normalization applied.The fallback pattern
res.data.data || res.dataensures robustness when the API response structure varies.README.md (1)
52-73: Excellent documentation of new features!The Environment and Theme & Styling sections provide clear, actionable guidance for developers working with the centralized theming system and environment configuration. The inclusion of quick check commands (
npm run check:theme,npm run check:colors) is particularly helpful.src/app/dashboard/vehicles/[vehicleId]/page.tsx (1)
7-8: Excellent toast integration!The replacement of browser
alert()calls with the new toast notification system significantly improves the user experience. The integration is clean and follows the established pattern from the useToast hook.Also applies to: 14-14, 58-61, 93-93
src/hooks/useToast.ts (1)
6-44: Clean toast hook implementation!The hook provides a well-structured API with typed functions for different toast types. The use of
useCallbackensures stable references and prevents unnecessary re-renders.src/app/admin/page.tsx (1)
97-97: LGTM! Theming applied correctly.The updates successfully replace hardcoded color classes with semantic theme utilities (
theme-button-primary,theme-alert-danger), aligning with the centralized theming system.Also applies to: 111-113
src/app/dashboard/projects/request/page.tsx (3)
119-124: LGTM! Theme class applied correctly.The button styling has been successfully migrated to use the centralized
theme-button-actionclass, which improves maintainability and consistency across the application.
137-141: LGTM! Alert styling migrated to theme tokens.The error alert has been properly updated to use
theme-alert-dangerandtheme-text-danger, ensuring consistent error presentation across the application.
255-272: LGTM! Submit button styling migrated to theme tokens.The submit button has been successfully updated to use
theme-button-action, maintaining consistency with the rest of the form while centralizing styling.src/app/components/dashboards/SuperAdminDashboard.tsx (3)
59-63: LGTM! Error alert migrated to theme token.The error display has been properly updated to use
theme-alert-danger, ensuring consistent error styling across the dashboard.
131-139: LGTM! Status text styling migrated to theme tokens.The service status display now uses semantic theme tokens (
theme-text-successfor active,theme-text-mutedfor inactive), maintaining clear visual distinction while improving maintainability.
156-163: LGTM! Border styling migrated to theme token.The audit log item borders now use
theme-border, ensuring consistent border colors across the application.package.json (2)
10-11: Excellent addition for theme compliance enforcement.The new validation scripts will help maintain consistency by automatically checking for hardcoded colors and verifying theme setup. Consider integrating these into your CI pipeline or pre-commit hooks for automated enforcement.
19-19: No compatibility concerns found.Next.js 16.0.3 (released Nov 13, 2025) is a patch release with stability improvements including Turbopack fixes, server-action logging fixes, and performance improvements. Next.js 16 is the supported version for React 19.2+, which confirms compatibility with the current React 19.1.0. This patch bump from 16.0.1 to 16.0.3 is safe to apply.
src/app/components/PaymentGateway.tsx (3)
125-129: LGTM! Error alert migrated to theme token.The error display now uses
theme-alert-danger, ensuring consistent error presentation throughout the payment flow.
131-135: LGTM! Success alert migrated to theme token.The success message now uses
theme-alert-success, providing consistent positive feedback across the application.
147-151: LGTM! Informational banner migrated to theme token.The security notice now uses
theme-alert-info, maintaining consistent informational styling throughout the payment gateway.src/app/dashboard/appointments/page.tsx (3)
90-105: LGTM! Filter tabs migrated to semantic classes.The filter tabs now use semantic classes (
filter-tabs-container,filter-tab-active,filter-tab-inactive), providing a centralized and consistent filter UI pattern.
108-137: LGTM! Empty state and card hover styling improved.The empty state now uses
automotive-card-staticfor appropriate non-interactive styling, and appointment cards have enhanced hover feedback with border color transitions.
166-172: LGTM! Special instructions styling migrated to theme token.The special instructions block now uses
theme-alert-info, ensuring consistent presentation of supplementary information.src/components/TimeTracker.tsx (3)
5-6: LGTM! Toast system integrated correctly.The toast hook and container are properly imported and initialized for displaying user feedback.
Also applies to: 15-15
74-93: LGTM! Alert replaced with toast notification.The clock-out confirmation now uses a toast notification instead of a browser alert, providing a better user experience and consistency with the application's notification system.
106-110: LGTM! Error alerts migrated to theme token.Both error states now use
theme-alert-danger, ensuring consistent error presentation throughout the time tracking flow.Also applies to: 127-131
src/app/dashboard/projects/[projectId]/page.tsx (3)
36-107: LGTM! Toast notifications provide excellent user feedback.The handlers now use toast notifications for both success and error scenarios, providing clear, non-intrusive feedback for quote and project approval/rejection actions. This is a significant UX improvement over previous error handling.
146-161: LGTM! Error state migrated to theme tokens.The error page now uses consistent theme classes (
theme-alert-danger,theme-text-danger,theme-button-action), ensuring uniform error presentation across the application.
197-230: LGTM! UI refinements and toast container added.The icon containers now use
shrink-0for proper flex layout behavior, the progress bar uses the themedprogress-accentclass, and theToastContaineris properly rendered to display notifications.Also applies to: 233-265, 365-378, 382-382
src/app/dashboard/appointments/[appointmentId]/page.tsx (6)
12-13: LGTM! Alert replaced with toast notification for invoice generation.The invoice generation success feedback now uses a toast notification instead of a browser alert (Line 289), providing a better user experience that's consistent with the application's notification system.
Also applies to: 33-33, 263-302
341-345: LGTM! Error alert migrated to theme token.The error display now uses
theme-alert-danger, ensuring consistent error presentation throughout the appointment detail page.
474-478: LGTM! Informational alerts migrated to theme token.The informational notices now use
theme-alert-info, providing consistent styling for supplementary information about employee assignments and vehicle arrival.Also applies to: 529-534
576-585: LGTM! Work completion success state uses theme token.The completed work display now uses
theme-alert-success, providing consistent visual feedback for successful work completion.
801-808: Verify theme class usage on section border.Line 802 applies
theme-alert-successas a border class (border-2 theme-alert-success). Theme alert classes are typically designed for container backgrounds and text, not borders. This might not provide the expected styling.Please verify that
theme-alert-successis intended for use as a border class. If not, consider using a dedicated border theme token or explicit border color classes:- <section className="automotive-card p-6 border-2 theme-alert-success"> + <section className="automotive-card p-6 border-2 border-green-200 dark:border-green-800">
829-829: LGTM! ToastContainer properly rendered.The
ToastContaineris appropriately placed at the end of the component to display all toast notifications.src/app/components/dashboards/EmployeeDashboard.tsx (2)
97-97: LGTM! Clean theme token migration.The error alert styling has been simplified to use the centralized
theme-alert-dangerclass, replacing verbose Tailwind color combinations. This aligns with the PR's theming objectives.
173-204: LGTM! Consistent theme token usage.Border and text color classes have been properly migrated to theme tokens (
theme-border,theme-text-info), ensuring consistent styling across light and dark modes.src/app/auth/resend-verification/page.tsx (1)
110-110: LGTM! Theme token applied correctly.Error text styling properly uses
theme-text-dangerfor centralized theming.src/app/dashboard/payments/page.tsx (2)
145-166: LGTM! Consistent stat-card migration.The summary statistics have been properly migrated from
automotive-cardto the standardizedstat-cardstructure with semanticstat-card-labelandstat-card-valueclasses. This improves consistency across the dashboard.
171-202: LGTM! Filter styling standardized.The filter buttons now use the centralized
filter-tabs-containerwithfilter-tab-activeandfilter-tab-inactivestates, ensuring consistent filter UI across all dashboard pages.src/app/dashboard/invoices/page.tsx (1)
143-158: LGTM! Consistent stat-card implementation.Statistics cards properly migrated to the standardized
stat-cardstructure with appropriate label/value semantics.src/components/Toast.tsx (2)
67-73: LGTM! Pointer events pattern is correct.The
pointer-events-noneon the container withpointer-events-autoon the child div is a standard pattern that allows clicks to pass through the empty space while keeping the toasts interactive.
45-45: No issues found.The
animate-slide-inclass is properly defined insrc/app/globals.css(lines 135-147) with the corresponding@keyframes slide-inanimation and.animate-slide-inCSS class. The Toast component's usage is correct.src/app/dashboard/services/page.tsx (2)
76-97: LGTM! Consistent stat-card implementation.The service statistics properly migrated to the standardized
stat-cardstructure, maintaining consistency across dashboard pages.
101-115: LGTM! Filter styling standardized.Filter tabs properly use the centralized
filter-tabs-containerwith semantic active/inactive states.src/app/components/dashboards/CustomerDashboard.tsx (1)
76-122: LGTM! Theme tokens applied correctly.Error alert and theme-based border/text classes have been properly applied for consistent theming.
src/app/components/RoleSwitcher.tsx (2)
16-41: LGTM! Role configuration migrated to theme tokens.The
roleConfighas been properly updated to use theme-based color and background classes, ensuring consistent styling across the application.
115-159: LGTM! Dropdown styling properly themed.The dropdown container and items use appropriate theme tokens for borders, backgrounds, and text, ensuring consistent appearance in light and dark modes.
src/app/dashboard/vehicles/page.tsx (1)
57-63: Theming and modal changes are consistent with the new design system.Spinner, error alert, empty-state icon, and both Add/Edit modal wrappers correctly adopt
theme-*andmodal-*tokens and keep the structure unchanged, so behavior should remain stable while matching the new theme layer.Also applies to: 81-85, 88-97, 100-115, 119-133
src/app/dashboard/layout.tsx (1)
45-47: Navigation theming refactor looks clean and non-breaking.Switching to
nav-item-active/nav-item-inactive,theme-border, andtheme-bg-secondarypreserves the existing layout and behaviors while aligning with the centralized theme tokens.Also applies to: 53-63, 74-79, 100-103, 133-135
src/app/dashboard/admin/users/page.tsx (3)
247-277: Stat cards align nicely with the new design tokens.The
stat-card,stat-card-label, andstat-card-valueusage makes the user metrics much more uniform; the per-status color accents on values (green/red/blue/orange) are clear and still easy to reason about.
279-289: Filter tab abstraction improves readability and consistency.Wrapping the role filters in
filter-tabs-container/filter-tabwith active/inactive variants is a good cleanup over ad-hoc button classes and should make future styling changes trivial.
441-445: Action button theming is consistent with the design system.Switching “Edit Roles” to
theme-button-actionkeeps semantics clear (primary vs secondary vs action) and matches the broader button-token approach in the dashboard.src/app/dashboard/admin/page.tsx (2)
34-42: Loading skeleton theming is consistent and non-breaking.Replacing gray skeleton blocks with
theme-bg-tertiarykeeps the loading state readable while aligning with the new theme palette.
78-147: Quick actions and stats successfully adopt dashboard-content-card and stat-card tokens.The new
dashboard-content-cardwrappers andstat-card/stat-card-label/stat-card-valueusage make the admin overview much more consistent without touching behavior; the per-card hover borders and colored stat values also give good at-a-glance cues.Also applies to: 153-167, 171-189, 193-203
src/app/dashboard/notifications/page.tsx (2)
90-99: Max width increase tomax-w-6xllooks consistent but verify layout on narrow screensExpanding the container from
max-w-4xltomax-w-6xlin both loading and main views should be fine, but please sanity‑check that content still reads well on laptop‑sized viewports and doesn’t make lines too long for readability.Also applies to: 102-104
162-168: Hover state refinements on notification cards look goodThe added
hover:shadow-lgand hover border variants for read vs unread cards are consistent and don’t affect the underlying logic for read state or actions. No issues from a functional standpoint.src/app/components/NotificationBell.tsx (3)
7-12: Local error layering over context error is reasonable and clearly implementedThe way
localErroris used (cleared on open and on successful mark operations, then rendered aslocalError || error) provides a clear, user‑specific error signal without fighting the context‑levelerror. The minimal Axios‑shape casting inside the catch blocks is also defensive enough for typical API errors.No functional issues; just make sure upstream
fetchNotificationsis already catching/reducing its own errors so you don’t end up with unhandled promise rejections whenawait fetchNotifications()runs on open.Also applies to: 28-55, 105-109
57-88: Themed bell button, badge, and fixed panel alignment look fineSwitching the bell button to
theme-toggle, applyingtheme-badge-dangerfor unread count, and pinning the panel with the fixedright-4 top-20container is consistent with the new design system, and click‑outside detection viapanelRef.containswill still work with a fixed child.The ripple overlay div is inert but harmless; assuming CSS handles the visual effect, there’s no behavioral concern.
Also applies to: 90-92
112-117: List item theming and “View all notifications” CTA are consistent with the rest of the dashboardThe switch to
theme-alert-infofor unread items andtheme-bg-tertiary/hover:theme-bg-hoverfor the footer link keeps the visual hierarchy clear without touching behavior. Mark‑as‑read behavior is unchanged; only the text styling moved to theme tokens, which looks fine.Also applies to: 141-147
src/app/dashboard/admin/service-types/page.tsx (1)
187-201: Form and action button theming aligns with the new design systemSwitching the primary actions to
theme-button-action/btn btn-primaryand the fields toform-input/form-select/form-textareakeeps the markup cleaner and centralizes styling. The modalmodal-contentwrapper also gives you a nice hook for consistent modal theming.No behavioral changes here; the validation and submit logic are preserved.
Also applies to: 249-272, 279-391
src/app/dashboard/time-logs/page.tsx (1)
120-133: Theming updates for access-denied, form, stats, and table are coherentUsing
theme-alert-dangerfor the access-denied block,form-input/form-select/form-textareafor fields,stat-cardfor summary tiles, anddashboard-content-card+theme-border/theme-bg-tertiaryfor the table keeps this page aligned with the rest of the dashboard theming.Row hover (
hover:theme-bg-hover) and muted placeholders for non-action cells (Line 380) read well and don’t affect the underlying permission logic.Also applies to: 180-198, 284-297, 308-318, 330-331, 353-353, 380-381
src/app/components/chatbot/AIChatWidget.tsx (2)
75-152: Error normalization and system message handling are thorough and defensiveThe helper functions for extracting status and server messages, plus
sanitizeForLog, give you concise console output without dumping huge validation payloads. The status‑aware user messages (401 vs 4xx validation vs generic/server message) and use of a'system'sender keep error feedback clear inside the chat history.Dependencies on
isLoading/sessionIdin theuseCallbackare appropriate; no functional issues spotted here.
165-231: Ignore this review comment—the code is correct for Tailwind CSS v4.In Tailwind CSS v4, linear-gradient utilities were renamed from
bg-gradient-*tobg-linear-*. The codebase confirms this: package.json specifies"tailwindcss": "^4", and the code correctly usesbg-linear-to-r(line 169). The reviewer's suggested change tobg-gradient-to-rreflects Tailwind v3 syntax and would break the gradient in this v4 project.Likely an incorrect or invalid review comment.
| - `.theme-button-primary`, `.theme-button-secondary` — semantic buttons | ||
| - `.theme-bg-primary`, `.theme-text-primary`, `.theme-border`, etc — consistent building blocks | ||
| - `.automotive-accent`, `.accent-badge`, `.text-gradient-accent`, `.progress-accent` — accent utilities |
There was a problem hiding this comment.
Fix markdown list indentation.
The nested list items use 3-space indentation but should use 2 spaces per Markdown best practices.
Apply this diff to fix the indentation:
-- A single global stylesheet lives at `src/app/globals.css` and contains all theme variables for light & dark mode, plus utility classes like:
- - `.theme-button-primary`, `.theme-button-secondary` — semantic buttons
- - `.theme-bg-primary`, `.theme-text-primary`, `.theme-border`, etc — consistent building blocks
- - `.automotive-accent`, `.accent-badge`, `.text-gradient-accent`, `.progress-accent` — accent utilities
+- A single global stylesheet lives at `src/app/globals.css` and contains all theme variables for light & dark mode, plus utility classes like:
+ - `.theme-button-primary`, `.theme-button-secondary` — semantic buttons
+ - `.theme-bg-primary`, `.theme-text-primary`, `.theme-border`, etc — consistent building blocks
+ - `.automotive-accent`, `.accent-badge`, `.text-gradient-accent`, `.progress-accent` — accent utilities
-- Quick checks added:
- - `npm run check:theme` — verifies `globals.css` and `ThemeContext` contain expected hooks and variables.
- - `npm run check:colors` — scans `src/` for hardcoded hex/rgb color usage (ignores `globals.css`).
+- Quick checks added:
+ - `npm run check:theme` — verifies `globals.css` and `ThemeContext` contain expected hooks and variables.
+ - `npm run check:colors` — scans `src/` for hardcoded hex/rgb color usage (ignores `globals.css`).Based on static analysis hints.
Also applies to: 70-71
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
63-63: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
64-64: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
65-65: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
🤖 Prompt for AI Agents
In README.md around lines 63-65 (and also apply the same fix to lines 70-71),
the nested markdown list items are indented with 3 spaces instead of the
expected 2; update each nested list line to use 2-space indentation so nested
bullets align with Markdown best practices (change each leading indentation from
three spaces to two spaces) and verify surrounding list markers and spacing
remain consistent.
| import fs from 'fs' | ||
| import path from 'path' | ||
|
|
||
| const root = path.resolve(__dirname, '..', 'src') |
There was a problem hiding this comment.
__dirname is not available in ES modules.
Line 5 uses __dirname, but this script uses ES module syntax (import statements). In ES modules, __dirname is undefined and will cause a runtime error.
Apply this diff to fix:
+import { fileURLToPath } from 'url'
+import { dirname } from 'path'
+
+const __filename = fileURLToPath(import.meta.url)
+const __dirname = dirname(__filename)
+
-const root = path.resolve(__dirname, '..', 'src')
+const root = path.resolve(__dirname, '..', 'src')📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const root = path.resolve(__dirname, '..', 'src') | |
| import { fileURLToPath } from 'url' | |
| import { dirname } from 'path' | |
| const __filename = fileURLToPath(import.meta.url) | |
| const __dirname = dirname(__filename) | |
| const root = path.resolve(__dirname, '..', 'src') |
🤖 Prompt for AI Agents
In scripts/check-hardcoded-colors.js around line 5, __dirname is used but this
file is an ES module so __dirname is undefined; replace use of __dirname by
deriving the directory from import.meta.url: import fileURLToPath from 'url' (or
destructure fileURLToPath) and compute const __filename =
fileURLToPath(import.meta.url) and const __dirname = path.dirname(__filename),
then set root = path.resolve(__dirname, '..', 'src'); add the import for
fileURLToPath at top and remove any direct __dirname usages.
| #!/usr/bin/env node | ||
| import fs from 'fs' | ||
| import path from 'path' | ||
|
|
||
| const globals = fs.readFileSync(path.resolve(__dirname, '../src/app/globals.css'), 'utf8') | ||
| const themeContext = fs.readFileSync(path.resolve(__dirname, '../src/app/contexts/ThemeContext.tsx'), 'utf8') | ||
|
|
There was a problem hiding this comment.
Fix ESM __dirname usage so the script can actually run
With import syntax, Node will treat this as an ES module (in a "type": "module" project), where __dirname is not defined. That means this script will currently error out instead of running your checks.
Define __dirname from import.meta.url (or drop __dirname entirely and resolve from process.cwd()), e.g.:
-#!/usr/bin/env node
-import fs from 'fs'
-import path from 'path'
-
-const globals = fs.readFileSync(path.resolve(__dirname, '../src/app/globals.css'), 'utf8')
-const themeContext = fs.readFileSync(path.resolve(__dirname, '../src/app/contexts/ThemeContext.tsx'), 'utf8')
+#!/usr/bin/env node
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const globals = fs.readFileSync(path.resolve(__dirname, '../src/app/globals.css'), 'utf8');
+const themeContext = fs.readFileSync(path.resolve(__dirname, '../src/app/contexts/ThemeContext.tsx'), 'utf8');🤖 Prompt for AI Agents
In scripts/check-theme-setup.js around lines 1 to 7, the script uses __dirname
which is undefined in ESM; replace its usage by deriving a directory from
import.meta.url (e.g. const __filename = fileURLToPath(import.meta.url) and
const __dirname = path.dirname(__filename)) or switch to resolving paths from
process.cwd(); if you choose the import.meta.url approach, add the required
import from 'url' (fileURLToPath) and then update the path.resolve calls to use
the computed __dirname variable.
| <div className="automotive-accent w-12 h-12 rounded-full flex items-center justify-center shadow-lg transform transition-transform duration-300 group-hover:scale-110"> | ||
| <span className="text-white font-bold text-lg">TT</span> | ||
| </div> | ||
| <h1 className="text-2xl font-bold theme-text-primary hidden sm:block"> | ||
| TechTorque Auto | ||
| TechTorque | ||
| </h1> |
There was a problem hiding this comment.
🧩 Analysis chain
Verify branding change is intentional.
The header branding has been updated from "TechTorque Auto" to "TechTorque" and the logo changed from a gradient-based BoltIcon to a simple "TT" badge. Ensure this branding change is consistent across all pages and intentional.
🏁 Script executed:
#!/bin/bash
# Description: Verify branding consistency across the codebase
# Search for remaining instances of "TechTorque Auto" to ensure consistency
rg -n "TechTorque Auto" --type tsx --type ts
# Search for TechTorque (standalone) usage in headers
rg -n -A2 -B2 "TechTorque</h1>" --type tsx --type tsLength of output: 55
🏁 Script executed:
#!/bin/bash
# Description: Verify branding consistency across the codebase with corrected syntax
# Search for remaining instances of "TechTorque Auto" (old branding)
echo "=== Searching for 'TechTorque Auto' (old branding) ==="
rg -n "TechTorque Auto" -g "*.tsx" -g "*.ts"
# Search for all header branding elements
echo -e "\n=== Searching for TechTorque header usage ==="
rg -n -A2 -B2 "TechTorque" -g "*.tsx" | grep -E "(TechTorque|<h1|className)" | head -40
# Search for BoltIcon usage (old logo component)
echo -e "\n=== Searching for BoltIcon usage ==="
rg -n "BoltIcon" -g "*.tsx" -g "*.ts"
# Search for "TT" badge or similar patterns
echo -e "\n=== Searching for TT badge or similar avatar patterns ==="
rg -n -B3 -A1 "TT" -g "*.tsx" | grep -E "(TT|avatar|badge)" | head -20Length of output: 8358
Branding change is incomplete and inconsistent across the codebase.
The code under review correctly uses the new "TechTorque" branding with the TT badge, but several pages still retain the old "TechTorque Auto" branding with BoltIcon:
- Homepage (src/app/page.tsx): lines 38, 233, 242 use "TechTorque Auto" + BoltIcon
- Payment gateway (src/app/payment-gateway/page.tsx): line 84 uses "TechTorque Auto" + BoltIcon
Other auth and dashboard pages have been updated to use the new branding. This mixed state creates inconsistent brand presentation across the application.
🤖 Prompt for AI Agents
In src/app/auth/resend-verification/page.tsx lines 136-141 and also update
src/app/page.tsx (lines ~38, 233, 242) and src/app/payment-gateway/page.tsx
(line ~84): replace any remaining "TechTorque Auto" + BoltIcon branding with the
new "TechTorque" branding and the TT badge used in resend-verification (match
the TT rounded badge and plain "TechTorque" heading styling), ensure classNames,
accessible text, and any aria-labels match the new brand, and remove or replace
BoltIcon imports/usages so branding is consistent across pages.
| isActive | ||
| ? `${config.bgColor} ${config.color} font-medium` | ||
| : 'theme-text-secondary hover:bg-gray-100 dark:hover:bg-gray-800' | ||
| : 'theme-text-secondary hover:theme-bg-hover' |
There was a problem hiding this comment.
Fix invalid Tailwind hover syntax.
The syntax hover:theme-bg-hover is invalid. Tailwind doesn't support applying hover modifiers to custom utility classes in this way. You need to define the hover state directly or use a proper Tailwind class.
Apply this diff to fix the syntax:
className={`w-full flex items-center gap-3 px-3 py-2 rounded-md text-sm transition-colors ${
isActive
? `${config.bgColor} ${config.color} font-medium`
- : 'theme-text-secondary hover:theme-bg-hover'
+ : 'theme-text-secondary hover:bg-gray-100 dark:hover:bg-gray-800'
}`}Alternatively, if you want a theme-based hover state, define it in your globals.css:
.hover-theme-bg:hover {
background-color: var(--bg-hover);
}Then use:
- : 'theme-text-secondary hover:theme-bg-hover'
+ : 'theme-text-secondary hover-theme-bg'🤖 Prompt for AI Agents
In src/app/components/RoleSwitcher.tsx around line 136, the token
`hover:theme-bg-hover` is invalid Tailwind syntax; replace it with a valid hover
utility or a custom CSS class. Either change the class to a proper Tailwind
hover utility that sets background (e.g. a hover:bg-... variant or
hover:bg-[var(--bg-hover)]), or add a custom rule in globals.css such as
.hover-theme-bg:hover { background-color: var(--bg-hover); } and use that class
name in the JSX instead of `hover:theme-bg-hover`.
| } catch (err: unknown) { | ||
| // Prefer any attached `response?.data?.message` but fall back to | ||
| // the error message. Our apiClient now augments error objects with | ||
| // status/response fields so we can provide a better user message. | ||
| console.error('Failed to fetch notifications:', err); | ||
| const axiosErr = err as AxiosError<unknown> | undefined; | ||
| // Prefer response.data.message when available, otherwise use Error.message | ||
| const msg = axiosErr?.response?.data && typeof axiosErr.response.data === 'object' && 'message' in axiosErr.response.data | ||
| ? // response.data typing varies; narrow to { message?: string } | ||
| (axiosErr.response.data as { message?: string }).message ?? (err instanceof Error ? err.message : 'Failed to fetch notifications') | ||
| : (err instanceof Error ? err.message : 'Failed to fetch notifications'); | ||
| setError(msg); |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Extract repetitive error handling logic to a helper function.
The error message extraction pattern is repeated identically in four places (fetchNotifications, markAsRead, markAllAsRead, deleteNotification). This violates DRY and makes maintenance harder.
Apply this refactor:
+// Helper to extract user-friendly error messages
+const extractErrorMessage = (err: unknown, fallback: string): string => {
+ const axiosErr = err as AxiosError<unknown> | undefined;
+ if (axiosErr?.response?.data && typeof axiosErr.response.data === 'object' && 'message' in axiosErr.response.data) {
+ return (axiosErr.response.data as { message?: string }).message ?? (err instanceof Error ? err.message : fallback);
+ }
+ return err instanceof Error ? err.message : fallback;
+};
+
const fetchNotifications = useCallback(async (unreadOnly = false) => {
// ...
} catch (err: unknown) {
- console.error('Failed to fetch notifications:', err);
- const axiosErr = err as AxiosError<unknown> | undefined;
- const msg = axiosErr?.response?.data && typeof axiosErr.response.data === 'object' && 'message' in axiosErr.response.data
- ? (axiosErr.response.data as { message?: string }).message ?? (err instanceof Error ? err.message : 'Failed to fetch notifications')
- : (err instanceof Error ? err.message : 'Failed to fetch notifications');
- setError(msg);
+ console.error('Failed to fetch notifications:', err);
+ setError(extractErrorMessage(err, 'Failed to fetch notifications'));
}Then apply the same simplification to markAsRead, markAllAsRead, and deleteNotification.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/app/contexts/NotificationContext.tsx around lines 57 to 68, the error
message extraction logic is duplicated; create a single helper function (e.g.
extractErrorMessage(err: unknown): string) in this file that encapsulates the
AxiosError/response.data.message checks and fallback to err.message or a default
string, reuse it from fetchNotifications, markAsRead, markAllAsRead, and
deleteNotification, and remove the in-place duplication so each catch simply
calls setError(extractErrorMessage(err)) after console.error.
| // Load reports on mount | ||
| useEffect(() => { | ||
| if (hasAccess) { | ||
| loadReports(); | ||
| } | ||
| }, [roles]); | ||
|
|
||
| const loadReports = async () => { | ||
| try { | ||
| setLoadingReports(true); | ||
| const data = await adminService.getReports(); | ||
| setReports(data); | ||
| } catch (err) { | ||
| console.error('Failed to load reports:', err); | ||
| showError('Failed to load reports history'); | ||
| } finally { | ||
| setLoadingReports(false); | ||
| } | ||
| }; |
There was a problem hiding this comment.
🧩 Analysis chain
Tighten useEffect dependencies for loadReports / hasAccess (address lint warning).
useEffect currently depends only on roles while using hasAccess and loadReports, which is why the hook-deps rule is warning. It’s functionally okay today, but easy to drift into stale-closure bugs later.
A small refactor using useCallback will both satisfy lint and keep behavior clear:
-import { useState, useEffect } from 'react';
+import { useState, useEffect, useCallback } from 'react';
@@
- const [reports, setReports] = useState<ReportResponse[]>([]);
- const [loadingReports, setLoadingReports] = useState(false);
-
- // Load reports on mount
- useEffect(() => {
- if (hasAccess) {
- loadReports();
- }
- }, [roles]);
-
- const loadReports = async () => {
+ const [reports, setReports] = useState<ReportResponse[]>([]);
+ const [loadingReports, setLoadingReports] = useState(false);
+
+ const loadReports = useCallback(async () => {
try {
setLoadingReports(true);
const data = await adminService.getReports();
setReports(data);
} catch (err) {
console.error('Failed to load reports:', err);
showError('Failed to load reports history');
} finally {
setLoadingReports(false);
}
- };
+ }, [showError]);
+
+ // Load reports on mount / when access changes
+ useEffect(() => {
+ if (hasAccess) {
+ loadReports();
+ }
+ }, [hasAccess, loadReports]);This keeps loadReports stable across renders (except when showError changes) and makes the effect’s dependency list explicit.
Also applies to: 30-41
🏁 Script executed:
#!/bin/bash
# Check if file exists and show lines 1-50 to understand context
if [ -f "src/app/dashboard/admin/reports/page.tsx" ]; then
echo "=== File found, showing lines 1-50 ==="
head -50 "src/app/dashboard/admin/reports/page.tsx"
else
echo "File not found at src/app/dashboard/admin/reports/page.tsx"
# Try to find similar files
echo "=== Searching for similar files ==="
find . -name "*reports*page*" -type f 2>/dev/null | head -10
fiLength of output: 1747
🏁 Script executed:
#!/bin/bash
# Search for showError usage and hasAccess to understand their scope
echo "=== Searching for showError definition/import ==="
rg -n "showError|useToast" src/app/dashboard/admin/reports/page.tsx -A2 -B2
echo ""
echo "=== Searching for hasAccess definition/import ==="
rg -n "hasAccess" src/app/dashboard/admin/reports/page.tsx -A1 -B1Length of output: 1494
🏁 Script executed:
#!/bin/bash
# Get more complete view of the useEffect and surrounding code
if [ -f "src/app/dashboard/admin/reports/page.tsx" ]; then
echo "=== Full file content ==="
cat "src/app/dashboard/admin/reports/page.tsx"
fiLength of output: 12386
Verify the useEffect dependencies and confirm the useCallback refactor is necessary.
The review correctly identifies an ESLint exhaustive-deps violation. The useEffect at lines 24–29 uses both hasAccess (line 25) and loadReports (line 26), but includes only [roles] in its dependency array. Additionally, loadReports is redefined on every render and captures showError in a closure, which could become stale if the showError reference changes.
The proposed refactor using useCallback with dependencies [showError] and updating the effect to depend on [hasAccess, loadReports] is correct and necessary. This ensures:
loadReportsremains stable across renders except whenshowErrorchanges- The effect properly reruns when either
hasAccessor the memoizedloadReportsfunction changes
Apply the suggested diff to resolve both the lint warning and prevent potential stale closure bugs.
🧰 Tools
🪛 GitHub Check: Install, Lint and Build
[warning] 28-28:
React Hook useEffect has missing dependencies: 'hasAccess' and 'loadReports'. Either include them or remove the dependency array
🤖 Prompt for AI Agents
In src/app/dashboard/admin/reports/page.tsx around lines 23 to 41, the useEffect
depends on roles but reads hasAccess and calls loadReports which is redefined
each render and closes over showError; refactor loadReports into a useCallback
that lists showError (and any other external vars it uses) in its dependency
array so the function is stable, then update the useEffect dependency array to
[hasAccess, loadReports] (remove roles) so the effect runs when access or the
memoized loader changes; ensure loadReports still sets loading state, calls
adminService.getReports, handles errors via the current showError, and resets
loading in finally.
| <div className="lg:col-span-2 space-y-6"> | ||
| <div className="automotive-card p-6"> | ||
| <div className="w-full rounded-lg overflow-hidden shadow-md bg-gradient-to-b from-white to-gray-50 dark:from-gray-900 dark:to-gray-800"> | ||
| <div className="w-full rounded-lg overflow-hidden shadow-md bg-linear-to-b from-white to-gray-50 dark:from-gray-900 dark:to-gray-800"> |
There was a problem hiding this comment.
Fix CSS class typo.
Line 108 uses bg-linear-to-b which is not a valid Tailwind class. This should be bg-gradient-to-b.
Apply this diff:
- <div className="w-full rounded-lg overflow-hidden shadow-md bg-linear-to-b from-white to-gray-50 dark:from-gray-900 dark:to-gray-800">
+ <div className="w-full rounded-lg overflow-hidden shadow-md bg-gradient-to-b from-white to-gray-50 dark:from-gray-900 dark:to-gray-800">📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <div className="w-full rounded-lg overflow-hidden shadow-md bg-linear-to-b from-white to-gray-50 dark:from-gray-900 dark:to-gray-800"> | |
| <div className="w-full rounded-lg overflow-hidden shadow-md bg-gradient-to-b from-white to-gray-50 dark:from-gray-900 dark:to-gray-800"> |
🤖 Prompt for AI Agents
In src/app/dashboard/vehicles/[vehicleId]/page.tsx around line 108, the div uses
an invalid Tailwind class "bg-linear-to-b"; replace it with the correct
"bg-gradient-to-b" so the background gradient works as intended and remove the
typo.
| /* Legacy support - keep for backward compatibility */ | ||
| .theme-filter-active { | ||
| background: linear-gradient(135deg, #0CA0E4 0%, #0CA0E4 100%); | ||
| color: white; | ||
| border: 1px solid #0CA0E4; | ||
| font-weight: 600; | ||
| box-shadow: 0 4px 6px -1px rgba(59, 130, 246, 0.3), 0 2px 4px -1px rgba(59, 130, 246, 0.2); | ||
| } | ||
|
|
||
| .theme-filter-inactive { | ||
| background-color: var(--bg-secondary); | ||
| color: var(--text-secondary); | ||
| border: 1px solid var(--border-color); | ||
| } | ||
|
|
||
| .theme-filter-inactive:hover { | ||
| background-color: #0CA0E4; | ||
| color: #0CA0E4; | ||
| border-color: #0CA0E4; | ||
| } | ||
|
|
||
| :root.dark .theme-filter-inactive:hover { | ||
| background-color:#0CA0E4; | ||
| color: #0CA0E4; | ||
| border-color: #60a5fa; | ||
| } |
There was a problem hiding this comment.
Fix invisible text on .theme-filter-inactive:hover.
In the legacy filter styles, the hover state sets text and background to the same color:
.theme-filter-inactive:hover {
background-color: #0CA0E4;
color: #0CA0E4;
border-color: #0CA0E4;
}This makes the label unreadable and hurts accessibility. Suggest something like:
.theme-filter-inactive:hover {
- background-color: #0CA0E4;
- color: #0CA0E4;
- border-color: #0CA0E4;
+ background-color: #0CA0E4;
+ color: #ffffff;
+ border-color: #0CA0E4;
}(or use the existing accent/text tokens if you prefer).
🤖 Prompt for AI Agents
In src/app/globals.css around lines 361 to 386, the hover rule for
.theme-filter-inactive sets background-color and color to the same hex
(#0CA0E4), making text invisible; update the hover styles so foreground and
background contrast (e.g., keep background #0CA0E4 but set color to a readable
value like white or the existing --text-accent/--text-primary token) and ensure
the border-color remains consistent (and adjust :root.dark variant to use a
contrasting text color as well).
| import axios from 'axios'; | ||
| import Cookies from 'js-cookie'; |
There was a problem hiding this comment.
Remove or gate logging of tokens and full auth responses
The new login implementation works functionally, but the debug logging is problematic:
console.log('Login response:', res.data);console.log('Extracted token:', token);- Similar logs in
verifyEmailalso print verification responses and access tokens.
Even on the client, logging tokens and full auth payloads is risky and noisy for production; they can leak into screenshots, error-reporting tools, or shared console logs.
I’d recommend either removing these logs entirely or gating them behind an explicit debug flag / non‑production check, e.g.:
async login(payload: LoginRequest) {
- try {
- // api baseURL already includes '/api/v1'
- const res = await api.post('/auth/login', payload);
- // backend returns token in body
- const token = res.data?.token || res.data?.accessToken || null;
- console.log('Login response:', res.data);
- console.log('Extracted token:', token);
+ try {
+ const res = await api.post('/auth/login', payload);
+ const token = res.data?.token || res.data?.accessToken || null;
if (token) {
Cookies.set(TOKEN_COOKIE, token, { expires: 7 });
- console.log('Token saved to cookie');
}
return res.data;
@@
- async verifyEmail(token: string) {
- console.log('authService.verifyEmail called with token:', token);
+ async verifyEmail(token: string) {
try {
const res = await api.post('/auth/verify-email', { token });
- console.log('Verification API response:', res.data);
- // Save token to cookie after verification
const accessToken = res.data?.token || res.data?.accessToken || null;
if (accessToken) {
Cookies.set(TOKEN_COOKIE, accessToken, { expires: 7 });
- console.log('Access token saved to cookie');
}
return res.data;The Axios-based error narrowing and rethrow logic itself looks fine.
Also applies to: 15-35, 85-95
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Style
✏️ Tip: You can customize this high-level summary in your review settings.