You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
2.8 KiB
TypeScript

import { Reducer } from "preact/hooks";
import {
Field,
FieldKind,
FieldOptions,
MaybePersistedSchema,
defaultOptionsForFieldKind,
} from "../../../common/schema.ts";
import { ViewState } from "../App/state.ts";
import { ReturnTypes, UnionToIntersection } from "../../../common/utils.ts";
import { deleteIdx, setIdx, setProp } from "../../../common/lib/imm.ts";
export const setName = (name: string) => ({ kind: "setName" as const, name });
export const addField = () => ({ kind: "addField" as const });
export const setFieldProp = <K extends keyof Field>(
index: number,
prop: K,
value: Field[K],
) => ({
kind: "setFieldProp" as const,
index,
prop,
value,
});
export type AllOptions = UnionToIntersection<FieldOptions[FieldKind]>;
export const setFieldOption = <K extends keyof AllOptions>(
index: number,
option: K,
value: AllOptions[K],
) => ({
kind: "setFieldOption" as const,
index,
option,
value,
});
export const deleteField = (index: number) => ({
kind: "deleteField" as const,
index,
});
export type Action = ReturnTypes<
[
typeof setName,
typeof addField,
typeof setFieldProp,
typeof deleteField,
typeof setFieldOption,
]
>;
export type State = MaybePersistedSchema;
const reduce_ = (state: State, action: Action): ViewState => {
if (action.kind == "setName") {
return {
kind: "SchemaEditor",
state: {
...state,
name: action.name,
},
};
} else if (action.kind == "addField") {
return {
kind: "SchemaEditor",
state: {
...state,
fields: [
...state.fields,
{
kind: "string",
name: "New field",
options: defaultOptionsForFieldKind("string"),
required: false,
},
],
},
};
} else if (action.kind == "setFieldProp") {
let field = setProp(state.fields[action.index], action.prop, action.value);
if (action.prop == "kind") {
field = setProp(field, "options", {
...defaultOptionsForFieldKind(field.kind),
...field.options,
});
}
return {
kind: "SchemaEditor",
state: {
...state,
fields: setIdx(state.fields, action.index, field),
},
};
} else if (action.kind == "setFieldOption") {
return {
kind: "SchemaEditor",
state: setProp(
state,
"fields",
setIdx(
state.fields,
action.index,
setProp(
state.fields[action.index],
"options",
setProp(
state.fields[action.index].options,
action.option as never,
action.value as never,
),
),
),
),
};
} else if (action.kind == "deleteField") {
return {
kind: "SchemaEditor",
state: setProp(state, "fields", deleteIdx(state.fields, action.index)),
};
}
return {
kind: "SchemaEditor",
state,
};
};
export const reduce: Reducer<ViewState, Action> = (state, action) => {
return reduce_(state.state as State, action);
};