summaryrefslogtreecommitdiff
path: root/app/api/email-template/preview/route.ts
blob: 6e066d27759103d7c85799a9710159a5d20eccbf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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 }
    );
  }
}