import React, { useState, useEffect } from "react"; import { Plus, Trash2 } from "lucide-react"; import { useAuth } from "../../contexts/AuthContext"; import { PanelShell, AccordionSection, useAccordion, Label, Field, Grid, RadioGroup, HelperText, IS, SS, focusIn, focusOut } from "./PanelShell"; import { participantListsApi, participantsApi, eventsApi, portfolioListOrganizationId } from "../../../services/api"; import type { Event, ParticipantListRecord } from "../../../services/api"; interface FilterRule { id: string; field: string; operator: string; value: string; } interface Form { listName: string; description: string; rules: FilterRule[]; conjunction: "AND" | "OR"; visibility: "Private" | "Shared"; autoUpdate: "Yes" | "No"; } const FIELD_OPTIONS = ["Status", "Tag", "Event"] as const; const OP_OPTIONS_IS = ["is", "is not"] as const; const STATUS_OPTIONS: { label: string; value: string }[] = [ { label: "Pending", value: "pending" }, { label: "Confirmed", value: "confirmed" }, { label: "Checked In", value: "checked_in" }, { label: "Cancelled", value: "cancelled" }, { label: "Rejected", value: "rejected" }, ]; const emptyForm = (): Form => ({ listName: "", description: "", rules: [{ id: `r-${Math.random().toString(36).slice(2)}`, field: "Status", operator: "is", value: "pending" }], conjunction: "AND", visibility: "Private", autoUpdate: "Yes", }); function newRuleId(i: number) { return `rule-${i}-${Math.random().toString(36).slice(2, 10)}`; } function normalizeApiRule(x: { field?: string; operator?: string; value?: string }, i: number): FilterRule { const fieldRaw = String(x.field ?? "Status"); const field = (FIELD_OPTIONS as readonly string[]).includes(fieldRaw) ? fieldRaw : "Status"; const opRaw = String(x.operator ?? "is").trim().toLowerCase(); const operator: FilterRule["operator"] = opRaw === "is not" ? "is not" : "is"; let value = String(x.value ?? ""); if (field === "Status") { const ok = STATUS_OPTIONS.some((s) => s.value === value); if (!ok) value = "pending"; } return { id: newRuleId(i), field, operator, value }; } function formFromListRecord(doc: ParticipantListRecord): Form { const r = doc.rules; const raw = Array.isArray(r?.rules) ? r.rules : []; const rules: FilterRule[] = raw.length ? raw.map((x, i) => normalizeApiRule(x, i)) : [{ id: newRuleId(0), field: "Status", operator: "is", value: "pending" }]; return { listName: doc.name, description: doc.description ?? "", rules, conjunction: r?.conjunction === "OR" ? "OR" : "AND", visibility: doc.visibility === "shared" ? "Shared" : "Private", autoUpdate: doc.autoUpdate !== false ? "Yes" : "No", }; } export function CreateCustomListPanel({ onClose, onCreated, onSaved, editList = null, }: { onClose: () => void; onCreated?: () => void; /** Called after a rule-based list is updated (edit mode). */ onSaved?: (list: ParticipantListRecord) => void; /** When set to a rule-based list, the panel opens in edit mode (same form, saves via PUT). */ editList?: ParticipantListRecord | null; }) { const { user } = useAuth(); const listOrgId = portfolioListOrganizationId(user); const TOTAL = 3; const acc = useAccordion(TOTAL); const isEdit = Boolean(editList?.type === "rule_based"); const [form, setForm] = useState