mafzaal's picture
Implement user session management and prompt customization in FastAPI and frontend
5d28468
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { Button } from './button';
import { Textarea } from './textarea';
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from './dialog';
import { Tabs, TabsContent, TabsList, TabsTrigger } from './tabs';
const PromptEditor = ({ userId, onPromptsChange }) => {
const [isLoading, setIsLoading] = useState(false);
const [prompts, setPrompts] = useState({
system_template: '',
user_template: ''
});
const [isOpen, setIsOpen] = useState(false);
const [saveStatus, setSaveStatus] = useState('');
// Fetch current prompts when the component mounts or userId changes
useEffect(() => {
if (isOpen && userId) {
fetchPrompts();
}
}, [userId, isOpen]);
const fetchPrompts = async () => {
try {
setIsLoading(true);
const response = await axios.get(`/prompts${userId ? `?user_id=${userId}` : ''}`);
setPrompts({
system_template: response.data.system_template,
user_template: response.data.user_template
});
setIsLoading(false);
} catch (error) {
console.error('Error fetching prompts:', error);
setIsLoading(false);
}
};
const handleSave = async () => {
try {
setIsLoading(true);
setSaveStatus('Saving...');
await axios.post('/prompts', prompts, {
params: userId ? { user_id: userId } : {}
});
setSaveStatus('Saved successfully!');
// Notify parent component about the prompt change
if (onPromptsChange) {
onPromptsChange(prompts);
}
setTimeout(() => {
setSaveStatus('');
setIsOpen(false);
}, 1500);
setIsLoading(false);
} catch (error) {
console.error('Error saving prompts:', error);
setSaveStatus('Error saving prompts');
setIsLoading(false);
}
};
const handleReset = async () => {
try {
setIsLoading(true);
await axios.post('/prompts/reset', {}, {
params: userId ? { user_id: userId } : {}
});
// Fetch the reset prompts
await fetchPrompts();
setSaveStatus('Reset to defaults');
setTimeout(() => setSaveStatus(''), 1500);
// Notify parent component about the prompt change
if (onPromptsChange) {
onPromptsChange(prompts);
}
setIsLoading(false);
} catch (error) {
console.error('Error resetting prompts:', error);
setSaveStatus('Error resetting prompts');
setIsLoading(false);
}
};
const handlePromptChange = (type, value) => {
setPrompts(prev => ({
...prev,
[type]: value
}));
};
return (
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogTrigger asChild>
<Button
variant="outline"
size="sm"
className="flex items-center gap-1 bg-secondary dark:bg-gray-700 text-foreground dark:text-gray-100 hover:bg-secondary/80 dark:hover:bg-gray-600 border-secondary dark:border-gray-600"
>
<span role="img" aria-label="customize" className="text-sm">⚙️</span>
<span>Customize Prompts</span>
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-4xl max-h-[90vh] overflow-y-auto">
<DialogHeader>
<DialogTitle>Customize AI Prompts</DialogTitle>
<DialogDescription>
Customize how the AI responds to your questions. Changes are saved automatically to your browser.
</DialogDescription>
</DialogHeader>
<Tabs defaultValue="system" className="w-full mt-4">
<TabsList className="grid w-full grid-cols-2">
<TabsTrigger value="system">System Prompt</TabsTrigger>
<TabsTrigger value="user">User Prompt</TabsTrigger>
</TabsList>
<TabsContent value="system" className="mt-4">
<div className="space-y-2">
<h3 className="text-sm font-medium">System Prompt Template</h3>
<p className="text-xs text-muted-foreground">
This controls how the AI formats its response and interacts with the context.
</p>
<Textarea
className="min-h-[450px] font-mono text-sm"
value={prompts.system_template}
onChange={(e) => handlePromptChange('system_template', e.target.value)}
placeholder="Enter system prompt template..."
disabled={isLoading}
/>
</div>
</TabsContent>
<TabsContent value="user" className="mt-4">
<div className="space-y-2">
<h3 className="text-sm font-medium">User Prompt Template</h3>
<p className="text-xs text-muted-foreground">
This controls how your question and the document context are combined. <code>{"{context}"}</code> and <code>{"{question}"}</code> are replaced with the actual values.
</p>
<Textarea
className="min-h-[450px] font-mono text-sm"
value={prompts.user_template}
onChange={(e) => handlePromptChange('user_template', e.target.value)}
placeholder="Enter user prompt template..."
disabled={isLoading}
/>
</div>
</TabsContent>
</Tabs>
<DialogFooter className="flex justify-between items-center">
<div className="text-sm text-muted-foreground">
{saveStatus}
</div>
<div className="flex space-x-2">
<Button
variant="outline"
onClick={handleReset}
disabled={isLoading}
>
Reset to Default
</Button>
<Button
onClick={handleSave}
disabled={isLoading}
>
Save Changes
</Button>
</div>
</DialogFooter>
</DialogContent>
</Dialog>
);
};
export default PromptEditor;