ci 오류 수정
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import type { Block, SectionBlockProps, TextBlockProps, ImageBlockProps } from "@/features/editor/state/editorStore";
|
||||
import type { EditorBlogTemplateMessages } from "@/features/i18n/messages/editorTemplates";
|
||||
|
||||
export function createBlogTemplateBlocks(opts: {
|
||||
sectionId: string;
|
||||
createId: () => string;
|
||||
messages: EditorBlogTemplateMessages;
|
||||
}): { blocks: Block[]; lastSelectedId: string } {
|
||||
const { sectionId, createId } = opts;
|
||||
const { sectionId, createId, messages } = opts;
|
||||
|
||||
const columns: SectionBlockProps["columns"] = [
|
||||
{ id: `${sectionId}_col_1`, span: 4 },
|
||||
@@ -33,14 +35,8 @@ export function createBlogTemplateBlocks(opts: {
|
||||
columnId: null,
|
||||
};
|
||||
|
||||
const postDefinitions = [
|
||||
{ title: "블로그 포스트 1", summary: "첫 번째 포스트 요약을 여기에 입력하세요." },
|
||||
{ title: "블로그 포스트 2", summary: "두 번째 포스트 요약을 여기에 입력하세요." },
|
||||
{ title: "블로그 포스트 3", summary: "세 번째 포스트 요약을 여기에 입력하세요." },
|
||||
];
|
||||
|
||||
const blogBlocks: Block[] = columns.flatMap((col, index) => {
|
||||
const post = postDefinitions[index] ?? postDefinitions[0];
|
||||
const post = messages.posts[index] ?? messages.posts[0];
|
||||
|
||||
const imageId = createId();
|
||||
const titleId = createId();
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import type { Block, SectionBlockProps, TextBlockProps, ButtonBlockProps } from "@/features/editor/state/editorStore";
|
||||
import type { EditorCtaTemplateMessages } from "@/features/i18n/messages/editorTemplates";
|
||||
|
||||
export function createCtaTemplateBlocks(opts: {
|
||||
sectionId: string;
|
||||
createId: () => string;
|
||||
messages: EditorCtaTemplateMessages;
|
||||
}): { blocks: Block[]; lastSelectedId: string } {
|
||||
const { sectionId, createId } = opts;
|
||||
const { sectionId, createId, messages } = opts;
|
||||
|
||||
const columns: SectionBlockProps["columns"] = [
|
||||
{ id: `${sectionId}_col_1`, span: 8 },
|
||||
@@ -37,7 +39,7 @@ export function createCtaTemplateBlocks(opts: {
|
||||
|
||||
const textId = createId();
|
||||
const textProps: TextBlockProps = {
|
||||
text: "지금 바로 행동을 유도하는 CTA 텍스트를 입력하세요.\n망설이지 말고 시작하세요!",
|
||||
text: messages.body,
|
||||
align: "left",
|
||||
size: "lg",
|
||||
} as any;
|
||||
@@ -51,7 +53,7 @@ export function createCtaTemplateBlocks(opts: {
|
||||
|
||||
const buttonId = createId();
|
||||
const buttonProps: ButtonBlockProps = {
|
||||
label: "CTA 버튼",
|
||||
label: messages.buttonLabel,
|
||||
href: "#",
|
||||
align: "center",
|
||||
size: "lg",
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import type { Block, SectionBlockProps, TextBlockProps } from "@/features/editor/state/editorStore";
|
||||
import type { EditorFaqTemplateMessages } from "@/features/i18n/messages/editorTemplates";
|
||||
|
||||
export function createFaqTemplateBlocks(opts: {
|
||||
sectionId: string;
|
||||
createId: () => string;
|
||||
messages: EditorFaqTemplateMessages;
|
||||
}): { blocks: Block[]; lastSelectedId: string } {
|
||||
const { sectionId, createId } = opts;
|
||||
const { sectionId, createId, messages } = opts;
|
||||
|
||||
const columns: SectionBlockProps["columns"] = [
|
||||
{ id: `${sectionId}_col_1`, span: 3 },
|
||||
@@ -38,7 +40,7 @@ export function createFaqTemplateBlocks(opts: {
|
||||
// Left Column: Title
|
||||
const titleId = createId();
|
||||
const titleProps: TextBlockProps = {
|
||||
text: "FAQ",
|
||||
text: messages.title,
|
||||
align: "left",
|
||||
size: "xl",
|
||||
bold: true,
|
||||
@@ -53,7 +55,7 @@ export function createFaqTemplateBlocks(opts: {
|
||||
|
||||
const subTitleId = createId();
|
||||
const subTitleProps: TextBlockProps = {
|
||||
text: "자주 묻는 질문",
|
||||
text: messages.subtitle,
|
||||
align: "left",
|
||||
size: "sm",
|
||||
color: "muted",
|
||||
@@ -68,22 +70,7 @@ export function createFaqTemplateBlocks(opts: {
|
||||
|
||||
|
||||
// Right Column: Q&A List
|
||||
const faqPairs = [
|
||||
{
|
||||
question: "서비스 이용료는 얼마인가요?",
|
||||
answer: "기본 기능은 무료로 제공되며, 프리미엄 기능은 월 구독료가 발생합니다.",
|
||||
},
|
||||
{
|
||||
question: "환불 정책은 어떻게 되나요?",
|
||||
answer: "결제 후 7일 이내에 사용 이력이 없는 경우 전액 환불 가능합니다.",
|
||||
},
|
||||
{
|
||||
question: "팀원 초대 기능이 있나요?",
|
||||
answer: "네, 프로 요금제 이상부터 팀원 초대가 가능합니다.",
|
||||
},
|
||||
];
|
||||
|
||||
const faqBlocks: Block[] = faqPairs.flatMap((pair) => {
|
||||
const faqBlocks: Block[] = messages.items.flatMap((pair) => {
|
||||
const qId = createId();
|
||||
const aId = createId();
|
||||
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import type { Block, SectionBlockProps, TextBlockProps } from "@/features/editor/state/editorStore";
|
||||
import type { EditorFeaturesTemplateMessages } from "@/features/i18n/messages/editorTemplates";
|
||||
|
||||
export function createFeaturesTemplateBlocks(opts: {
|
||||
sectionId: string;
|
||||
createId: () => string;
|
||||
messages: EditorFeaturesTemplateMessages;
|
||||
}): { blocks: Block[]; lastSelectedId: string } {
|
||||
const { sectionId, createId } = opts;
|
||||
const { sectionId, createId, messages } = opts;
|
||||
|
||||
const columns = [
|
||||
{ id: `${sectionId}_col_1`, span: 4 },
|
||||
@@ -38,13 +40,13 @@ export function createFeaturesTemplateBlocks(opts: {
|
||||
const descId = createId();
|
||||
|
||||
const titleProps: TextBlockProps = {
|
||||
text: `Feature ${index + 1} 제목`,
|
||||
text: `${messages.itemTitlePrefix} ${index + 1}${messages.itemTitleSuffix}`.trim(),
|
||||
align: "left",
|
||||
size: "lg",
|
||||
} as any;
|
||||
|
||||
const descProps: TextBlockProps = {
|
||||
text: "해당 기능을 간단히 설명하는 텍스트입니다.",
|
||||
text: messages.itemDescription,
|
||||
align: "left",
|
||||
size: "sm",
|
||||
} as any;
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import type { Block, SectionBlockProps, TextBlockProps } from "@/features/editor/state/editorStore";
|
||||
import type { EditorFooterTemplateMessages } from "@/features/i18n/messages/editorTemplates";
|
||||
|
||||
export function createFooterTemplateBlocks(opts: {
|
||||
sectionId: string;
|
||||
createId: () => string;
|
||||
messages: EditorFooterTemplateMessages;
|
||||
}): { blocks: Block[]; lastSelectedId: string } {
|
||||
const { sectionId, createId } = opts;
|
||||
const { sectionId, createId, messages } = opts;
|
||||
|
||||
const columns: SectionBlockProps["columns"] = [
|
||||
{ id: `${sectionId}_col_1`, span: 4 },
|
||||
@@ -54,7 +56,7 @@ export function createFooterTemplateBlocks(opts: {
|
||||
|
||||
const descId = createId();
|
||||
const descProps: TextBlockProps = {
|
||||
text: "더 나은 웹사이트를 위한 최고의 선택.",
|
||||
text: messages.description,
|
||||
align: "left",
|
||||
size: "sm",
|
||||
color: "muted",
|
||||
@@ -70,7 +72,7 @@ export function createFooterTemplateBlocks(opts: {
|
||||
// Col 2: Links
|
||||
const linksId = createId();
|
||||
const linksProps: TextBlockProps = {
|
||||
text: "서비스 소개\n요금제\n고객지원\n문의하기",
|
||||
text: messages.linksText,
|
||||
align: "center",
|
||||
size: "sm",
|
||||
color: "muted",
|
||||
|
||||
@@ -6,12 +6,14 @@ import type {
|
||||
TextBlockProps,
|
||||
ButtonBlockProps,
|
||||
} from "@/features/editor/state/editorStore";
|
||||
import type { EditorHeroTemplateMessages } from "@/features/i18n/messages/editorTemplates";
|
||||
|
||||
export function createHeroTemplateBlocks(opts: {
|
||||
sectionId: string;
|
||||
createId: () => string;
|
||||
messages: EditorHeroTemplateMessages;
|
||||
}): { blocks: Block[]; lastSelectedId: string } {
|
||||
const { sectionId, createId } = opts;
|
||||
const { sectionId, createId, messages } = opts;
|
||||
|
||||
const sectionProps: SectionBlockProps = {
|
||||
background: "default",
|
||||
@@ -41,7 +43,7 @@ export function createHeroTemplateBlocks(opts: {
|
||||
|
||||
const heroHeadlineId = createId();
|
||||
const heroHeadlineProps: TextBlockProps = {
|
||||
text: "Hero 제목을 여기에 입력하세요",
|
||||
text: messages.headline,
|
||||
align: "center",
|
||||
size: "lg",
|
||||
} as any;
|
||||
@@ -55,7 +57,7 @@ export function createHeroTemplateBlocks(opts: {
|
||||
|
||||
const heroSubId = createId();
|
||||
const heroSubProps: TextBlockProps = {
|
||||
text: "제품이나 서비스를 한 문장으로 설명하는 서브텍스트입니다.",
|
||||
text: messages.subheadline,
|
||||
align: "center",
|
||||
size: "base",
|
||||
} as any;
|
||||
@@ -69,7 +71,7 @@ export function createHeroTemplateBlocks(opts: {
|
||||
|
||||
const heroButtonId = createId();
|
||||
const heroButtonProps: ButtonBlockProps = {
|
||||
label: "지금 시작하기",
|
||||
label: messages.primaryButtonLabel,
|
||||
href: "#",
|
||||
align: "center",
|
||||
size: "md",
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import type { Block, SectionBlockProps, TextBlockProps, ImageBlockProps } from "@/features/editor/state/editorStore";
|
||||
import type { EditorTeamTemplateMessages } from "@/features/i18n/messages/editorTemplates";
|
||||
|
||||
export function createTeamTemplateBlocks(opts: {
|
||||
sectionId: string;
|
||||
createId: () => string;
|
||||
messages: EditorTeamTemplateMessages;
|
||||
}): { blocks: Block[]; lastSelectedId: string } {
|
||||
const { sectionId, createId } = opts;
|
||||
const { sectionId, createId, messages } = opts;
|
||||
|
||||
const columns: SectionBlockProps["columns"] = [
|
||||
{ id: `${sectionId}_col_1`, span: 4 },
|
||||
@@ -33,14 +35,8 @@ export function createTeamTemplateBlocks(opts: {
|
||||
columnId: null,
|
||||
};
|
||||
|
||||
const memberDefinitions = [
|
||||
{ name: "홍길동", role: "Product Designer", bio: "사용자 경험을 설계합니다." },
|
||||
{ name: "김영희", role: "Frontend Engineer", bio: "깔끔한 UI를 구현합니다." },
|
||||
{ name: "이철수", role: "Backend Engineer", bio: "안정적인 인프라를 책임집니다." },
|
||||
];
|
||||
|
||||
const teamBlocks: Block[] = columns.flatMap((col, index) => {
|
||||
const m = memberDefinitions[index] ?? memberDefinitions[0];
|
||||
const m = messages.members[index] ?? messages.members[0];
|
||||
|
||||
const imageId = createId();
|
||||
const nameId = createId();
|
||||
|
||||
@@ -9,6 +9,8 @@ import { createCtaTemplateBlocks } from "@/app/editor/templates/ctaTemplate";
|
||||
import { createFaqTemplateBlocks } from "@/app/editor/templates/faqTemplate";
|
||||
import { createPricingTemplateBlocks } from "@/app/editor/templates/pricingTemplate";
|
||||
import { createTestimonialsTemplateBlocks } from "@/app/editor/templates/testimonialsTemplate";
|
||||
import { getEditorTemplatesMessages } from "@/features/i18n/messages/editorTemplates";
|
||||
import { DEFAULT_LOCALE } from "@/features/i18n/locale";
|
||||
|
||||
// 블록 타입 정의: 텍스트/버튼/이미지/비디오/섹션/구분선/리스트/폼 블록/폼 요소 블록
|
||||
export type BlockType =
|
||||
@@ -914,9 +916,11 @@ const createEditorState = (set: any, get: any): EditorState => {
|
||||
}
|
||||
}
|
||||
|
||||
const tpl = getEditorTemplatesMessages(DEFAULT_LOCALE);
|
||||
const { blocks: templateBlocks, lastSelectedId } = createHeroTemplateBlocks({
|
||||
sectionId,
|
||||
createId,
|
||||
messages: tpl.hero,
|
||||
});
|
||||
|
||||
pushHistoryImpl(set, get);
|
||||
@@ -937,11 +941,6 @@ const createEditorState = (set: any, get: any): EditorState => {
|
||||
});
|
||||
},
|
||||
|
||||
// 리스트 아이템 선택 상태를 업데이트한다.
|
||||
selectListItem: (itemId) => {
|
||||
set({ selectedListItemId: itemId ?? null });
|
||||
},
|
||||
|
||||
// Features 템플릿 섹션 추가: 3컬럼(4/4/4) 섹션과 각 컬럼의 제목/설명 텍스트를 생성한다
|
||||
addFeaturesTemplateSection: () => {
|
||||
const { selectedBlockId, blocks } = get();
|
||||
@@ -956,9 +955,11 @@ const createEditorState = (set: any, get: any): EditorState => {
|
||||
}
|
||||
}
|
||||
|
||||
const tpl = getEditorTemplatesMessages(DEFAULT_LOCALE);
|
||||
const { blocks: templateBlocks, lastSelectedId } = createFeaturesTemplateBlocks({
|
||||
sectionId,
|
||||
createId,
|
||||
messages: tpl.features,
|
||||
});
|
||||
|
||||
pushHistoryImpl(set, get);
|
||||
@@ -993,9 +994,11 @@ const createEditorState = (set: any, get: any): EditorState => {
|
||||
}
|
||||
}
|
||||
|
||||
const tpl = getEditorTemplatesMessages(DEFAULT_LOCALE);
|
||||
const { blocks: templateBlocks, lastSelectedId } = createBlogTemplateBlocks({
|
||||
sectionId,
|
||||
createId,
|
||||
messages: tpl.blog,
|
||||
});
|
||||
|
||||
pushHistoryImpl(set, get);
|
||||
@@ -1030,9 +1033,11 @@ const createEditorState = (set: any, get: any): EditorState => {
|
||||
}
|
||||
}
|
||||
|
||||
const tpl = getEditorTemplatesMessages(DEFAULT_LOCALE);
|
||||
const { blocks: templateBlocks, lastSelectedId } = createTeamTemplateBlocks({
|
||||
sectionId,
|
||||
createId,
|
||||
messages: tpl.team,
|
||||
});
|
||||
|
||||
pushHistoryImpl(set, get);
|
||||
@@ -1067,9 +1072,11 @@ const createEditorState = (set: any, get: any): EditorState => {
|
||||
}
|
||||
}
|
||||
|
||||
const tpl = getEditorTemplatesMessages(DEFAULT_LOCALE);
|
||||
const { blocks: templateBlocks, lastSelectedId } = createFooterTemplateBlocks({
|
||||
sectionId,
|
||||
createId,
|
||||
messages: tpl.footer,
|
||||
});
|
||||
|
||||
pushHistoryImpl(set, get);
|
||||
@@ -1104,9 +1111,11 @@ const createEditorState = (set: any, get: any): EditorState => {
|
||||
}
|
||||
}
|
||||
|
||||
const tpl = getEditorTemplatesMessages(DEFAULT_LOCALE);
|
||||
const { blocks: templateBlocks, lastSelectedId } = createCtaTemplateBlocks({
|
||||
sectionId,
|
||||
createId,
|
||||
messages: tpl.cta,
|
||||
});
|
||||
|
||||
pushHistoryImpl(set, get);
|
||||
@@ -1141,9 +1150,11 @@ const createEditorState = (set: any, get: any): EditorState => {
|
||||
}
|
||||
}
|
||||
|
||||
const tpl = getEditorTemplatesMessages(DEFAULT_LOCALE);
|
||||
const { blocks: templateBlocks, lastSelectedId } = createFaqTemplateBlocks({
|
||||
sectionId,
|
||||
createId,
|
||||
messages: tpl.faq,
|
||||
});
|
||||
|
||||
pushHistoryImpl(set, get);
|
||||
@@ -1733,6 +1744,11 @@ const createEditorState = (set: any, get: any): EditorState => {
|
||||
}));
|
||||
},
|
||||
|
||||
// 현재 선택된 리스트 아이템 ID 를 상태에 저장한다.
|
||||
selectListItem: (itemId) => {
|
||||
set({ selectedListItemId: itemId });
|
||||
},
|
||||
|
||||
// 선택된 리스트 아이템을 들여쓰기한다.
|
||||
indentSelectedListItem: (blockId) => {
|
||||
const { blocks, selectedListItemId } = get();
|
||||
|
||||
@@ -7,24 +7,24 @@ export function LocaleSwitcher() {
|
||||
const locale = useAppLocale();
|
||||
const { setLocale } = useLocaleActions();
|
||||
|
||||
const handleChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const nextLocale = event.target.value as AppLocale;
|
||||
const handleToggle = () => {
|
||||
const nextLocale: AppLocale = locale === "en" ? "ko" : "en";
|
||||
setLocale(nextLocale);
|
||||
};
|
||||
|
||||
const labelText = locale === "en" ? "EN" : "KO";
|
||||
|
||||
return (
|
||||
<div className="fixed bottom-4 right-4 z-50 text-xs">
|
||||
<label className="inline-flex items-center gap-1 rounded border border-slate-300 bg-white/80 px-2 py-1 text-slate-700 shadow-sm backdrop-blur dark:border-slate-700 dark:bg-slate-900/80 dark:text-slate-100">
|
||||
<span>Language</span>
|
||||
<select
|
||||
className="bg-transparent text-xs outline-none"
|
||||
value={locale}
|
||||
onChange={handleChange}
|
||||
>
|
||||
<option value="en">English</option>
|
||||
<option value="ko">한국어</option>
|
||||
</select>
|
||||
</label>
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Toggle locale"
|
||||
className="inline-flex items-center justify-center rounded-full border border-slate-300 bg-white/80 px-2 py-1 text-slate-700 shadow-sm backdrop-blur dark:border-slate-700 dark:bg-slate-900/80 dark:text-slate-100"
|
||||
onClick={handleToggle}
|
||||
>
|
||||
{labelText}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user