107 lines
2.9 KiB
TypeScript
107 lines
2.9 KiB
TypeScript
import type { BuilderScreen } from "@/lib/admin/builder/types";
|
||
import type { ListOptionDefinition } from "@/lib/funnel/types";
|
||
|
||
export interface CreateTemplateScreenOptions {
|
||
templateId?: string;
|
||
screenId: string;
|
||
position: { x: number; y: number };
|
||
}
|
||
|
||
export interface BuilderTemplateDefinition {
|
||
id: string;
|
||
label: string;
|
||
description?: string;
|
||
create: (options: CreateTemplateScreenOptions, overrides?: Partial<BuilderScreen>) => BuilderScreen;
|
||
}
|
||
|
||
export const DEFAULT_TEMPLATE_ID = "list";
|
||
|
||
function cloneOptions(options: ListOptionDefinition[]): ListOptionDefinition[] {
|
||
return options.map((option) => ({ ...option }));
|
||
}
|
||
|
||
const LIST_TEMPLATE: BuilderTemplateDefinition = {
|
||
id: "list",
|
||
label: "Вопрос с вариантами",
|
||
create: ({ screenId, position }, overrides) => {
|
||
const base: BuilderScreen = {
|
||
id: screenId,
|
||
template: "list",
|
||
header: {
|
||
progress: {
|
||
current: 1,
|
||
total: 1,
|
||
label: "1 of 1",
|
||
},
|
||
},
|
||
title: {
|
||
text: "Новый экран",
|
||
font: "manrope",
|
||
weight: "bold",
|
||
},
|
||
subtitle: {
|
||
text: "Опишите вопрос справа",
|
||
color: "muted",
|
||
font: "inter",
|
||
},
|
||
list: {
|
||
selectionType: "single",
|
||
options: cloneOptions([
|
||
{ id: "option-1", label: "Вариант 1" },
|
||
{ id: "option-2", label: "Вариант 2" },
|
||
]),
|
||
},
|
||
navigation: {
|
||
defaultNextScreenId: undefined,
|
||
rules: [],
|
||
},
|
||
position,
|
||
};
|
||
|
||
if (!overrides) {
|
||
return base;
|
||
}
|
||
|
||
return {
|
||
...base,
|
||
...overrides,
|
||
list: overrides.list
|
||
? {
|
||
...base.list,
|
||
...overrides.list,
|
||
options: overrides.list.options ?? base.list.options,
|
||
}
|
||
: base.list,
|
||
navigation: overrides.navigation
|
||
? {
|
||
defaultNextScreenId:
|
||
overrides.navigation.defaultNextScreenId ?? base.navigation?.defaultNextScreenId,
|
||
rules: overrides.navigation.rules ?? base.navigation?.rules ?? [],
|
||
}
|
||
: base.navigation,
|
||
};
|
||
},
|
||
};
|
||
|
||
const BUILDER_TEMPLATES: BuilderTemplateDefinition[] = [LIST_TEMPLATE];
|
||
|
||
export function getTemplateDefinition(templateId: string): BuilderTemplateDefinition {
|
||
return BUILDER_TEMPLATES.find((template) => template.id === templateId) ?? LIST_TEMPLATE;
|
||
}
|
||
|
||
export function createTemplateScreen(
|
||
options: CreateTemplateScreenOptions,
|
||
overrides?: Partial<BuilderScreen>
|
||
): BuilderScreen {
|
||
const definition = getTemplateDefinition(options.templateId ?? DEFAULT_TEMPLATE_ID);
|
||
return definition.create(options, overrides);
|
||
}
|
||
|
||
export function getTemplateOptions(): { id: string; label: string; description?: string }[] {
|
||
return BUILDER_TEMPLATES.map((template) => ({
|
||
id: template.id,
|
||
label: template.label,
|
||
description: template.description,
|
||
}));
|
||
}
|