import { useState, useEffect } from "react"; import { Dialog, DialogTitle, DialogContent, TextField, Autocomplete, DialogActions, Button, Checkbox, FormControl, FormControlLabel, Box, MenuItem, Select, InputLabel } from "@mui/material"; import VisibilityIcon from '@mui/icons-material/Visibility'; import Template from "@/types/template"; import Mailing from "@/types/mailing"; import Target from "@/types/target"; import EmailList from "@/components/forms/EmailList"; import TestEmailList from "@/types/testEmailList"; import TemplateViewer from "@/components/modals/TemplateViewer" import TargetSampleModal from "@/components/modals/TargetSampleModal" import { useSetupData, SetupData } from "@/context/SetupDataContext"; import { useForm, Controller, Resolver } from "react-hook-form"; import { yupResolver } from "@hookform/resolvers/yup"; import * as yup from "yup"; import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import dayjs, { Dayjs } from 'dayjs'; // Import Dayjs for date handling import utc from 'dayjs/plugin/utc'; // Import the UTC plugin import { toast } from "react-toastify"; dayjs.extend(utc); type MailingEditProps = { open: boolean; mailing: Mailing | null; onClose: (reason: 'backdropClick' | 'escapeKeyDown' | 'saved' | 'cancelled') => void; onSave: (updatedMailing: Mailing) => void; }; //const statusOptions = [ // { code: 'C', name: 'Cancelled' }, // { code: 'ED', name: 'Editing' }, // { code: 'ER', name: 'Error' }, // { code: 'QE', name: 'Queueing Error' }, // { code: 'S', name: 'Sent' }, // { code: 'SC', name: 'Scheduled' }, // { code: 'SD', name: 'Sending' }, //]; const recurringTypeOptions = [ { code: 'D', name: 'Daily' }, { code: 'M', name: 'Monthly' }, { code: 'W', name: 'Weekly' }, ]; const schema = yup.object().shape({ id: yup.number().nullable(), name: yup.string().required("Name is required") .test("unique-name", "Name must be unique", async function (value) { if (value.length === 0) return true; return await nameIsAvailable(this.parent.id, value); }), description: yup.string().default(""), templateId: yup.number().typeError("Template is required").required("Template is required").test("valid-template", "Invalid template", function (value) { const setupData = this.options.context?.setupData as SetupData; return setupData.templates.some(t => t.id === value); }), targetId: yup.number().typeError("Target is required").required("Target is required").test("valid-target", "Invalid target", function (value) { const setupData = this.options.context?.setupData as SetupData; return setupData.targets.some(t => t.id === value); }), statusCode: yup.string().default("ED"), scheduleDate: yup.string() .nullable() .when("$scheduleForLater", (scheduleForLater, schema) => { const isScheduledForLater = scheduleForLater[0] ?? false; return isScheduledForLater ? schema .required("Schedule date is required when scheduled for later") .matches( /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/, "Schedule date must be a valid UTC ISO string (e.g., 'YYYY-MM-DDTHH:mm:ssZ')" ) .test("is-future", "Schedule date must be in the future", (value) => { if (!value) return true; // Nullable when not required return dayjs(value).isAfter(dayjs()); }) : schema.nullable(); }), //scheduleDate: yup.date().nullable(), // .when("statusCode", { // is: (value: string) => value === "SC" || value === "SD", // String comparison // then: (schema) => schema.required("Schedule date is required for scheduled or sending status"), // otherwise: (schema) => schema.nullable(), //}), sentDate: yup.date().nullable().default(null), sessionActivityId: yup.string().nullable(), recurringTypeCode: yup .string() .nullable() .when("$recurring", (recurring, schema) => { // Use context variable const isRecurring = recurring[0] ?? false; return isRecurring ? schema.oneOf(recurringTypeOptions.map((r) => r.code), "Invalid recurring type") : schema.nullable(); }), recurringStartDate: yup.string() .nullable() .when("$recurring", (recurring, schema) => { const isRecurring = recurring[0] ?? false; return isRecurring ? schema .required("Recurring start date is required when recurring") .matches( /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/, "Recurring start date must be a valid UTC ISO string (e.g., 'YYYY-MM-DDTHH:mm:ssZ')" ) .test("is-future", "Recurring start date must be in the future", (value) => { if (!value) return true; // Nullable when not required return dayjs(value).isAfter(dayjs()); }) : schema.nullable(); }), //.when("recurringTypeCode", { //is: (value: string) => value !== "" && value !== null, // String comparison for "None" //then: (schema) => schema.required("Recurring start date is required when recurring type is set"), //otherwise: (schema) => schema.nullable(), //}), }); const nameIsAvailable = async (id: number, name: string) => { const response = await fetch(`/api/mailings/available?${id > 0 ? "id=" + id + "&" : ""}name=${name}`); const data = await response.json(); return data.available; }; const getNextAvailableName = async (id: number, name: string) => { const response = await fetch(`/api/mailings/nextavailablename?${id > 0 ? "id=" + id + "&" : ""}name=${name}`); const data = await response.json(); return data.name; }; const defaultMailing: Mailing = { id: 0, name: "", description: "", templateId: 0, targetId: 0, statusCode: "ED", scheduleDate: null, sentDate: null, sessionActivityId: null, recurringTypeCode: null, recurringStartDate: null, }; const MailingEdit = ({ open, mailing, onClose, onSave }: MailingEditProps) => { const isNew = !mailing || mailing.id === 0; const setupData: SetupData = useSetupData(); const [approved, setApproved] = useState(false); const [recurring, setRecurring] = useState(false); const [scheduleForLater, setScheduleForLater] = useState(false); const [testEmailListId, setTestEmailListId] = useState(null); const [emails, setEmails] = useState([]); // State for email array const [templateViewerOpen, setTemplateViewerOpen] = useState(false); const [currentTemplate, setCurrentTemplate] = useState