reaminig 5-t-9

This commit is contained in:
alorig
2025-11-18 06:36:56 +05:00
parent 9facd12082
commit 68a98208b1
31 changed files with 5210 additions and 153 deletions

View File

@@ -0,0 +1,118 @@
.progress-modal-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.progress-modal {
background: white;
border-radius: 8px;
padding: 24px;
min-width: 400px;
max-width: 500px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.progress-modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}
.progress-modal-header h3 {
margin: 0;
font-size: 18px;
font-weight: 600;
}
.progress-modal-close {
background: none;
border: none;
cursor: pointer;
padding: 4px;
display: flex;
align-items: center;
justify-content: center;
color: #666;
transition: color 0.2s;
}
.progress-modal-close:hover {
color: #000;
}
.progress-modal-content {
display: flex;
flex-direction: column;
gap: 16px;
}
.progress-modal-message {
margin: 0;
color: #666;
font-size: 14px;
}
.progress-modal-bar {
display: flex;
flex-direction: column;
gap: 8px;
}
.progress-modal-bar-track {
height: 8px;
background: #e5e7eb;
border-radius: 4px;
overflow: hidden;
}
.progress-modal-bar-fill {
height: 100%;
background: #3b82f6;
transition: width 0.3s ease;
}
.progress-modal-bar-text {
font-size: 12px;
color: #666;
text-align: center;
}
.progress-modal-spinner {
display: flex;
justify-content: center;
padding: 16px;
}
.progress-modal-spinner .spin {
animation: spin 1s linear infinite;
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.progress-modal-task-id {
margin: 0;
font-size: 12px;
color: #999;
text-align: center;
}
.progress-modal-task-id code {
background: #f3f4f6;
padding: 2px 6px;
border-radius: 4px;
font-family: monospace;
}

View File

@@ -0,0 +1,76 @@
import { useEffect } from 'react';
import { X, Loader2 } from 'lucide-react';
import './ProgressModal.css';
interface ProgressModalProps {
isOpen: boolean;
onClose: () => void;
title: string;
message?: string;
progress?: {
current: number;
total: number;
};
taskId?: string;
}
export function ProgressModal({ isOpen, onClose, title, message, progress, taskId }: ProgressModalProps) {
useEffect(() => {
if (isOpen) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = '';
}
return () => {
document.body.style.overflow = '';
};
}, [isOpen]);
if (!isOpen) return null;
const progressPercent = progress ? Math.round((progress.current / progress.total) * 100) : 0;
return (
<div className="progress-modal-overlay" onClick={onClose}>
<div className="progress-modal" onClick={(e) => e.stopPropagation()}>
<div className="progress-modal-header">
<h3>{title}</h3>
<button type="button" className="progress-modal-close" onClick={onClose} aria-label="Close">
<X size={20} />
</button>
</div>
<div className="progress-modal-content">
{message && <p className="progress-modal-message">{message}</p>}
{progress && (
<div className="progress-modal-bar">
<div className="progress-modal-bar-track">
<div
className="progress-modal-bar-fill"
style={{ width: `${progressPercent}%` }}
/>
</div>
<span className="progress-modal-bar-text">
{progress.current} of {progress.total} pages
</span>
</div>
)}
{!progress && (
<div className="progress-modal-spinner">
<Loader2 className="spin" size={24} />
</div>
)}
{taskId && (
<p className="progress-modal-task-id">
Task ID: <code>{taskId}</code>
</p>
)}
</div>
</div>
</div>
);
}