import { useState, useEffect } from 'react'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Switch } from '@/components/ui/switch'; import { Textarea } from '@/components/ui/textarea'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { FileText, Database, Bell, Loader2, Plus, Trash2, Save } from 'lucide-react'; import { getForm16Config, putForm16Config, type Form16AdminConfig as Form16ConfigType, type Form16NotificationItem, type Form16Notification26AsItem, } from '@/services/adminApi'; import { toast } from 'sonner'; function isValidEmail(s: string): boolean { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(s.trim()); } interface ViewerTableProps { emails: string[]; onAdd: (email: string) => void; onRemove: (email: string) => void; placeholder?: string; } function ViewerTable({ emails, onAdd, onRemove, placeholder }: ViewerTableProps) { const [input, setInput] = useState(''); const add = () => { const e = input.trim().toLowerCase(); if (!e) return; if (!isValidEmail(e)) { toast.error('Please enter a valid email address'); return; } if (emails.includes(e)) { toast.error('This email is already in the list'); return; } onAdd(e); setInput(''); }; return (
setInput(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && (e.preventDefault(), add())} className="flex-1" />
{emails.length > 0 ? (
Email Actions {emails.map((email) => ( {email} ))}
) : (

No viewers added. Add emails above or leave empty to allow all RE users with access.

)}
); } function defaultNotif(enabled: boolean, template: string): Form16NotificationItem { return { enabled, template }; } const default26AsNotif = (): Form16Notification26AsItem => ({ enabled: true, templateRe: '26AS data has been added. Please review and use for matching dealer Form 16 submissions.', templateDealers: 'New 26AS data has been uploaded. You can now submit your Form 16 for the relevant quarter if you haven’t already.', }); export function Form16AdminConfig() { const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [submissionViewerEmails, setSubmissionViewerEmails] = useState([]); const [twentySixAsViewerEmails, setTwentySixAsViewerEmails] = useState([]); const [reminderEnabled, setReminderEnabled] = useState(true); const [reminderDays, setReminderDays] = useState(7); const [notification26AsDataAdded, setNotification26AsDataAdded] = useState(default26AsNotif()); const [notificationForm16SuccessCreditNote, setNotificationForm16SuccessCreditNote] = useState(defaultNotif(true, 'Form 16 submitted successfully. Credit note: [CreditNoteRef].')); const [notificationForm16Unsuccessful, setNotificationForm16Unsuccessful] = useState(defaultNotif(true, 'Form 16 submission was unsuccessful. Issue: [Issue]. Please review.')); const [alertSubmitForm16Enabled, setAlertSubmitForm16Enabled] = useState(true); const [alertSubmitForm16FrequencyDays, setAlertSubmitForm16FrequencyDays] = useState(0); const [alertSubmitForm16FrequencyHours, setAlertSubmitForm16FrequencyHours] = useState(24); const [alertSubmitForm16RunAtTime, setAlertSubmitForm16RunAtTime] = useState('09:00'); const [alertSubmitForm16Template, setAlertSubmitForm16Template] = useState('Please submit your Form 16 at your earliest. [Name], due date: [DueDate].'); const [reminderNotificationEnabled, setReminderNotificationEnabled] = useState(true); const [reminderFrequencyDays, setReminderFrequencyDays] = useState(0); const [reminderFrequencyHours, setReminderFrequencyHours] = useState(12); const [reminderRunAtTime, setReminderRunAtTime] = useState('10:00'); const [reminderNotificationTemplate, setReminderNotificationTemplate] = useState('Reminder: Form 16 submission is pending. [Name], [Request ID]. Please review.'); useEffect(() => { let mounted = true; getForm16Config() .then((config: Form16ConfigType) => { if (!mounted) return; setSubmissionViewerEmails(config.submissionViewerEmails ?? []); setTwentySixAsViewerEmails(config.twentySixAsViewerEmails ?? []); setReminderEnabled(config.reminderEnabled ?? true); setReminderDays(typeof config.reminderDays === 'number' ? config.reminderDays : 7); if (config.notification26AsDataAdded) { const n = config.notification26AsDataAdded as Form16Notification26AsItem & { template?: string }; setNotification26AsDataAdded({ enabled: n.enabled ?? true, templateRe: n.templateRe ?? n.template ?? default26AsNotif().templateRe, templateDealers: n.templateDealers ?? default26AsNotif().templateDealers, }); } if (config.notificationForm16SuccessCreditNote) setNotificationForm16SuccessCreditNote(config.notificationForm16SuccessCreditNote); if (config.notificationForm16Unsuccessful) setNotificationForm16Unsuccessful(config.notificationForm16Unsuccessful); setAlertSubmitForm16Enabled(config.alertSubmitForm16Enabled ?? true); setAlertSubmitForm16FrequencyDays(config.alertSubmitForm16FrequencyDays ?? 0); setAlertSubmitForm16FrequencyHours(config.alertSubmitForm16FrequencyHours ?? 24); setAlertSubmitForm16RunAtTime(config.alertSubmitForm16RunAtTime !== undefined && config.alertSubmitForm16RunAtTime !== null ? config.alertSubmitForm16RunAtTime : '09:00'); setAlertSubmitForm16Template(config.alertSubmitForm16Template ?? 'Please submit your Form 16 at your earliest. [Name], due date: [DueDate].'); setReminderNotificationEnabled(config.reminderNotificationEnabled ?? true); setReminderFrequencyDays(config.reminderFrequencyDays ?? 0); setReminderFrequencyHours(config.reminderFrequencyHours ?? 12); setReminderRunAtTime(config.reminderRunAtTime !== undefined && config.reminderRunAtTime !== null ? config.reminderRunAtTime : '10:00'); setReminderNotificationTemplate(config.reminderNotificationTemplate ?? 'Reminder: Form 16 submission is pending. [Name], [Request ID]. Please review.'); }) .catch(() => { if (mounted) toast.error('Failed to load Form 16 configuration'); }) .finally(() => { if (mounted) setLoading(false); }); return () => { mounted = false; }; }, []); const handleSave = async () => { setSaving(true); try { await putForm16Config({ submissionViewerEmails, twentySixAsViewerEmails, reminderEnabled, reminderDays: Math.max(1, Math.min(365, reminderDays)) || 7, notification26AsDataAdded, notificationForm16SuccessCreditNote, notificationForm16Unsuccessful, alertSubmitForm16Enabled, alertSubmitForm16FrequencyDays: Math.max(0, Math.min(365, alertSubmitForm16FrequencyDays)), alertSubmitForm16FrequencyHours: Math.max(0, Math.min(168, alertSubmitForm16FrequencyHours)), alertSubmitForm16RunAtTime: alertSubmitForm16RunAtTime ?? '', alertSubmitForm16Template, reminderNotificationEnabled, reminderFrequencyDays: Math.max(0, Math.min(365, reminderFrequencyDays)), reminderFrequencyHours: Math.max(0, Math.min(168, reminderFrequencyHours)), reminderRunAtTime: reminderRunAtTime ?? '', reminderNotificationTemplate, }); toast.success('Form 16 configuration saved'); } catch { toast.error('Failed to save Form 16 configuration'); } finally { setSaving(false); } }; if (loading) { return (
); } return (
{/* Page header */}

Form 16 Administration

Configure Form 16 access, who can view submission data and 26AS, and notification settings.

{/* Summary cards */}

Submission data viewers (RE)

{submissionViewerEmails.length}

Who can see Form 16 submissions

26AS viewers (RE)

{twentySixAsViewerEmails.length}

Who can see 26AS page

Reminders to dealers

{reminderEnabled ? 'On' : 'Off'}

Pending Form 16 reminder schedule

Email / in-app notifications

{[ notification26AsDataAdded?.enabled, notificationForm16SuccessCreditNote?.enabled, notificationForm16Unsuccessful?.enabled, alertSubmitForm16Enabled, reminderNotificationEnabled, ].filter(Boolean).length}{' '} / 5 enabled

To dealers and RE as per rules below

{/* Submission data viewers */} Submission data – who can see Users with these email addresses can see Form 16 submission data (and the Form 16 menu in the sidebar). Use the exact login email of each user (the same email they use to sign in). Leave the list empty to allow all RE users with Form 16 access. setSubmissionViewerEmails((prev) => [...prev, email].sort())} onRemove={(email) => setSubmissionViewerEmails((prev) => prev.filter((e) => e !== email))} placeholder="e.g., user@royalenfield.com" /> {/* 26AS viewers */} 26AS page and button – who can see Users with these email addresses can see the 26AS page and 26AS menu item. Use the exact login email of each user. Leave empty to allow all RE users. setTwentySixAsViewerEmails((prev) => [...prev, email].sort())} onRemove={(email) => setTwentySixAsViewerEmails((prev) => prev.filter((e) => e !== email))} placeholder="e.g., user@royalenfield.com" /> {/* Notifications and reminders (simple toggles) */} Reminder schedule (for dealers) When reminders are enabled, dealers with pending Form 16 for a quarter are reminded at this interval. Set how often (in days) the system may send them a reminder to submit Form 16.
setReminderDays(parseInt(e.target.value, 10) || 7)} />
{/* Notification Configuration – Form 16 events */} Email and in-app notifications Configure who receives each notification, what triggers it, and when it is sent. Templates support placeholders such as [Name], [Request ID], [DueDate].

Form 16 notifications – recipient and trigger

{/* 26AS data added – separate message for RE users and for dealers */}

26AS data added

Sent to: RE users who can view 26AS, and separately to all dealers. When: As soon as new 26AS data is uploaded.