fix form
This commit is contained in:
parent
f281803f1e
commit
55a1e8c6e1
@ -1,16 +1,12 @@
|
|||||||
import { h, VNode } from "preact";
|
|
||||||
import { HeroSections } from "./HeroSections.js";
|
|
||||||
import "./scss/main.css";
|
|
||||||
import { Dashboard } from "./Dashborad.js";
|
|
||||||
import { Form } from "./Form.js";
|
|
||||||
import { TranslationProvider } from "@gnu-taler/web-util/browser";
|
import { TranslationProvider } from "@gnu-taler/web-util/browser";
|
||||||
|
import { h, VNode } from "preact";
|
||||||
|
import { Dashboard } from "./Dashborad.js";
|
||||||
|
import "./scss/main.css";
|
||||||
|
|
||||||
export function App(): VNode {
|
export function App(): VNode {
|
||||||
return (
|
return (
|
||||||
<TranslationProvider source={{}}>
|
<TranslationProvider source={{}}>
|
||||||
<Dashboard>
|
<Dashboard />
|
||||||
<Form />
|
|
||||||
</Dashboard>
|
|
||||||
</TranslationProvider>
|
</TranslationProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,8 @@ import {
|
|||||||
ChevronDownIcon,
|
ChevronDownIcon,
|
||||||
MagnifyingGlassIcon,
|
MagnifyingGlassIcon,
|
||||||
} from "@heroicons/react/20/solid";
|
} from "@heroicons/react/20/solid";
|
||||||
import { useState } from "preact/hooks";
|
import { useRef, useState } from "preact/hooks";
|
||||||
|
import { Form } from "./Form.js";
|
||||||
|
|
||||||
const navigation = [
|
const navigation = [
|
||||||
{ name: "Dashboard", href: "#", icon: HomeIcon, current: true },
|
{ name: "Dashboard", href: "#", icon: HomeIcon, current: true },
|
||||||
@ -43,9 +44,10 @@ function classNames(...classes: string[]) {
|
|||||||
export function Dashboard({
|
export function Dashboard({
|
||||||
children,
|
children,
|
||||||
}: {
|
}: {
|
||||||
children: ComponentChildren;
|
children?: ComponentChildren;
|
||||||
}): VNode {
|
}): VNode {
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||||
|
const logRef = useRef<HTMLPreElement>(null);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -53,6 +55,7 @@ export function Dashboard({
|
|||||||
<Transition.Root show={sidebarOpen} as={Fragment}>
|
<Transition.Root show={sidebarOpen} as={Fragment}>
|
||||||
<Dialog
|
<Dialog
|
||||||
as="div"
|
as="div"
|
||||||
|
/* @ts-ignore */
|
||||||
class="relative z-50 lg:hidden"
|
class="relative z-50 lg:hidden"
|
||||||
onClose={setSidebarOpen}
|
onClose={setSidebarOpen}
|
||||||
>
|
>
|
||||||
@ -195,9 +198,12 @@ export function Dashboard({
|
|||||||
alt="Your Company"
|
alt="Your Company"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="text-white text-sm">
|
||||||
|
<pre ref={logRef}></pre>
|
||||||
|
</div>
|
||||||
<nav class="flex flex-1 flex-col">
|
<nav class="flex flex-1 flex-col">
|
||||||
<ul role="list" class="flex flex-1 flex-col gap-y-7">
|
<ul role="list" class="flex flex-1 flex-col gap-y-7">
|
||||||
<li>
|
{/* <li>
|
||||||
<ul role="list" class="-mx-2 space-y-1">
|
<ul role="list" class="-mx-2 space-y-1">
|
||||||
{navigation.map((item) => (
|
{navigation.map((item) => (
|
||||||
<li key={item.name}>
|
<li key={item.name}>
|
||||||
@ -224,8 +230,8 @@ export function Dashboard({
|
|||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li> */}
|
||||||
<li>
|
{/* <li>
|
||||||
<div class="text-xs font-semibold leading-6 text-indigo-200">
|
<div class="text-xs font-semibold leading-6 text-indigo-200">
|
||||||
Your teams
|
Your teams
|
||||||
</div>
|
</div>
|
||||||
@ -249,7 +255,7 @@ export function Dashboard({
|
|||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li> */}
|
||||||
<li class="mt-auto">
|
<li class="mt-auto">
|
||||||
<a
|
<a
|
||||||
href="#"
|
href="#"
|
||||||
@ -314,7 +320,11 @@ export function Dashboard({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Profile dropdown */}
|
{/* Profile dropdown */}
|
||||||
<Menu as="div" class="relative">
|
<Menu
|
||||||
|
as="div"
|
||||||
|
/* @ts-ignore */
|
||||||
|
class="relative"
|
||||||
|
>
|
||||||
<Menu.Button class="-m-1.5 flex items-center p-1.5">
|
<Menu.Button class="-m-1.5 flex items-center p-1.5">
|
||||||
<span class="sr-only">Open user menu</span>
|
<span class="sr-only">Open user menu</span>
|
||||||
<img
|
<img
|
||||||
@ -368,7 +378,16 @@ export function Dashboard({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<main class="py-10">
|
<main class="py-10">
|
||||||
<div class="px-4 sm:px-6 lg:px-8">{children}</div>
|
<div class="px-4 sm:px-6 lg:px-8">
|
||||||
|
<div class="mx-auto max-w-3xl">
|
||||||
|
<Form
|
||||||
|
onUpdate={(v) => {
|
||||||
|
if (!logRef.current) return;
|
||||||
|
logRef.current.innerHTML = JSON.stringify(v, undefined, 1);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { AbsoluteTime, TranslatedString } from "@gnu-taler/taler-util";
|
import { AbsoluteTime, TranslatedString } from "@gnu-taler/taler-util";
|
||||||
import { useTranslationContext } from "@gnu-taler/web-util/browser";
|
import { useTranslationContext } from "@gnu-taler/web-util/browser";
|
||||||
import { Fragment, h } from "preact";
|
import { Fragment, h } from "preact";
|
||||||
import { useState } from "preact/hooks";
|
import { useRef, useState } from "preact/hooks";
|
||||||
import { FormProvider } from "./forms/FormProvider.js";
|
import { FormProvider, FormState } from "./forms/FormProvider.js";
|
||||||
import { DoubleColumnForm, RenderAllFieldsByUiConfig } from "./forms/forms.js";
|
import { DoubleColumnForm, RenderAllFieldsByUiConfig } from "./forms/forms.js";
|
||||||
import { CircleStackIcon } from "@heroicons/react/24/outline";
|
import { CircleStackIcon } from "@heroicons/react/24/outline";
|
||||||
|
|
||||||
@ -218,232 +218,234 @@ const firstForm: DoubleColumnForm = [
|
|||||||
name: "filler.when",
|
name: "filler.when",
|
||||||
pattern: "dd/MM/yyyy",
|
pattern: "dd/MM/yyyy",
|
||||||
label: "Date" as TranslatedString,
|
label: "Date" as TranslatedString,
|
||||||
|
help: "format 'dd/MM/yyyy'" as TranslatedString,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
title: "Information on customer" as TranslatedString,
|
// title: "Information on customer" as TranslatedString,
|
||||||
description:
|
// description:
|
||||||
"The customer is the person with whom the member concludes the contract with regard to the financial service provided (civil law). Does the member act as director of a domiciliary company, this domiciliary company is the customer." as TranslatedString,
|
// "The customer is the person with whom the member concludes the contract with regard to the financial service provided (civil law). Does the member act as director of a domiciliary company, this domiciliary company is the customer." as TranslatedString,
|
||||||
fields: [
|
// fields: [
|
||||||
{
|
// {
|
||||||
type: "choiceStacked",
|
// type: "choiceStacked",
|
||||||
props: {
|
// props: {
|
||||||
name: "customerType",
|
// name: "customerType",
|
||||||
label: "Type of customer" as TranslatedString,
|
// label: "Type of customer" as TranslatedString,
|
||||||
required: true,
|
// required: true,
|
||||||
choices: [
|
// choices: [
|
||||||
{
|
// {
|
||||||
label: "Natural person" as TranslatedString,
|
// label: "Natural person" as TranslatedString,
|
||||||
value: "natural",
|
// value: "natural",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
label: "Legal entity" as TranslatedString,
|
// label: "Legal entity" as TranslatedString,
|
||||||
value: "legal",
|
// value: "legal",
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: "text",
|
// type: "text",
|
||||||
props: {
|
// props: {
|
||||||
name: "naturalCustomer.fullName",
|
// name: "naturalCustomer.fullName",
|
||||||
label: "Full name" as TranslatedString,
|
// label: "Full name" as TranslatedString,
|
||||||
required: true,
|
// required: true,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: "text",
|
// type: "text",
|
||||||
props: {
|
// props: {
|
||||||
name: "naturalCustomer.address",
|
// name: "naturalCustomer.address",
|
||||||
label: "Residential address" as TranslatedString,
|
// label: "Residential address" as TranslatedString,
|
||||||
required: true,
|
// required: true,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: "integer",
|
// type: "integer",
|
||||||
props: {
|
// props: {
|
||||||
name: "naturalCustomer.telephone",
|
// name: "naturalCustomer.telephone",
|
||||||
label: "Telephone" as TranslatedString,
|
// label: "Telephone" as TranslatedString,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: "text",
|
// type: "text",
|
||||||
props: {
|
// props: {
|
||||||
name: "naturalCustomer.email",
|
// name: "naturalCustomer.email",
|
||||||
label: "E-mail" as TranslatedString,
|
// label: "E-mail" as TranslatedString,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: "text",
|
// type: "text",
|
||||||
props: {
|
// props: {
|
||||||
name: "naturalCustomer.dateOfBirth",
|
// name: "naturalCustomer.dateOfBirth",
|
||||||
label: "Date of birth" as TranslatedString,
|
// label: "Date of birth" as TranslatedString,
|
||||||
required: true,
|
// required: true,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: "text",
|
// type: "text",
|
||||||
props: {
|
// props: {
|
||||||
name: "naturalCustomer.nationality",
|
// name: "naturalCustomer.nationality",
|
||||||
label: "Nationality" as TranslatedString,
|
// label: "Nationality" as TranslatedString,
|
||||||
required: true,
|
// required: true,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: "text",
|
// type: "text",
|
||||||
props: {
|
// props: {
|
||||||
name: "naturalCustomer.document",
|
// name: "naturalCustomer.document",
|
||||||
label: "Identification document" as TranslatedString,
|
// label: "Identification document" as TranslatedString,
|
||||||
required: true,
|
// required: true,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: "text",
|
// type: "text",
|
||||||
props: {
|
// props: {
|
||||||
name: "naturalCustomer.companyName",
|
// name: "naturalCustomer.companyName",
|
||||||
label: "Company name" as TranslatedString,
|
// label: "Company name" as TranslatedString,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: "text",
|
// type: "text",
|
||||||
props: {
|
// props: {
|
||||||
name: "naturalCustomer.office",
|
// name: "naturalCustomer.office",
|
||||||
label: "Registered office" as TranslatedString,
|
// label: "Registered office" as TranslatedString,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: "text",
|
// type: "text",
|
||||||
props: {
|
// props: {
|
||||||
name: "naturalCustomer.companyDocument",
|
// name: "naturalCustomer.companyDocument",
|
||||||
label: "Company identification document" as TranslatedString,
|
// label: "Company identification document" as TranslatedString,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: "text",
|
// type: "text",
|
||||||
props: {
|
// props: {
|
||||||
name: "legalCustomer.companyName",
|
// name: "legalCustomer.companyName",
|
||||||
label: "Company name" as TranslatedString,
|
// label: "Company name" as TranslatedString,
|
||||||
required: true,
|
// required: true,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: "text",
|
// type: "text",
|
||||||
props: {
|
// props: {
|
||||||
name: "legalCustomer.domicile",
|
// name: "legalCustomer.domicile",
|
||||||
label: "Domicile" as TranslatedString,
|
// label: "Domicile" as TranslatedString,
|
||||||
required: true,
|
// required: true,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: "text",
|
// type: "text",
|
||||||
props: {
|
// props: {
|
||||||
name: "legalCustomer.contactPerson",
|
// name: "legalCustomer.contactPerson",
|
||||||
label: "Contact person" as TranslatedString,
|
// label: "Contact person" as TranslatedString,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: "text",
|
// type: "text",
|
||||||
props: {
|
// props: {
|
||||||
name: "legalCustomer.telephone",
|
// name: "legalCustomer.telephone",
|
||||||
label: "Telephone" as TranslatedString,
|
// label: "Telephone" as TranslatedString,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: "text",
|
// type: "text",
|
||||||
props: {
|
// props: {
|
||||||
name: "legalCustomer.email",
|
// name: "legalCustomer.email",
|
||||||
label: "E-mail" as TranslatedString,
|
// label: "E-mail" as TranslatedString,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: "text",
|
// type: "text",
|
||||||
props: {
|
// props: {
|
||||||
name: "legalCustomer.document",
|
// name: "legalCustomer.document",
|
||||||
label: "Identification document" as TranslatedString,
|
// label: "Identification document" as TranslatedString,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
title:
|
// title:
|
||||||
"Information on the natural persons who establish the business relationship for legal entities and partnerships" as TranslatedString,
|
// "Information on the natural persons who establish the business relationship for legal entities and partnerships" as TranslatedString,
|
||||||
description:
|
// description:
|
||||||
"For legal entities and partnerships the identity of the natural persons who establish the business relationship must be verified." as TranslatedString,
|
// "For legal entities and partnerships the identity of the natural persons who establish the business relationship must be verified." as TranslatedString,
|
||||||
fields: [
|
// fields: [
|
||||||
{
|
// {
|
||||||
type: "array",
|
// type: "array",
|
||||||
props: {
|
// props: {
|
||||||
name: "businessEstablisher",
|
// name: "businessEstablisher",
|
||||||
label: "Persons" as TranslatedString,
|
// label: "Persons" as TranslatedString,
|
||||||
required: true,
|
// required: true,
|
||||||
tooltip: "hola" as TranslatedString,
|
// tooltip: "hola" as TranslatedString,
|
||||||
placeholder: "this is the placeholder" as TranslatedString,
|
// placeholder: "this is the placeholder" as TranslatedString,
|
||||||
fields: [
|
// fields: [
|
||||||
{
|
// {
|
||||||
type: "text",
|
// type: "text",
|
||||||
props: {
|
// props: {
|
||||||
name: "fullName",
|
// name: "fullName",
|
||||||
label: "Full name" as TranslatedString,
|
// label: "Full name" as TranslatedString,
|
||||||
required: true,
|
// required: true,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: "text",
|
// type: "text",
|
||||||
props: {
|
// props: {
|
||||||
name: "address",
|
// name: "address",
|
||||||
label: "Residential address" as TranslatedString,
|
// label: "Residential address" as TranslatedString,
|
||||||
required: true,
|
// required: true,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
type: "date",
|
// type: "date",
|
||||||
props: {
|
// props: {
|
||||||
name: "dateOfBirth",
|
// name: "dateOfBirth",
|
||||||
label: "Date of birth" as TranslatedString,
|
// label: "Date of birth" as TranslatedString,
|
||||||
required: true,
|
// required: true,
|
||||||
},
|
// help: "format 'dd/MM/yyyy'" as TranslatedString,
|
||||||
},
|
// },
|
||||||
{
|
// },
|
||||||
type: "text",
|
// {
|
||||||
props: {
|
// type: "text",
|
||||||
name: "nationality",
|
// props: {
|
||||||
label: "Nationality" as TranslatedString,
|
// name: "nationality",
|
||||||
required: true,
|
// label: "Nationality" as TranslatedString,
|
||||||
},
|
// required: true,
|
||||||
},
|
// },
|
||||||
{
|
// },
|
||||||
type: "text",
|
// {
|
||||||
props: {
|
// type: "text",
|
||||||
name: "typeOfAuthorization",
|
// props: {
|
||||||
label:
|
// name: "typeOfAuthorization",
|
||||||
"Type of authorization (signatory of representation)" as TranslatedString,
|
// label:
|
||||||
required: true,
|
// "Type of authorization (signatory of representation)" as TranslatedString,
|
||||||
},
|
// required: true,
|
||||||
},
|
// },
|
||||||
{
|
// },
|
||||||
type: "text",
|
// {
|
||||||
props: {
|
// type: "text",
|
||||||
name: "document",
|
// props: {
|
||||||
label: "Identification document" as TranslatedString,
|
// name: "document",
|
||||||
required: true,
|
// label: "Identification document" as TranslatedString,
|
||||||
},
|
// required: true,
|
||||||
},
|
// },
|
||||||
{
|
// },
|
||||||
type: "text",
|
// {
|
||||||
props: {
|
// type: "text",
|
||||||
name: "powerOfAttorneyArrangements",
|
// props: {
|
||||||
label: "Residential address" as TranslatedString,
|
// name: "powerOfAttorneyArrangements",
|
||||||
required: true,
|
// label: "Residential address" as TranslatedString,
|
||||||
},
|
// required: true,
|
||||||
},
|
// },
|
||||||
],
|
// },
|
||||||
labelField: "fullName",
|
// ],
|
||||||
},
|
// labelField: "fullName",
|
||||||
},
|
// },
|
||||||
],
|
// },
|
||||||
},
|
// ],
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
title: "Acceptance of business relationship" as TranslatedString,
|
title: "Acceptance of business relationship" as TranslatedString,
|
||||||
fields: [
|
fields: [
|
||||||
@ -453,6 +455,7 @@ const firstForm: DoubleColumnForm = [
|
|||||||
name: "acceptance.when",
|
name: "acceptance.when",
|
||||||
pattern: "dd/MM/yyyy",
|
pattern: "dd/MM/yyyy",
|
||||||
label: "Date (conclusion of contract)" as TranslatedString,
|
label: "Date (conclusion of contract)" as TranslatedString,
|
||||||
|
help: "format 'dd/MM/yyyy'" as TranslatedString,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -522,6 +525,7 @@ const firstForm: DoubleColumnForm = [
|
|||||||
name: "acceptance.language",
|
name: "acceptance.language",
|
||||||
label: "Languages" as TranslatedString,
|
label: "Languages" as TranslatedString,
|
||||||
choices: languageList,
|
choices: languageList,
|
||||||
|
unique: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -533,256 +537,244 @@ const firstForm: DoubleColumnForm = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
title:
|
// title:
|
||||||
"Information on the beneficial owner of the assets and/or controlling person" as TranslatedString,
|
// "Information on the beneficial owner of the assets and/or controlling person" as TranslatedString,
|
||||||
description:
|
// description:
|
||||||
"Establishment of the beneficial owner of the assets and/or controlling person" as TranslatedString,
|
// "Establishment of the beneficial owner of the assets and/or controlling person" as TranslatedString,
|
||||||
fields: [
|
// fields: [
|
||||||
{
|
// {
|
||||||
type: "choiceStacked",
|
// type: "choiceStacked",
|
||||||
props: {
|
// props: {
|
||||||
name: "establishment",
|
// name: "establishment",
|
||||||
label: "The customer is" as TranslatedString,
|
// label: "The customer is" as TranslatedString,
|
||||||
required: true,
|
// required: true,
|
||||||
choices: [
|
// choices: [
|
||||||
{
|
// {
|
||||||
label:
|
// label:
|
||||||
"a natural person and there are no doubts that this person is the sole beneficial owner of the assets" as TranslatedString,
|
// "a natural person and there are no doubts that this person is the sole beneficial owner of the assets" as TranslatedString,
|
||||||
value: "natural",
|
// value: "natural",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
label:
|
// label:
|
||||||
"a foundation (or a similar construct; incl. underlying companies)" as TranslatedString,
|
// "a foundation (or a similar construct; incl. underlying companies)" as TranslatedString,
|
||||||
value: "foundation",
|
// value: "foundation",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
label: "a trust (incl. underlying companies)" as TranslatedString,
|
// label: "a trust (incl. underlying companies)" as TranslatedString,
|
||||||
value: "trust",
|
// value: "trust",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
label:
|
// label:
|
||||||
"a life insurance policy with separately managed accounts/securities accounts" as TranslatedString,
|
// "a life insurance policy with separately managed accounts/securities accounts" as TranslatedString,
|
||||||
value: "insurance-wrapper",
|
// value: "insurance-wrapper",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
label: "all other cases" as TranslatedString,
|
// label: "all other cases" as TranslatedString,
|
||||||
value: "other",
|
// value: "other",
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
title:
|
// title:
|
||||||
"Evaluation with regard to embargo procedures/terrorism lists on establishing the business relationship" as TranslatedString,
|
// "Evaluation with regard to embargo procedures/terrorism lists on establishing the business relationship" as TranslatedString,
|
||||||
description:
|
// description:
|
||||||
"Verification whether the customer, beneficial owners of the assets, controlling persons, authorized representatives or other involved persons are listed on an embargo/terrorism list (date of verification/result)" as TranslatedString,
|
// "Verification whether the customer, beneficial owners of the assets, controlling persons, authorized representatives or other involved persons are listed on an embargo/terrorism list (date of verification/result)" as TranslatedString,
|
||||||
fields: [
|
// fields: [
|
||||||
{
|
// {
|
||||||
type: "textArea",
|
// type: "textArea",
|
||||||
props: {
|
// props: {
|
||||||
name: "embargoEvaluation",
|
// name: "embargoEvaluation",
|
||||||
help: "The evaluation must be made at the beginning of the business relationship and has to be repeated in the case of permanent business relationship every time the according lists are updated." as TranslatedString,
|
// help: "The evaluation must be made at the beginning of the business relationship and has to be repeated in the case of permanent business relationship every time the according lists are updated." as TranslatedString,
|
||||||
label: "Evaluation" as TranslatedString,
|
// label: "Evaluation" as TranslatedString,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
},
|
// },
|
||||||
|
// {
|
||||||
{
|
// title:
|
||||||
title:
|
// "In the case of cash transactions/occasional customers: Information on type and purpose of business relationship" as TranslatedString,
|
||||||
"In the case of cash transactions/occasional customers: Information on type and purpose of business relationship" as TranslatedString,
|
// description:
|
||||||
description:
|
// "These details are only necessary for occasional customers, i.e. money exchange, money and asset transfer or other cash transactions provided that no customer profile (VQF doc. No. 902.5) is created" as TranslatedString,
|
||||||
"These details are only necessary for occasional customers, i.e. money exchange, money and asset transfer or other cash transactions provided that no customer profile (VQF doc. No. 902.5) is created" as TranslatedString,
|
// fields: [
|
||||||
fields: [
|
// {
|
||||||
{
|
// type: "choiceStacked",
|
||||||
type: "choiceStacked",
|
// props: {
|
||||||
props: {
|
// name: "cashTransactions.typeOfBusiness",
|
||||||
name: "cashTransactions.typeOfBusiness",
|
// label: "Type of business relationship" as TranslatedString,
|
||||||
label: "Type of business relationship" as TranslatedString,
|
// choices: [
|
||||||
choices: [
|
// {
|
||||||
{
|
// label: "Money exchange" as TranslatedString,
|
||||||
label: "Money exchange" as TranslatedString,
|
// value: "money-exchange",
|
||||||
value: "money-exchange",
|
// },
|
||||||
},
|
// {
|
||||||
{
|
// label: "Money and asset transfer" as TranslatedString,
|
||||||
label: "Money and asset transfer" as TranslatedString,
|
// value: "money-and-asset-transfer",
|
||||||
value: "money-and-asset-transfer",
|
// },
|
||||||
},
|
// {
|
||||||
{
|
// label:
|
||||||
label:
|
// "Other cash transactions. Specify below" as TranslatedString,
|
||||||
"Other cash transactions. Specify below" as TranslatedString,
|
// value: "other",
|
||||||
value: "other",
|
// },
|
||||||
},
|
// ],
|
||||||
],
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// {
|
||||||
{
|
// type: "text",
|
||||||
type: "text",
|
// props: {
|
||||||
props: {
|
// name: "cashTransactions.otherTypeOfBusiness",
|
||||||
name: "cashTransactions.otherTypeOfBusiness",
|
// required: true,
|
||||||
required: true,
|
// label: "Specify other cash transactions:" as TranslatedString,
|
||||||
label: "Specify other cash transactions:" as TranslatedString,
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// {
|
||||||
{
|
// type: "textArea",
|
||||||
type: "textArea",
|
// props: {
|
||||||
props: {
|
// name: "cashTransactions.purpose",
|
||||||
name: "cashTransactions.purpose",
|
// label:
|
||||||
label:
|
// "Purpose of the business relationship (purpose of service requested)" as TranslatedString,
|
||||||
"Purpose of the business relationship (purpose of service requested)" as TranslatedString,
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// ],
|
||||||
],
|
// },
|
||||||
},
|
// {
|
||||||
{
|
// title: "Enclosures" as TranslatedString,
|
||||||
title: "Enclosures" as TranslatedString,
|
// fields: [
|
||||||
fields: [
|
// {
|
||||||
{
|
// type: "text",
|
||||||
type: "text",
|
// props: {
|
||||||
props: {
|
// label: "Customer identification documents" as TranslatedString,
|
||||||
label: "Customer identification documents" as TranslatedString,
|
// name: "ASd",
|
||||||
name: "ASd",
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// ],
|
||||||
],
|
// },
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export function Form() {
|
function formBehavior(v: Form902_1e.Form): FormState<Form902_1e.Form> {
|
||||||
|
return {
|
||||||
|
filler: {
|
||||||
|
fullName: {
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
when: {
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
acceptance: {
|
||||||
|
thirdPartyFullName: {
|
||||||
|
hidden: v.acceptance?.typeOfCorrespondence !== "correspondence-address",
|
||||||
|
},
|
||||||
|
thirdPartyAddress: {
|
||||||
|
hidden: v.acceptance?.typeOfCorrespondence !== "correspondence-address",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cashTransactions: {
|
||||||
|
otherTypeOfBusiness: {
|
||||||
|
hidden: v.cashTransactions?.typeOfBusiness !== "other",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
naturalCustomer: {
|
||||||
|
fullName: {
|
||||||
|
hidden: v.customerType !== "natural",
|
||||||
|
},
|
||||||
|
address: {
|
||||||
|
hidden: v.customerType !== "natural",
|
||||||
|
},
|
||||||
|
telephone: {
|
||||||
|
hidden: v.customerType !== "natural",
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
hidden: v.customerType !== "natural",
|
||||||
|
},
|
||||||
|
dateOfBirth: {
|
||||||
|
hidden: v.customerType !== "natural",
|
||||||
|
},
|
||||||
|
nationality: {
|
||||||
|
hidden: v.customerType !== "natural",
|
||||||
|
},
|
||||||
|
document: {
|
||||||
|
hidden: v.customerType !== "natural",
|
||||||
|
},
|
||||||
|
companyName: {
|
||||||
|
hidden: v.customerType !== "natural",
|
||||||
|
},
|
||||||
|
office: {
|
||||||
|
hidden: v.customerType !== "natural",
|
||||||
|
},
|
||||||
|
companyDocument: {
|
||||||
|
hidden: v.customerType !== "natural",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legalCustomer: {
|
||||||
|
companyName: {
|
||||||
|
hidden: v.customerType !== "legal",
|
||||||
|
},
|
||||||
|
contactPerson: {
|
||||||
|
hidden: v.customerType !== "legal",
|
||||||
|
},
|
||||||
|
document: {
|
||||||
|
hidden: v.customerType !== "legal",
|
||||||
|
},
|
||||||
|
domicile: {
|
||||||
|
hidden: v.customerType !== "legal",
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
hidden: v.customerType !== "legal",
|
||||||
|
},
|
||||||
|
telephone: {
|
||||||
|
hidden: v.customerType !== "legal",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Form({ onUpdate }: { onUpdate: (d: any) => void }) {
|
||||||
const { i18n } = useTranslationContext();
|
const { i18n } = useTranslationContext();
|
||||||
const formState = useState<Form902_1e.Form>({
|
const initial: Form902_1e.Form = {
|
||||||
filler: {
|
filler: {
|
||||||
fullName: "Sebastian Marchano",
|
fullName: "Sebastian Marchano",
|
||||||
when: {
|
when: {
|
||||||
t_ms: Date.now(),
|
t_ms: Date.now(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// acceptance: {
|
} as Form902_1e.Form;
|
||||||
// language: ["spa"],
|
|
||||||
// },
|
|
||||||
// businessEstablisher: [
|
|
||||||
// {
|
|
||||||
// document: "2121",
|
|
||||||
// fullName: "sebastian marchano",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// document: "3131",
|
|
||||||
// fullName: "romina cordoba",
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
} as Form902_1e.Form);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormProvider
|
<Fragment>
|
||||||
state={formState}
|
<FormProvider
|
||||||
computeFormState={(v) => {
|
initialValue={initial}
|
||||||
return {
|
onUpdate={onUpdate}
|
||||||
filler: {
|
computeFormState={formBehavior}
|
||||||
fullName: {
|
>
|
||||||
disabled: true,
|
<div class="space-y-10 divide-y -mt-5 divide-gray-900/10">
|
||||||
},
|
{firstForm.map((section) => {
|
||||||
when: {
|
return (
|
||||||
disabled: true,
|
<div class="grid grid-cols-1 gap-x-8 gap-y-8 pt-5 md:grid-cols-3">
|
||||||
},
|
<div class="px-4 sm:px-0">
|
||||||
},
|
<h2 class="text-base font-semibold leading-7 text-gray-900">
|
||||||
acceptance: {
|
{section.title}
|
||||||
thirdPartyFullName: {
|
</h2>
|
||||||
hidden:
|
{section.description && (
|
||||||
v.acceptance?.typeOfCorrespondence !== "correspondence-address",
|
<p class="mt-1 text-sm leading-6 text-gray-600">
|
||||||
},
|
{section.description}
|
||||||
thirdPartyAddress: {
|
</p>
|
||||||
hidden:
|
)}
|
||||||
v.acceptance?.typeOfCorrespondence !== "correspondence-address",
|
</div>
|
||||||
},
|
<div class="bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2">
|
||||||
},
|
<div class="px-4 py-6 sm:p-8">
|
||||||
cashTransactions: {
|
<div class="grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
|
||||||
otherTypeOfBusiness: {
|
<RenderAllFieldsByUiConfig fields={section.fields} />
|
||||||
hidden: v.cashTransactions?.typeOfBusiness !== "other",
|
</div>
|
||||||
},
|
|
||||||
},
|
|
||||||
naturalCustomer: {
|
|
||||||
fullName: {
|
|
||||||
hidden: v.customerType !== "natural",
|
|
||||||
},
|
|
||||||
address: {
|
|
||||||
hidden: v.customerType !== "natural",
|
|
||||||
},
|
|
||||||
telephone: {
|
|
||||||
hidden: v.customerType !== "natural",
|
|
||||||
},
|
|
||||||
email: {
|
|
||||||
hidden: v.customerType !== "natural",
|
|
||||||
},
|
|
||||||
dateOfBirth: {
|
|
||||||
hidden: v.customerType !== "natural",
|
|
||||||
},
|
|
||||||
nationality: {
|
|
||||||
hidden: v.customerType !== "natural",
|
|
||||||
},
|
|
||||||
document: {
|
|
||||||
hidden: v.customerType !== "natural",
|
|
||||||
},
|
|
||||||
companyName: {
|
|
||||||
hidden: v.customerType !== "natural",
|
|
||||||
},
|
|
||||||
office: {
|
|
||||||
hidden: v.customerType !== "natural",
|
|
||||||
},
|
|
||||||
companyDocument: {
|
|
||||||
hidden: v.customerType !== "natural",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
legalCustomer: {
|
|
||||||
companyName: {
|
|
||||||
hidden: v.customerType !== "legal",
|
|
||||||
},
|
|
||||||
contactPerson: {
|
|
||||||
hidden: v.customerType !== "legal",
|
|
||||||
},
|
|
||||||
document: {
|
|
||||||
hidden: v.customerType !== "legal",
|
|
||||||
},
|
|
||||||
domicile: {
|
|
||||||
hidden: v.customerType !== "legal",
|
|
||||||
},
|
|
||||||
email: {
|
|
||||||
hidden: v.customerType !== "legal",
|
|
||||||
},
|
|
||||||
telephone: {
|
|
||||||
hidden: v.customerType !== "legal",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div class="space-y-10 divide-y -mt-5 divide-gray-900/10">
|
|
||||||
{firstForm.map((section) => {
|
|
||||||
return (
|
|
||||||
<div class="grid grid-cols-1 gap-x-8 gap-y-8 pt-5 md:grid-cols-3">
|
|
||||||
<div class="px-4 sm:px-0">
|
|
||||||
<h2 class="text-base font-semibold leading-7 text-gray-900">
|
|
||||||
{section.title}
|
|
||||||
</h2>
|
|
||||||
{section.description && (
|
|
||||||
<p class="mt-1 text-sm leading-6 text-gray-600">
|
|
||||||
{section.description}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div class="bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2">
|
|
||||||
<div class="px-4 py-6 sm:p-8">
|
|
||||||
<div class="grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
|
|
||||||
<RenderAllFieldsByUiConfig fields={section.fields} />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
);
|
||||||
);
|
})}
|
||||||
})}
|
</div>
|
||||||
</div>
|
</FormProvider>
|
||||||
</FormProvider>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,7 @@ export function HeroSections() {
|
|||||||
</nav>
|
</nav>
|
||||||
<Dialog
|
<Dialog
|
||||||
as="div"
|
as="div"
|
||||||
|
/* @ts-ignore */
|
||||||
class="lg:hidden"
|
class="lg:hidden"
|
||||||
open={mobileMenuOpen}
|
open={mobileMenuOpen}
|
||||||
onClose={setMobileMenuOpen}
|
onClose={setMobileMenuOpen}
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
import { AbsoluteTime, TranslatedString } from "@gnu-taler/taler-util";
|
import { AbsoluteTime, TranslatedString } from "@gnu-taler/taler-util";
|
||||||
import { ComponentChildren, VNode, createContext, h } from "preact";
|
import { ComponentChildren, VNode, createContext, h } from "preact";
|
||||||
import { StateUpdater, useMemo } from "preact/hooks";
|
import { MutableRef, StateUpdater, useRef } from "preact/hooks";
|
||||||
|
|
||||||
export interface FormType<T> {
|
export interface FormType<T> {
|
||||||
initialValue: Partial<T>;
|
value: MutableRef<Partial<T>>;
|
||||||
value: Partial<T>;
|
initialValue?: Partial<T>;
|
||||||
onUpdate: StateUpdater<T>;
|
onUpdate?: StateUpdater<T>;
|
||||||
computeFormState?: (v: T) => FormState<T>;
|
computeFormState?: (v: T) => FormState<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
export const FormContext = createContext<FormType<any>>({});
|
export const FormContext = createContext<FormType<any>>({});
|
||||||
|
|
||||||
type FormState<T> = {
|
export type FormState<T> = {
|
||||||
[field in keyof T]?: T[field] extends AbsoluteTime
|
[field in keyof T]?: T[field] extends AbsoluteTime
|
||||||
? Partial<InputFieldState>
|
? Partial<InputFieldState>
|
||||||
: T[field] extends object
|
: T[field] extends object
|
||||||
@ -33,21 +33,20 @@ export interface InputFieldState {
|
|||||||
|
|
||||||
export function FormProvider<T>({
|
export function FormProvider<T>({
|
||||||
children,
|
children,
|
||||||
state,
|
initialValue,
|
||||||
|
onUpdate,
|
||||||
computeFormState,
|
computeFormState,
|
||||||
}: {
|
}: {
|
||||||
state: [Partial<T>, StateUpdater<T>];
|
initialValue?: Partial<T>;
|
||||||
|
onUpdate?: (v: Partial<T>) => void;
|
||||||
computeFormState?: (v: T) => FormState<T>;
|
computeFormState?: (v: T) => FormState<T>;
|
||||||
children: ComponentChildren;
|
children: ComponentChildren;
|
||||||
}): VNode {
|
}): VNode {
|
||||||
const [value, onUpdate] = state;
|
const value = useRef(initialValue ?? {});
|
||||||
const initialValue = useMemo(() => value, []);
|
|
||||||
const contextValue = useMemo(
|
|
||||||
() => ({ initialValue, value, onUpdate, computeFormState }),
|
|
||||||
[value, onUpdate, computeFormState],
|
|
||||||
);
|
|
||||||
return (
|
return (
|
||||||
<FormContext.Provider value={contextValue}>
|
<FormContext.Provider
|
||||||
|
value={{ initialValue, value, onUpdate, computeFormState }}
|
||||||
|
>
|
||||||
<form>{children}</form>
|
<form>{children}</form>
|
||||||
</FormContext.Provider>
|
</FormContext.Provider>
|
||||||
);
|
);
|
||||||
|
@ -17,10 +17,9 @@ export function InputArray(
|
|||||||
const [selectedIndex, setSelected] = useState<number | undefined>(undefined);
|
const [selectedIndex, setSelected] = useState<number | undefined>(undefined);
|
||||||
const selected =
|
const selected =
|
||||||
selectedIndex === undefined ? undefined : list[selectedIndex];
|
selectedIndex === undefined ? undefined : list[selectedIndex];
|
||||||
const formState = useState(selected ?? {});
|
const [subForm, updateSubForm] = useState(selected ?? {});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const [, update] = formState;
|
updateSubForm(selected);
|
||||||
update(selected);
|
|
||||||
}, [selected]);
|
}, [selected]);
|
||||||
return (
|
return (
|
||||||
<div class="sm:col-span-6">
|
<div class="sm:col-span-6">
|
||||||
@ -118,7 +117,7 @@ export function InputArray(
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
{selectedIndex !== undefined && (
|
{selectedIndex !== undefined && (
|
||||||
<FormProvider state={formState}>
|
<FormProvider initialValue={subForm} onUpdate={updateSubForm}>
|
||||||
<div class="px-4 py-6">
|
<div class="px-4 py-6">
|
||||||
<div class="grid grid-cols-1 gap-y-8 ">
|
<div class="grid grid-cols-1 gap-y-8 ">
|
||||||
<RenderAllFieldsByUiConfig fields={fields} />
|
<RenderAllFieldsByUiConfig fields={fields} />
|
||||||
@ -149,8 +148,7 @@ export function InputArray(
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const newValue = [...list];
|
const newValue = [...list];
|
||||||
const [confirmed] = formState;
|
newValue.splice(selectedIndex, 1, subForm);
|
||||||
newValue.splice(selectedIndex, 1, confirmed);
|
|
||||||
onChange(newValue);
|
onChange(newValue);
|
||||||
setSelected(undefined);
|
setSelected(undefined);
|
||||||
}}
|
}}
|
||||||
|
@ -43,7 +43,7 @@ export function InputChoiceStacked(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="sm:col-span-4">
|
<div class="sm:col-span-6">
|
||||||
<LabelWithTooltipMaybeRequired
|
<LabelWithTooltipMaybeRequired
|
||||||
label={label}
|
label={label}
|
||||||
required={required}
|
required={required}
|
||||||
@ -81,7 +81,7 @@ export function InputChoiceStacked(
|
|||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
name="server-size"
|
name="server-size"
|
||||||
value={choice.value}
|
defaultValue={choice.value}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
onChange(choice.value);
|
onChange(choice.value);
|
||||||
}}
|
}}
|
||||||
|
@ -18,12 +18,11 @@ export function InputDate(
|
|||||||
converter={{
|
converter={{
|
||||||
fromStringUI: (v) => {
|
fromStringUI: (v) => {
|
||||||
if (!v) return { t_ms: "never" };
|
if (!v) return { t_ms: "never" };
|
||||||
console.log("from", v);
|
|
||||||
const t_ms = parse(v, pattern, Date.now()).getTime();
|
const t_ms = parse(v, pattern, Date.now()).getTime();
|
||||||
return { t_ms };
|
return { t_ms };
|
||||||
},
|
},
|
||||||
toStringUI: (v) => {
|
toStringUI: (v) => {
|
||||||
return v === undefined
|
return !v || !v.t_ms
|
||||||
? ""
|
? ""
|
||||||
: v.t_ms === "never"
|
: v.t_ms === "never"
|
||||||
? "never"
|
? "never"
|
||||||
|
@ -243,7 +243,7 @@ export function InputLine<T>(props: { type: string } & UIFormProps<T>): VNode {
|
|||||||
onChange(fromString(e.currentTarget.value));
|
onChange(fromString(e.currentTarget.value));
|
||||||
}}
|
}}
|
||||||
placeholder={placeholder ? placeholder : undefined}
|
placeholder={placeholder ? placeholder : undefined}
|
||||||
value={toString(value)}
|
defaultValue={toString(value)}
|
||||||
disabled={state.disabled}
|
disabled={state.disabled}
|
||||||
aria-invalid={showError}
|
aria-invalid={showError}
|
||||||
// aria-describedby="email-error"
|
// aria-describedby="email-error"
|
||||||
@ -262,7 +262,7 @@ export function InputLine<T>(props: { type: string } & UIFormProps<T>): VNode {
|
|||||||
onChange(fromString(e.currentTarget.value));
|
onChange(fromString(e.currentTarget.value));
|
||||||
}}
|
}}
|
||||||
placeholder={placeholder ? placeholder : undefined}
|
placeholder={placeholder ? placeholder : undefined}
|
||||||
value={toString(value)}
|
defaultValue={toString(value)}
|
||||||
disabled={state.disabled}
|
disabled={state.disabled}
|
||||||
aria-invalid={showError}
|
aria-invalid={showError}
|
||||||
// aria-describedby="email-error"
|
// aria-describedby="email-error"
|
||||||
|
@ -7,9 +7,11 @@ import { useState } from "preact/hooks";
|
|||||||
export function InputSelectMultiple(
|
export function InputSelectMultiple(
|
||||||
props: {
|
props: {
|
||||||
choices: Choice[];
|
choices: Choice[];
|
||||||
|
unique?: boolean;
|
||||||
} & UIFormProps<Array<string>>,
|
} & UIFormProps<Array<string>>,
|
||||||
): VNode {
|
): VNode {
|
||||||
const { name, label, choices, placeholder, tooltip, required } = props;
|
const { name, label, choices, placeholder, tooltip, required, unique } =
|
||||||
|
props;
|
||||||
const { value, onChange } = useField<{ [s: string]: Array<string> }>(name);
|
const { value, onChange } = useField<{ [s: string]: Array<string> }>(name);
|
||||||
|
|
||||||
const [filter, setFilter] = useState<string | undefined>(undefined);
|
const [filter, setFilter] = useState<string | undefined>(undefined);
|
||||||
@ -26,7 +28,7 @@ export function InputSelectMultiple(
|
|||||||
return regex.test(v.label);
|
return regex.test(v.label);
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<div class="sm:col-span-4">
|
<div class="sm:col-span-6">
|
||||||
<LabelWithTooltipMaybeRequired
|
<LabelWithTooltipMaybeRequired
|
||||||
label={label}
|
label={label}
|
||||||
required={required}
|
required={required}
|
||||||
@ -101,18 +103,19 @@ export function InputSelectMultiple(
|
|||||||
role="listbox"
|
role="listbox"
|
||||||
>
|
>
|
||||||
{filteredChoices.map((v, idx) => {
|
{filteredChoices.map((v, idx) => {
|
||||||
let clazz =
|
|
||||||
"relative flex border p-4 focus:outline-none disabled:text-grey";
|
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
class="relative cursor-pointer select-none py-2 pl-3 pr-9 text-gray-900 hover:text-white hover:bg-indigo-600"
|
class="relative cursor-pointer select-none py-2 pl-3 pr-9 text-gray-900 hover:text-white hover:bg-indigo-600"
|
||||||
id="option-0"
|
id="option-0"
|
||||||
role="option"
|
role="option"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
setFilter(undefined);
|
||||||
|
if (unique && list.indexOf(v.value) !== -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const newValue = [...list];
|
const newValue = [...list];
|
||||||
newValue.splice(0, 0, v.value);
|
newValue.splice(0, 0, v.value);
|
||||||
onChange(newValue);
|
onChange(newValue);
|
||||||
setFilter(undefined);
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
// tabindex="-1"
|
// tabindex="-1"
|
||||||
|
@ -13,14 +13,14 @@ export function useField<T>(name: keyof T): InputFieldHandler<T[keyof T]> {
|
|||||||
initialValue,
|
initialValue,
|
||||||
value: formValue,
|
value: formValue,
|
||||||
computeFormState,
|
computeFormState,
|
||||||
onUpdate,
|
onUpdate: notifyUpdate,
|
||||||
} = useContext(FormContext);
|
} = useContext(FormContext);
|
||||||
type P = typeof name;
|
type P = typeof name;
|
||||||
type V = T[P];
|
type V = T[P];
|
||||||
const [isDirty, setDirty] = useState(false);
|
const formState = computeFormState ? computeFormState(formValue.current) : {};
|
||||||
const formState = computeFormState ? computeFormState(formValue) : {};
|
|
||||||
|
|
||||||
const fieldValue = readField(formValue, String(name)) as V;
|
const fieldValue = readField(formValue.current, String(name)) as V;
|
||||||
|
const [currentValue, setCurrentValue] = useState<any | undefined>(undefined);
|
||||||
const fieldState = readField<Partial<InputFieldState>>(
|
const fieldState = readField<Partial<InputFieldState>>(
|
||||||
formState,
|
formState,
|
||||||
String(name),
|
String(name),
|
||||||
@ -35,16 +35,21 @@ export function useField<T>(name: keyof T): InputFieldHandler<T[keyof T]> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function onChange(value: V): void {
|
function onChange(value: V): void {
|
||||||
setDirty(true);
|
setCurrentValue(value);
|
||||||
return onUpdate((prev: any) => {
|
formValue.current = setValueDeeper(
|
||||||
return setValueDeeper(prev, String(name).split("."), value);
|
formValue.current,
|
||||||
});
|
String(name).split("."),
|
||||||
|
value,
|
||||||
|
);
|
||||||
|
if (notifyUpdate) {
|
||||||
|
notifyUpdate(formValue.current);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
value: fieldValue,
|
value: fieldValue,
|
||||||
onChange,
|
onChange,
|
||||||
isDirty,
|
isDirty: currentValue !== undefined,
|
||||||
state,
|
state,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user