From df649da20c8056ea177903e5a2b1c9515b76b2d0 Mon Sep 17 00:00:00 2001 From: Isabella Lam Date: Fri, 7 Aug 2026 12:40:23 -0400 Subject: [PATCH 1/2] Remove TemplateSelector file From 106c73d5e45d47d572d519b960d79d4de2eb9cec Mon Sep 17 00:00:00 2001 From: Isabella Lam Date: Fri, 7 Aug 2026 13:36:35 -0400 Subject: [PATCH 2/2] reemove template selector --- js/src/features/emails/TemplateManager.tsx | 347 ++++++++++++++++++ .../emails/_components/TemplateSelector.tsx | 96 ----- js/src/features/emails/api/emailAPI.ts | 27 ++ 3 files changed, 374 insertions(+), 96 deletions(-) create mode 100644 js/src/features/emails/TemplateManager.tsx delete mode 100644 js/src/features/emails/_components/TemplateSelector.tsx diff --git a/js/src/features/emails/TemplateManager.tsx b/js/src/features/emails/TemplateManager.tsx new file mode 100644 index 0000000..58b41b9 --- /dev/null +++ b/js/src/features/emails/TemplateManager.tsx @@ -0,0 +1,347 @@ +import type { + EmailTemplate, + SendRequest, + MessagePreview, +} from "@/features/emails/dto/emailDto"; + +import { EmailPreviewer } from "@/features/emails/_components/EmailPreviewer"; +import { + listTemplates, + createTemplate, + deleteTemplate, + sendToLegacyPreviewApi, +} from "@/features/emails/api/emailAPI"; +import { + showEmailSuccess, + showEmailError, +} from "@/features/emails/api/emailError"; +import { + Tabs, + Stack, + Table, + Button, + Modal, + Text, + TextInput, + Textarea, + Group, + ActionIcon, + Tooltip, + Box, + Flex, +} from "@mantine/core"; +import { IconTrash, IconPlus } from "@tabler/icons-react"; +import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; +import { useState } from "react"; + +/** + * UNREACHABLE: This component is currently not reachable in the app's UI. It is intended for future implementation in managing email templates. + * TemplateManager component allows users to view, create, and delete email templates. + * It also provides a preview feature to visualize how the email will look with sample data. + */ +export function TemplateManager() { + const queryClient = useQueryClient(); + const [showCreateModal, setShowCreateModal] = useState(false); + const [formData, setFormData] = useState({ name: "", subject: "", body: "" }); + const [previewData, setPreviewData] = useState(null); + + const { data: templates, isLoading } = useQuery({ + queryKey: ["emailTemplates"], + queryFn: () => listTemplates(), + }); + + const createMutation = useMutation({ + mutationFn: async () => { + return await createTemplate({ + name: formData.name, + subject: formData.subject, + body: formData.body, + }); + }, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ["emailTemplates"] }); + showEmailSuccess( + "Template Created", + `"${formData.name}" created successfully`, + ); + setFormData({ name: "", subject: "", body: "" }); + setShowCreateModal(false); + }, + onError: (error) => { + showEmailError( + "Creation Failed", + error instanceof Error ? error.message : "Unknown error", + ); + }, + }); + + const deleteMutation = useMutation({ + mutationFn: async (templateId: string) => { + return await deleteTemplate(templateId); + }, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ["emailTemplates"] }); + showEmailSuccess("Template Deleted", "Template removed successfully"); + }, + onError: (error) => { + showEmailError( + "Delete Failed", + error instanceof Error ? error.message : "Unknown error", + ); + }, + }); + + const handlePreviewTemplate = async () => { + if (!formData.subject || !formData.body) { + showEmailError("Missing Fields", "Subject and body are required"); + return; + } + + try { + // Create fake messages with sample variables to preview + const request: SendRequest = { + subject: formData.subject, + body: formData.body, + replyTo: null, + messages: [ + { + recipients: [ + { + email: "sample@example.com", + variableToValue: { + "per1.name": "Alice", + "per1.email": "alice@example.com", + "per2.name": "Bob", + "per2.email": "bob@example.com", + }, + }, + ], + }, + ], + }; + + const previews = await sendToLegacyPreviewApi(request); + setPreviewData(previews || []); + } catch (error) { + showEmailError( + "Preview Failed", + error instanceof Error ? error.message : "Unknown error", + ); + } + }; + + const rows = (templates || []).map((template) => ( + + + + {template.name} + + + + + {new Date(template.createdAt).toLocaleDateString()} + + + + + { + if (confirm(`Delete template "${template.name}"?`)) { + deleteMutation.mutate(template.id); + } + }} + loading={deleteMutation.isPending} + > + + + + + + )); + + return ( + + + Templates ({templates?.length || 0}) + Create New + + + + + Available Templates + + + {isLoading ? + Loading templates... + : (templates || []).length === 0 ? + No templates yet. Create one to get started. + : + + + Name + Created + Action + + + {rows} +
+ } +
+
+ + + + Create New Template + + setFormData({ + ...formData, + name: e.currentTarget.value, + }) + } + /> +