From 4614210aa9878922cfa1e424ce677ef893a1b6b2 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Mon, 29 Sep 2025 13:31:40 +0000 Subject: (대표님) 구매 권한설정, data room 등 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/email-template/preview/route.ts | 117 ++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 app/api/email-template/preview/route.ts (limited to 'app/api/email-template') diff --git a/app/api/email-template/preview/route.ts b/app/api/email-template/preview/route.ts new file mode 100644 index 00000000..6e066d27 --- /dev/null +++ b/app/api/email-template/preview/route.ts @@ -0,0 +1,117 @@ +import { NextResponse } from 'next/server'; +import db from "@/db/db"; +import { templateDetailView } from '@/db/schema'; +import { eq } from 'drizzle-orm'; +import handlebars from 'handlebars'; + +// Handlebars helper 등록 +handlebars.registerHelper('formatDate', function(date: any, format: string) { + if (!date) return ''; + + const d = new Date(date); + if (isNaN(d.getTime())) return ''; + + const year = d.getFullYear(); + const month = String(d.getMonth() + 1).padStart(2, '0'); + const day = String(d.getDate()).padStart(2, '0'); + const hours = String(d.getHours()).padStart(2, '0'); + const minutes = String(d.getMinutes()).padStart(2, '0'); + const seconds = String(d.getSeconds()).padStart(2, '0'); + + switch (format) { + case 'YYYY-MM-DD': + return `${year}-${month}-${day}`; + case 'YYYY-MM-DD HH:mm:ss': + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; + case 'YYYY-MM-DD HH:mm': + return `${year}-${month}-${day} ${hours}:${minutes}`; + default: + return d.toLocaleDateString('ko-KR'); + } +}); + +export async function POST(request: Request) { + try { + const { templateSlug, sampleData } = await request.json(); + + if (!templateSlug) { + return NextResponse.json( + { + success: false, + error: '템플릿 슬러그가 필요합니다.' + }, + { status: 400 } + ); + } + + // 데이터베이스에서 템플릿 조회 + const templates = await db + .select() + .from(templateDetailView) + .where(eq(templateDetailView.slug, templateSlug)) + .limit(1); + + if (templates.length === 0) { + return NextResponse.json( + { + success: false, + error: '템플릿을 찾을 수 없습니다.' + }, + { status: 404 } + ); + } + + const template = templates[0]; + + if (!template.isActive) { + return NextResponse.json( + { + success: false, + error: '비활성화된 템플릿입니다.' + }, + { status: 400 } + ); + } + + // HTML 템플릿에서 t helper 제거 ({{t 'key'}} -> {{key}}) + let subjectTemplateStr = template.subject || ''; + let contentTemplateStr = template.content || ''; + + // {{t 'key'}} 패턴을 {{key}}로 치환 + subjectTemplateStr = subjectTemplateStr.replace(/\{\{t\s+['"]([^'"]+)['"]\}\}/g, '{{$1}}'); + contentTemplateStr = contentTemplateStr.replace(/\{\{t\s+['"]([^'"]+)['"]\}\}/g, '{{$1}}'); + + // Handlebars 템플릿 컴파일 및 렌더링 + try { + const subjectTemplate = handlebars.compile(subjectTemplateStr); + const contentTemplate = handlebars.compile(contentTemplateStr); + + const renderedSubject = subjectTemplate(sampleData); + const renderedContent = contentTemplate(sampleData); + + return NextResponse.json({ + success: true, + subject: renderedSubject, + html: renderedContent + }); + } catch (compileError) { + console.error('템플릿 컴파일 오류:', compileError); + return NextResponse.json( + { + success: false, + error: '템플릿 처리 중 오류가 발생했습니다.' + }, + { status: 500 } + ); + } + } catch (error) { + console.error('미리보기 생성 실패:', error); + return NextResponse.json( + { + success: false, + error: '미리보기를 생성하는데 실패했습니다.' + }, + { status: 500 } + ); + } +} -- cgit v1.2.3