first version able to send

This commit is contained in:
2026-06-11 00:04:00 +02:00
parent be793fb3e7
commit 93fb55273c
16 changed files with 869 additions and 645 deletions

View File

@@ -10,16 +10,7 @@ import { useCampaignDraftEditor } from "./hooks/useCampaignDraftEditor";
import { asRecord, isAuditLockedVersion, isRecord, versionLockReason } from "./utils/campaignView";
import { getBool, getText, updateNested } from "./utils/draftEditor";
import FieldValueInput from "./components/FieldValueInput";
const fieldTypeOptions = ["string", "integer", "double", "date", "password"];
type FieldDefinition = {
name: string;
label: string;
type: string;
required: boolean;
can_override: boolean;
};
import { fieldTypeOptions, humanizeFieldName, normalizeFieldType, type CampaignFieldDefinition } from "./utils/fieldDefinitions";
export default function CampaignFieldsPage({ settings, campaignId }: { settings: ApiSettings; campaignId: string }) {
@@ -55,7 +46,7 @@ export default function CampaignFieldsPage({ settings, campaignId }: { settings:
markDirty();
}
function patchFields(nextFields: FieldDefinition[]) {
function patchFields(nextFields: CampaignFieldDefinition[]) {
patchDraft(["fields"], nextFields.map((field) => ({
name: field.name,
type: field.type || "string",
@@ -70,7 +61,7 @@ export default function CampaignFieldsPage({ settings, campaignId }: { settings:
}
function setField(index: number, patchValue: Partial<FieldDefinition>) {
function setField(index: number, patchValue: Partial<CampaignFieldDefinition>) {
const nextFields = fields.map((field, currentIndex) => currentIndex === index ? { ...field, ...patchValue } : field);
patchFields(nextFields);
}
@@ -191,7 +182,7 @@ export default function CampaignFieldsPage({ settings, campaignId }: { settings:
<td><input value={field.name} disabled={locked} placeholder="field_name" onChange={(event) => renameField(index, event.target.value)} /></td>
<td><input value={field.label} disabled={locked} placeholder="Display label" onChange={(event) => setField(index, { label: event.target.value })} /></td>
<td>
<select value={field.type} disabled={locked} onChange={(event) => setField(index, { type: event.target.value })}>
<select value={field.type} disabled={locked} onChange={(event) => setField(index, { type: normalizeFieldType(event.target.value) })}>
{fieldTypeOptions.map((option) => <option key={option} value={option}>{option}</option>)}
</select>
</td>
@@ -215,12 +206,12 @@ export default function CampaignFieldsPage({ settings, campaignId }: { settings:
);
}
function normalizeFields(value: unknown): FieldDefinition[] {
function normalizeFields(value: unknown): CampaignFieldDefinition[] {
if (!Array.isArray(value)) return [];
return value.filter(isRecord).map((field) => ({
name: getText(field, "name"),
label: getText(field, "label"),
type: fieldTypeOptions.includes(getText(field, "type")) ? getText(field, "type") : "string",
type: normalizeFieldType(getText(field, "type")),
required: getBool(field, "required"),
can_override: getBool(field, "can_override", true)
}));
@@ -238,7 +229,7 @@ function migrateFieldOverridePolicy(draft: Record<string, unknown>, editorState:
return updateNested(draft, ["fields"], fields);
}
function describeFieldNameProblem(fields: FieldDefinition[]): string {
function describeFieldNameProblem(fields: CampaignFieldDefinition[]): string {
const names = fields.map((field) => field.name.trim());
if (names.some((name) => !name)) {
return "Field IDs must not be empty before saving.";
@@ -255,7 +246,7 @@ function describeFieldNameProblem(fields: FieldDefinition[]): string {
return `Duplicate field ID${duplicates.size === 1 ? "" : "s"}: ${[...duplicates].sort().join(", ")}. Field IDs must be unique before saving.`;
}
function uniqueFieldName(fields: FieldDefinition[]): string {
function uniqueFieldName(fields: CampaignFieldDefinition[]): string {
const existing = new Set(fields.map((field) => field.name));
let counter = fields.length + 1;
let name = `field_${counter}`;
@@ -265,8 +256,3 @@ function uniqueFieldName(fields: FieldDefinition[]): string {
}
return name;
}
function humanizeFieldName(name: string): string {
return name.replace(/_/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
}