import React, { useEffect, useState } from "react"; import { Check, X } from "lucide-react"; import type { Event } from "../../../services/api/types"; import type { ParticipantListRecord } from "../../../services/api/participantLists"; import { tagChipStyle } from "./participantTagUtils"; export type BulkDialogKind = null | "addTags" | "removeTags" | "assignEvents" | "newList" | "addToList"; export function ParticipantBulkDialogs({ bulkDialog, bulkBusy, selectedCount, selectedTagValues, onToggleTag, availableTags, removeTagOptions, tagScope = "global", newListName, onNewListNameChange, newListDesc, onNewListDescChange, eventsPick, eventPickIds, onToggleEventPick, fixedLists, addToListId, onAddToListIdChange, onClose, onApplyTags, onAssignEvents, onCreateList, onAddToList, }: { bulkDialog: BulkDialogKind; bulkBusy: boolean; selectedCount: number; selectedTagValues: string[]; onToggleTag: (tag: string) => void; availableTags: string[]; removeTagOptions: string[]; /** Event page = tags stored on this event membership; global = org-wide root tags. */ tagScope?: "event" | "global"; newListName: string; onNewListNameChange: (v: string) => void; newListDesc: string; onNewListDescChange: (v: string) => void; eventsPick: Event[]; eventPickIds: Set; onToggleEventPick: (id: string) => void; fixedLists: ParticipantListRecord[]; addToListId: string; onAddToListIdChange: (id: string) => void; onClose: () => void; onApplyTags: (action: "add_tags" | "remove_tags", overrideTags?: string[]) => void; onAssignEvents: () => void; onCreateList: () => void; onAddToList: () => void; }) { const [manualTagInput, setManualTagInput] = useState(""); useEffect(() => { if (bulkDialog !== "addTags" && bulkDialog !== "removeTags") setManualTagInput(""); }, [bulkDialog]); const addManualTags = () => { const tokens = manualTagInput .split(/[\n,;]+/) .map((token) => token.trim()) .filter(Boolean); if (!tokens.length) return []; tokens.forEach((token) => { if (!selectedTagValues.includes(token)) onToggleTag(token); }); setManualTagInput(""); return Array.from(new Set([...selectedTagValues, ...tokens])); }; const overlay = (children: React.ReactNode) => (
!bulkBusy && onClose()} >
e.stopPropagation()} > {children}
); const footer = (primary: React.ReactNode) => (
{primary}
); if (bulkDialog === "addTags" || bulkDialog === "removeTags") { const tagOptions = bulkDialog === "removeTags" ? removeTagOptions : availableTags; const emptyMessage = bulkDialog === "removeTags" ? "No tags are currently assigned to the selected participants." : tagScope === "event" ? "No tags are available yet for this event." : "No tags are available yet for this organisation."; const scopeHint = tagScope === "event" ? bulkDialog === "addTags" ? "Tags apply to this event only (also shown on the person’s global record, not on other events)." : "Removes tags from this event only. Organisation-wide tags of the same name stay visible here." : bulkDialog === "addTags" ? "Tags apply organisation-wide and appear on every event for these people." : "Removes the tag from the person entirely (organisation-wide and any event-specific copies)."; return overlay( <>

{bulkDialog === "addTags" ? "Add tags" : "Remove tags"}

Type a tag or select one below to apply to {selectedCount} selected participant(s).

{scopeHint}

setManualTagInput(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter" || e.key === "," || e.key === ";") { e.preventDefault(); addManualTags(); } }} placeholder={bulkDialog === "addTags" ? "Type a tag and press Enter" : "Type a tag and press Enter"} style={{ width: "100%", padding: "8px 12px", borderRadius: "var(--radius-button)", border: "1px solid var(--border)", fontSize: "var(--text-sm)", boxSizing: "border-box", marginBottom: "10px" }} /> {selectedTagValues.length > 0 && (
Selected
{selectedTagValues.map((tag) => { const tc = tagChipStyle(tag); return ( ); })}
)} {tagOptions.length === 0 ? (

{emptyMessage}

) : (
{tagOptions .filter(tag => !selectedTagValues.includes(tag)) .map((tag) => { const active = selectedTagValues.includes(tag); const tc = tagChipStyle(tag); return ( ); })}
)} {footer( )} ); } if (bulkDialog === "assignEvents") { return overlay( <>

Assign to event(s)

{selectedCount} people · adds pending membership where missing.

{eventsPick.map((ev) => ( ))}
{footer( )} ); } if (bulkDialog === "newList") { return overlay( <>

New custom list

Fixed list with {selectedCount} selected people.

onNewListNameChange(e.target.value)} placeholder="List name" style={{ width: "100%", padding: "8px 12px", borderRadius: "var(--radius-button)", border: "1px solid var(--border)", marginBottom: "8px", boxSizing: "border-box", fontSize: "var(--text-sm)" }} />