|
import React from 'react';
|
|
import { motion } from 'framer-motion';
|
|
|
|
const ProcessingProgress = ({ progress, isVisible }) => {
|
|
if (!isVisible) return null;
|
|
|
|
const {
|
|
current,
|
|
total,
|
|
status,
|
|
fileName,
|
|
totalPages,
|
|
currentPage,
|
|
totalCharacters,
|
|
pageCharacters,
|
|
phase,
|
|
consoleLogs = []
|
|
} = progress;
|
|
const percentage = total > 0 ? Math.round((current / total) * 100) : 0;
|
|
|
|
return (
|
|
<motion.div
|
|
className="processing-progress-overlay"
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
exit={{ opacity: 0 }}
|
|
>
|
|
<div className="processing-progress-container">
|
|
<div className="progress-content">
|
|
<div className="progress-header">
|
|
<h3>🌙 Luna Processing</h3>
|
|
<div className="progress-file">
|
|
📄 {fileName || 'Processing file...'}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="progress-bar-container">
|
|
<div className="progress-bar">
|
|
<motion.div
|
|
className="progress-fill"
|
|
initial={{ width: 0 }}
|
|
animate={{ width: `${percentage}%` }}
|
|
transition={{ duration: 0.5, ease: "easeOut" }}
|
|
/>
|
|
</div>
|
|
<div className="progress-percentage">{percentage}%</div>
|
|
</div>
|
|
|
|
<div className="progress-status">
|
|
{status && (
|
|
<motion.div
|
|
key={status}
|
|
initial={{ opacity: 0, y: 10 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
className="status-text"
|
|
>
|
|
{status}
|
|
</motion.div>
|
|
)}
|
|
</div>
|
|
|
|
{totalPages > 1 && (
|
|
<div className="progress-details">
|
|
<div className="progress-counter">
|
|
<span className="counter-current">{currentPage || 0}</span>
|
|
<span className="counter-separator">/</span>
|
|
<span className="counter-total">{totalPages}</span>
|
|
<span className="counter-label">pages</span>
|
|
</div>
|
|
|
|
{totalCharacters > 0 && (
|
|
<div className="progress-stats">
|
|
<div className="stat-item">
|
|
<span className="stat-label">Total Characters:</span>
|
|
<span className="stat-value">{totalCharacters.toLocaleString()}</span>
|
|
</div>
|
|
{pageCharacters > 0 && (
|
|
<div className="stat-item">
|
|
<span className="stat-label">Last Page:</span>
|
|
<span className="stat-value">{pageCharacters.toLocaleString()} chars</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
)}
|
|
|
|
{consoleLogs.length > 0 && (
|
|
<div className="console-logs">
|
|
<div className="console-header">📋 Live Process Log</div>
|
|
<div className="console-content">
|
|
{consoleLogs.slice(-6).map((log, index) => (
|
|
<div key={index} className="console-line">
|
|
<span className="console-time">
|
|
{new Date(log.timestamp).toLocaleTimeString('th-TH', {
|
|
hour12: false,
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
second: '2-digit'
|
|
})}
|
|
</span>
|
|
<span className="console-message">{log.message}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<div className="processing-animation">
|
|
<div className="processing-dots">
|
|
<div className="dot"></div>
|
|
<div className="dot"></div>
|
|
<div className="dot"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
);
|
|
};
|
|
|
|
export default ProcessingProgress; |