aboutsummaryrefslogtreecommitdiff
path: root/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.tsx
blob: 3b39cf9c44373453f29fbd71404136bda87c606a (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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/* eslint-disable @typescript-eslint/camelcase */
import { UserAttributeSpec, validators } from "anastasis-core";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
import { useAnastasisContext } from "../../context/anastasis";
import { AnastasisClientFrame, withProcessLabel } from "./index";
import { LabeledInput } from "../../components/fields/LabeledInput";
import { DateInput } from "../../components/fields/DateInput";

export function AttributeEntryScreen(): VNode {
  const reducer = useAnastasisContext()
  const state = reducer?.currentReducerState
  const currentIdentityAttributes = state && "identity_attributes" in state ? (state.identity_attributes || {}) : {}
  const [attrs, setAttrs] = useState<Record<string, string>>(currentIdentityAttributes);

  if (!reducer) {
    return <div>no reducer in context</div>
  }
  if (!reducer.currentReducerState || !("required_attributes" in reducer.currentReducerState)) {
    return <div>invalid state</div>
  }


  return (
    <AnastasisClientFrame
      title={withProcessLabel(reducer, "Who are you?")}
      onNext={() => reducer.transition("enter_user_attributes", {
        identity_attributes: attrs,
      })}
    >
      <div class="columns">
        <div class="column is-half">

          {reducer.currentReducerState.required_attributes?.map((x, i: number) => {
            const value = attrs[x.name]
            function checkIfValid(): string | undefined {
              const pattern = x['validation-regex']
              if (pattern) {
                const re = new RegExp(pattern)
                if (!re.test(value)) return 'The value is invalid'
              }
              const logic = x['validation-logic']
              if (logic) {
                const func = (validators as any)[logic];
                if (func && typeof func === 'function' && !func(value)) return 'Please check the value'
              }
              const optional = x.optional
              console.log('optiona', optional)
              if (!optional && !value) {
                return 'This value is required'
              }
              return undefined
            }

            return (
              <AttributeEntryField
                key={i}
                isFirst={i == 0}
                setValue={(v: string) => setAttrs({ ...attrs, [x.name]: v })}
                spec={x}
                isValid={checkIfValid}
                value={value} />
            );
          })}

        </div>
        <div class="column is-half" >
          <h1><b>This stay private</b></h1>
          <p>The information you have entered here:
          </p>
          <ul>
            <li>
              <span class="icon is-right">
                <i class="mdi mdi-circle-small" />
              </span>
              Will be hashed, and therefore unreadable
            </li>
            <li><span class="icon is-right">
              <i class="mdi mdi-circle-small" />
            </span>The non-hashed version is not shared</li>
          </ul>
        </div>
      </div>
    </AnastasisClientFrame>
  );
}

interface AttributeEntryFieldProps {
  isFirst: boolean;
  value: string;
  setValue: (newValue: string) => void;
  spec: UserAttributeSpec;
  isValid: () => string | undefined;
}

function AttributeEntryField(props: AttributeEntryFieldProps): VNode {
  const errorMessage = props.isValid()

  return (
    <div>
      {props.spec.type === 'date' ?
        <DateInput
          grabFocus={props.isFirst}
          label={props.spec.label}
          error={errorMessage}
          bind={[props.value, props.setValue]}
        /> :
        <LabeledInput
          grabFocus={props.isFirst}
          label={props.spec.label}
          error={errorMessage}
          bind={[props.value, props.setValue]}
        />
      }
      <span>
        <span class="icon is-right">
          <i class="mdi mdi-eye-off" />
        </span>
        This stay private
      </span>
    </div>
  );
}