Files
ERitors-Scribe-Desktop/components/StaticAlert.tsx
natreex c9cf99e166 Update imports and Electron compatibility
- Removed unnecessary React imports.
- Adjusted package.json scripts for Electron integration.
- Updated components to replace Next.js-specific imports with Electron-compatible alternatives.
- Minor tsconfig.json changes for better compatibility.
2025-11-16 11:55:52 -05:00

135 lines
4.5 KiB
TypeScript

'use client'
import {useEffect, useState, useRef} from 'react';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {
faCheckCircle,
faExclamationCircle,
faInfoCircle,
faTimes,
faTimesCircle
} from '@fortawesome/free-solid-svg-icons';
interface StaticAlertProps {
type: 'success' | 'error' | 'info' | 'warning';
message: string;
onClose: () => void;
}
const iconMap = {
success: faCheckCircle,
error: faExclamationCircle,
info: faInfoCircle,
warning: faTimesCircle,
};
const bgColorMap = {
success: 'bg-success',
error: 'bg-error',
info: 'bg-info',
warning: 'bg-warning',
};
export default function StaticAlert(
{type, message, onClose}: StaticAlertProps) {
const [visible, setVisible] = useState(false);
const onCloseRef = useRef(onClose);
useEffect(() => {
onCloseRef.current = onClose;
}, [onClose]);
useEffect(() => {
setVisible(true);
const timer = setTimeout(() => {
setVisible(false);
setTimeout(() => onCloseRef.current(), 500); // Wait for fade out animation to complete
}, 4800);
return () => {
clearTimeout(timer);
};
}, []);
const handleClose = () => {
setVisible(false);
setTimeout(() => onCloseRef.current(), 1000); // Wait for fade out animation to complete
};
return (
<div
className={`max-w-sm rounded-xl shadow-2xl transition-all duration-500 ease-in-out transform ${
visible ? 'translate-x-0 opacity-100' : 'translate-x-full opacity-0'
} overflow-hidden font-['Montserrat'] border border-secondary/50 backdrop-blur-sm`}
>
<div className={`p-4 ${bgColorMap[type]} flex items-center relative`}>
<div className="absolute top-0 left-0 w-full h-1 bg-white/30 rounded-t-xl"></div>
<div
className="mr-4 flex-shrink-0 rounded-full bg-white/20 p-2.5 text-text-primary flex items-center justify-center shadow-md">
<FontAwesomeIcon
icon={iconMap[type]}
size="lg"
className="animate-pulse"
style={{
animation: 'pulse 2s infinite'
}}
/>
</div>
<div className="flex-grow mr-3">
<div className="text-text-primary font-medium text-base">{message}</div>
</div>
<button
onClick={handleClose}
className="text-text-primary/90 hover:text-text-primary p-1.5 rounded-lg hover:bg-white/20 transition-all duration-300"
style={{
transition: 'all 0.3s ease',
}}
onMouseEnter={(e) => {
e.currentTarget.style.transform = 'rotate(90deg)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.transform = 'rotate(0deg)';
}}
>
<FontAwesomeIcon icon={faTimes}/>
</button>
</div>
<div className="h-1.5 w-full bg-secondary/50 relative">
<div
className={`h-full ${
type === 'success' ? 'bg-success' :
type === 'error' ? 'bg-error' :
type === 'warning' ? 'bg-warning' :
'bg-info'
} shadow-sm`}
style={{
animation: 'shrink 5s linear forwards',
width: '100%'
}}
></div>
</div>
<style>{`
@keyframes pulse {
0% {
opacity: 0.7;
}
50% {
opacity: 1;
}
100% {
opacity: 0.7;
}
}
@keyframes shrink {
0% {
width: 100%;
}
100% {
width: 0%;
}
}
`}</style>
</div>
);
}