dr-data Claude commited on
Commit
8e5e6d5
·
1 Parent(s): cc2485e

Fix OpenRouter API key input field validation

Browse files

- Add client-side validation to check API key before sending requests
- Improve error handling with toast notifications and provider modal
- Add computed value to ensure proper API key validation
- Fix API key serialization to handle empty strings properly
- Add proper trimming and undefined handling for edge cases

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

Files changed (1) hide show
  1. components/editor/ask-ai/index.tsx +27 -3
components/editor/ask-ai/index.tsx CHANGED
@@ -50,6 +50,11 @@ export function AskAI({
50
  setSelectedElement: React.Dispatch<React.SetStateAction<HTMLElement | null>>;
51
  }) {
52
  const [openrouterApiKey] = useLocalStorage<string>("openrouter-api-key", "");
 
 
 
 
 
53
  const refThink = useRef<HTMLDivElement | null>(null);
54
  const audio = useRef<HTMLAudioElement | null>(null);
55
 
@@ -105,8 +110,18 @@ export function AskAI({
105
  promptLength: prompt.length,
106
  hasSelectedElement: !!selectedElementHtml,
107
  selectedElementLength: selectedElementHtml.length,
108
- totalHtmlLength: html.length
 
109
  });
 
 
 
 
 
 
 
 
 
110
  const request = await fetch("/api/ask-ai", {
111
  method: "PUT",
112
  body: JSON.stringify({
@@ -116,7 +131,7 @@ export function AskAI({
116
  model,
117
  html,
118
  selectedElementHtml,
119
- openrouterApiKey,
120
  }),
121
  headers: {
122
  "Content-Type": "application/json",
@@ -159,6 +174,15 @@ export function AskAI({
159
  htmlLength: html.length
160
  });
161
 
 
 
 
 
 
 
 
 
 
162
  const request = await fetch("/api/ask-ai", {
163
  method: "POST",
164
  body: JSON.stringify({
@@ -167,7 +191,7 @@ export function AskAI({
167
  model,
168
  html: isSameHtml ? "" : html,
169
  redesignMarkdown,
170
- openrouterApiKey,
171
  }),
172
  headers: {
173
  "Content-Type": "application/json",
 
50
  setSelectedElement: React.Dispatch<React.SetStateAction<HTMLElement | null>>;
51
  }) {
52
  const [openrouterApiKey] = useLocalStorage<string>("openrouter-api-key", "");
53
+
54
+ // Check if OpenRouter API key is properly loaded from localStorage
55
+ const isOpenRouterApiKeyValid = useMemo(() => {
56
+ return openrouterApiKey && openrouterApiKey.trim().length > 0;
57
+ }, [openrouterApiKey]);
58
  const refThink = useRef<HTMLDivElement | null>(null);
59
  const audio = useRef<HTMLAudioElement | null>(null);
60
 
 
110
  promptLength: prompt.length,
111
  hasSelectedElement: !!selectedElementHtml,
112
  selectedElementLength: selectedElementHtml.length,
113
+ totalHtmlLength: html.length,
114
+ hasOpenRouterApiKey: isOpenRouterApiKeyValid
115
  });
116
+
117
+ // Validate OpenRouter API key if using OpenRouter
118
+ if (provider === "openrouter" && !isOpenRouterApiKeyValid) {
119
+ toast.error("OpenRouter API key is required for this model");
120
+ setOpenProvider(true);
121
+ setProviderError("OpenRouter API key is required for this model");
122
+ setisAiWorking(false);
123
+ return;
124
+ }
125
  const request = await fetch("/api/ask-ai", {
126
  method: "PUT",
127
  body: JSON.stringify({
 
131
  model,
132
  html,
133
  selectedElementHtml,
134
+ openrouterApiKey: openrouterApiKey?.trim() || undefined,
135
  }),
136
  headers: {
137
  "Content-Type": "application/json",
 
174
  htmlLength: html.length
175
  });
176
 
177
+ // Validate OpenRouter API key if using OpenRouter
178
+ if (provider === "openrouter" && !isOpenRouterApiKeyValid) {
179
+ toast.error("OpenRouter API key is required for this model");
180
+ setOpenProvider(true);
181
+ setProviderError("OpenRouter API key is required for this model");
182
+ setisAiWorking(false);
183
+ return;
184
+ }
185
+
186
  const request = await fetch("/api/ask-ai", {
187
  method: "POST",
188
  body: JSON.stringify({
 
191
  model,
192
  html: isSameHtml ? "" : html,
193
  redesignMarkdown,
194
+ openrouterApiKey: openrouterApiKey?.trim() || undefined,
195
  }),
196
  headers: {
197
  "Content-Type": "application/json",