chat fixes
Focus: textarea gets refocused via inputRef after the AI response (or error) lands Persistence: chat history saved to localStorage keyed by trip ID, loaded on mount — survives refreshes
This commit is contained in:
@@ -497,6 +497,8 @@ interface SuggestionCard {
|
||||
added?: boolean;
|
||||
}
|
||||
|
||||
const CHAT_STORAGE_KEY = (tripId: string) => `drb-trip-chat-${tripId}`;
|
||||
|
||||
function AssistantPanel({
|
||||
trip,
|
||||
onAddEvent,
|
||||
@@ -504,15 +506,26 @@ function AssistantPanel({
|
||||
trip: TripRecord & { events: TripEvent[] };
|
||||
onAddEvent: (event: TripEvent) => void;
|
||||
}) {
|
||||
const [messages, setMessages] = useState<ChatMessage[]>([]);
|
||||
const storageKey = CHAT_STORAGE_KEY(trip.trip_id);
|
||||
const [messages, setMessages] = useState<ChatMessage[]>(() => {
|
||||
try {
|
||||
const saved = localStorage.getItem(storageKey);
|
||||
return saved ? JSON.parse(saved) : [];
|
||||
} catch { return []; }
|
||||
});
|
||||
const [input, setInput] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const bottomRef = useRef<HTMLDivElement>(null);
|
||||
const bottomRef = useRef<HTMLDivElement>(null);
|
||||
const inputRef = useRef<HTMLTextAreaElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
||||
}, [messages]);
|
||||
|
||||
useEffect(() => {
|
||||
try { localStorage.setItem(storageKey, JSON.stringify(messages)); } catch { /* quota */ }
|
||||
}, [messages, storageKey]);
|
||||
|
||||
async function send() {
|
||||
const text = input.trim();
|
||||
if (!text || loading) return;
|
||||
@@ -540,6 +553,7 @@ function AssistantPanel({
|
||||
]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
inputRef.current?.focus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -703,6 +717,7 @@ function AssistantPanel({
|
||||
<div className="px-3 py-3 border-t border-gray-800 shrink-0">
|
||||
<div className="flex gap-2">
|
||||
<textarea
|
||||
ref={inputRef}
|
||||
value={input}
|
||||
onChange={(e) => { setInput(e.target.value); e.target.style.height = "auto"; e.target.style.height = `${Math.min(e.target.scrollHeight, 120)}px`; }}
|
||||
onKeyDown={(e) => e.key === "Enter" && !e.shiftKey && (e.preventDefault(), send())}
|
||||
|
||||
Reference in New Issue
Block a user