style: Update AIChatWidget UI#20
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughReplaces external auth hook with a local/mock auth flow, adds in-file theming constants, changes API endpoint to localhost with token-in-header/payload, improves error handling and response processing (supports optional Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant User
participant UI as AIChatWidget
participant Auth as localAuthHook
participant API as localhost:/api/ai/chat
Note over UI,Auth: New local token flow
User->>UI: enters message & submits
UI->>UI: append immediate user message to history
UI->>Auth: request token (mock/local)
Auth-->>UI: return token (or null)
UI->>API: POST payload + token in header/payload
API-->>UI: 200 OK with { reply, tool_executed? }
alt tool_executed present
UI->>UI: prepend tool indicator to AI reply
end
UI->>User: render updated message list (styled via theme classes)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 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: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/app/components/chatbot/AIChatWidget.tsx (1)
79-79: Fix ESLint error: replaceanytype annotation.Line 79 has an ESLint error from the
no-explicit-anyrule. Theerrorparameter should be typed more specifically. UseErrororunknowninstead.- } catch (error: any) { + } catch (error: unknown) {If using
unknown, you'll need to add type guards when accessing error properties:- } catch (error: any) { + } catch (error: unknown) { console.error("Chat Error:", error); const errorMessage: Message = { - text: error.message.includes('401') + text: error instanceof Error && error.message.includes('401') ? "Your session has expired. Please log in again." : "Sorry, I'm having trouble with the services. Try again later.", sender: 'system' };Alternatively, use
Errorif you're confident the caught error is always an Error instance:- } catch (error: any) { + } catch (error: Error) {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/app/components/chatbot/AIChatWidget.tsx(1 hunks)
🧰 Additional context used
🪛 GitHub Actions: Build and Test Frontend_Web
src/app/components/chatbot/AIChatWidget.tsx
[error] 79-79: ESLint: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any (no-explicit-any)
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
src/app/components/chatbot/AIChatWidget.tsx (1)
4-15: Consider a proper theme system for better maintainability.The theme object groups CSS classes, which is an improvement over scattered hardcoded styles. However, for better theme management, consider using CSS variables, Tailwind's built-in dark mode utilities directly, or a theme provider like next-themes.
📜 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 (2)
package.json(1 hunks)src/app/components/chatbot/AIChatWidget.tsx(3 hunks)
🧰 Additional context used
🪛 GitHub Actions: Build and Test Frontend_Web
src/app/components/chatbot/AIChatWidget.tsx
[error] 110-110: ESLint: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
🪛 GitHub Check: Install, Lint and Build
src/app/components/chatbot/AIChatWidget.tsx
[failure] 110-110:
Unexpected any. Specify a different type
🔇 Additional comments (5)
package.json (1)
14-14: LGTM!The lucide-react dependency is properly integrated and used for UI icons (Sparkles, Bolt) in the AIChatWidget component.
src/app/components/chatbot/AIChatWidget.tsx (4)
1-2: LGTM!Icon imports are correctly integrated with the lucide-react dependency and used appropriately in the UI.
17-27: LGTM!The
tool_executedfield is properly typed as optional and correctly integrated with the response handling logic.
91-104: LGTM!The enhanced error handling with HTTP status fallback and the tool execution indicator provide better user feedback and debugging visibility.
130-200: LGTM!The UI updates improve visual consistency with theme-based styling, add helpful visual indicators (icons), and provide clear user feedback when authentication is required.
|
|
||
| const API_ENDPOINT = '/api/v1/ai/chat'; // This will be routed by your API Gateway | ||
| // NOTE: Using localhost:8091 to test against the locally running FastAPI service | ||
| const API_ENDPOINT = 'http://localhost:8091/api/v1/ai/chat'; |
There was a problem hiding this comment.
Replace hardcoded localhost URL with environment variable.
The API endpoint is hardcoded to localhost:8091, which will fail in production, staging, and any non-local environment.
Use an environment variable for the base URL:
-const API_ENDPOINT = 'http://localhost:8091/api/v1/ai/chat';
+const API_ENDPOINT = `${process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:8091'}/api/v1/ai/chat`;Then configure .env.local (local), .env.production, etc.:
NEXT_PUBLIC_API_BASE_URL=https://api.yourdomain.com
📝 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 API_ENDPOINT = 'http://localhost:8091/api/v1/ai/chat'; | |
| const API_ENDPOINT = `${process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:8091'}/api/v1/ai/chat`; |
🤖 Prompt for AI Agents
In src/app/components/chatbot/AIChatWidget.tsx around line 36, replace the
hardcoded API endpoint 'http://localhost:8091/api/v1/ai/chat' with a URL built
from an environment variable: read process.env.NEXT_PUBLIC_API_BASE_URL (falling
back to a sensible default only for local dev if needed), append
'/api/v1/ai/chat' while normalizing slashes to avoid double slashes, and
export/use that constant; update docs/.env files to include
NEXT_PUBLIC_API_BASE_URL for each environment.
| // --- MOCK AUTH HOOK --- | ||
| // Provides a mock token; replace this with your actual useAuth hook | ||
| const useAuth = (): AuthHook => ({ | ||
| token: "mock-jwt-token-for-user-12345", | ||
| isLoggedIn: true | ||
| }); |
There was a problem hiding this comment.
Remove mock authentication before production deployment.
The mock useAuth hook returns a hardcoded token and always reports the user as logged in. This bypasses real authentication and poses a security risk.
Replace with your actual authentication hook:
-// --- MOCK AUTH HOOK ---
-// Provides a mock token; replace this with your actual useAuth hook
-const useAuth = (): AuthHook => ({
- token: "mock-jwt-token-for-user-12345",
- isLoggedIn: true
-});
+// Import your real auth hook
+import { useAuth } from '@/hooks/useAuth'; // or your actual auth hook locationCommittable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/app/components/chatbot/AIChatWidget.tsx around lines 38 to 43, remove the
mock useAuth hook that returns a hardcoded token and replace it with your real
authentication hook (e.g., import and call your existing useAuth/useUser hook);
ensure the component reads the token from the real hook, handles the
unauthenticated state (null/undefined token or isLoggedIn false) gracefully
(show login prompt or disable features), and do not leave any hardcoded tokens
in source code or logs.
| const payload = { | ||
| query: message, | ||
| session_id: sessionId, | ||
| token: userToken, // Passed in body for Agent_Bot context retrieval | ||
| token: userToken, // Sent in body for Agent_Bot context | ||
| }; | ||
|
|
||
| const response = await fetch(API_ENDPOINT, { | ||
| method: 'POST', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| 'Authorization': `Bearer ${userToken}`, // Passed in header for Gateway validation | ||
| 'Authorization': `Bearer ${userToken}`, // Sent in header for Gateway validation |
There was a problem hiding this comment.
Token is transmitted twice—clarify the intent or remove redundancy.
The token is sent in both the request body (line 79) and the Authorization header (line 86). This duplication may cause confusion about which location is authoritative.
If the Gateway validates via header and Agent_Bot needs it in the body, document this clearly:
const payload = {
query: message,
session_id: sessionId,
- token: userToken, // Sent in body for Agent_Bot context
+ token: userToken, // REQUIRED: Agent_Bot service needs token in body for internal routing
};
const response = await fetch(API_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
- 'Authorization': `Bearer ${userToken}`, // Sent in header for Gateway validation
+ 'Authorization': `Bearer ${userToken}`, // REQUIRED: API Gateway validates token in header
},
body: JSON.stringify(payload),
});Otherwise, if only one is needed, remove the redundant transmission.
🤖 Prompt for AI Agents
In src/app/components/chatbot/AIChatWidget.tsx around lines 76 to 86, the user
token is being sent twice (in payload.session_id/token and again in the
Authorization header) causing ambiguity; either remove the token field from the
JSON payload and rely solely on the Authorization header for Gateway validation,
or if the downstream Agent_Bot requires the token in the body, keep both but add
a clear comment explaining that header is for Gateway auth and body.token is for
Agent_Bot, and update any related types/tests to reflect the chosen approach.
| setSessionId(data.session_id); // CRITICAL: Save the session ID for the next turn | ||
| setSessionId(data.session_id); // CRITICAL: Save the session ID | ||
|
|
||
| } catch (error: any) { |
There was a problem hiding this comment.
Replace any type with specific error type.
Using any defeats TypeScript's type safety and is flagged by the linter.
Apply this diff:
-} catch (error: any) {
+} catch (error: unknown) {
console.error("Chat Error:", error);
const errorMessage: Message = {
- text: "Sorry, I'm having trouble connecting to the services. Please try again later.",
+ text: error instanceof Error ? error.message : "Sorry, I'm having trouble connecting to the services. Please try again later.",
sender: 'system'
};Or if you prefer to keep the generic message:
-} catch (error: any) {
+} catch (error: unknown) {
console.error("Chat Error:", error);Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 GitHub Actions: Build and Test Frontend_Web
[error] 110-110: ESLint: Unexpected any. Specify a different type. @typescript-eslint/no-explicit-any
🪛 GitHub Check: Install, Lint and Build
[failure] 110-110:
Unexpected any. Specify a different type
🤖 Prompt for AI Agents
In src/app/components/chatbot/AIChatWidget.tsx around line 110, the catch clause
currently uses the `any` type which bypasses TypeScript safety; change the catch
parameter to `unknown` (or `error: unknown`) and then narrow it before use
(e.g., use `if (error instanceof Error) { const msg = error.message } else {
const msg = String(error) }`) or explicitly type-guard/extract the message so
you never assume `any`; update subsequent error handling/logging to use the
safely extracted message.
Summary by CodeRabbit
New Features
Bug Fixes / Reliability
Chores
Dependencies