diff --git a/src/app/(main)/dashboard/template-item.tsx b/src/app/(main)/dashboard/template-item.tsx index 62c77b3..39b12d0 100644 --- a/src/app/(main)/dashboard/template-item.tsx +++ b/src/app/(main)/dashboard/template-item.tsx @@ -15,6 +15,7 @@ export default function TemplateItem({ template }: { template: Template }) { // TODO: global loading return await createInvitation({ title: template.title, + thumbnailUrl: template.thumbnailUrl, customFields: template.customFields, }); }, diff --git a/src/app/(main)/i/[subdomain]/page.tsx b/src/app/(main)/i/[subdomain]/page.tsx index e52aed3..76dbccf 100644 --- a/src/app/(main)/i/[subdomain]/page.tsx +++ b/src/app/(main)/i/[subdomain]/page.tsx @@ -18,13 +18,20 @@ export async function generateMetadata( if (!invitation) { return {}; } - const previousImages = (await parent).openGraph?.images || []; + + const images = (await parent).openGraph?.images || []; + if (invitation.thumbnailUrl) { + images.unshift(invitation.thumbnailUrl); + } return { title: { default: invitation.title, template: "%s | 인비", }, + openGraph: { + images, + }, }; } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 513a8df..65e997d 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -6,6 +6,10 @@ import "./globals.css"; export const metadata: Metadata = { title: "초대장 플랫폼, 인비", description: "따뜻한 마음을 담아 당신의 환대를 전해보세요.", + openGraph: { + images: + "http://t1.daumcdn.net/brunch/service/user/d4v5/image/Axc3mTi7LoZC2GpsBWosDpRrNPU.png", + }, }; export default function RootLayout({ diff --git a/src/components/editor/sidebar/sidebar-settings-tab.tsx b/src/components/editor/sidebar/sidebar-settings-tab.tsx index 61a55c8..f64fcba 100644 --- a/src/components/editor/sidebar/sidebar-settings-tab.tsx +++ b/src/components/editor/sidebar/sidebar-settings-tab.tsx @@ -3,6 +3,7 @@ import { useForm } from "@tanstack/react-form"; import { useMutation } from "@tanstack/react-query"; import { LinkIcon } from "lucide-react"; +import { useMemo } from "react"; import { toast } from "sonner"; import { useEditor } from "~/components/editor/provider"; import ImageDropzone from "~/components/editor/ui/image-dropzone"; @@ -145,7 +146,7 @@ function CustomDomainSection() { function SEOSection() { const { editor, dispatch } = useEditor(); - const onCopyLink = async () => { + const handleCopyLink = async () => { const link = `https://${editor.config.invitationSubdomain}.invi.my`; try { @@ -173,6 +174,25 @@ function SEOSection() { }, }); + const updateThumbnailMutation = useMutation({ + mutationFn: async () => { + await updateInvitation({ + id: editor.config.invitationId, + thumbnailUrl: editor.config.invitationThumbnail, + }); + }, + onSuccess: () => { + toast.success("SEO 설정이 저장되었습니다."); + }, + onError: () => { + toast.error("SEO 설정에 실패했습니다."); + }, + }); + + const isPending = useMemo(() => { + return uploadImageMutation.isPending || updateThumbnailMutation.isPending; + }, [uploadImageMutation.isPending, updateThumbnailMutation.isPending]); + return (