import { useState, useEffect } from 'react'; import { useParams, useNavigate, Link } from 'react-router-dom'; import { api } from '../../api/apiClient'; import { toast } from '../../components/common/ToastContainer'; import { PageHeader } from '../../components/common/PageComponents'; const DAY_OPTIONS = [ { key: 'MON', label: 'Mon' }, { key: 'TUE', label: 'Tue' }, { key: 'WED', label: 'Wed' }, { key: 'THU', label: 'Thu' }, { key: 'FRI', label: 'Fri' }, { key: 'SAT', label: 'Sat' }, { key: 'SUN', label: 'Sun' }, ]; function formatTime12h(timeStr) { if (!timeStr) return ''; const [h, m] = timeStr.split(':').map(Number); const ampm = h >= 12 ? 'PM' : 'AM'; const hour = h % 12 || 12; return `${hour}:${String(m).padStart(2, '0')} ${ampm}`; } export default function SchedulerFormView() { const { id } = useParams(); const isEdit = !!id; const navigate = useNavigate(); const [suites, setSuites] = useState([]); const [form, setForm] = useState({ testSuiteId: '', environmentId: '', targetGroupId: '', executionType: '', browserType: '', browserVersion: '', status: 'active', recurrenceType: 'once', scheduledDate: '', scheduledTime: '', recurrenceDays: [], recurrenceEndDate: '', }); const [envs, setEnvs] = useState([]); const [pools, setPools] = useState([]); const [saving, setSaving] = useState(false); const [loaded, setLoaded] = useState(!isEdit); const set = (k, v) => setForm(p => ({ ...p, [k]: v })); const today = new Date().toISOString().slice(0, 10); useEffect(() => { api('/api/test-suites').then(r => r.json()).then(setSuites).catch(() => {}); api('/api/environments').then(r => r.json()).then(d => setEnvs(d || [])).catch(() => {}); api('/api/groups').then(r => r.json()).then(d => setPools(d || [])).catch(() => {}); }, []); useEffect(() => { if (isEdit) { api('/api/schedulers').then(r => r.json()).then(all => { const s = all.find(x => x.id === +id); if (s) { setForm({ testSuiteId: s.testSuiteId || '', environmentId: s.environmentId || '', targetGroupId: s.targetGroupId || '', executionType: s.executionType || '', browserType: s.browserType || '', browserVersion: s.browserVersion || '', status: s.status || 'active', recurrenceType: s.recurrenceType || 'once', scheduledDate: s.scheduledDate || '', scheduledTime: s.scheduledTime ? s.scheduledTime.substring(0, 5) : '', recurrenceDays: s.recurrenceDays ? s.recurrenceDays.split(',').map(d => d.trim()) : [], recurrenceEndDate: s.recurrenceEndDate || '', }); } setLoaded(true); }); } }, [id, isEdit]); const toggleDay = (dayKey) => { setForm(p => { const days = p.recurrenceDays.includes(dayKey) ? p.recurrenceDays.filter(d => d !== dayKey) : [...p.recurrenceDays, dayKey]; return { ...p, recurrenceDays: days }; }); }; const buildSummary = () => { if (form.executionType === 'now') return 'β–Ά Will run immediately when saved.'; if (form.executionType !== 'scheduled') return ''; const timeStr = form.scheduledTime ? formatTime12h(form.scheduledTime) : 'β€”'; const dateStr = form.scheduledDate ? new Date(form.scheduledDate + 'T00:00').toLocaleDateString('en-IN', { weekday: 'long', day: '2-digit', month: 'long', year: 'numeric' }) : 'β€”'; switch (form.recurrenceType) { case 'once': return `πŸ“… Runs once on ${dateStr} at ${timeStr}`; case 'daily': return `πŸ” Runs every day at ${timeStr}${form.scheduledDate ? ', starting ' + dateStr : ''}`; case 'weekly': { const daysLabel = form.recurrenceDays.length ? form.recurrenceDays.map(k => DAY_OPTIONS.find(d => d.key === k)?.label || k).join(', ') : 'no days selected'; return `πŸ” Runs every ${daysLabel} at ${timeStr}`; } case 'monthly': return `πŸ” Runs monthly${form.scheduledDate ? ' on day ' + new Date(form.scheduledDate + 'T00:00').getDate() : ''} at ${timeStr}`; default: return ''; } }; const save = async (e) => { e.preventDefault(); setSaving(true); const suite = suites.find(s => String(s.id) === String(form.testSuiteId)); const payload = { testSuiteId: form.testSuiteId ? +form.testSuiteId : null, environmentId: form.environmentId ? +form.environmentId : null, targetGroupId: form.targetGroupId ? +form.targetGroupId : null, testSuiteName: suite?.name || '', executionType: form.executionType, browserType: form.browserType, browserVersion: form.browserVersion || null, status: form.status, recurrenceType: form.executionType === 'scheduled' ? form.recurrenceType : null, scheduledDate: form.executionType === 'scheduled' && form.scheduledDate ? form.scheduledDate : null, scheduledTime: form.executionType === 'scheduled' && form.scheduledTime ? form.scheduledTime + ':00' : null, recurrenceDays: form.executionType === 'scheduled' && form.recurrenceType === 'weekly' ? form.recurrenceDays.join(',') : null, recurrenceEndDate: form.executionType === 'scheduled' && form.recurrenceEndDate ? form.recurrenceEndDate : null, timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, }; const url = isEdit ? `/api/schedulers/${id}` : '/api/schedulers'; const method = isEdit ? 'PUT' : 'POST'; const r = await api(url, { method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (r.ok) { toast('success', isEdit ? 'Updated!' : 'Created!', 'Scheduler saved successfully.'); setTimeout(() => navigate('/scheduler'), 800); } else { toast('error', 'Failed', 'Could not save scheduler.'); setSaving(false); } }; if (!loaded) return
; return (
← Back} />

πŸ“… Schedule Configuration

Configure when this test suite should run

Test Suite & Browser
set('browserVersion', e.target.value)} />
Require a specific major browser version.
Execution Timing
{form.executionType === 'scheduled' && (
set('scheduledDate', e.target.value)} required={form.recurrenceType === 'once' || form.recurrenceType === 'monthly'} />
set('scheduledTime', e.target.value)} required />
{[ { key: 'once', icon: '1️⃣', label: 'Once', sub: 'Single execution' }, { key: 'daily', icon: 'πŸ“†', label: 'Daily', sub: 'Every day' }, { key: 'weekly', icon: 'πŸ—“οΈ', label: 'Weekly', sub: 'Choose days' }, { key: 'monthly', icon: 'πŸ“…', label: 'Monthly', sub: 'Same date each month' }, ].map(opt => ( ))}
{form.recurrenceType === 'weekly' && (
{DAY_OPTIONS.map(d => ( ))}
{form.recurrenceDays.length === 0 && ( Please select at least one day. )}
)} {form.recurrenceType !== 'once' && (
set('recurrenceEndDate', e.target.value)} />
)} {buildSummary() && (
πŸ“‹ {buildSummary()}
)}
)}
Cancel
); }