Files
ERitors-Scribe-Desktop/components/QSTextGeneratedPreview.tsx

122 lines
6.0 KiB
TypeScript

import React, {ReactPortal, useEffect, useState} from 'react';
import {createPortal} from 'react-dom';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {faPaperPlane, faStop, faSync, faX} from '@fortawesome/free-solid-svg-icons';
import {useTranslations} from "next-intl";
interface QSTextGeneratedPreviewProps {
onClose: () => void;
onRefresh: () => void;
value: string;
onInsert: () => void;
isGenerating?: boolean;
onStop?: () => void;
}
export default function QSTextGeneratedPreview(
{
onClose,
onRefresh,
value,
onInsert,
isGenerating = false,
onStop,
}: QSTextGeneratedPreviewProps): ReactPortal | null {
const [mounted, setMounted] = useState(false);
const [isVisible, setIsVisible] = useState(false);
const t = useTranslations();
useEffect((): () => void => {
setMounted(true);
const timer = setTimeout(() => setIsVisible(true), 10);
return (): void => {
setMounted(false);
setIsVisible(false);
clearTimeout(timer);
};
}, []);
const handleClose = (): void => {
setIsVisible(false);
setTimeout(onClose, 300); // Attend la fin de l'animation avant de fermer
};
if (!mounted) return null;
const modalContent = (
<div
className={`fixed inset-0 z-50 flex items-center justify-center font-['Lora'] transition-opacity duration-300 ${isVisible ? 'opacity-100' : 'opacity-0'}`}>
<div className="absolute inset-0 bg-overlay" onClick={handleClose}></div>
<div
className={`relative w-[90%] max-w-2xl h-[80%] bg-tertiary/90 backdrop-blur-sm rounded-2xl overflow-hidden border border-secondary/50 shadow-2xl flex flex-col transition-all duration-300 ${isVisible ? 'scale-100 opacity-100' : 'scale-95 opacity-0'}`}>
<div
className="flex justify-between items-center px-5 py-4 bg-secondary/30 backdrop-blur-sm border-b border-secondary/50 shadow-sm">
<div className="flex items-center">
<h2 className="text-xl font-['ADLaM_Display'] text-text-primary">{t("qsTextPreview.title")}</h2>
</div>
<div className="flex items-center space-x-2">
{isGenerating && onStop ? (
<button
onClick={onStop}
className="w-9 h-9 rounded-xl bg-red-500 text-white hover:bg-red-600 transition-all duration-200 hover:scale-110 flex justify-center items-center shadow-sm hover:shadow-md"
>
<FontAwesomeIcon icon={faStop}/>
</button>
) : (
<button
onClick={onRefresh}
className="w-9 h-9 rounded-xl bg-secondary/50 text-primary hover:bg-secondary transition-all duration-200 hover:scale-110 flex justify-center items-center shadow-sm hover:shadow-md border border-secondary/50"
>
<FontAwesomeIcon icon={faSync}/>
</button>
)}
<button
onClick={handleClose}
className="text-muted hover:text-text-primary p-2 rounded-xl hover:bg-secondary transition-all duration-200 hover:scale-110"
>
<FontAwesomeIcon icon={faX} className={'h-5 w-5'}/>
</button>
</div>
</div>
<div className="flex-1 p-5 overflow-auto custom-scrollbar">
<div
className="w-full bg-darkest-background text-text-primary p-5 rounded-xl border border-secondary/50 shadow-inner">
{isGenerating && !value ? (
<div className="space-y-4 animate-pulse">
<div className="h-4 bg-secondary/30 rounded w-full"></div>
<div className="h-4 bg-secondary/30 rounded w-11/12"></div>
<div className="h-4 bg-secondary/30 rounded w-full"></div>
<div className="h-4 bg-secondary/30 rounded w-10/12"></div>
<div className="h-4 bg-secondary/30 rounded w-full"></div>
<div className="h-4 bg-secondary/30 rounded w-9/12"></div>
<div className="h-4 bg-secondary/30 rounded w-full"></div>
<div className="h-4 bg-secondary/30 rounded w-11/12"></div>
</div>
) : (
<div className="space-y-4">
<div className="text-justify leading-relaxed whitespace-pre-wrap fade-in-text">
{value}
</div>
</div>
)}
</div>
</div>
<div
className="px-5 py-4 bg-secondary/30 backdrop-blur-sm border-t border-secondary/50 flex justify-end shadow-inner">
<button
onClick={onInsert}
className="flex items-center py-2.5 px-5 rounded-xl bg-primary text-text-primary hover:bg-primary-dark transition-all duration-200 hover:scale-105 shadow-md hover:shadow-lg font-medium"
>
<FontAwesomeIcon icon={faPaperPlane} className="mr-2"/>
{t("qsTextPreview.insert")}
</button>
</div>
</div>
</div>
);
return createPortal(modalContent, document.body);
}