'use client'; import React, { useState, useEffect } from 'react'; import { ScheduledFunction, EdgeFunction } from '@/lib/vfs/types'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Loader2, AlertCircle, Info } from 'lucide-react'; interface ScheduledFunctionEditorProps { scheduledFunction: ScheduledFunction | null; edgeFunctions: EdgeFunction[]; isOpen: boolean; onClose: () => void; onSave: (data: Partial) => Promise; } export function ScheduledFunctionEditor({ scheduledFunction: fn, edgeFunctions, isOpen, onClose, onSave, }: ScheduledFunctionEditorProps) { const [name, setName] = useState(fn?.name || ''); const [functionId, setFunctionId] = useState(fn?.functionId || ''); const [cronExpression, setCronExpression] = useState(fn?.cronExpression || ''); const [timezone, setTimezone] = useState(fn?.timezone || 'UTC'); const [description, setDescription] = useState(fn?.description || ''); const [config, setConfig] = useState(fn?.config ? JSON.stringify(fn.config, null, 2) : '{}'); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); useEffect(() => { if (isOpen) { setName(fn?.name || ''); setFunctionId(fn?.functionId || ''); setCronExpression(fn?.cronExpression || ''); setTimezone(fn?.timezone || 'UTC'); setDescription(fn?.description || ''); setConfig(fn?.config ? JSON.stringify(fn.config, null, 2) : '{}'); setError(null); } }, [fn, isOpen]); const handleSave = async () => { setError(null); if (!name.trim()) { setError('Name is required'); return; } if (!/^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$/.test(name)) { setError('Name must be lowercase letters, numbers, and hyphens only'); return; } if (!functionId) { setError('Edge function selection is required'); return; } if (!cronExpression.trim()) { setError('Cron expression is required'); return; } let parsedConfig: Record = {}; if (config.trim()) { try { const parsed = JSON.parse(config); if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) { setError('Config must be a JSON object'); return; } parsedConfig = parsed; } catch { setError('Config must be valid JSON'); return; } } setSaving(true); try { await onSave({ name: name.trim(), functionId, cronExpression: cronExpression.trim(), timezone: timezone.trim() || 'UTC', description: description.trim() || undefined, config: parsedConfig, enabled: fn?.enabled ?? true, }); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to save scheduled function'); } finally { setSaving(false); } }; return ( {fn ? 'Edit Schedule' : 'Create Schedule'} Run an edge function on a cron schedule.
{/* Name */}
setName(e.target.value.toLowerCase())} placeholder="daily-report" disabled={!!fn} />
{/* Edge Function */}
{edgeFunctions.length === 0 && (

No edge functions available. Create one in the Functions tab first.

)}
{/* Cron Expression */}
setCronExpression(e.target.value)} placeholder="0 8 * * *" className="font-mono" />
{/* Timezone */}
setTimezone(e.target.value)} placeholder="UTC" />

e.g. UTC, America/New_York, Europe/London

{/* Description */}
setDescription(e.target.value)} placeholder="What does this schedule do?" />
{/* Config */}