summaryrefslogtreecommitdiff
path: root/packages/web-util/src/forms/InputAbsoluteTime.tsx
blob: f5fd4fc5032132d1331e5a8d006b909c1bb2a4d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import { AbsoluteTime } from "@gnu-taler/taler-util";
import { format, parse } from "date-fns";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
import { Calendar } from "./Calendar.js";
import { Dialog } from "./Dialog.js";
import { UIFormProps } from "./FormProvider.js";
import { InputLine } from "./InputLine.js";
import { useField } from "./useField.js";
import { noHandlerPropsAndNoContextForField } from "./InputArray.js";

export function InputAbsoluteTime<T extends object, K extends keyof T>(
  properties: { pattern?: string } & UIFormProps<T, K>,
): VNode {
  const pattern = properties.pattern ?? "dd/MM/yyyy";
  const [open, setOpen] = useState(false);

  //FIXME: remove deprecated
  const fieldCtx = useField<T, K>(properties.name);
  const { value, onChange } =
    properties.handler ?? fieldCtx ?? noHandlerPropsAndNoContextForField(properties.name);
  return (
    <Fragment>
      <InputLine<T, K>
        type="text"
        after={{
          type: "button",
          onClick: () => {
            setOpen(true);
          },
          // icon: <CalendarIcon class="h-6 w-6" />,
          children: (
            <svg
              xmlns="http://www.w3.org/2000/svg"
              fill="none"
              viewBox="0 0 24 24"
              stroke-width="1.5"
              stroke="currentColor"
              class="w-6 h-6"
            >
              <path
                stroke-linecap="round"
                stroke-linejoin="round"
                d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5"
              />
            </svg>
          ),
        }}
        converter={{
          //@ts-ignore
          fromStringUI: (v): AbsoluteTime | undefined => {
            if (!v) return undefined;
            try {
              const t_ms = parse(v, pattern, Date.now()).getTime();
              return AbsoluteTime.fromMilliseconds(t_ms);
            } catch (e) {
              return undefined;
            }
          },
          //@ts-ignore
          toStringUI: (v: AbsoluteTime | undefined) => {
            return !v || !v.t_ms
              ? undefined
              : v.t_ms === "never"
                ? "never"
                : format(v.t_ms, pattern);
          },
        }}
        {...properties}
      />
      {open && (
        <Dialog onClose={() => setOpen(false)}>
          <Calendar
            value={(value as AbsoluteTime) ?? AbsoluteTime.now()}
            onChange={(v) => {
              onChange(v as any);
              setOpen(false);
            }}
          />
        </Dialog>
      )}
      {/* {open &&
        <Dialog onClose={() => setOpen(false)} >
          <TimePicker value={value as AbsoluteTime ?? AbsoluteTime.now()}
            onChange={(v) => {
              onChange(v as any)
            }}
            onConfirm={() => {
              setOpen(false)
            }} />
        </Dialog>} */}
    </Fragment>
  );
}