atelier/shelves/backend/templates/index.ts
2025-02-02 12:24:00 -05:00

58 lines
1.3 KiB
TypeScript

export function View(props: { title: string; body: string }) {
return `
<!DOCTYPE html>
<html lang="en">
<head>
<title>${props.title} - Shelves</title>
</head>
<body>
${props.body}
<script src="/static/js/bundle.js" type="text/javascript" module></script>
</body>
</html>
`;
}
export type FormFieldType = 'text' | 'textarea' | 'file' | 'number';
export type FormFieldProps = {
name: string;
type: FormFieldType;
label: string;
error?: string;
required?: boolean;
};
export function FormField(props: FormFieldProps) {
const input = () => {
const attrs = `name='${props.name}' id="${props.name}" ${
(props.required ?? true) && "required aria-required='true'"
}`;
if (props.type === 'textarea') {
return `<textarea ${attrs}></textarea>`;
} else {
return `<input type="${props.type}" ${attrs}>`;
}
};
return `
<div class="form-input">
<label for="${props.name}">${props.label}</label>
${input()}
<div class="error" id="${props.name}-error" aria-live="polite">${
props.error ?? ''
}</div>
</div>
`;
}
export function Form(
props: { action: string; fields: FormFieldProps[]; hasFileData?: boolean },
) {
return `
<form action="${props.action}" method="POST" ${
props.hasFileData ? "enctype='multipart/form-data'" : ''
}>
${props.fields.map(FormField).join('')}
<input type="submit" value="Submit">
</form>
`;
}