import React, { useState, useMemo, useCallback } from "react"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { __ } from "../lib/i18n"; import { deleteEmailSequence, fetchEmailLogs, fetchEmailSequences, updateEmailSequenceStatus, } from "../api/email-automation-api"; import { useToast } from "../components/ui/toast"; import { Card, CardContent, CardFooter, CardHeader, CardTitle, } from "../components/ui/card"; import { Button } from "../components/ui/button"; import { Badge } from "../components/ui/badge"; import { PageHeader } from "../components/common/PageHeader"; import { ConfirmationDialog } from "../components/ui/confirmation-dialog"; import PremiumUpgradeCard from "./premium-pages/EmailAutomation"; import { Mail, Edit, Clock, FileText, Bell, Plus, Trash2, Play, Pause, Zap, GitBranch, Loader2, Save, Settings2, Send, } from "lucide-react"; import { isProPluginActive, isEmailAutomationModuleEnabled, } from "../lib/plugin-utils"; import { useEmailSettingsManager } from "../hooks/useEmailSettingsManager"; import { EmailDeliverySection } from "../components/settings/EmailDeliverySection"; import { EmailTemplatesList } from "../components/email/EmailTemplatesList"; import { Pagination } from "../components/shared"; interface EmailLog { id: number; template_key: string; recipient_email: string; recipient_name: string; subject: string; status: "sent" | "failed" | "opened" | "clicked"; sent_at: string; } interface EmailSequence { id: number; name: string; description: string; trigger_type: string; trigger_config: any; status: "active" | "paused" | "draft"; applicable_to: string; trip_ids: number[]; steps_count?: number; } const EmailSequencesList: React.FC = () => { const queryClient = useQueryClient(); const { showToast } = useToast(); const { data: sequencesData, isLoading } = useQuery({ queryKey: ["email-sequences"], queryFn: () => fetchEmailSequences(), enabled: isEmailAutomationModuleEnabled(), }); const deleteMutation = useMutation({ mutationFn: async (id: number) => { return await deleteEmailSequence(id); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["email-sequences"] }); showToast(__("Sequence deleted"), "success"); }, }); const toggleStatusMutation = useMutation({ mutationFn: async ({ id, status }: { id: number; status: string }) => { return await updateEmailSequenceStatus(id, status); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["email-sequences"] }); showToast(__("Sequence status updated"), "success"); }, }); const sequences = ( Array.isArray(sequencesData) ? sequencesData : [] ) as EmailSequence[]; const navigateToCreate = () => { window.location.href = "admin.php?page=yatra&subpage=email-automation&tab=sequence&action=create"; }; const navigateToEdit = (id: number) => { window.location.href = `admin.php?page=yatra&subpage=email-automation&tab=sequence&action=edit&id=${id}`; }; if (isLoading) { return (
{/* Header Skeleton */}
{/* Sequences List Skeleton */}
{[1, 2, 3].map((i) => (
))}
); } const getStatusBadge = (status: string) => { switch (status) { case "active": return ( {__("Active")} ); case "paused": return ( {__("Paused")} ); default: return ( {__("Draft")} ); } }; const emailEvents = (window as any).yatraAdmin?.emailEvents || []; const getTriggerLabel = (triggerType: string) => { const ev = emailEvents.find((e: { key?: string }) => e.key === triggerType); return ev?.name || triggerType; }; return (
{/* Header */}

{__("Email Sequences")}

{__("Create automated email workflows triggered by events")}

{/* Sequences List */} {sequences.length === 0 ? (

{__("No Sequences Yet")}

{__( "Create your first automated email sequence to engage customers at the right time.", )}

) : (
{sequences.map((sequence) => (

{sequence.name}

{getStatusBadge(sequence.status)}

{sequence.description || __("No description")}

{getTriggerLabel(sequence.trigger_type)} {sequence.steps_count || 0} {__("steps")}
{sequence.status === "active" ? ( ) : ( )}
))}
)}
); }; const EmailLogsList: React.FC = () => { const [page, setPage] = useState(1); const perPage = 20; const { data: logsData, isLoading } = useQuery({ queryKey: ["email-logs", page, perPage], queryFn: () => fetchEmailLogs({ page, per_page: perPage }), enabled: isEmailAutomationModuleEnabled(), }); const logs = (logsData?.items ?? []) as EmailLog[]; const totalItems = logsData?.total ?? 0; const totalPages = Math.max(1, Math.ceil(totalItems / perPage)); if (isLoading) { return (
{[1, 2, 3, 4, 5].map((i) => ( ))} {[1, 2, 3, 4, 5].map((row) => ( {[1, 2, 3, 4, 5].map((col) => ( ))} ))}
); } return ( {__("Email Logs")} {logs.length === 0 ? (
{__("No emails sent yet")}
) : (
{logs.map((log) => ( ))}
{__("Recipient")} {__("Subject")} {__("Template")} {__("Status")} {__("Sent")}
{log.recipient_name || "-"}
{log.recipient_email}
{log.subject} {log.template_key} {log.status} {log.sent_at ? new Date(log.sent_at).toLocaleString() : "—"}
)} {logs.length > 0 && totalPages > 1 && (
)}
); }; type EmailHubTab = "delivery" | "templates" | "sequences" | "logs"; function getInitialEmailHubTab(): EmailHubTab { if (typeof window === "undefined") return "delivery"; const tab = new URLSearchParams(window.location.search).get("tab"); if (tab === "sequences" || tab === "sequence") return "sequences"; if (tab === "template" || tab === "templates") return "templates"; if (tab === "logs") return "logs"; if (tab === "delivery" || tab === "core") return "delivery"; return "delivery"; } const EmailAutomationModulePrompt: React.FC = () => (

{__("Enable the Email Automation module", "yatra")}

{__( "Yatra Pro is active. Turn on Email Automation under Modules to use custom templates, sequences, and send logs.", "yatra", )}

); const EmailAutomation: React.FC = () => { const emailMgr = useEmailSettingsManager(); const [activeTab, setActiveTab] = useState(() => { const t = getInitialEmailHubTab(); if (!isProPluginActive() && (t === "sequences" || t === "logs")) { return "delivery"; } return t; }); const showProAutomationExtras = isProPluginActive(); const automationReady = isEmailAutomationModuleEnabled(); const tabs = [ { key: "delivery" as const, label: __("Delivery", "yatra"), icon: Send, }, { key: "templates" as const, label: __("Templates", "yatra"), icon: FileText, }, ...(showProAutomationExtras ? [ { key: "sequences" as const, label: __("Sequences", "yatra"), icon: GitBranch, }, { key: "logs" as const, label: __("Email logs", "yatra"), icon: Mail, }, ] : []), ]; return (
{activeTab === "delivery" && ( <> {!emailMgr.ready ? (
) : ( )} )} {activeTab === "templates" && ( <> {automationReady && (

{__( "Customer booking, payment, cancellation, and trip-reminder emails use the matching template when its body is filled; otherwise the free plugin defaults or settings HTML apply. Admin: New Booking sends when that template has a body (plain-text admin notices from checkout and notifications are skipped to avoid duplicates). Other booking.created templates send in addition to the customer email. Booking Confirmed uses the “Booking Confirmed” row when a booking moves to confirmed; Trip Completed uses its template instead of the generic completed email when the body is filled.", "yatra", )}

)} {!emailMgr.ready && !automationReady ? (
) : ( )} )} {activeTab === "sequences" && (automationReady ? ( ) : isProPluginActive() ? ( ) : ( ))} {activeTab === "logs" && (automationReady ? ( ) : isProPluginActive() ? ( ) : ( ))}
{(activeTab === "delivery" || activeTab === "templates") && emailMgr.ready && ( )}
); }; export default EmailAutomation;