ui-nyla/src/components/DashboardPrompts/DashboardPromptSet/DashboardPromptSet.tsx
idittrich-valueon 1366982db0 deployment2
2025-05-07 12:08:11 +02:00

183 lines
No EOL
8.3 KiB
TypeScript

import { useState, useEffect } from 'react';
import styles from './DashboardPromptSet.module.css';
import { useUserPrompts } from '../../../auth/Hooks/use-user-prompts';
import { useUserFiles } from '../../../auth/Hooks/use-user-files';
import { FaEdit, FaRedo, FaChevronRight } from 'react-icons/fa';
import PromptItemDelete from './PromptItemDelete';
import PromptItemShare from './PromptItemShare';
import NewPromptButton from './NewPromptButton';
import { motion, AnimatePresence } from 'framer-motion';
import { useSearchParams } from 'react-router-dom';
import { useFileOperations } from '../../../hooks/use-file-operations';
import { FileList } from './FileList';
const formatPromptText = (text: string) => {
// Split text at 5 or more consecutive spaces
const parts = text.split(/\s{4,}/g);
// Join with line breaks
return parts.join('\n');
};
function DashboardPromptSet() {
const { prompts, loading, error, refetch } = useUserPrompts();
const { files, loading: filesLoading } = useUserFiles();
const [expandedPrompts, setExpandedPrompts] = useState<Set<string>>(new Set());
const [searchParams] = useSearchParams();
const { downloadingFiles, downloadError, handleFileDownload } = useFileOperations();
useEffect(() => {
if (!loading && prompts.length > 0) {
const expandedPrompt = searchParams.get('expandedPrompt');
console.log('URL Parameter expandedPrompt:', expandedPrompt);
console.log('Available prompts:', prompts.map(p => ({ id: p.id, title: p.prompt_title })));
console.log('Current expandedPrompts:', Array.from(expandedPrompts));
if (expandedPrompt) {
const matchingPrompt = prompts.find(p => p.id.toString() === expandedPrompt.toString());
console.log('Matching prompt:', matchingPrompt);
if (matchingPrompt) {
console.log('Setting expanded prompt:', matchingPrompt.id);
setExpandedPrompts(new Set([matchingPrompt.id]));
}
}
}
}, [searchParams, prompts, loading]);
const toggleExpand = (promptId: string) => {
console.log('Toggling prompt:', promptId);
setExpandedPrompts(prev => {
const newSet = new Set(prev);
if (newSet.has(promptId)) {
newSet.delete(promptId);
} else {
newSet.add(promptId);
}
return newSet;
});
};
const handleDelete = async () => {
try {
await refetch(); // Refetch prompts after successful deletion
} catch (error) {
console.error('Error deleting prompt:', error);
}
};
const getPromptFiles = (promptId: string | null) => {
if (!files || !promptId) return { uploadedFiles: [], downloadFiles: [] };
const promptFiles = files.filter(file => {
// Check if either file.prompt_id or promptId is null
if (file.prompt_id === null || promptId === null) return false;
return file.prompt_id.toString() === promptId.toString();
});
return {
uploadedFiles: promptFiles.filter(file => file.action === 'upload'),
downloadFiles: promptFiles.filter(file => file.action === 'download')
};
};
return (
<div className={styles.container}>
<NewPromptButton />
{loading || filesLoading ? (
<div>Loading...</div>
) : error ? (
<div>Error: {error}</div>
) : (
<div className={styles.promptList}>
{prompts.map(prompt => (
<motion.div
key={prompt.id}
className={styles.promptCard}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.3 }}
>
<div className={styles.promptHeader}>
<motion.button
className={styles.expandButton}
onClick={() => toggleExpand(prompt.id)}
animate={{
rotate: expandedPrompts.has(prompt.id) ? 90 : 0
}}
transition={{ duration: 0.2 }}
>
<FaChevronRight />
</motion.button>
<h2 className={styles.promptTitle}>{prompt.prompt_title}</h2>
<div className={styles.actionButtons}>
<button className={styles.iconButton} title="Edit">
<FaEdit />
</button>
<PromptItemDelete
promptId={prompt.id}
promptTitle={prompt.prompt_title}
onDelete={handleDelete}
/>
<button className={styles.iconButton} title="Repeat">
<FaRedo />
</button>
<PromptItemShare
promptId={prompt.id}
promptTitle={prompt.prompt_title}
/>
</div>
</div>
<AnimatePresence initial={false}>
{expandedPrompts.has(prompt.id) && (
<motion.div
className={styles.promptContentWrapper}
initial={{ height: 0, opacity: 0, borderTopWidth: 0 }}
animate={{
height: "auto",
opacity: 1,
borderTopWidth: 1,
transition: {
height: { duration: 0.3, ease: "easeOut" },
opacity: { duration: 0.2, delay: 0.1 },
borderTopWidth: { duration: 0.2, delay: 0.1 }
}
}}
exit={{
height: 0,
opacity: 0,
borderTopWidth: 0,
transition: {
height: { duration: 0.3, ease: "easeIn" },
opacity: { duration: 0.2 },
borderTopWidth: { duration: 0.1 }
}
}}
>
<div className={styles.promptContent}>
{formatPromptText(prompt.user_prompt).split('\n').map((line, index) => (
<p key={index}>{line}</p>
))}
</div>
<FileList
{...getPromptFiles(prompt.id)}
downloadingFiles={downloadingFiles}
onFileClick={handleFileDownload}
/>
{downloadError && (
<div className={styles.errorMessage}>
{downloadError}
</div>
)}
</motion.div>
)}
</AnimatePresence>
</motion.div>
))}
</div>
)}
</div>
);
}
export default DashboardPromptSet;