폼전송 기능 수정
CI / test (push) Failing after 4m53s
CI / e2e (push) Has been skipped
CI / pr_and_merge (push) Has been skipped

This commit is contained in:
2025-12-07 19:11:06 +09:00
parent 96fa34cd86
commit 243083261f
27 changed files with 1025 additions and 5 deletions
+100 -2
View File
@@ -1,7 +1,9 @@
"use client";
import { useState } from "react";
import type { Block, ButtonBlockProps, FormBlockProps } from "@/features/editor/state/editorStore";
import { NumericPropertyControl } from "@/features/editor/components/NumericPropertyControl";
import { computeFormControllerPublicTokens } from "@/features/editor/utils/formHelpers";
interface FormControllerPanelProps {
block: Block; // type === "form"
@@ -13,8 +15,59 @@ interface FormControllerPanelProps {
export function FormControllerPanel({ block, blocks, selectedBlockId, updateBlock }: FormControllerPanelProps) {
if (!selectedBlockId || block.id !== selectedBlockId) return null;
const [showSheetsGuide, setShowSheetsGuide] = useState(false);
const formProps = block.props as FormBlockProps;
const sheetsScriptExample = (() => {
const tokens = computeFormControllerPublicTokens(block, blocks);
const fieldNames = tokens.fields.map((f) => f.name).filter((name) => !!name);
if (fieldNames.length === 0) {
return (
"function doPost(e) {\n" +
' var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("시트1");\n' +
" if (!sheet) { sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0]; }\n" +
" var params = e.parameter; // x-www-form-urlencoded\n" +
" var row = [\n" +
' params.name || "",\n' +
' params.email || "",\n' +
' params.message || "",\n' +
" new Date(),\n" +
" ];\n" +
" sheet.appendRow(row);\n" +
" return ContentService\n" +
" .createTextOutput(JSON.stringify({ ok: true }))\n" +
" .setMimeType(ContentService.MimeType.JSON);\n" +
"}"
);
}
const headerNames = [...fieldNames, "createdAt"];
const rowLines = fieldNames.map((name) => ` params.${name} || "",`);
rowLines.push(" new Date(),");
const lines: string[] = [];
lines.push("function doPost(e) {");
lines.push(' var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("시트1");');
lines.push(" if (!sheet) { sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0]; }");
lines.push(" var params = e.parameter; // x-www-form-urlencoded");
lines.push(" // 시트의 1행 헤더는 다음과 같이 맞춰 주세요:");
lines.push(` // ${headerNames.join(", ")}`);
lines.push(" var row = [");
for (const line of rowLines) {
lines.push(line);
}
lines.push(" ];");
lines.push(" sheet.appendRow(row);");
lines.push(" return ContentService");
lines.push(" .createTextOutput(JSON.stringify({ ok: true }))");
lines.push(" .setMimeType(ContentService.MimeType.JSON);");
lines.push("}");
return lines.join("\n");
})();
return (
<div className="space-y-4 text-xs">
<p className="text-slate-400">
@@ -40,9 +93,9 @@ export function FormControllerPanel({ block, blocks, selectedBlockId, updateBloc
</div>
{formProps.submitTarget === "webhook" && (
<div className="space-y-2">
<div className="space-y-3">
<label className="flex flex-col gap-1">
<span className="text-slate-400">Webhook / Google Sheets URL</span>
<span className="text-slate-400">Webhook URL (: Google Apps Script URL)</span>
<input
className="w-full rounded border border-slate-700 bg-slate-950 px-2 py-1 text-xs outline-none focus:border-sky-500"
placeholder="예: https://script.google.com/macros/s/.../exec"
@@ -126,6 +179,16 @@ export function FormControllerPanel({ block, blocks, selectedBlockId, updateBloc
}}
/>
</label>
<div className="flex justify-end">
<button
type="button"
className="inline-flex items-center gap-1 rounded border border-slate-700 bg-slate-900 px-2 py-1 text-[11px] text-slate-100 hover:bg-slate-800"
onClick={() => setShowSheetsGuide(true)}
>
Google Sheets
</button>
</div>
</div>
)}
</div>
@@ -325,6 +388,41 @@ export function FormControllerPanel({ block, blocks, selectedBlockId, updateBloc
</select>
</div>
</div>
{showSheetsGuide && (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-slate-950/70">
<div className="w-full max-w-xl rounded border border-slate-800 bg-slate-950 px-4 py-3 shadow-lg">
<div className="mb-2 flex items-center justify-between">
<h4 className="text-[11px] font-semibold text-slate-100">Google Sheets </h4>
<button
type="button"
className="text-[11px] text-slate-400 hover:text-slate-100"
onClick={() => setShowSheetsGuide(false)}
aria-label="Google Sheets 연동 가이드 닫기"
>
</button>
</div>
<p className="text-[11px] text-slate-400 leading-relaxed">
, Google Apps Script URL .
.
</p>
<ol className="list-decimal list-inside space-y-1 text-[11px] text-slate-400 mt-2">
<li>Google Sheets , 1 name, email, message .</li>
<li> "확장 프로그램 → 앱스 스크립트" .</li>
<li>"배포 → 새 배포" , URL(/exec) Webhook URL .</li>
</ol>
<div className="mt-2 space-y-1">
<span className="text-[11px] text-slate-400"> Apps Script </span>
<textarea
className="w-full h-40 rounded border border-slate-800 bg-slate-950 px-2 py-1 text-[11px] font-mono text-slate-200"
readOnly
value={sheetsScriptExample}
/>
</div>
</div>
</div>
)}
</div>
);
}