PATH:
home
/
cf7x
/
public_html
/
wp-content_
/
plugins
/
email-validator
/
src
import React, { useState, useEffect, useCallback, useRef } from 'react'; import { Paper, Button, CircularProgress, Stack } from '@mui/material'; import { __ } from '@wordpress/i18n'; const EVA_DATA = window.EVA || {}; function ValidationControls({ running, startLoading, stopLoading, inputLimit, setInputLimit, onStart, onStop }) { return ( <Stack direction="row" spacing={2} sx={{ mb: 2 }}> <input type="number" min={1} max={5000} value={inputLimit} onChange={e => setInputLimit(Number(e.target.value))} style={{ width: 120, marginRight: 16, padding: 8, fontSize: 16 }} placeholder={__('Quantity', 'email-validator')} /> <Button variant="contained" color="primary" onClick={onStart} disabled={running || startLoading} startIcon={startLoading ? <CircularProgress size={16} color="inherit" /> : null} > {__('Start', 'email-validator')} </Button> <Button variant="outlined" color="error" onClick={onStop} disabled={!running || stopLoading} startIcon={stopLoading ? <CircularProgress size={16} color="inherit" /> : null} > {__('Stop', 'email-validator')} </Button> </Stack> ); } function ValidationSummary({ total, processed, running, lastUpdated }) { return ( <div style={{ marginTop: 16, marginBottom: 16, padding: 16, background: '#f5f7fa', borderRadius: 10, boxShadow: '0 2px 8px rgba(0,0,0,0.04)' }}> <div style={{ fontWeight: 700, fontSize: 18, marginBottom: 12 }}>{__('Summary', 'email-validator')}</div> <Stack direction="row" spacing={6} alignItems="center"> <div style={{ fontWeight: 500, fontSize: 16 }}> {__('Total Records:', 'email-validator')} <span style={{ fontWeight: 700, color: '#1976d2' }}>{total.toLocaleString()}</span> </div> <div style={{ fontWeight: 500, fontSize: 16 }}> {__('Pending Records:', 'email-validator')} <span style={{ fontWeight: 700, color: '#d32f2f' }}>{Math.max(0, total - processed).toLocaleString()}</span> </div> <div style={{ fontWeight: 500, fontSize: 16, display: 'flex', alignItems: 'center' }}> {__('Validated:', 'email-validator')} <span style={{ fontWeight: 700, color: '#388e3c', marginRight: 8 }}>{processed.toLocaleString()}</span> {running && <CircularProgress size={16} color="success" />} </div> </Stack> {lastUpdated && ( <div style={{ marginTop: 8, fontSize: 13, color: '#888', fontWeight: 400 }}> {__('Last updated:', 'email-validator')} {lastUpdated.toLocaleTimeString()} </div> )} </div> ); } function ProgressBar({ total, processed }) { const percent = total > 0 ? Math.min(100, Math.floor((processed / total) * 100)) : 0; const barWidth = percent > 0 ? `max(${percent}%, 32px)` : '0%'; return ( <div style={{ marginTop: 16, marginBottom: 16 }}> <div style={{ fontWeight: 500, marginBottom: 8 }}>{__('Progress', 'email-validator')}</div> <Stack direction="row" alignItems="center" spacing={2}> <div style={{ flex: 1 }}> <div style={{ background: '#eee', borderRadius: 8, height: 30, position: 'relative', overflow: 'hidden' }} > <div style={{ background: percent > 0 ? '#1976d2' : 'transparent', height: '100%', width: barWidth, minWidth: percent > 0 ? 32 : 0, transition: 'width 0.3s ease' }} ></div> <div style={{ position: 'absolute', top: 0, left: 0, height: '100%', width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 700, fontSize: 16, color: percent > 50 ? '#fff' : '#1976d2', pointerEvents: 'none' }} > {percent}% </div> </div> </div> <div style={{ minWidth: 160, textAlign: 'right', fontWeight: 500, fontSize: 16 }}> {processed.toLocaleString()} / {total.toLocaleString()} {__('records', 'email-validator')} </div> </Stack> </div> ); } const RunValidationApp = () => { const [lastUpdated, setLastUpdated] = useState(null); const [running, setRunning] = useState(false); const [startLoading, setStartLoading] = useState(false); const [stopLoading, setStopLoading] = useState(false); const [total, setTotal] = useState(0); const [processed, setProcessed] = useState(0); const [inputLimit, setInputLimit] = useState(50); const pollRef = useRef(null); const fetchProgress = useCallback(() => { fetch(EVA_DATA.ajaxUrl + '?action=eva_get_latest_validation_records&nonce=' + EVA_DATA.nonce) .then(res => res.json()) .then(data => { if (data && data.data) { const processed = Number(data.data.processed) || 0; const total = Number(data.data.total) || 0; setProcessed(processed); setTotal(total); setLastUpdated(new Date()); // Stop polling if complete if (pollRef.current && total > 0 && processed >= total) { clearInterval(pollRef.current); pollRef.current = null; setRunning(false); } } }); }, []); const startValidation = useCallback(() => { setStartLoading(true); fetch(EVA_DATA.ajaxUrl, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, body: `action=eva_start_validation&nonce=${EVA_DATA.nonce}&limit=${inputLimit}` }) .then(res => res.json()) .then((data) => { setRunning(true); setStartLoading(false); fetchProgress(); pollRef.current = setInterval(fetchProgress, 2000); }); }, [fetchProgress, inputLimit]); const stopValidation = useCallback(() => { setStopLoading(true); fetch(EVA_DATA.ajaxUrl, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, body: `action=eva_stop_validation&nonce=${EVA_DATA.nonce}` }) .then(res => res.json()) .then(() => { setRunning(false); setStopLoading(false); if (pollRef.current) { clearInterval(pollRef.current); pollRef.current = null; } }); }, []); useEffect(() => { fetchProgress(); return () => { if (pollRef.current) { clearInterval(pollRef.current); pollRef.current = null; } }; }, []); return ( <Paper sx={{ p: 3, mb: 3, borderRadius: 3, boxShadow: 3 }}> <h2 style={{ fontWeight: 600, marginBottom: 16 }}>{__('Run Validation (AJAX)', 'email-validator')}</h2> <ValidationControls running={running} startLoading={startLoading} stopLoading={stopLoading} inputLimit={inputLimit} setInputLimit={setInputLimit} onStart={startValidation} onStop={stopValidation} /> <ValidationSummary total={total} processed={processed} running={running} lastUpdated={lastUpdated} /> <ProgressBar total={total} processed={processed} /> </Paper> ); }; export default RunValidationApp;
[+]
..
[-] index.jsx
[open]
[-] run-validation-entry.js
[open]
[-] run-validation.jsx
[open]