wallet-core/packages/aml-backoffice-ui/src/handlers/InputChoiceStacked.tsx
2023-06-05 10:04:09 -03:00

112 lines
3.3 KiB
TypeScript

import { TranslatedString } from "@gnu-taler/taler-util";
import { Fragment, VNode, h } from "preact";
import { LabelWithTooltipMaybeRequired, UIFormProps } from "./InputLine.js";
import { useField } from "./useField.js";
export interface Choice<V> {
label: TranslatedString;
description?: TranslatedString;
value: V;
}
export function InputChoiceStacked<T extends object, K extends keyof T>(
props: {
choices: Choice<T[K]>[];
} & UIFormProps<T, K>,
): VNode {
const {
choices,
name,
label,
tooltip,
help,
placeholder,
required,
before,
after,
converter,
} = props;
const { value, onChange, state, isDirty } = useField<T, K>(name);
if (state.hidden) {
return <Fragment />;
}
return (
<div class="sm:col-span-6">
<LabelWithTooltipMaybeRequired
label={label}
required={required}
tooltip={tooltip}
/>
<fieldset class="mt-2">
<div class="space-y-4">
{choices.map((choice) => {
// const currentValue = !converter
// ? choice.value
// : converter.fromStringUI(choice.value) ?? "";
let clazz =
"border relative block cursor-pointer rounded-lg bg-white px-6 py-4 shadow-sm focus:outline-none sm:flex sm:justify-between";
if (choice.value === value) {
clazz +=
" border-transparent border-indigo-600 ring-2 ring-indigo-600";
} else {
clazz += " border-gray-300";
}
return (
<label class={clazz}>
<input
type="radio"
name="server-size"
// defaultValue={choice.value}
value={
(!converter
? (choice.value as string)
: converter?.toStringUI(choice.value)) ?? ""
}
onClick={(e) => {
onChange(
(value === choice.value
? undefined
: choice.value) as T[K],
);
}}
class="sr-only"
aria-labelledby="server-size-0-label"
aria-describedby="server-size-0-description-0 server-size-0-description-1"
/>
<span class="flex items-center">
<span class="flex flex-col text-sm">
<span
id="server-size-0-label"
class="font-medium text-gray-900"
>
{choice.label}
</span>
{choice.description !== undefined && (
<span
id="server-size-0-description-0"
class="text-gray-500"
>
<span class="block sm:inline">
{choice.description}
</span>
</span>
)}
</span>
</span>
</label>
);
})}
</div>
</fieldset>
{help && (
<p class="mt-2 text-sm text-gray-500" id="email-description">
{help}
</p>
)}
</div>
);
}