"use client";
import { api } from "~/trpc/react";
import { Spinner } from "@usesend/ui/src/spinner";
import { Input } from "@usesend/ui/src/input";
import { Editor } from "@usesend/email-editor";
import { useState } from "react";
import { Template } from "@prisma/client";
import { toast } from "@usesend/ui/src/toaster";
import { useDebouncedCallback } from "use-debounce";
import { formatDistanceToNow } from "date-fns";
import { ArrowLeft } from "lucide-react";
import Link from "next/link";
import { use } from "react";
const IMAGE_SIZE_LIMIT = 10 * 1024 * 1024;
export default function EditTemplatePage({
params,
}: {
params: Promise<{ templateId: string }>;
}) {
const { templateId } = use(params);
const {
data: template,
isLoading,
error,
} = api.template.getTemplate.useQuery(
{ templateId: templateId },
{
enabled: !!templateId,
},
);
if (isLoading) {
return (
);
}
if (error) {
return (
);
}
if (!template) {
return Template not found
;
}
return ;
}
function TemplateEditor({
template,
}: {
template: Template & { imageUploadSupported: boolean };
}) {
const utils = api.useUtils();
const [json, setJson] = useState | undefined>(
template.content ? JSON.parse(template.content) : undefined,
);
const [isSaving, setIsSaving] = useState(false);
const [name, setName] = useState(template.name);
const [subject, setSubject] = useState(template.subject);
const updateTemplateMutation = api.template.updateTemplate.useMutation({
onSuccess: () => {
utils.template.getTemplate.invalidate();
setIsSaving(false);
},
});
const getUploadUrl = api.template.generateImagePresignedUrl.useMutation();
function updateEditorContent() {
updateTemplateMutation.mutate({
templateId: template.id,
content: JSON.stringify(json),
});
}
const deboucedUpdateTemplate = useDebouncedCallback(
updateEditorContent,
1000,
);
const handleFileChange = async (file: File) => {
if (file.size > IMAGE_SIZE_LIMIT) {
throw new Error(
`File should be less than ${IMAGE_SIZE_LIMIT / 1024 / 1024}MB`,
);
}
console.log("file type: ", file.type);
const { uploadUrl, imageUrl } = await getUploadUrl.mutateAsync({
name: file.name,
type: file.type,
templateId: template.id,
});
const response = await fetch(uploadUrl, {
method: "PUT",
body: file,
});
if (!response.ok) {
throw new Error("Failed to upload file");
}
return imageUrl;
};
return (
{isSaving ? (
) : (
)}
{formatDistanceToNow(template.updatedAt) === "less than a minute"
? "just now"
: `${formatDistanceToNow(template.updatedAt)} ago`}
{
setJson(content.getJSON());
setIsSaving(true);
deboucedUpdateTemplate();
}}
variables={["email", "firstName", "lastName"]}
uploadImage={
template.imageUploadSupported ? handleFileChange : undefined
}
/>
);
}