Add components for Act management and integrate Electron setup
This commit is contained in:
134
components/StaticAlert.tsx
Normal file
134
components/StaticAlert.tsx
Normal file
@@ -0,0 +1,134 @@
|
||||
'use client'
|
||||
import React, {useEffect, useState} 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 = React.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 jsx>{`
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
opacity: 0.7;
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shrink {
|
||||
0% {
|
||||
width: 100%;
|
||||
}
|
||||
100% {
|
||||
width: 0%;
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user