import { ParsedICSEvent, parseICSFile, toast } from "@xtablo/shared"; import { EventInsert } from "@xtablo/shared/types/events.types"; import { CreateTablo } from "@xtablo/shared/types/tablos.types"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@xtablo/ui/components/select"; import { useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { useCreateEvents } from "../hooks/events"; import { useCreateTablo, useTablosList } from "../hooks/tablos"; import { useUser } from "../providers/UserStoreProvider"; interface ImportICSModalProps { onClose: () => void; } export const ImportICSModal = ({ onClose }: ImportICSModalProps) => { const { t } = useTranslation("components"); const user = useUser(); const fileInputRef = useRef(null); const [selectedFile, setSelectedFile] = useState(null); const [parsedEvents, setParsedEvents] = useState([]); const [selectedTabloId, setSelectedTabloId] = useState(""); const [newTabloName, setNewTabloName] = useState(""); const [createNewTablo, setCreateNewTablo] = useState(false); const [isImporting, setIsImporting] = useState(false); const { data: tablos, isLoading: tablosLoading } = useTablosList(); const createTabloMutation = useCreateTablo(); const createEvents = useCreateEvents(); const handleFileSelect = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (file && file.name.endsWith(".ics")) { setSelectedFile(file); const reader = new FileReader(); reader.onload = (e) => { const content = e.target?.result as string; try { const events = parseICSFile(content); setParsedEvents(events); if (events.length === 0) { toast.add( { title: t("importICSModal.toasts.noEvents.title"), description: t("importICSModal.toasts.noEvents.description"), type: "warning", }, { timeout: 4000 } ); } } catch (error) { console.error("Error parsing ICS file:", error); toast.add( { title: t("importICSModal.toasts.readError.title"), description: t("importICSModal.toasts.readError.description"), type: "error", }, { timeout: 4000 } ); } }; reader.readAsText(file); } else { toast.add( { title: t("importICSModal.toasts.invalidFormat.title"), description: t("importICSModal.toasts.invalidFormat.description"), type: "error", }, { timeout: 4000 } ); } }; const handleImport = async () => { if (parsedEvents.length === 0) { toast.add( { title: t("importICSModal.toasts.noEventsToImport.title"), description: t("importICSModal.toasts.noEventsToImport.description"), type: "warning", }, { timeout: 3000 } ); return; } if (!createNewTablo && !selectedTabloId) { toast.add( { title: t("importICSModal.toasts.tabloRequired.title"), description: t("importICSModal.toasts.tabloRequired.description"), type: "warning", }, { timeout: 3000 } ); return; } if (createNewTablo && !newTabloName.trim()) { toast.add( { title: t("importICSModal.toasts.tabloNameRequired.title"), description: t("importICSModal.toasts.tabloNameRequired.description"), type: "warning", }, { timeout: 3000 } ); return; } setIsImporting(true); try { const targetTabloId = selectedTabloId; const eventsToInsert = parsedEvents.map((event) => { const eventData: EventInsert = { title: event.title, description: event.description || "", start_date: event.start_date, start_time: event.start_time, end_time: event.end_time || event.start_time, tablo_id: targetTabloId, created_by: user.id, }; return eventData; }); if (createNewTablo) { const newTabloData: CreateTablo = { name: newTabloName.trim(), color: "bg-blue-500", image: null, status: "todo", events: eventsToInsert, }; await createTabloMutation.mutateAsync(newTabloData); toast.add( { title: t("importICSModal.toasts.importSuccess.title"), description: t("importICSModal.toasts.importSuccess.description", { count: parsedEvents.length, }), type: "success", }, { timeout: 4000 } ); } else { await createEvents(eventsToInsert); } onClose(); } catch (error) { console.error("Error importing events:", error); toast.add( { title: t("importICSModal.toasts.importError.title"), description: t("importICSModal.toasts.importError.description"), type: "error", }, { timeout: 4000 } ); } finally { setIsImporting(false); } }; return (
{/* Header */}

{t("importICSModal.title")}

{t("importICSModal.subtitle")}
{/* Form Content */}
{/* File Selection */}
{selectedFile && ( {selectedFile.name} )}
{parsedEvents.length > 0 && (
{t("importICSModal.messages.eventsFound", { count: parsedEvents.length })}
)}
{/* Tablo Selection */}
{/* Create new tablo option */}
{ setCreateNewTablo(e.target.checked); if (e.target.checked) { setSelectedTabloId(""); } }} className="rounded border-gray-300 dark:border-gray-600" />
{createNewTablo ? ( setNewTabloName(e.target.value)} placeholder={t("importICSModal.placeholders.newTabloName")} className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-green-500 dark:bg-gray-800 dark:text-white" /> ) : ( )}
{/* Preview */} {parsedEvents.length > 0 && (
{parsedEvents.slice(0, 5).map((event, index) => (
{event.title} {event.start_date} {event.start_time.substring(0, 5)}
))} {parsedEvents.length > 5 && (
{t("importICSModal.messages.andMore", { count: parsedEvents.length - 5 })}
)}
)}
{/* Footer */}
); };