|
1 | 1 | "use client"; |
2 | 2 |
|
3 | | -import { ArrowLeftIcon, BotIcon, SendIcon } from "lucide-react"; |
| 3 | +import { BotIcon, SendIcon } from "lucide-react"; |
4 | 4 | import { useCallback, useEffect, useRef, useState } from "react"; |
5 | 5 | import type { Team } from "@/api/team"; |
6 | 6 | import { MarkdownRenderer } from "@/components/blocks/markdown-renderer"; |
7 | 7 | import { Reasoning } from "@/components/chat/Reasoning"; |
8 | 8 | import { Button } from "@/components/ui/button"; |
9 | 9 | import { Textarea } from "@/components/ui/textarea"; |
10 | 10 | import { useDashboardRouter } from "@/lib/DashboardRouter"; |
11 | | -import { SupportHeader } from "./SupportHeader"; |
12 | 11 | import { SupportTicketForm } from "./SupportTicketForm"; |
13 | 12 |
|
14 | 13 | interface CreateSupportCaseProps { |
@@ -213,178 +212,157 @@ export function CreateSupportCase({ team, authToken }: CreateSupportCaseProps) { |
213 | 212 | }, [_handleStartChat]); |
214 | 213 |
|
215 | 214 | return ( |
216 | | - <div className="min-h-screen bg-background text-foreground"> |
217 | | - <SupportHeader |
218 | | - buttonText="" |
219 | | - buttonIcon={ArrowLeftIcon} |
220 | | - onButtonClick={() => {}} |
221 | | - /> |
222 | | - |
223 | | - <div className="container flex max-w-6xl flex-col gap-4 py-6 pb-20 px-4 sm:px-6 lg:px-8"> |
224 | | - <div className="mb-4"> |
225 | | - <Button |
226 | | - onClick={handleBackToSupport} |
227 | | - variant="outline" |
228 | | - className="border-border bg-card text-foreground hover:bg-accent hover:text-foreground" |
229 | | - > |
230 | | - <span className="flex items-center gap-2"> |
231 | | - <ArrowLeftIcon className="w-4 h-4" /> |
232 | | - Back to Support |
233 | | - </span> |
234 | | - </Button> |
235 | | - </div> |
236 | | - |
237 | | - <div className="max-w-4xl mx-auto"> |
238 | | - <div className="border border-border bg-card rounded-lg h-[800px] flex flex-col"> |
239 | | - {/* Chat Header */} |
240 | | - <div className="flex items-center gap-3 p-4 border-b border-border"> |
241 | | - <div className="relative bg-primary/10 p-2 rounded-full"> |
242 | | - <BotIcon className="w-5 h-5 text-primary" /> |
243 | | - <div className="absolute -top-1 -right-1 w-3 h-3 bg-green-500 rounded-full border-2 border-card"></div> |
244 | | - </div> |
245 | | - <div> |
246 | | - <h3 className="text-foreground font-medium"> |
247 | | - Ask AI for support |
248 | | - </h3> |
249 | | - <p className="text-xs text-muted-foreground">Online</p> |
250 | | - </div> |
| 215 | + <div className="flex flex-col gap-4 py-6 pb-20 px-4 sm:px-6 lg:px-8"> |
| 216 | + <div className="max-w-4xl mx-auto"> |
| 217 | + <div className="border border-border bg-card rounded-lg h-[800px] flex flex-col"> |
| 218 | + {/* Chat Header */} |
| 219 | + <div className="flex items-center gap-3 p-4 border-b border-border"> |
| 220 | + <div className="relative bg-primary/10 p-2 rounded-full"> |
| 221 | + <BotIcon className="w-5 h-5 text-primary" /> |
| 222 | + <div className="absolute -top-1 -right-1 w-3 h-3 bg-green-500 rounded-full border-2 border-card"></div> |
251 | 223 | </div> |
| 224 | + <div> |
| 225 | + <h3 className="text-foreground font-medium"> |
| 226 | + Ask AI for support |
| 227 | + </h3> |
| 228 | + <p className="text-xs text-muted-foreground">Online</p> |
| 229 | + </div> |
| 230 | + </div> |
252 | 231 |
|
253 | | - {/* Chat Messages */} |
254 | | - <div |
255 | | - className="flex-1 p-6 overflow-y-auto space-y-4" |
256 | | - ref={chatContainerRef} |
257 | | - > |
258 | | - {chatMessages.map((message, index) => ( |
| 232 | + {/* Chat Messages */} |
| 233 | + <div |
| 234 | + className="flex-1 p-6 overflow-y-auto space-y-4" |
| 235 | + ref={chatContainerRef} |
| 236 | + > |
| 237 | + {chatMessages.map((message, index) => ( |
| 238 | + <div |
| 239 | + key={message.id} |
| 240 | + className={`flex ${message.isUser ? "justify-end" : "justify-start"}`} |
| 241 | + > |
259 | 242 | <div |
260 | | - key={message.id} |
261 | | - className={`flex ${message.isUser ? "justify-end" : "justify-start"}`} |
| 243 | + className={`max-w-[80%] p-4 rounded-lg ${ |
| 244 | + message.isUser |
| 245 | + ? "bg-primary text-primary-foreground" |
| 246 | + : "bg-muted text-foreground border border-border" |
| 247 | + }`} |
262 | 248 | > |
263 | | - <div |
264 | | - className={`max-w-[80%] p-4 rounded-lg ${ |
265 | | - message.isUser |
266 | | - ? "bg-primary text-primary-foreground" |
267 | | - : "bg-muted text-foreground border border-border" |
268 | | - }`} |
269 | | - > |
270 | | - {message.isUser ? ( |
271 | | - <p className="text-sm whitespace-pre-line"> |
272 | | - {message.content} |
273 | | - </p> |
274 | | - ) : message.content === "__reasoning__" ? ( |
275 | | - <Reasoning isPending={true} texts={[]} /> |
276 | | - ) : ( |
277 | | - <MarkdownRenderer |
278 | | - className="text-sm" |
279 | | - li={{ className: "text-foreground" }} |
280 | | - p={{ className: "text-foreground" }} |
281 | | - markdownText={message.content} |
282 | | - /> |
283 | | - )} |
284 | | - <p className="text-xs opacity-70 mt-2"> |
285 | | - {new Date(message.timestamp).toLocaleTimeString()} |
| 249 | + {message.isUser ? ( |
| 250 | + <p className="text-sm whitespace-pre-line"> |
| 251 | + {message.content} |
286 | 252 | </p> |
| 253 | + ) : message.content === "__reasoning__" ? ( |
| 254 | + <Reasoning isPending={true} texts={[]} /> |
| 255 | + ) : ( |
| 256 | + <MarkdownRenderer |
| 257 | + className="text-sm" |
| 258 | + li={{ className: "text-foreground" }} |
| 259 | + p={{ className: "text-foreground" }} |
| 260 | + markdownText={message.content} |
| 261 | + /> |
| 262 | + )} |
| 263 | + <p className="text-xs opacity-70 mt-2"> |
| 264 | + {new Date(message.timestamp).toLocaleTimeString()} |
| 265 | + </p> |
| 266 | + |
| 267 | + {/* Show Back to Support button for success message */} |
| 268 | + {!message.isUser && message.isSuccessMessage && ( |
| 269 | + <div className="mt-3 pt-3 border-t border-border"> |
| 270 | + <Button |
| 271 | + onClick={handleBackToSupport} |
| 272 | + size="sm" |
| 273 | + className="bg-primary hover:bg-primary/80 text-primary-foreground transition-opacity" |
| 274 | + > |
| 275 | + Back to Support |
| 276 | + </Button> |
| 277 | + </div> |
| 278 | + )} |
287 | 279 |
|
288 | | - {/* Show Back to Support button for success message */} |
289 | | - {!message.isUser && message.isSuccessMessage && ( |
| 280 | + {/* Show Create Support Case button in the AI response - only if form not shown and after user interaction */} |
| 281 | + {!message.isUser && |
| 282 | + index === chatMessages.length - 1 && |
| 283 | + !showCreateForm && |
| 284 | + !message.isSuccessMessage && |
| 285 | + message.content !== "__reasoning__" && |
| 286 | + chatMessages.length > 2 && ( |
290 | 287 | <div className="mt-3 pt-3 border-t border-border"> |
291 | 288 | <Button |
292 | | - onClick={handleBackToSupport} |
| 289 | + onClick={() => setShowCreateForm(true)} |
293 | 290 | size="sm" |
294 | 291 | className="bg-primary hover:bg-primary/80 text-primary-foreground transition-opacity" |
295 | 292 | > |
296 | | - Back to Support |
| 293 | + Create Support Case |
297 | 294 | </Button> |
298 | 295 | </div> |
299 | 296 | )} |
300 | 297 |
|
301 | | - {/* Show Create Support Case button in the AI response - only if form not shown and after user interaction */} |
302 | | - {!message.isUser && |
303 | | - index === chatMessages.length - 1 && |
304 | | - !showCreateForm && |
305 | | - !message.isSuccessMessage && |
306 | | - message.content !== "__reasoning__" && |
307 | | - chatMessages.length > 2 && ( |
308 | | - <div className="mt-3 pt-3 border-t border-border"> |
309 | | - <Button |
310 | | - onClick={() => setShowCreateForm(true)} |
311 | | - size="sm" |
312 | | - className="bg-primary hover:bg-primary/80 text-primary-foreground transition-opacity" |
313 | | - > |
| 298 | + {/* Show Support Case Form in the same message bubble when button is clicked */} |
| 299 | + {!message.isUser && |
| 300 | + index === chatMessages.length - 1 && |
| 301 | + showCreateForm && |
| 302 | + message.content !== "__reasoning__" && ( |
| 303 | + <div className="mt-4 pt-4 border-t border-border"> |
| 304 | + <div className="mb-4"> |
| 305 | + <h3 className="text-lg font-semibold text-foreground mb-2"> |
314 | 306 | Create Support Case |
315 | | - </Button> |
| 307 | + </h3> |
| 308 | + <p className="text-sm text-muted-foreground"> |
| 309 | + Let's create a detailed support case for our |
| 310 | + technical team. |
| 311 | + </p> |
316 | 312 | </div> |
317 | | - )} |
318 | 313 |
|
319 | | - {/* Show Support Case Form in the same message bubble when button is clicked */} |
320 | | - {!message.isUser && |
321 | | - index === chatMessages.length - 1 && |
322 | | - showCreateForm && |
323 | | - message.content !== "__reasoning__" && ( |
324 | | - <div className="mt-4 pt-4 border-t border-border"> |
325 | | - <div className="mb-4"> |
326 | | - <h3 className="text-lg font-semibold text-foreground mb-2"> |
327 | | - Create Support Case |
328 | | - </h3> |
329 | | - <p className="text-sm text-muted-foreground"> |
330 | | - Let's create a detailed support case for our |
331 | | - technical team. |
332 | | - </p> |
333 | | - </div> |
334 | | - |
335 | | - <SupportTicketForm |
336 | | - team={team} |
337 | | - productLabel={productLabel} |
338 | | - setProductLabel={setProductLabel} |
339 | | - conversationId={conversationId} |
340 | | - onSuccess={() => { |
341 | | - setShowCreateForm(false); |
342 | | - setProductLabel(""); |
343 | | - setChatMessages((prev) => [ |
344 | | - ...prev, |
345 | | - { |
346 | | - id: Date.now(), |
347 | | - content: `✅ **Support case created successfully!**\n\nYour case has been submitted to our technical team. You'll receive updates via email at ${team.billingEmail}.\n\nYou can track your case in the support portal above.`, |
348 | | - isUser: false, |
349 | | - timestamp: new Date().toISOString(), |
350 | | - isSuccessMessage: true, |
351 | | - }, |
352 | | - ]); |
353 | | - }} |
354 | | - /> |
355 | | - </div> |
356 | | - )} |
357 | | - </div> |
358 | | - </div> |
359 | | - ))} |
360 | | - <div ref={messagesEndRef} /> |
361 | | - </div> |
362 | | - |
363 | | - {/* Chat Input */} |
364 | | - {!showCreateForm && ( |
365 | | - <div className="p-6 border-t border-border"> |
366 | | - <div className="relative"> |
367 | | - <Textarea |
368 | | - placeholder="Type your message here..." |
369 | | - value={chatInput} |
370 | | - onChange={(e) => setChatInput(e.target.value)} |
371 | | - onKeyDown={handleChatKeyPress} |
372 | | - className="flex-1 min-h-[120px] max-h-[300px] bg-background border-border text-foreground placeholder:text-muted-foreground focus-visible:ring-0 focus-visible:ring-offset-0 focus-visible:border-primary resize-y pr-12" |
373 | | - /> |
374 | | - <Button |
375 | | - onClick={handleChatSend} |
376 | | - disabled={!chatInput.trim()} |
377 | | - className="absolute bottom-3 right-3 bg-primary hover:bg-primary/90 text-primary-foreground disabled:opacity-50 disabled:cursor-not-allowed h-8 w-8 p-0" |
378 | | - > |
379 | | - <SendIcon className="w-4 h-4" /> |
380 | | - </Button> |
| 314 | + <SupportTicketForm |
| 315 | + team={team} |
| 316 | + productLabel={productLabel} |
| 317 | + setProductLabel={setProductLabel} |
| 318 | + conversationId={conversationId} |
| 319 | + onSuccess={() => { |
| 320 | + setShowCreateForm(false); |
| 321 | + setProductLabel(""); |
| 322 | + setChatMessages((prev) => [ |
| 323 | + ...prev, |
| 324 | + { |
| 325 | + id: Date.now(), |
| 326 | + content: `✅ **Support case created successfully!**\n\nYour case has been submitted to our technical team. You'll receive updates via email at ${team.billingEmail}.\n\nYou can track your case in the support portal above.`, |
| 327 | + isUser: false, |
| 328 | + timestamp: new Date().toISOString(), |
| 329 | + isSuccessMessage: true, |
| 330 | + }, |
| 331 | + ]); |
| 332 | + }} |
| 333 | + /> |
| 334 | + </div> |
| 335 | + )} |
381 | 336 | </div> |
382 | | - <p className="text-xs text-muted-foreground mt-2"> |
383 | | - Press Enter to send, Shift+Enter for new line |
384 | | - </p> |
385 | 337 | </div> |
386 | | - )} |
| 338 | + ))} |
| 339 | + <div ref={messagesEndRef} /> |
387 | 340 | </div> |
| 341 | + |
| 342 | + {/* Chat Input */} |
| 343 | + {!showCreateForm && ( |
| 344 | + <div className="p-6 border-t border-border"> |
| 345 | + <div className="relative"> |
| 346 | + <Textarea |
| 347 | + placeholder="Type your message here..." |
| 348 | + value={chatInput} |
| 349 | + onChange={(e) => setChatInput(e.target.value)} |
| 350 | + onKeyDown={handleChatKeyPress} |
| 351 | + className="flex-1 min-h-[120px] max-h-[300px] bg-background border-border text-foreground placeholder:text-muted-foreground focus-visible:ring-0 focus-visible:ring-offset-0 focus-visible:border-primary resize-y pr-12" |
| 352 | + /> |
| 353 | + <Button |
| 354 | + onClick={handleChatSend} |
| 355 | + disabled={!chatInput.trim()} |
| 356 | + className="absolute bottom-3 right-3 bg-primary hover:bg-primary/90 text-primary-foreground disabled:opacity-50 disabled:cursor-not-allowed h-8 w-8 p-0" |
| 357 | + > |
| 358 | + <SendIcon className="w-4 h-4" /> |
| 359 | + </Button> |
| 360 | + </div> |
| 361 | + <p className="text-xs text-muted-foreground mt-2"> |
| 362 | + Press Enter to send, Shift+Enter for new line |
| 363 | + </p> |
| 364 | + </div> |
| 365 | + )} |
388 | 366 | </div> |
389 | 367 | </div> |
390 | 368 | </div> |
|
0 commit comments