Skip to content

Commit c4c8e01

Browse files
Refactor DocsPage component to optimize Q&A handling
1 parent 176b917 commit c4c8e01

File tree

2 files changed

+39
-12
lines changed

2 files changed

+39
-12
lines changed

src/app/(protected)/chat/page.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,12 @@ import { Button } from "@/components/ui/button";
66
import { Input } from "@/components/ui/input";
77
import { Badge } from "@/components/ui/badge";
88
import { ScrollArea } from "@/components/ui/scroll-area";
9-
import { Skeleton } from "@/components/ui/skeleton";
109
import {
1110
Send,
1211
MessageSquare,
13-
Code2,
1412
Sparkles,
15-
AlertCircle,
1613
Loader2,
1714
FileCode,
18-
Bot,
1915
Plus
2016
} from "lucide-react";
2117
import { toast } from "sonner";

src/app/(protected)/docs/page.tsx

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client";
22

3-
import React, { useState, useEffect } from 'react';
3+
import React, { useState, useEffect, useCallback, useRef } from 'react';
44
import { useProjectsContext } from '@/context/ProjectsContext';
55
import { getProjectDocs, regenerateProjectDocs, modifyDocsWithQna, getDocsQnaHistory, createDocsShare, revokeDocsShare, getDocsShare, deleteDocsQnaRecord, deleteAllDocsQnaHistory } from '@/lib/actions';
66
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
@@ -99,6 +99,7 @@ function DocsPage() {
9999
const [qnaQuestion, setQnaQuestion] = useState('');
100100
const [isProcessingQna, setIsProcessingQna] = useState(false);
101101
const [activeTab, setActiveTab] = useState('preview');
102+
const qnaInputRef = useRef<HTMLTextAreaElement>(null);
102103
const [shareToken, setShareToken] = useState<string | null>(null);
103104
const [isCreatingShare, setIsCreatingShare] = useState(false);
104105
const [isRevokingShare, setIsRevokingShare] = useState(false);
@@ -215,13 +216,15 @@ function DocsPage() {
215216
};
216217

217218
const handleQnaSubmit = async () => {
218-
if (!selectedProjectId || !qnaQuestion.trim()) return;
219+
// Get value from ref if available, otherwise use state
220+
const questionValue = qnaInputRef.current?.value || qnaQuestion;
221+
if (!selectedProjectId || !questionValue.trim()) return;
219222

220223
setIsProcessingQna(true);
221224
setError(null);
222225

223226
try {
224-
const result = await modifyDocsWithQna(selectedProjectId, qnaQuestion);
227+
const result = await modifyDocsWithQna(selectedProjectId, questionValue);
225228
setDocsData(result.docs);
226229
if (result.docs.content) {
227230
setMetadata(parseDocsMetadata(result.docs.content));
@@ -230,6 +233,9 @@ function DocsPage() {
230233
// Add to Q&A history
231234
setQnaHistory(prev => [result.qnaRecord, ...prev]);
232235
setQnaQuestion('');
236+
if (qnaInputRef.current) {
237+
qnaInputRef.current.value = '';
238+
}
233239

234240
// Switch to preview tab to show the updated docs
235241
setActiveTab('preview');
@@ -249,6 +255,16 @@ function DocsPage() {
249255
}
250256
};
251257

258+
// Optimized onChange handler to prevent lag - debounced state update for button disabled state
259+
const handleQnaQuestionChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
260+
const value = e.target.value;
261+
// Update state with a small delay to prevent blocking the input
262+
// The input itself updates immediately (uncontrolled), state syncs for button logic
263+
setTimeout(() => {
264+
setQnaQuestion(value);
265+
}, 0);
266+
}, []);
267+
252268
const fetchQnaHistory = async () => {
253269
if (!selectedProjectId) return;
254270

@@ -529,6 +545,16 @@ function DocsPage() {
529545
</div>
530546
</div>
531547

548+
{/* Regenerating Status Indicator */}
549+
{isRegenerating && (
550+
<div className="mx-2 sm:mx-4 mb-4 sm:mb-6">
551+
<div className="bg-white/10 border border-white/20 rounded-lg px-3 sm:px-4 py-2 sm:py-3 flex items-center gap-2 sm:gap-3">
552+
<Loader2 className="h-4 w-4 sm:h-5 sm:w-5 text-white animate-spin flex-shrink-0" />
553+
<span className="text-white text-sm sm:text-base mobile-no-truncate">Regenerating documentation...</span>
554+
</div>
555+
</div>
556+
)}
557+
532558
{metadata && (
533559
<div className="px-2 sm:px-4 mb-4 sm:mb-6">
534560
<div className="flex flex-wrap gap-1 sm:gap-2 md:gap-3">
@@ -731,8 +757,9 @@ function DocsPage() {
731757
<div className="pb-4 sm:pb-6 border-b border-white/10">
732758
<div className="space-y-4 sm:space-y-6">
733759
<textarea
734-
value={qnaQuestion}
735-
onChange={(e) => setQnaQuestion(e.target.value)}
760+
ref={qnaInputRef}
761+
defaultValue={qnaQuestion}
762+
onChange={handleQnaQuestionChange}
736763
placeholder="Which file contains authentication logic?"
737764
className="w-full h-[60px] sm:h-[80px] p-2 sm:p-3 bg-black/30 border border-white/20 rounded-lg resize-none text-sm sm:text-base text-white placeholder:text-white/50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent mobile-no-truncate"
738765
onKeyDown={(e) => {
@@ -741,10 +768,14 @@ function DocsPage() {
741768
handleQnaSubmit();
742769
}
743770
}}
771+
autoComplete="off"
772+
autoCorrect="off"
773+
autoCapitalize="off"
774+
spellCheck="false"
744775
/>
745776
<Button
746777
onClick={handleQnaSubmit}
747-
disabled={isProcessingQna || !qnaQuestion.trim()}
778+
disabled={isProcessingQna || !(qnaInputRef.current?.value || qnaQuestion).trim()}
748779
className="w-full bg-red-600 hover:bg-red-700 text-white py-2 sm:py-3 rounded-lg transition-colors h-[40px] sm:h-[48px] text-sm sm:text-base font-medium"
749780
>
750781
{isProcessingQna ? (
@@ -866,8 +897,8 @@ function DocsPage() {
866897
>
867898
{isRegenerating ? (
868899
<>
869-
<Loader2 className="h-5 w-5 mr-2 animate-spin" />
870-
Generating Documentation...
900+
<Loader2 className="h-5 w-5 mr-2 animate-spin flex-shrink-0" />
901+
<span>Generating Documentation...</span>
871902
</>
872903
) : (
873904
<>

0 commit comments

Comments
 (0)