From 21b60c8f6ff69bf114779a767a3ac3355f69a34f Mon Sep 17 00:00:00 2001
From: Sebastian <sebasjm@gmail.com>
Date: Tue, 26 Oct 2021 12:08:03 -0300
Subject: added core validators, worked on look and feel

---
 packages/anastasis-webui/src/pages/home/AuthMethodEmailSetup.tsx | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'packages/anastasis-webui/src/pages/home/AuthMethodEmailSetup.tsx')

diff --git a/packages/anastasis-webui/src/pages/home/AuthMethodEmailSetup.tsx b/packages/anastasis-webui/src/pages/home/AuthMethodEmailSetup.tsx
index 9567e0ef7..5243c5259 100644
--- a/packages/anastasis-webui/src/pages/home/AuthMethodEmailSetup.tsx
+++ b/packages/anastasis-webui/src/pages/home/AuthMethodEmailSetup.tsx
@@ -6,7 +6,8 @@ import {
 import { h, VNode } from "preact";
 import { useState } from "preact/hooks";
 import { AuthMethodSetupProps } from "./AuthenticationEditorScreen";
-import { AnastasisClientFrame, LabeledInput } from "./index";
+import { AnastasisClientFrame } from "./index";
+import { LabeledInput } from "../../components/fields/LabeledInput";
 
 export function AuthMethodEmailSetup(props: AuthMethodSetupProps): VNode {
   const [email, setEmail] = useState("");
-- 
cgit v1.2.3


From 32318a80f48bf52ca7823a0c055164f43bdaf1d6 Mon Sep 17 00:00:00 2001
From: Sebastian <sebasjm@gmail.com>
Date: Wed, 27 Oct 2021 15:13:35 -0300
Subject: working version with improved ui

---
 .../src/components/fields/DateInput.tsx            |   4 +-
 .../src/components/fields/LabeledInput.tsx         |  40 ------
 .../src/components/fields/NumberInput.tsx          |  41 +++++++
 .../src/components/fields/TextInput.tsx            |  40 ++++++
 .../src/components/menu/SideBar.tsx                |  43 +++----
 .../src/components/picker/DatePicker.tsx           |  10 +-
 .../pages/home/AttributeEntryScreen.stories.tsx    |  28 +++--
 .../src/pages/home/AttributeEntryScreen.tsx        |  25 +++-
 .../src/pages/home/AuthMethodEmailSetup.tsx        |   4 +-
 .../src/pages/home/AuthMethodPostSetup.tsx         |  12 +-
 .../src/pages/home/AuthMethodQuestionSetup.tsx     |   6 +-
 .../pages/home/ChallengeOverviewScreen.stories.tsx | 134 ++++++++++++++++++++-
 .../src/pages/home/ChallengeOverviewScreen.tsx     | 118 +++++++++++-------
 .../home/ContinentSelectionScreen.stories.tsx      |   1 +
 .../pages/home/RecoveryFinishedScreen.stories.tsx  |   2 +-
 .../src/pages/home/SecretEditorScreen.tsx          |   6 +-
 .../src/pages/home/SecretSelectionScreen.tsx       | 116 ++++++++++++------
 .../src/pages/home/SolveEmailEntry.tsx             |  26 ----
 .../src/pages/home/SolvePostEntry.tsx              |  24 ----
 .../src/pages/home/SolveQuestionEntry.tsx          |  24 ----
 .../anastasis-webui/src/pages/home/SolveScreen.tsx | 121 ++++++++++++++++---
 .../src/pages/home/SolveSmsEntry.tsx               |  26 ----
 .../src/pages/home/SolveUnsupportedEntry.tsx       |  12 --
 .../src/wallet/Transaction.tsx                     |  14 +--
 24 files changed, 559 insertions(+), 318 deletions(-)
 delete mode 100644 packages/anastasis-webui/src/components/fields/LabeledInput.tsx
 create mode 100644 packages/anastasis-webui/src/components/fields/NumberInput.tsx
 create mode 100644 packages/anastasis-webui/src/components/fields/TextInput.tsx
 delete mode 100644 packages/anastasis-webui/src/pages/home/SolveEmailEntry.tsx
 delete mode 100644 packages/anastasis-webui/src/pages/home/SolvePostEntry.tsx
 delete mode 100644 packages/anastasis-webui/src/pages/home/SolveQuestionEntry.tsx
 delete mode 100644 packages/anastasis-webui/src/pages/home/SolveSmsEntry.tsx
 delete mode 100644 packages/anastasis-webui/src/pages/home/SolveUnsupportedEntry.tsx

(limited to 'packages/anastasis-webui/src/pages/home/AuthMethodEmailSetup.tsx')

diff --git a/packages/anastasis-webui/src/components/fields/DateInput.tsx b/packages/anastasis-webui/src/components/fields/DateInput.tsx
index c45acc6d2..e1c354f7b 100644
--- a/packages/anastasis-webui/src/components/fields/DateInput.tsx
+++ b/packages/anastasis-webui/src/components/fields/DateInput.tsx
@@ -8,6 +8,7 @@ export interface DateInputProps {
   grabFocus?: boolean;
   tooltip?: string;
   error?: string;
+  years?: Array<number>;
   bind: [string, (x: string) => void];
 }
 
@@ -19,7 +20,7 @@ export function DateInput(props: DateInputProps): VNode {
     }
   }, [props.grabFocus]);
   const [opened, setOpened2] = useState(false)
-  function setOpened(v: boolean) {
+  function setOpened(v: boolean): void {
     console.log('dale', v)
     setOpened2(v)
   }
@@ -50,6 +51,7 @@ export function DateInput(props: DateInputProps): VNode {
     {showError && <p class="help is-danger">{props.error}</p>}
     <DatePicker
       opened={opened}
+      years={props.years}
       closeFunction={() => setOpened(false)}
       dateReceiver={(d) => {
         setDirty(true)
diff --git a/packages/anastasis-webui/src/components/fields/LabeledInput.tsx b/packages/anastasis-webui/src/components/fields/LabeledInput.tsx
deleted file mode 100644
index 96d634a4f..000000000
--- a/packages/anastasis-webui/src/components/fields/LabeledInput.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import { h, VNode } from "preact";
-import { useLayoutEffect, useRef, useState } from "preact/hooks";
-
-export interface LabeledInputProps {
-  label: string;
-  grabFocus?: boolean;
-  error?: string;
-  tooltip?: string;
-  bind: [string, (x: string) => void];
-}
-
-export function LabeledInput(props: LabeledInputProps): VNode {
-  const inputRef = useRef<HTMLInputElement>(null);
-  useLayoutEffect(() => {
-    if (props.grabFocus) {
-      inputRef.current?.focus();
-    }
-  }, [props.grabFocus]);
-  const value = props.bind[0];
-  const [dirty, setDirty] = useState(false)
-  const showError = dirty && props.error
-  return (<div class="field">
-    <label class="label">
-      {props.label}
-      {props.tooltip && <span class="icon has-tooltip-right" data-tooltip={props.tooltip}>
-        <i class="mdi mdi-information" />
-      </span>}
-    </label>
-    <div class="control has-icons-right">
-      <input
-        value={value}
-        class={showError ? 'input is-danger' : 'input'}
-        onChange={(e) => {setDirty(true); props.bind[1]((e.target as HTMLInputElement).value)}}
-        ref={inputRef}
-        style={{ display: "block" }} />
-    </div>
-    {showError && <p class="help is-danger">{props.error}</p>}
-  </div>
-  );
-}
diff --git a/packages/anastasis-webui/src/components/fields/NumberInput.tsx b/packages/anastasis-webui/src/components/fields/NumberInput.tsx
new file mode 100644
index 000000000..af9bbe66b
--- /dev/null
+++ b/packages/anastasis-webui/src/components/fields/NumberInput.tsx
@@ -0,0 +1,41 @@
+import { h, VNode } from "preact";
+import { useLayoutEffect, useRef, useState } from "preact/hooks";
+
+export interface TextInputProps {
+  label: string;
+  grabFocus?: boolean;
+  error?: string;
+  tooltip?: string;
+  bind: [string, (x: string) => void];
+}
+
+export function NumberInput(props: TextInputProps): VNode {
+  const inputRef = useRef<HTMLInputElement>(null);
+  useLayoutEffect(() => {
+    if (props.grabFocus) {
+      inputRef.current?.focus();
+    }
+  }, [props.grabFocus]);
+  const value = props.bind[0];
+  const [dirty, setDirty] = useState(false)
+  const showError = dirty && props.error
+  return (<div class="field">
+    <label class="label">
+      {props.label}
+      {props.tooltip && <span class="icon has-tooltip-right" data-tooltip={props.tooltip}>
+        <i class="mdi mdi-information" />
+      </span>}
+    </label>
+    <div class="control has-icons-right">
+      <input
+        value={value}
+        type="number"
+        class={showError ? 'input is-danger' : 'input'}
+        onChange={(e) => {setDirty(true); props.bind[1]((e.target as HTMLInputElement).value)}}
+        ref={inputRef}
+        style={{ display: "block" }} />
+    </div>
+    {showError && <p class="help is-danger">{props.error}</p>}
+  </div>
+  );
+}
diff --git a/packages/anastasis-webui/src/components/fields/TextInput.tsx b/packages/anastasis-webui/src/components/fields/TextInput.tsx
new file mode 100644
index 000000000..fa6fd9792
--- /dev/null
+++ b/packages/anastasis-webui/src/components/fields/TextInput.tsx
@@ -0,0 +1,40 @@
+import { h, VNode } from "preact";
+import { useLayoutEffect, useRef, useState } from "preact/hooks";
+
+export interface TextInputProps {
+  label: string;
+  grabFocus?: boolean;
+  error?: string;
+  tooltip?: string;
+  bind: [string, (x: string) => void];
+}
+
+export function TextInput(props: TextInputProps): VNode {
+  const inputRef = useRef<HTMLInputElement>(null);
+  useLayoutEffect(() => {
+    if (props.grabFocus) {
+      inputRef.current?.focus();
+    }
+  }, [props.grabFocus]);
+  const value = props.bind[0];
+  const [dirty, setDirty] = useState(false)
+  const showError = dirty && props.error
+  return (<div class="field">
+    <label class="label">
+      {props.label}
+      {props.tooltip && <span class="icon has-tooltip-right" data-tooltip={props.tooltip}>
+        <i class="mdi mdi-information" />
+      </span>}
+    </label>
+    <div class="control has-icons-right">
+      <input
+        value={value}
+        class={showError ? 'input is-danger' : 'input'}
+        onChange={(e) => {setDirty(true); props.bind[1]((e.target as HTMLInputElement).value)}}
+        ref={inputRef}
+        style={{ display: "block" }} />
+    </div>
+    {showError && <p class="help is-danger">{props.error}</p>}
+  </div>
+  );
+}
diff --git a/packages/anastasis-webui/src/components/menu/SideBar.tsx b/packages/anastasis-webui/src/components/menu/SideBar.tsx
index 12223d473..87e771009 100644
--- a/packages/anastasis-webui/src/components/menu/SideBar.tsx
+++ b/packages/anastasis-webui/src/components/menu/SideBar.tsx
@@ -64,9 +64,8 @@ export function Sidebar({ mobile }: Props): VNode {
             </li>
           }
           {reducer.currentReducerState && reducer.currentReducerState.backup_state ? <Fragment>
-            <li class={
-                reducer.currentReducerState.backup_state === BackupStates.ContinentSelecting ||
-                reducer.currentReducerState.backup_state === BackupStates.CountrySelecting ? 'is-active' : ''}>
+            <li class={reducer.currentReducerState.backup_state === BackupStates.ContinentSelecting ||
+              reducer.currentReducerState.backup_state === BackupStates.CountrySelecting ? 'is-active' : ''}>
               <div class="ml-4">
                 <span class="menu-item-label"><Translate>Location &amp; Currency</Translate></span>
               </div>
@@ -79,73 +78,65 @@ export function Sidebar({ mobile }: Props): VNode {
             <li class={reducer.currentReducerState.backup_state === BackupStates.AuthenticationsEditing ? 'is-active' : ''}>
               <div class="ml-4">
 
-                <span class="menu-item-label"><Translate>Auth methods</Translate></span>
+                <span class="menu-item-label"><Translate>Authorization methods</Translate></span>
               </div>
             </li>
             <li class={reducer.currentReducerState.backup_state === BackupStates.PoliciesReviewing ? 'is-active' : ''}>
               <div class="ml-4">
 
-                <span class="menu-item-label"><Translate>PoliciesReviewing</Translate></span>
+                <span class="menu-item-label"><Translate>Policies reviewing</Translate></span>
               </div>
             </li>
             <li class={reducer.currentReducerState.backup_state === BackupStates.SecretEditing ? 'is-active' : ''}>
               <div class="ml-4">
 
-                <span class="menu-item-label"><Translate>SecretEditing</Translate></span>
+                <span class="menu-item-label"><Translate>Secret input</Translate></span>
               </div>
             </li>
             <li class={reducer.currentReducerState.backup_state === BackupStates.PoliciesPaying ? 'is-active' : ''}>
               <div class="ml-4">
 
-                <span class="menu-item-label"><Translate>PoliciesPaying</Translate></span>
+                <span class="menu-item-label"><Translate>Payment (optional)</Translate></span>
               </div>
             </li>
             <li class={reducer.currentReducerState.backup_state === BackupStates.BackupFinished ? 'is-active' : ''}>
               <div class="ml-4">
 
-                <span class="menu-item-label"><Translate>BackupFinished</Translate></span>
+                <span class="menu-item-label"><Translate>Backup completed</Translate></span>
               </div>
             </li>
             <li class={reducer.currentReducerState.backup_state === BackupStates.TruthsPaying ? 'is-active' : ''}>
               <div class="ml-4">
 
-                <span class="menu-item-label"><Translate>TruthsPaying</Translate></span>
+                <span class="menu-item-label"><Translate>Truth Paying</Translate></span>
               </div>
             </li>
           </Fragment> : (reducer.currentReducerState && reducer.currentReducerState?.recovery_state && <Fragment>
-            <li class={reducer.currentReducerState.recovery_state === RecoveryStates.ContinentSelecting ? 'is-active' : ''}>
+            <li class={reducer.currentReducerState.recovery_state === RecoveryStates.ContinentSelecting ||
+              reducer.currentReducerState.recovery_state === RecoveryStates.CountrySelecting ? 'is-active' : ''}>
               <div class="ml-4">
-                <span class="menu-item-label"><Translate>ContinentSelecting</Translate></span>
-              </div>
-            </li>
-            <li class={reducer.currentReducerState.recovery_state === RecoveryStates.CountrySelecting ? 'is-active' : ''}>
-              <div class="ml-4">
-                <span class="menu-item-label"><Translate>CountrySelecting</Translate></span>
+                <span class="menu-item-label"><Translate>Location &amp; Currency</Translate></span>
               </div>
             </li>
             <li class={reducer.currentReducerState.recovery_state === RecoveryStates.UserAttributesCollecting ? 'is-active' : ''}>
               <div class="ml-4">
-                <span class="menu-item-label"><Translate>UserAttributesCollecting</Translate></span>
+                <span class="menu-item-label"><Translate>Personal information</Translate></span>
               </div>
             </li>
             <li class={reducer.currentReducerState.recovery_state === RecoveryStates.SecretSelecting ? 'is-active' : ''}>
               <div class="ml-4">
-                <span class="menu-item-label"><Translate>SecretSelecting</Translate></span>
-              </div>
-            </li>
-            <li class={reducer.currentReducerState.recovery_state === RecoveryStates.ChallengeSelecting ? 'is-active' : ''}>
-              <div class="ml-4">
-                <span class="menu-item-label"><Translate>ChallengeSelecting</Translate></span>
+                <span class="menu-item-label"><Translate>Secret selection</Translate></span>
               </div>
             </li>
-            <li class={reducer.currentReducerState.recovery_state === RecoveryStates.ChallengeSolving ? 'is-active' : ''}>
+            <li class={reducer.currentReducerState.recovery_state === RecoveryStates.ChallengeSelecting ||
+              reducer.currentReducerState.recovery_state === RecoveryStates.ChallengeSolving ? 'is-active' : ''}>
               <div class="ml-4">
-                <span class="menu-item-label"><Translate>ChallengeSolving</Translate></span>
+                <span class="menu-item-label"><Translate>Solve Challenges</Translate></span>
               </div>
             </li>
             <li class={reducer.currentReducerState.recovery_state === RecoveryStates.RecoveryFinished ? 'is-active' : ''}>
               <div class="ml-4">
-                <span class="menu-item-label"><Translate>RecoveryFinished</Translate></span>
+                <span class="menu-item-label"><Translate>Secret recovered</Translate></span>
               </div>
             </li>
           </Fragment>)}
diff --git a/packages/anastasis-webui/src/components/picker/DatePicker.tsx b/packages/anastasis-webui/src/components/picker/DatePicker.tsx
index e51b3db68..5b33fa8be 100644
--- a/packages/anastasis-webui/src/components/picker/DatePicker.tsx
+++ b/packages/anastasis-webui/src/components/picker/DatePicker.tsx
@@ -24,6 +24,7 @@ import { h, Component } from "preact";
 interface Props {
   closeFunction?: () => void;
   dateReceiver?: (d: Date) => void;
+  years?: Array<number>;
   opened?: boolean;
 }
 interface State {
@@ -207,9 +208,9 @@ export class DatePicker extends Component<Props, State> {
   }
 
   componentDidUpdate() {
-    if (this.state.selectYearMode) {
-      document.getElementsByClassName('selected')[0].scrollIntoView(); // works in every browser incl. IE, replace with scrollIntoViewIfNeeded when browsers support it
-    }
+    // if (this.state.selectYearMode) {
+    //   document.getElementsByClassName('selected')[0].scrollIntoView(); // works in every browser incl. IE, replace with scrollIntoViewIfNeeded when browsers support it
+    // }
   }
 
   constructor() {
@@ -296,8 +297,7 @@ export class DatePicker extends Component<Props, State> {
             </div>}
 
             {selectYearMode && <div class="datePicker--selectYear">
-
-              {yearArr.map(year => (
+              {(this.props.years || yearArr).map(year => (
                 <span key={year} class={(year === displayedYear) ? 'selected' : ''} onClick={this.changeDisplayedYear}>
                   {year}
                 </span>
diff --git a/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.stories.tsx
index d9be48fb4..32d7817e3 100644
--- a/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.stories.tsx
@@ -40,21 +40,21 @@ export default {
 export const Backup = createExample(TestedComponent, {
   ...reducerStatesExample.backupAttributeEditing,
   required_attributes: [{
-    name: 'first',
+    name: 'first name',
     label: 'first',
-    type: 'type',
+    type: 'string',
     uuid: 'asdasdsa1',
     widget: 'wid',
   }, {
-    name: 'pepe',
+    name: 'last name',
     label: 'second',
-    type: 'type',
+    type: 'string',
     uuid: 'asdasdsa2',
     widget: 'wid',
   }, {
-    name: 'pepe2',
+    name: 'date',
     label: 'third',
-    type: 'type',
+    type: 'date',
     uuid: 'asdasdsa3',
     widget: 'calendar',
   }]
@@ -65,19 +65,19 @@ export const Recovery = createExample(TestedComponent, {
   required_attributes: [{
     name: 'first',
     label: 'first',
-    type: 'type',
+    type: 'string',
     uuid: 'asdasdsa1',
     widget: 'wid',
   }, {
     name: 'pepe',
     label: 'second',
-    type: 'type',
+    type: 'string',
     uuid: 'asdasdsa2',
     widget: 'wid',
   }, {
     name: 'pepe2',
     label: 'third',
-    type: 'type',
+    type: 'date',
     uuid: 'asdasdsa3',
     widget: 'calendar',
   }]
@@ -110,12 +110,20 @@ const allWidgets = [
   "anastasis_gtk_xx_square",
 ]
 
+function typeForWidget(name: string): string {
+  if (["anastasis_gtk_xx_prime",
+    "anastasis_gtk_xx_square",
+  ].includes(name)) return "number";
+  if (["anastasis_gtk_ia_birthdate"].includes(name)) return "date"
+  return "string";
+}
+
 export const WithAllPosibleWidget = createExample(TestedComponent, {
   ...reducerStatesExample.backupAttributeEditing,
   required_attributes: allWidgets.map(w => ({
     name: w,
     label: `widget: ${w}`,
-    type: 'type',
+    type: typeForWidget(w),
     uuid: `uuid-${w}`,
     widget: w
   }))
diff --git a/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.tsx b/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.tsx
index 3b39cf9c4..f74dcefba 100644
--- a/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.tsx
@@ -4,8 +4,9 @@ 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 { TextInput } from "../../components/fields/TextInput";
 import { DateInput } from "../../components/fields/DateInput";
+import { NumberInput } from "../../components/fields/NumberInput";
 
 export function AttributeEntryScreen(): VNode {
   const reducer = useAnastasisContext()
@@ -65,6 +66,7 @@ export function AttributeEntryScreen(): VNode {
 
         </div>
         <div class="column is-half" >
+          <p>This personal information will help to locate your secret in the first place</p>
           <h1><b>This stay private</b></h1>
           <p>The information you have entered here:
           </p>
@@ -92,20 +94,33 @@ interface AttributeEntryFieldProps {
   spec: UserAttributeSpec;
   isValid: () => string | undefined;
 }
-
+const possibleBirthdayYear: Array<number> = []
+for (let i = 0; i < 100; i++ ) {
+  possibleBirthdayYear.push(2020 - i)
+}
 function AttributeEntryField(props: AttributeEntryFieldProps): VNode {
   const errorMessage = props.isValid()
 
   return (
     <div>
-      {props.spec.type === 'date' ?
+      {props.spec.type === 'date' &&
         <DateInput
+          grabFocus={props.isFirst}
+          label={props.spec.label}
+          years={possibleBirthdayYear}
+          error={errorMessage}
+          bind={[props.value, props.setValue]}
+        />}
+      {props.spec.type === 'number' &&
+        <NumberInput
           grabFocus={props.isFirst}
           label={props.spec.label}
           error={errorMessage}
           bind={[props.value, props.setValue]}
-        /> :
-        <LabeledInput
+        />
+      }
+      {props.spec.type === 'string' &&
+        <TextInput
           grabFocus={props.isFirst}
           label={props.spec.label}
           error={errorMessage}
diff --git a/packages/anastasis-webui/src/pages/home/AuthMethodEmailSetup.tsx b/packages/anastasis-webui/src/pages/home/AuthMethodEmailSetup.tsx
index 5243c5259..c3783ea6c 100644
--- a/packages/anastasis-webui/src/pages/home/AuthMethodEmailSetup.tsx
+++ b/packages/anastasis-webui/src/pages/home/AuthMethodEmailSetup.tsx
@@ -7,7 +7,7 @@ import { h, VNode } from "preact";
 import { useState } from "preact/hooks";
 import { AuthMethodSetupProps } from "./AuthenticationEditorScreen";
 import { AnastasisClientFrame } from "./index";
-import { LabeledInput } from "../../components/fields/LabeledInput";
+import { TextInput } from "../../components/fields/TextInput";
 
 export function AuthMethodEmailSetup(props: AuthMethodSetupProps): VNode {
   const [email, setEmail] = useState("");
@@ -19,7 +19,7 @@ export function AuthMethodEmailSetup(props: AuthMethodSetupProps): VNode {
         email.
       </p>
       <div>
-        <LabeledInput
+        <TextInput
           label="Email address"
           grabFocus
           bind={[email, setEmail]} />
diff --git a/packages/anastasis-webui/src/pages/home/AuthMethodPostSetup.tsx b/packages/anastasis-webui/src/pages/home/AuthMethodPostSetup.tsx
index 1c2a9a92e..c4ddeff91 100644
--- a/packages/anastasis-webui/src/pages/home/AuthMethodPostSetup.tsx
+++ b/packages/anastasis-webui/src/pages/home/AuthMethodPostSetup.tsx
@@ -6,7 +6,7 @@ import {
 import { h, VNode } from "preact";
 import { useState } from "preact/hooks";
 import { AuthMethodSetupProps } from "./AuthenticationEditorScreen";
-import { LabeledInput } from "../../components/fields/LabeledInput";
+import { TextInput } from "../../components/fields/TextInput";
 
 export function AuthMethodPostSetup(props: AuthMethodSetupProps): VNode {
   const [fullName, setFullName] = useState("");
@@ -42,22 +42,22 @@ export function AuthMethodPostSetup(props: AuthMethodSetupProps): VNode {
           code that you will receive in a letter to that address.
         </p>
         <div>
-          <LabeledInput
+          <TextInput
             grabFocus
             label="Full Name"
             bind={[fullName, setFullName]} />
         </div>
         <div>
-          <LabeledInput label="Street" bind={[street, setStreet]} />
+          <TextInput label="Street" bind={[street, setStreet]} />
         </div>
         <div>
-          <LabeledInput label="City" bind={[city, setCity]} />
+          <TextInput label="City" bind={[city, setCity]} />
         </div>
         <div>
-          <LabeledInput label="Postal Code" bind={[postcode, setPostcode]} />
+          <TextInput label="Postal Code" bind={[postcode, setPostcode]} />
         </div>
         <div>
-          <LabeledInput label="Country" bind={[country, setCountry]} />
+          <TextInput label="Country" bind={[country, setCountry]} />
         </div>
         <div>
           <button onClick={() => props.cancel()}>Cancel</button>
diff --git a/packages/anastasis-webui/src/pages/home/AuthMethodQuestionSetup.tsx b/packages/anastasis-webui/src/pages/home/AuthMethodQuestionSetup.tsx
index c2bd24ef9..f1bab94ab 100644
--- a/packages/anastasis-webui/src/pages/home/AuthMethodQuestionSetup.tsx
+++ b/packages/anastasis-webui/src/pages/home/AuthMethodQuestionSetup.tsx
@@ -7,7 +7,7 @@ import { h, VNode } from "preact";
 import { useState } from "preact/hooks";
 import { AuthMethodSetupProps } from "./AuthenticationEditorScreen";
 import { AnastasisClientFrame } from "./index";
-import { LabeledInput } from "../../components/fields/LabeledInput";
+import { TextInput } from "../../components/fields/TextInput";
 
 export function AuthMethodQuestionSetup(props: AuthMethodSetupProps): VNode {
   const [questionText, setQuestionText] = useState("");
@@ -29,13 +29,13 @@ export function AuthMethodQuestionSetup(props: AuthMethodSetupProps): VNode {
           here.
         </p>
         <div>
-          <LabeledInput
+          <TextInput
             label="Security question"
             grabFocus
             bind={[questionText, setQuestionText]} />
         </div>
         <div>
-          <LabeledInput label="Answer" bind={[answerText, setAnswerText]} />
+          <TextInput label="Answer" bind={[answerText, setAnswerText]} />
         </div>
         <div>
           <button onClick={() => props.cancel()}>Cancel</button>
diff --git a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx
index def44c5a6..758963574 100644
--- a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx
@@ -37,7 +37,7 @@ export default {
   },
 };
 
-export const OneChallenge = createExample(TestedComponent, {
+export const OneUnsolvedPolicy = createExample(TestedComponent, {
   ...reducerStatesExample.challengeSelecting,
   recovery_information: {
     policies: [[{ uuid: '1' }]],
@@ -50,7 +50,7 @@ export const OneChallenge = createExample(TestedComponent, {
   },
 } as ReducerState);
 
-export const MoreChallenges = createExample(TestedComponent, {
+export const SomePoliciesOneSolved = createExample(TestedComponent, {
   ...reducerStatesExample.challengeSelecting,
   recovery_information: {
     policies: [[{ uuid: '1' }, { uuid: '2' }], [{ uuid: 'uuid-3' }]],
@@ -75,13 +75,13 @@ export const MoreChallenges = createExample(TestedComponent, {
     'uuid-3': {
       state: 'solved'
     }
-  }
+  },
 } as ReducerState);
 
 export const OneBadConfiguredPolicy = createExample(TestedComponent, {
   ...reducerStatesExample.challengeSelecting,
   recovery_information: {
-    policies: [[{ uuid: '2' }]],
+    policies: [[{ uuid: '1' }, { uuid: '2' }]],
     challenges: [{
       cost: 'USD:1',
       instructions: 'just go for it',
@@ -91,4 +91,130 @@ export const OneBadConfiguredPolicy = createExample(TestedComponent, {
   },
 } as ReducerState);
 
+export const OnePolicyWithAllTheChallenges = createExample(TestedComponent, {
+  ...reducerStatesExample.challengeSelecting,
+  recovery_information: {
+    policies: [[
+      { uuid: '1' },
+      { uuid: '2' },
+      { uuid: '3' },
+      { uuid: '4' },
+      { uuid: '5' },
+      { uuid: '6' },
+    ]],
+    challenges: [{
+      cost: 'USD:1',
+      instructions: 'answer the a question correctly',
+      type: 'question',
+      uuid: '1',
+    },{
+      cost: 'USD:1',
+      instructions: 'enter a text received by a sms',
+      type: 'sms',
+      uuid: '2',
+    },{
+      cost: 'USD:1',
+      instructions: 'enter a text received by a email',
+      type: 'email',
+      uuid: '3',
+    },{
+      cost: 'USD:1',
+      instructions: 'enter a code based on a time-based one-time password',
+      type: 'totp',
+      uuid: '4',
+    },{
+      cost: 'USD:1',
+      instructions: 'send a wire transfer to an account',
+      type: 'iban',
+      uuid: '5',
+    },{
+      cost: 'USD:1',
+      instructions: 'just go for it',
+      type: 'new-type-of-challenge',
+      uuid: '6',
+    }],
+  },
+} as ReducerState);
+
+
+export const OnePolicyWithAllTheChallengesInDifferentState = createExample(TestedComponent, {
+  ...reducerStatesExample.challengeSelecting,
+  recovery_information: {
+    policies: [[
+      { uuid: '1' },
+      { uuid: '2' },
+      { uuid: '3' },
+      { uuid: '4' },
+      { uuid: '5' },
+      { uuid: '6' },
+      { uuid: '7' },
+      { uuid: '8' },
+      { uuid: '9' },
+      { uuid: '10' },
+    ]],
+    challenges: [{
+      cost: 'USD:1',
+      instructions: 'answer the a question correctly',
+      type: 'question',
+      uuid: '1',
+    },{
+      cost: 'USD:1',
+      instructions: 'answer the a question correctly',
+      type: 'question',
+      uuid: '2',
+    },{
+      cost: 'USD:1',
+      instructions: 'answer the a question correctly',
+      type: 'question',
+      uuid: '3',
+    },{
+      cost: 'USD:1',
+      instructions: 'answer the a question correctly',
+      type: 'question',
+      uuid: '4',
+    },{
+      cost: 'USD:1',
+      instructions: 'answer the a question correctly',
+      type: 'question',
+      uuid: '5',
+    },{
+      cost: 'USD:1',
+      instructions: 'answer the a question correctly',
+      type: 'question',
+      uuid: '6',
+    },{
+      cost: 'USD:1',
+      instructions: 'answer the a question correctly',
+      type: 'question',
+      uuid: '7',
+    },{
+      cost: 'USD:1',
+      instructions: 'answer the a question correctly',
+      type: 'question',
+      uuid: '8',
+    },{
+      cost: 'USD:1',
+      instructions: 'answer the a question correctly',
+      type: 'question',
+      uuid: '9',
+    },{
+      cost: 'USD:1',
+      instructions: 'answer the a question correctly',
+      type: 'question',
+      uuid: '10',
+    }],
+  },
+  challenge_feedback: {
+    1: { state: 'solved' },
+    2: { state: 'hint' },
+    3: { state: 'details' },
+    4: { state: 'body' },
+    5: { state: 'redirect' },
+    6: { state: 'server-failure' },
+    7: { state: 'truth-unknown' },
+    8: { state: 'rate-limit-exceeded' },
+    9: { state: 'authentication-timeout' },
+    10: { state: 'external-instructions' },
+  }
+} as ReducerState);
 export const NoPolicies = createExample(TestedComponent, reducerStatesExample.challengeSelecting);
diff --git a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx
index c9b52e91b..3bb3fb837 100644
--- a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx
@@ -1,3 +1,4 @@
+import { ChallengeFeedback } from "anastasis-core";
 import { h, VNode } from "preact";
 import { useAnastasisContext } from "../../context/anastasis";
 import { AnastasisClientFrame } from "./index";
@@ -13,65 +14,94 @@ export function ChallengeOverviewScreen(): VNode {
   }
 
   const policies = reducer.currentReducerState.recovery_information?.policies ?? [];
-  const chArr = reducer.currentReducerState.recovery_information?.challenges ?? [];
-  const challengeFeedback = reducer.currentReducerState?.challenge_feedback;
+  const knownChallengesArray = reducer.currentReducerState.recovery_information?.challenges ?? [];
+  const challengeFeedback = reducer.currentReducerState?.challenge_feedback ?? {};
 
-  const challenges: {
+  const knownChallengesMap: {
     [uuid: string]: {
       type: string;
       instructions: string;
       cost: string;
+      feedback: ChallengeFeedback | undefined;
     };
   } = {};
-  for (const ch of chArr) {
-    challenges[ch.uuid] = {
+  for (const ch of knownChallengesArray) {
+    knownChallengesMap[ch.uuid] = {
       type: ch.type,
       cost: ch.cost,
       instructions: ch.instructions,
+      feedback: challengeFeedback[ch.uuid]
     };
   }
+  const policiesWithInfo = policies.map(row => {
+    let isPolicySolved = true
+    const challenges = row.map(({ uuid }) => {
+      const info = knownChallengesMap[uuid];
+      const isChallengeSolved = info?.feedback?.state === 'solved'
+      isPolicySolved = isPolicySolved && isChallengeSolved
+      return { info, uuid, isChallengeSolved }
+    }).filter(ch => ch.info !== undefined)
+
+    return { isPolicySolved, challenges }
+  })
+
+  const atLeastThereIsOnePolicySolved = policiesWithInfo.find(p => p.isPolicySolved) !== undefined
+
   return (
-    <AnastasisClientFrame title="Recovery: Solve challenges">
-      <h2>Policies</h2>
-      {!policies.length && <p>
-        No policies found
-      </p>}
-      {policies.map((row, i) => {
+    <AnastasisClientFrame hideNext={!atLeastThereIsOnePolicySolved} title="Recovery: Solve challenges">
+      {!policies.length ? <p>
+        No policies found, try with another version of the secret
+      </p> : (policies.length === 1 ? <p>
+        One policy found for this secret. You need to solve all the challenges in order to recover your secret.
+      </p> : <p>
+        We have found {policies.length} polices. You need to solve all the challenges from one policy in order
+        to recover your secret.
+      </p>)}
+      {policiesWithInfo.map((row, i) => {
+        const tableBody = row.challenges.map(({ info, uuid }) => {
+          return (
+            <tr key={uuid}>
+              <td>{info.type}</td>
+              <td>
+                {info.instructions}
+              </td>
+              <td>{info.feedback?.state ?? "unknown"}</td>
+              <td>{info.cost}</td>
+              <td>
+                {info.feedback?.state !== "solved" ? (
+                  <a onClick={() => reducer.transition("select_challenge", { uuid })}>
+                    Solve
+                  </a>
+                ) : null}
+              </td>
+            </tr>
+          );
+        })
         return (
           <div key={i}>
-            <h3>Policy #{i + 1}</h3>
-            {row.map(column => {
-              const ch = challenges[column.uuid];
-              if (!ch) return <div>
-                There is no challenge for this policy
-              </div>
-              const feedback = challengeFeedback?.[column.uuid];
-              return (
-                <div key={column.uuid}
-                  style={{
-                    borderLeft: "2px solid gray",
-                    paddingLeft: "0.5em",
-                    borderRadius: "0.5em",
-                    marginTop: "0.5em",
-                    marginBottom: "0.5em",
-                  }}
-                >
-                  <h4>
-                    {ch.type} ({ch.instructions})
-                  </h4>
-                  <p>Status: {feedback?.state ?? "unknown"}</p>
-                  {feedback?.state !== "solved" ? (
-                    <button
-                      onClick={() => reducer.transition("select_challenge", {
-                        uuid: column.uuid,
-                      })}
-                    >
-                      Solve
-                    </button>
-                  ) : null}
-                </div>
-              );
-            })}
+            <b>Policy #{i + 1}</b>
+            {row.challenges.length === 0 && <p>
+              This policy doesn't have challenges
+            </p>}
+            {row.challenges.length === 1 && <p>
+              This policy just have one challenge to be solved
+            </p>}
+            {row.challenges.length > 1 && <p>
+              This policy have {row.challenges.length} challenges
+            </p>}
+            <table class="table">
+              <thead>
+                <tr>
+                  <td>Challenge type</td>
+                  <td>Description</td>
+                  <td>Status</td>
+                  <td>Cost</td>
+                </tr>
+              </thead>
+              <tbody>
+                {tableBody}
+              </tbody>
+            </table>
           </div>
         );
       })}
diff --git a/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.stories.tsx
index 8744a2b79..2186eb42d 100644
--- a/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.stories.tsx
@@ -36,4 +36,5 @@ export default {
 };
 
 export const Backup = createExample(TestedComponent, reducerStatesExample.backupSelectContinent);
+
 export const Recovery = createExample(TestedComponent, reducerStatesExample.recoverySelectContinent);
diff --git a/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.stories.tsx
index b5933db17..0d2ebb778 100644
--- a/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.stories.tsx
@@ -37,7 +37,7 @@ export default {
   },
 };
 
-export const NormalEnding = createExample(TestedComponent, {
+export const GoodEnding = createExample(TestedComponent, {
   ...reducerStatesExample.recoveryFinished,
   core_secret: { mime: 'text/plain', value: 'hello' }
 } as ReducerState);
diff --git a/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx b/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx
index f5fd7c0d1..79a46761c 100644
--- a/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx
@@ -5,7 +5,7 @@ import { useState } from "preact/hooks";
 import { useAnastasisContext } from "../../context/anastasis";
 import {
   AnastasisClientFrame} from "./index";
-import { LabeledInput } from "../../components/fields/LabeledInput";
+import { TextInput } from "../../components/fields/TextInput";
 
 export function SecretEditorScreen(): VNode {
   const reducer = useAnastasisContext()
@@ -47,14 +47,14 @@ export function SecretEditorScreen(): VNode {
       onNext={() => secretNext()}
     >
       <div>
-        <LabeledInput
+        <TextInput
           label="Secret Name:"
           grabFocus
           bind={[secretName, setSecretName]}
         />
       </div>
       <div>
-        <LabeledInput
+        <TextInput
           label="Secret Value:"
           bind={[secretValue, setSecretValue]}
         />
diff --git a/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx b/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx
index 903f57868..5d67ee472 100644
--- a/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx
@@ -29,15 +29,31 @@ export function SecretSelectionScreen(): VNode {
         version: n,
         provider_url: p,
       });
-      setSelectingVersion(false);
     });
+    setSelectingVersion(false);
   }
 
+  const providerList = Object.keys(reducer.currentReducerState.authentication_providers ?? {})
   const recoveryDocument = reducer.currentReducerState.recovery_document
   if (!recoveryDocument) {
     return (
-      <AnastasisClientFrame hideNav title="Recovery: Problem">
-        <p>No recovery document found</p>
+      <AnastasisClientFrame hideNext title="Recovery: Problem">
+        <p>No recovery document found, try with another provider</p>
+        <table class="table">
+          <tr>
+            <td><b>Provider</b></td>
+            <td>
+              <select onChange={(e) => setOtherProvider((e.target as any).value)}>
+                <option key="none" disabled selected > Choose another provider </option>
+                {providerList.map(prov => (
+                  <option key={prov} value={prov}>
+                    {prov}
+                  </option>
+                ))}
+              </select>
+            </td>
+          </tr>
+        </table>
       </AnastasisClientFrame>
     )
   }
@@ -45,43 +61,75 @@ export function SecretSelectionScreen(): VNode {
     return (
       <AnastasisClientFrame hideNav title="Recovery: Select secret">
         <p>Select a different version of the secret</p>
-        <select onChange={(e) => setOtherProvider((e.target as any).value)}>
-          {Object.keys(reducer.currentReducerState.authentication_providers ?? {}).map(
-            (x, i) => (
-              <option key={i} selected={x === recoveryDocument.provider_url} value={x}>
-                {x}
-              </option>
-            )
-          )}
-        </select>
-        <div>
-          <input
-            value={otherVersion}
-            onChange={(e) => setOtherVersion(Number((e.target as HTMLInputElement).value))}
-            type="number" />
-          <button onClick={() => selectVersion(otherProvider, otherVersion)}>
-            Use this version
-          </button>
-        </div>
-        <div>
-          <button onClick={() => selectVersion(otherProvider, 0)}>
-            Use latest version
-          </button>
-        </div>
-        <div>
-          <button onClick={() => setSelectingVersion(false)}>Cancel</button>
+        <table class="table">
+          <tr>
+            <td><b>Provider</b></td>
+            <td>
+              <select onChange={(e) => setOtherProvider((e.target as any).value)}>
+                {providerList.map(prov => (
+                  <option key={prov} selected={prov === recoveryDocument.provider_url} value={prov}>
+                    {prov}
+                  </option>
+                ))}
+              </select>
+            </td>
+          </tr>
+          <tr>
+            <td><b>Version</b></td>
+            <td>
+              <input
+                value={otherVersion}
+                onChange={(e) => setOtherVersion(Number((e.target as HTMLInputElement).value))}
+                type="number" />
+            </td>
+            <td>
+              <a onClick={() => setOtherVersion(0)}>set to latest version</a>
+            </td>
+          </tr>
+        </table>
+        <div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
+          <button class="button" onClick={() => setSelectingVersion(false)}>Cancel</button>
+          <button class="button is-info" onClick={() => selectVersion(otherProvider, otherVersion)}>Confirm</button>
         </div>
+
       </AnastasisClientFrame>
     );
   }
   return (
     <AnastasisClientFrame title="Recovery: Select secret">
-      <p>Provider: {recoveryDocument.provider_url}</p>
-      <p>Secret version: {recoveryDocument.version}</p>
-      <p>Secret name: {recoveryDocument.secret_name}</p>
-      <button onClick={() => setSelectingVersion(true)}>
-        Select different secret
-      </button>
+      <p>Secret found, you can select another version or continue to the challenges solving</p>
+      <table class="table">
+        <tr>
+          <td>
+            <b>Provider</b>
+            <span class="icon has-tooltip-right" data-tooltip="Service provider backing up your secret">
+              <i class="mdi mdi-information" />
+            </span>
+          </td>
+          <td>{recoveryDocument.provider_url}</td>
+          <td><a onClick={() => setSelectingVersion(true)}>use another provider</a></td>
+        </tr>
+        <tr>
+          <td>
+            <b>Secret version</b>
+            <span class="icon has-tooltip-right" data-tooltip="Secret version to be recovered">
+              <i class="mdi mdi-information" />
+            </span>
+          </td>
+          <td>{recoveryDocument.version}</td>
+          <td><a onClick={() => setSelectingVersion(true)}>use another version</a></td>
+        </tr>
+        <tr>
+          <td>
+            <b>Secret name</b>
+            <span class="icon has-tooltip-right" data-tooltip="Secret identifier">
+              <i class="mdi mdi-information" />
+            </span>
+          </td>
+          <td>{recoveryDocument.secret_name}</td>
+          <td> </td>
+        </tr>
+      </table>
     </AnastasisClientFrame>
   );
 }
diff --git a/packages/anastasis-webui/src/pages/home/SolveEmailEntry.tsx b/packages/anastasis-webui/src/pages/home/SolveEmailEntry.tsx
deleted file mode 100644
index 0d70405e5..000000000
--- a/packages/anastasis-webui/src/pages/home/SolveEmailEntry.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-import { h, VNode } from "preact";
-import { useState } from "preact/hooks";
-import { useAnastasisContext } from "../../context/anastasis";
-import { AnastasisClientFrame } from "./index";
-import { LabeledInput } from "../../components/fields/LabeledInput";
-import { SolveEntryProps } from "./SolveScreen";
-
-export function SolveEmailEntry({ challenge, feedback }: SolveEntryProps): VNode {
-  const [answer, setAnswer] = useState("");
-  const reducer = useAnastasisContext()
-  const next = (): void => {
-    if (reducer) reducer.transition("solve_challenge", {
-      answer,
-    })
-  };
-  return (
-    <AnastasisClientFrame
-      title="Recovery: Solve challenge"
-      onNext={() => next()}
-    >
-      <p>Feedback: {JSON.stringify(feedback)}</p>
-      <p>{challenge.instructions}</p>
-      <LabeledInput label="Answer" grabFocus bind={[answer, setAnswer]} />
-    </AnastasisClientFrame>
-  );
-}
diff --git a/packages/anastasis-webui/src/pages/home/SolvePostEntry.tsx b/packages/anastasis-webui/src/pages/home/SolvePostEntry.tsx
deleted file mode 100644
index 22b8d470b..000000000
--- a/packages/anastasis-webui/src/pages/home/SolvePostEntry.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import { h, VNode } from "preact";
-import { useState } from "preact/hooks";
-import { useAnastasisContext } from "../../context/anastasis";
-import { AnastasisClientFrame } from "./index";
-import { LabeledInput } from "../../components/fields/LabeledInput";
-import { SolveEntryProps } from "./SolveScreen";
-
-export function SolvePostEntry({ challenge, feedback }: SolveEntryProps): VNode {
-  const [answer, setAnswer] = useState("");
-  const reducer = useAnastasisContext()
-  const next = (): void => {
-    if (reducer) reducer.transition("solve_challenge", { answer })
-  };
-  return (
-    <AnastasisClientFrame
-      title="Recovery: Solve challenge"
-      onNext={() => next()}
-    >
-      <p>Feedback: {JSON.stringify(feedback)}</p>
-      <p>{challenge.instructions}</p>
-      <LabeledInput label="Answer" grabFocus bind={[answer, setAnswer]} />
-    </AnastasisClientFrame>
-  );
-}
diff --git a/packages/anastasis-webui/src/pages/home/SolveQuestionEntry.tsx b/packages/anastasis-webui/src/pages/home/SolveQuestionEntry.tsx
deleted file mode 100644
index 319289381..000000000
--- a/packages/anastasis-webui/src/pages/home/SolveQuestionEntry.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import { h, VNode } from "preact";
-import { useState } from "preact/hooks";
-import { useAnastasisContext } from "../../context/anastasis";
-import { AnastasisClientFrame } from "./index";
-import { LabeledInput } from "../../components/fields/LabeledInput";
-import { SolveEntryProps } from "./SolveScreen";
-
-export function SolveQuestionEntry({ challenge, feedback }: SolveEntryProps): VNode {
-  const [answer, setAnswer] = useState("");
-  const reducer = useAnastasisContext()
-  const next = (): void => {
-    if (reducer) reducer.transition("solve_challenge", { answer })
-  };
-  return (
-    <AnastasisClientFrame
-      title="Recovery: Solve challenge"
-      onNext={() => next()}
-    >
-      <p>Feedback: {JSON.stringify(feedback)}</p>
-      <p>Question: {challenge.instructions}</p>
-      <LabeledInput label="Answer" grabFocus bind={[answer, setAnswer]} />
-    </AnastasisClientFrame>
-  );
-}
diff --git a/packages/anastasis-webui/src/pages/home/SolveScreen.tsx b/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
index 05ae50b48..077726e02 100644
--- a/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
@@ -1,28 +1,36 @@
-import { h, VNode } from "preact";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { AnastasisClientFrame } from ".";
 import { ChallengeFeedback, ChallengeInfo } from "../../../../anastasis-core/lib";
+import { TextInput } from "../../components/fields/TextInput";
 import { useAnastasisContext } from "../../context/anastasis";
-import { SolveEmailEntry } from "./SolveEmailEntry";
-import { SolvePostEntry } from "./SolvePostEntry";
-import { SolveQuestionEntry } from "./SolveQuestionEntry";
-import { SolveSmsEntry } from "./SolveSmsEntry";
-import { SolveUnsupportedEntry } from "./SolveUnsupportedEntry";
 
 export function SolveScreen(): VNode {
   const reducer = useAnastasisContext()
-
+  const [answer, setAnswer] = useState("");
+  
   if (!reducer) {
-    return <div>no reducer in context</div>
+    return <AnastasisClientFrame hideNext title="Recovery problem">
+      <div>no reducer in context</div>
+    </AnastasisClientFrame>
   }
   if (!reducer.currentReducerState || reducer.currentReducerState.recovery_state === undefined) {
-    return <div>invalid state</div>
+    return <AnastasisClientFrame hideNext title="Recovery problem">
+      <div>invalid state</div>
+    </AnastasisClientFrame>
   }
 
   if (!reducer.currentReducerState.recovery_information) {
-    return <div>no recovery information found</div>
+    return <AnastasisClientFrame hideNext title="Recovery problem">
+      <div>no recovery information found</div>
+    </AnastasisClientFrame>
   }
   if (!reducer.currentReducerState.selected_challenge_uuid) {
-    return <div>no selected uuid</div>
+    return <AnastasisClientFrame hideNext title="Recovery problem">
+      <div>no selected uuid</div>
+    </AnastasisClientFrame>
   }
+
   const chArr = reducer.currentReducerState.recovery_information.challenges;
   const challengeFeedback = reducer.currentReducerState.challenge_feedback ?? {};
   const selectedUuid = reducer.currentReducerState.selected_challenge_uuid;
@@ -39,16 +47,99 @@ export function SolveScreen(): VNode {
     email: SolveEmailEntry,
     post: SolvePostEntry,
   };
-  const SolveDialog = dialogMap[selectedChallenge?.type] ?? SolveUnsupportedEntry;
+  const SolveDialog = selectedChallenge === undefined ? SolveUndefinedEntry : dialogMap[selectedChallenge.type] ?? SolveUnsupportedEntry;
+
+  function onNext(): void {
+    reducer?.transition("solve_challenge", { answer })
+  }
+  function onCancel(): void {
+    reducer?.back()
+  }
+  
+
   return (
-    <SolveDialog
-      challenge={selectedChallenge}
-      feedback={challengeFeedback[selectedUuid]} />
+    <AnastasisClientFrame
+      hideNav
+      title="Recovery: Solve challenge"
+    >
+      <SolveDialog
+        id={selectedUuid}
+        answer={answer}
+        setAnswer={setAnswer}
+        challenge={selectedChallenge}
+        feedback={challengeFeedback[selectedUuid]} />
+
+      <div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
+          <button class="button" onClick={onCancel}>Cancel</button>
+          <button class="button is-info" onClick={onNext} >Confirm</button>
+        </div>
+    </AnastasisClientFrame>
   );
 }
 
 export interface SolveEntryProps {
+  id: string;
   challenge: ChallengeInfo;
   feedback?: ChallengeFeedback;
+  answer: string;
+  setAnswer: (s:string) => void;
 }
 
+function SolveSmsEntry({ challenge, answer, setAnswer }: SolveEntryProps): VNode {
+  return (<Fragment>
+      <p>An sms has been sent to "<b>{challenge.instructions}</b>". Type the code below</p>
+      <TextInput label="Answer" grabFocus bind={[answer, setAnswer]} />
+  </Fragment>
+  );
+}
+function SolveQuestionEntry({ challenge, answer, setAnswer }: SolveEntryProps): VNode {
+  return (
+    <Fragment>
+      <p>Type the answer to the following question:</p>
+      <pre>
+        {challenge.instructions}
+      </pre>
+      <TextInput label="Answer" grabFocus bind={[answer, setAnswer]} />
+    </Fragment>
+  );
+}
+
+function SolvePostEntry({ challenge, answer, setAnswer }: SolveEntryProps): VNode {
+  return (
+    <Fragment>
+      <p>instruction for post type challenge "<b>{challenge.instructions}</b>"</p>
+      <TextInput label="Answer" grabFocus bind={[answer, setAnswer]} />
+    </Fragment>
+  );
+}
+
+function SolveEmailEntry({ challenge, answer, setAnswer }: SolveEntryProps): VNode {
+  return (
+    <Fragment>
+      <p>An email has been sent to "<b>{challenge.instructions}</b>". Type the code below</p>
+      <TextInput label="Answer" grabFocus bind={[answer, setAnswer]} />
+    </Fragment>
+  );
+}
+
+function SolveUnsupportedEntry(props: SolveEntryProps): VNode {
+  return (
+    <Fragment>
+      <p>
+        The challenge selected is not supported for this UI. Please update this version or try using another policy.
+      </p>
+      <p>
+        <b>Challenge type:</b> {props.challenge.type}
+      </p>
+    </Fragment>
+  );
+}
+function SolveUndefinedEntry(props: SolveEntryProps): VNode {
+  return (
+    <Fragment >
+      <p>
+        There is no challenge information for id <b>"{props.id}"</b>. Try resetting the recovery session.
+      </p>
+    </Fragment>
+  );
+}
diff --git a/packages/anastasis-webui/src/pages/home/SolveSmsEntry.tsx b/packages/anastasis-webui/src/pages/home/SolveSmsEntry.tsx
deleted file mode 100644
index c4cf3a680..000000000
--- a/packages/anastasis-webui/src/pages/home/SolveSmsEntry.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-import { h, VNode } from "preact";
-import { useState } from "preact/hooks";
-import { useAnastasisContext } from "../../context/anastasis";
-import { AnastasisClientFrame } from "./index";
-import { LabeledInput } from "../../components/fields/LabeledInput";
-import { SolveEntryProps } from "./SolveScreen";
-
-export function SolveSmsEntry({ challenge, feedback }: SolveEntryProps): VNode {
-  const [answer, setAnswer] = useState("");
-  const reducer = useAnastasisContext()
-  const next = (): void => {
-    if (reducer) reducer.transition("solve_challenge", {
-      answer,
-    })
-  };
-  return (
-    <AnastasisClientFrame
-      title="Recovery: Solve challenge"
-      onNext={() => next()}
-    >
-      <p>Feedback: {JSON.stringify(feedback)}</p>
-      <p>{challenge.instructions}</p>
-      <LabeledInput label="Answer" grabFocus bind={[answer, setAnswer]} />
-    </AnastasisClientFrame>
-  );
-}
diff --git a/packages/anastasis-webui/src/pages/home/SolveUnsupportedEntry.tsx b/packages/anastasis-webui/src/pages/home/SolveUnsupportedEntry.tsx
deleted file mode 100644
index 7f538d249..000000000
--- a/packages/anastasis-webui/src/pages/home/SolveUnsupportedEntry.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import { h, VNode } from "preact";
-import { AnastasisClientFrame } from "./index";
-import { SolveEntryProps } from "./SolveScreen";
-
-export function SolveUnsupportedEntry(props: SolveEntryProps): VNode {
-  return (
-    <AnastasisClientFrame hideNext title="Recovery: Solve challenge">
-      <p>{JSON.stringify(props.challenge)}</p>
-      <p>Challenge not supported.</p>
-    </AnastasisClientFrame>
-  );
-}
diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
index 8a97ad50c..cf41efb59 100644
--- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
@@ -14,17 +14,17 @@
  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import { AmountJson, AmountLike, Amounts, i18n, Transaction, TransactionType } from "@gnu-taler/taler-util";
+import { AmountLike, Amounts, i18n, Transaction, TransactionType } from "@gnu-taler/taler-util";
 import { format } from "date-fns";
-import { Fragment, JSX, VNode, h } from "preact";
+import { JSX, VNode } from "preact";
 import { route } from 'preact-router';
 import { useEffect, useState } from "preact/hooks";
-import * as wxApi from "../wxApi";
-import { Pages } from "../NavigationBar";
-import emptyImg from "../../static/img/empty.png"
-import { Button, ButtonBox, ButtonBoxDestructive, ButtonDestructive, ButtonPrimary, ExtraLargeText, FontIcon, LargeText, ListOfProducts, PopupBox, Row, RowBorderGray, SmallLightText, WalletBox, WarningBox } from "../components/styled";
+import emptyImg from "../../static/img/empty.png";
 import { ErrorMessage } from "../components/ErrorMessage";
 import { Part } from "../components/Part";
+import { ButtonBox, ButtonBoxDestructive, ButtonPrimary, FontIcon, ListOfProducts, RowBorderGray, SmallLightText, WalletBox, WarningBox } from "../components/styled";
+import { Pages } from "../NavigationBar";
+import * as wxApi from "../wxApi";
 
 export function TransactionPage({ tid }: { tid: string; }): JSX.Element {
   const [transaction, setTransaction] = useState<
@@ -42,7 +42,7 @@ export function TransactionPage({ tid }: { tid: string; }): JSX.Element {
       }
     };
     fetchData();
-  }, []);
+  }, [tid]);
 
   if (!transaction) {
     return <div><i18n.Translate>Loading ...</i18n.Translate></div>;
-- 
cgit v1.2.3


From 88d142d2098ad87613222e9a0c6df478a78f6528 Mon Sep 17 00:00:00 2001
From: Sebastian <sebasjm@gmail.com>
Date: Mon, 1 Nov 2021 16:10:49 -0300
Subject: more styling

added placeholders for inputs
import declaration for png
next button now has tooltip providing info about whats missing
a lot more of examples for UI testing
added qr dependency for totp rendering
added email and field input types
added all auth method setup screens
added modal when there is not auth provider
merge continent and country into location section
others improvements as well...
---
 packages/anastasis-core/src/reducer-types.ts       |   6 +-
 packages/anastasis-webui/package.json              |   3 +-
 packages/anastasis-webui/src/assets/empty.png      | Bin 0 -> 2785 bytes
 .../anastasis-webui/src/assets/example/id1.jpg     | Bin 0 -> 103558 bytes
 .../src/assets/icons/auth_method/email.svg         |   1 +
 .../src/assets/icons/auth_method/postal.svg        |   1 +
 .../src/assets/icons/auth_method/question.svg      |   1 +
 .../src/assets/icons/auth_method/sms.svg           |   1 +
 .../src/assets/icons/auth_method/video.svg         |   1 +
 packages/anastasis-webui/src/components/QR.tsx     |  35 ++++
 .../src/components/fields/DateInput.tsx            |   5 +-
 .../src/components/fields/EmailInput.tsx           |  44 +++++
 .../src/components/fields/FileInput.tsx            |  81 ++++++++
 .../src/components/fields/ImageInput.tsx           |  81 ++++++++
 .../src/components/fields/NumberInput.tsx          |   2 +
 .../src/components/fields/TextInput.tsx            |   2 +
 .../src/components/menu/SideBar.tsx                |   5 +-
 packages/anastasis-webui/src/declaration.d.ts      |   4 +
 .../src/pages/home/AttributeEntryScreen.tsx        |  84 +++++----
 .../src/pages/home/AuthMethodEmailSetup.tsx        |  43 -----
 .../src/pages/home/AuthMethodPostSetup.tsx         |  69 -------
 .../src/pages/home/AuthMethodQuestionSetup.tsx     |  47 -----
 .../src/pages/home/AuthMethodSmsSetup.tsx          |  51 -----
 .../home/AuthenticationEditorScreen.stories.tsx    |  55 ++++++
 .../src/pages/home/AuthenticationEditorScreen.tsx  | 199 ++++++++++++++------
 .../pages/home/BackupFinishedScreen.stories.tsx    |   2 +-
 .../src/pages/home/BackupFinishedScreen.tsx        |  30 +--
 .../src/pages/home/ChallengeOverviewScreen.tsx     |   3 +-
 .../src/pages/home/ChallengePayingScreen.tsx       |   2 +-
 .../src/pages/home/ContinentSelectionScreen.tsx    | 102 +++++++++-
 .../src/pages/home/CountrySelectionScreen.tsx      |   2 +-
 .../src/pages/home/PoliciesPayingScreen.tsx        |   2 +-
 .../src/pages/home/RecoveryFinishedScreen.tsx      |   4 +-
 .../pages/home/ReviewPoliciesScreen.stories.tsx    | 208 ++++++++++++++++++---
 .../src/pages/home/ReviewPoliciesScreen.tsx        |  52 +++---
 .../src/pages/home/SecretEditorScreen.tsx          |   5 +
 .../src/pages/home/SecretSelectionScreen.tsx       |   2 +-
 .../src/pages/home/SolveScreen.stories.tsx         |  12 +-
 .../anastasis-webui/src/pages/home/SolveScreen.tsx |  26 +--
 .../AuthMethodEmailSetup.stories.tsx               |  66 +++++++
 .../home/authMethodSetup/AuthMethodEmailSetup.tsx  |  62 ++++++
 .../AuthMethodIbanSetup.stories.tsx                |  65 +++++++
 .../home/authMethodSetup/AuthMethodIbanSetup.tsx   |  68 +++++++
 .../AuthMethodPostSetup.stories.tsx                |  66 +++++++
 .../home/authMethodSetup/AuthMethodPostSetup.tsx   | 102 ++++++++++
 .../AuthMethodQuestionSetup.stories.tsx            |  66 +++++++
 .../authMethodSetup/AuthMethodQuestionSetup.tsx    |  70 +++++++
 .../authMethodSetup/AuthMethodSmsSetup.stories.tsx |  66 +++++++
 .../home/authMethodSetup/AuthMethodSmsSetup.tsx    |  63 +++++++
 .../AuthMethodTotpSetup.stories.tsx                |  64 +++++++
 .../home/authMethodSetup/AuthMethodTotpSetup.tsx   |  47 +++++
 .../AuthMethodVideoSetup.stories.tsx               |  66 +++++++
 .../home/authMethodSetup/AuthMethodVideoSetup.tsx  |  56 ++++++
 .../src/pages/home/authMethodSetup/index.tsx       |  68 +++++++
 packages/anastasis-webui/src/pages/home/index.tsx  |  23 +--
 packages/anastasis-webui/src/scss/main.scss        |   8 +-
 packages/anastasis-webui/src/utils/index.tsx       |   8 +-
 pnpm-lock.yaml                                     |   2 +
 58 files changed, 1882 insertions(+), 427 deletions(-)
 create mode 100644 packages/anastasis-webui/src/assets/empty.png
 create mode 100644 packages/anastasis-webui/src/assets/example/id1.jpg
 create mode 100644 packages/anastasis-webui/src/assets/icons/auth_method/email.svg
 create mode 100644 packages/anastasis-webui/src/assets/icons/auth_method/postal.svg
 create mode 100644 packages/anastasis-webui/src/assets/icons/auth_method/question.svg
 create mode 100644 packages/anastasis-webui/src/assets/icons/auth_method/sms.svg
 create mode 100644 packages/anastasis-webui/src/assets/icons/auth_method/video.svg
 create mode 100644 packages/anastasis-webui/src/components/QR.tsx
 create mode 100644 packages/anastasis-webui/src/components/fields/EmailInput.tsx
 create mode 100644 packages/anastasis-webui/src/components/fields/FileInput.tsx
 create mode 100644 packages/anastasis-webui/src/components/fields/ImageInput.tsx
 delete mode 100644 packages/anastasis-webui/src/pages/home/AuthMethodEmailSetup.tsx
 delete mode 100644 packages/anastasis-webui/src/pages/home/AuthMethodPostSetup.tsx
 delete mode 100644 packages/anastasis-webui/src/pages/home/AuthMethodQuestionSetup.tsx
 delete mode 100644 packages/anastasis-webui/src/pages/home/AuthMethodSmsSetup.tsx
 create mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodEmailSetup.stories.tsx
 create mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodEmailSetup.tsx
 create mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodIbanSetup.stories.tsx
 create mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodIbanSetup.tsx
 create mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodPostSetup.stories.tsx
 create mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodPostSetup.tsx
 create mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodQuestionSetup.stories.tsx
 create mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodQuestionSetup.tsx
 create mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodSmsSetup.stories.tsx
 create mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodSmsSetup.tsx
 create mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodTotpSetup.stories.tsx
 create mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodTotpSetup.tsx
 create mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodVideoSetup.stories.tsx
 create mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodVideoSetup.tsx
 create mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/index.tsx

(limited to 'packages/anastasis-webui/src/pages/home/AuthMethodEmailSetup.tsx')

diff --git a/packages/anastasis-core/src/reducer-types.ts b/packages/anastasis-core/src/reducer-types.ts
index d70712709..57f67f0d0 100644
--- a/packages/anastasis-core/src/reducer-types.ts
+++ b/packages/anastasis-core/src/reducer-types.ts
@@ -47,7 +47,7 @@ export interface ReducerStateBackup {
   code?: undefined;
   currencies?: string[];
   continents?: ContinentInfo[];
-  countries?: any;
+  countries?: CountryInfo[];
   identity_attributes?: { [n: string]: string };
   authentication_providers?: { [url: string]: AuthenticationProviderStatus };
   authentication_methods?: AuthMethod[];
@@ -129,8 +129,8 @@ export interface ReducerStateRecovery {
 
   identity_attributes?: { [n: string]: string };
 
-  continents?: any;
-  countries?: any;
+  continents?: ContinentInfo[];
+  countries?: CountryInfo[];
 
   selected_continent?: string;
   selected_country?: string;
diff --git a/packages/anastasis-webui/package.json b/packages/anastasis-webui/package.json
index 4cdb00243..2f2577a92 100644
--- a/packages/anastasis-webui/package.json
+++ b/packages/anastasis-webui/package.json
@@ -29,7 +29,8 @@
     "jed": "1.1.1",
     "preact": "^10.3.1",
     "preact-render-to-string": "^5.1.4",
-    "preact-router": "^3.2.1"
+    "preact-router": "^3.2.1",
+    "qrcode-generator": "^1.4.4"
   },
   "devDependencies": {
     "@creativebulma/bulma-tooltip": "^1.2.0",
diff --git a/packages/anastasis-webui/src/assets/empty.png b/packages/anastasis-webui/src/assets/empty.png
new file mode 100644
index 000000000..5120d3138
Binary files /dev/null and b/packages/anastasis-webui/src/assets/empty.png differ
diff --git a/packages/anastasis-webui/src/assets/example/id1.jpg b/packages/anastasis-webui/src/assets/example/id1.jpg
new file mode 100644
index 000000000..5d022a379
Binary files /dev/null and b/packages/anastasis-webui/src/assets/example/id1.jpg differ
diff --git a/packages/anastasis-webui/src/assets/icons/auth_method/email.svg b/packages/anastasis-webui/src/assets/icons/auth_method/email.svg
new file mode 100644
index 000000000..3e44b8779
--- /dev/null
+++ b/packages/anastasis-webui/src/assets/icons/auth_method/email.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6zm-2 0l-8 5-8-5h16zm0 12H4V8l8 5 8-5v10z"/></svg>
\ No newline at end of file
diff --git a/packages/anastasis-webui/src/assets/icons/auth_method/postal.svg b/packages/anastasis-webui/src/assets/icons/auth_method/postal.svg
new file mode 100644
index 000000000..3787b8350
--- /dev/null
+++ b/packages/anastasis-webui/src/assets/icons/auth_method/postal.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M17 15h2v2h-2zM17 11h2v2h-2zM17 7h2v2h-2zM13.74 7l1.26.84V7z"/><path d="M10 3v1.51l2 1.33V5h9v14h-4v2h6V3z"/><path d="M8.17 5.7L15 10.25V21H1V10.48L8.17 5.7zM10 19h3v-7.84L8.17 8.09 3 11.38V19h3v-6h4v6z"/></svg>
\ No newline at end of file
diff --git a/packages/anastasis-webui/src/assets/icons/auth_method/question.svg b/packages/anastasis-webui/src/assets/icons/auth_method/question.svg
new file mode 100644
index 000000000..a346556b2
--- /dev/null
+++ b/packages/anastasis-webui/src/assets/icons/auth_method/question.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M11 23.59v-3.6c-5.01-.26-9-4.42-9-9.49C2 5.26 6.26 1 11.5 1S21 5.26 21 10.5c0 4.95-3.44 9.93-8.57 12.4l-1.43.69zM11.5 3C7.36 3 4 6.36 4 10.5S7.36 18 11.5 18H13v2.3c3.64-2.3 6-6.08 6-9.8C19 6.36 15.64 3 11.5 3zm-1 11.5h2v2h-2zm2-1.5h-2c0-3.25 3-3 3-5 0-1.1-.9-2-2-2s-2 .9-2 2h-2c0-2.21 1.79-4 4-4s4 1.79 4 4c0 2.5-3 2.75-3 5z"/></svg>
\ No newline at end of file
diff --git a/packages/anastasis-webui/src/assets/icons/auth_method/sms.svg b/packages/anastasis-webui/src/assets/icons/auth_method/sms.svg
new file mode 100644
index 000000000..ed15679bf
--- /dev/null
+++ b/packages/anastasis-webui/src/assets/icons/auth_method/sms.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M17 1.01L7 1c-1.1 0-1.99.9-1.99 2v18c0 1.1.89 2 1.99 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z"/></svg>
\ No newline at end of file
diff --git a/packages/anastasis-webui/src/assets/icons/auth_method/video.svg b/packages/anastasis-webui/src/assets/icons/auth_method/video.svg
new file mode 100644
index 000000000..69de5e0b4
--- /dev/null
+++ b/packages/anastasis-webui/src/assets/icons/auth_method/video.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><g><path d="M18,10.48V6c0-1.1-0.9-2-2-2H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2v-4.48l4,3.98v-11L18,10.48z M16,9.69V18H4V6h12V9.69z"/><circle cx="10" cy="10" r="2"/><path d="M14,15.43c0-0.81-0.48-1.53-1.22-1.85C11.93,13.21,10.99,13,10,13c-0.99,0-1.93,0.21-2.78,0.58C6.48,13.9,6,14.62,6,15.43 V16h8V15.43z"/></g></g></svg>
\ No newline at end of file
diff --git a/packages/anastasis-webui/src/components/QR.tsx b/packages/anastasis-webui/src/components/QR.tsx
new file mode 100644
index 000000000..48f1a7c12
--- /dev/null
+++ b/packages/anastasis-webui/src/components/QR.tsx
@@ -0,0 +1,35 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { h, VNode } from "preact";
+import { useEffect, useRef } from "preact/hooks";
+import qrcode from "qrcode-generator";
+
+export function QR({ text }: { text: string }): VNode {
+  const divRef = useRef<HTMLDivElement>(null);
+  useEffect(() => {
+    const qr = qrcode(0, 'L');
+    qr.addData(text);
+    qr.make();
+    if (divRef.current) divRef.current.innerHTML = qr.createSvgTag({
+      scalable: true,
+    });
+  });
+
+  return <div style={{ width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
+    <div style={{ width: '50%', minWidth: 200, maxWidth: 300 }} ref={divRef} />
+  </div>;
+}
diff --git a/packages/anastasis-webui/src/components/fields/DateInput.tsx b/packages/anastasis-webui/src/components/fields/DateInput.tsx
index e1c354f7b..69a05fcf3 100644
--- a/packages/anastasis-webui/src/components/fields/DateInput.tsx
+++ b/packages/anastasis-webui/src/components/fields/DateInput.tsx
@@ -25,7 +25,7 @@ export function DateInput(props: DateInputProps): VNode {
     setOpened2(v)
   }
 
-  const value = props.bind[0];
+  const value = props.bind[0] || "";
   const [dirty, setDirty] = useState(false)
   const showError = dirty && props.error
 
@@ -40,7 +40,8 @@ export function DateInput(props: DateInputProps): VNode {
       <input
         type="text"
         class={showError ? 'input is-danger' : 'input'}
-        onClick={() => { setOpened(true) }}
+        readonly
+        onFocus={() => { setOpened(true) } }
         value={value}
         ref={inputRef} />
 
diff --git a/packages/anastasis-webui/src/components/fields/EmailInput.tsx b/packages/anastasis-webui/src/components/fields/EmailInput.tsx
new file mode 100644
index 000000000..e0fca0f46
--- /dev/null
+++ b/packages/anastasis-webui/src/components/fields/EmailInput.tsx
@@ -0,0 +1,44 @@
+import { h, VNode } from "preact";
+import { useLayoutEffect, useRef, useState } from "preact/hooks";
+
+export interface TextInputProps {
+  label: string;
+  grabFocus?: boolean;
+  error?: string;
+  placeholder?: string;
+  tooltip?: string;
+  bind: [string, (x: string) => void];
+}
+
+export function EmailInput(props: TextInputProps): VNode {
+  const inputRef = useRef<HTMLInputElement>(null);
+  useLayoutEffect(() => {
+    if (props.grabFocus) {
+      inputRef.current?.focus();
+    }
+  }, [props.grabFocus]);
+  const value = props.bind[0];
+  const [dirty, setDirty] = useState(false)
+  const showError = dirty && props.error
+  return (<div class="field">
+    <label class="label">
+      {props.label}
+      {props.tooltip && <span class="icon has-tooltip-right" data-tooltip={props.tooltip}>
+        <i class="mdi mdi-information" />
+      </span>}
+    </label>
+    <div class="control has-icons-right">
+      <input
+        value={value}
+        required
+        placeholder={props.placeholder}
+        type="email"
+        class={showError ? 'input is-danger' : 'input'}
+        onChange={(e) => {setDirty(true); props.bind[1]((e.target as HTMLInputElement).value)}}
+        ref={inputRef}
+        style={{ display: "block" }} />
+    </div>
+    {showError && <p class="help is-danger">{props.error}</p>}
+  </div>
+  );
+}
diff --git a/packages/anastasis-webui/src/components/fields/FileInput.tsx b/packages/anastasis-webui/src/components/fields/FileInput.tsx
new file mode 100644
index 000000000..8b144ea43
--- /dev/null
+++ b/packages/anastasis-webui/src/components/fields/FileInput.tsx
@@ -0,0 +1,81 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+import { h, VNode } from "preact";
+import { useLayoutEffect, useRef, useState } from "preact/hooks";
+import { TextInputProps } from "./TextInput";
+
+const MAX_IMAGE_UPLOAD_SIZE = 1024 * 1024
+
+export function FileInput(props: TextInputProps): VNode {
+  const inputRef = useRef<HTMLInputElement>(null);
+  useLayoutEffect(() => {
+    if (props.grabFocus) {
+      inputRef.current?.focus();
+    }
+  }, [props.grabFocus]);
+
+  const value = props.bind[0];
+  // const [dirty, setDirty] = useState(false)
+  const image = useRef<HTMLInputElement>(null)
+  const [sizeError, setSizeError] = useState(false)
+  function onChange(v: string): void {
+    // setDirty(true);
+    props.bind[1](v);
+  }
+  return <div class="field">
+    <label class="label">
+      <a onClick={() => image.current?.click()}>
+        {props.label}
+      </a>
+      {props.tooltip && <span class="icon has-tooltip-right" data-tooltip={props.tooltip}>
+        <i class="mdi mdi-information" />
+      </span>}
+    </label>
+    <div class="control">
+      <input
+        ref={image} style={{ display: 'none' }}
+        type="file" name={String(name)}
+        onChange={e => {
+          const f: FileList | null = e.currentTarget.files
+          if (!f || f.length != 1) {
+            return onChange("")
+          }
+          if (f[0].size > MAX_IMAGE_UPLOAD_SIZE) {
+            setSizeError(true)
+            return onChange("")
+          }
+          setSizeError(false)
+          return f[0].arrayBuffer().then(b => {
+            const b64 = btoa(
+              new Uint8Array(b)
+                .reduce((data, byte) => data + String.fromCharCode(byte), '')
+            )
+            return onChange(`data:${f[0].type};base64,${b64}` as any)
+          })
+        }} />
+      {props.error && <p class="help is-danger">{props.error}</p>}
+      {sizeError && <p class="help is-danger">
+        File should be smaller than 1 MB
+      </p>}
+    </div>
+  </div>
+}
+
diff --git a/packages/anastasis-webui/src/components/fields/ImageInput.tsx b/packages/anastasis-webui/src/components/fields/ImageInput.tsx
new file mode 100644
index 000000000..d5bf643d4
--- /dev/null
+++ b/packages/anastasis-webui/src/components/fields/ImageInput.tsx
@@ -0,0 +1,81 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+import { h, VNode } from "preact";
+import { useLayoutEffect, useRef, useState } from "preact/hooks";
+import emptyImage from "../../assets/empty.png";
+import { TextInputProps } from "./TextInput";
+
+const MAX_IMAGE_UPLOAD_SIZE = 1024 * 1024
+
+export function ImageInput(props: TextInputProps): VNode {
+  const inputRef = useRef<HTMLInputElement>(null);
+  useLayoutEffect(() => {
+    if (props.grabFocus) {
+      inputRef.current?.focus();
+    }
+  }, [props.grabFocus]);
+
+  const value = props.bind[0];
+  // const [dirty, setDirty] = useState(false)
+  const image = useRef<HTMLInputElement>(null)
+  const [sizeError, setSizeError] = useState(false)
+  function onChange(v: string): void {
+    // setDirty(true);
+    props.bind[1](v);
+  }
+  return <div class="field">
+    <label class="label">
+      {props.label}
+      {props.tooltip && <span class="icon has-tooltip-right" data-tooltip={props.tooltip}>
+        <i class="mdi mdi-information" />
+      </span>}
+    </label>
+    <div class="control">
+      <img src={!value ? emptyImage : value} style={{ width: 200, height: 200 }} onClick={() => image.current?.click()} />
+      <input
+        ref={image} style={{ display: 'none' }}
+        type="file" name={String(name)}
+        onChange={e => {
+          const f: FileList | null = e.currentTarget.files
+          if (!f || f.length != 1) {
+            return onChange(emptyImage)
+          }
+          if (f[0].size > MAX_IMAGE_UPLOAD_SIZE) {
+            setSizeError(true)
+            return onChange(emptyImage)
+          }
+          setSizeError(false)
+          return f[0].arrayBuffer().then(b => {
+            const b64 = btoa(
+              new Uint8Array(b)
+                .reduce((data, byte) => data + String.fromCharCode(byte), '')
+            )
+            return onChange(`data:${f[0].type};base64,${b64}` as any)
+          })
+        }} />
+      {props.error && <p class="help is-danger">{props.error}</p>}
+      {sizeError && <p class="help is-danger">
+        Image should be smaller than 1 MB
+      </p>}
+    </div>
+  </div>
+}
+
diff --git a/packages/anastasis-webui/src/components/fields/NumberInput.tsx b/packages/anastasis-webui/src/components/fields/NumberInput.tsx
index af9bbe66b..2b6cdcd2c 100644
--- a/packages/anastasis-webui/src/components/fields/NumberInput.tsx
+++ b/packages/anastasis-webui/src/components/fields/NumberInput.tsx
@@ -5,6 +5,7 @@ export interface TextInputProps {
   label: string;
   grabFocus?: boolean;
   error?: string;
+  placeholder?: string;
   tooltip?: string;
   bind: [string, (x: string) => void];
 }
@@ -30,6 +31,7 @@ export function NumberInput(props: TextInputProps): VNode {
       <input
         value={value}
         type="number"
+        placeholder={props.placeholder}
         class={showError ? 'input is-danger' : 'input'}
         onChange={(e) => {setDirty(true); props.bind[1]((e.target as HTMLInputElement).value)}}
         ref={inputRef}
diff --git a/packages/anastasis-webui/src/components/fields/TextInput.tsx b/packages/anastasis-webui/src/components/fields/TextInput.tsx
index fa6fd9792..4bb785cd3 100644
--- a/packages/anastasis-webui/src/components/fields/TextInput.tsx
+++ b/packages/anastasis-webui/src/components/fields/TextInput.tsx
@@ -5,6 +5,7 @@ export interface TextInputProps {
   label: string;
   grabFocus?: boolean;
   error?: string;
+  placeholder?: string;
   tooltip?: string;
   bind: [string, (x: string) => void];
 }
@@ -29,6 +30,7 @@ export function TextInput(props: TextInputProps): VNode {
     <div class="control has-icons-right">
       <input
         value={value}
+        placeholder={props.placeholder}
         class={showError ? 'input is-danger' : 'input'}
         onChange={(e) => {setDirty(true); props.bind[1]((e.target as HTMLInputElement).value)}}
         ref={inputRef}
diff --git a/packages/anastasis-webui/src/components/menu/SideBar.tsx b/packages/anastasis-webui/src/components/menu/SideBar.tsx
index 87e771009..35720e0f1 100644
--- a/packages/anastasis-webui/src/components/menu/SideBar.tsx
+++ b/packages/anastasis-webui/src/components/menu/SideBar.tsx
@@ -33,6 +33,7 @@ interface Props {
 export function Sidebar({ mobile }: Props): VNode {
   // const config = useConfigContext();
   const config = { version: 'none' }
+  // FIXME: add replacement for __VERSION__ with the current version
   const process = { env: { __VERSION__: '0.0.0' } }
   const reducer = useAnastasisContext()!
 
@@ -105,12 +106,12 @@ export function Sidebar({ mobile }: Props): VNode {
                 <span class="menu-item-label"><Translate>Backup completed</Translate></span>
               </div>
             </li>
-            <li class={reducer.currentReducerState.backup_state === BackupStates.TruthsPaying ? 'is-active' : ''}>
+            {/* <li class={reducer.currentReducerState.backup_state === BackupStates.TruthsPaying ? 'is-active' : ''}>
               <div class="ml-4">
 
                 <span class="menu-item-label"><Translate>Truth Paying</Translate></span>
               </div>
-            </li>
+            </li> */}
           </Fragment> : (reducer.currentReducerState && reducer.currentReducerState?.recovery_state && <Fragment>
             <li class={reducer.currentReducerState.recovery_state === RecoveryStates.ContinentSelecting ||
               reducer.currentReducerState.recovery_state === RecoveryStates.CountrySelecting ? 'is-active' : ''}>
diff --git a/packages/anastasis-webui/src/declaration.d.ts b/packages/anastasis-webui/src/declaration.d.ts
index b32fb70fc..edd3a07a3 100644
--- a/packages/anastasis-webui/src/declaration.d.ts
+++ b/packages/anastasis-webui/src/declaration.d.ts
@@ -10,6 +10,10 @@ declare module '*.jpeg' {
     const content: any;
     export default content;
 }
+declare module '*.png' {
+    const content: any;
+    export default content;
+}
 declare module 'jed' {
     const x: any;
     export = x;
diff --git a/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.tsx b/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.tsx
index f74dcefba..2c7f54c5b 100644
--- a/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.tsx
@@ -1,6 +1,6 @@
 /* eslint-disable @typescript-eslint/camelcase */
 import { UserAttributeSpec, validators } from "anastasis-core";
-import { h, VNode } from "preact";
+import { Fragment, h, VNode } from "preact";
 import { useState } from "preact/hooks";
 import { useAnastasisContext } from "../../context/anastasis";
 import { AnastasisClientFrame, withProcessLabel } from "./index";
@@ -20,53 +20,38 @@ export function AttributeEntryScreen(): VNode {
   if (!reducer.currentReducerState || !("required_attributes" in reducer.currentReducerState)) {
     return <div>invalid state</div>
   }
+  const reqAttr = reducer.currentReducerState.required_attributes || []
+  let hasErrors = false;
 
+  const fieldList: VNode[] = reqAttr.map((spec, i: number) => {
+    const value = attrs[spec.name]
+    const error = checkIfValid(value, spec)
+    hasErrors = hasErrors || error !== undefined
+    return (
+      <AttributeEntryField
+        key={i}
+        isFirst={i == 0}
+        setValue={(v: string) => setAttrs({ ...attrs, [spec.name]: v })}
+        spec={spec}
+        errorMessage={error}
+        value={value} />
+    );
+  })
 
   return (
     <AnastasisClientFrame
       title={withProcessLabel(reducer, "Who are you?")}
+      hideNext={hasErrors ? "Complete the form." : undefined}
       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} />
-            );
-          })}
-
+          {fieldList}
         </div>
         <div class="column is-half" >
-          <p>This personal information will help to locate your secret in the first place</p>
+          <p>This personal information will help to locate your secret.</p>
           <h1><b>This stay private</b></h1>
           <p>The information you have entered here:
           </p>
@@ -92,14 +77,13 @@ interface AttributeEntryFieldProps {
   value: string;
   setValue: (newValue: string) => void;
   spec: UserAttributeSpec;
-  isValid: () => string | undefined;
+  errorMessage: string | undefined;
 }
 const possibleBirthdayYear: Array<number> = []
-for (let i = 0; i < 100; i++ ) {
+for (let i = 0; i < 100; i++) {
   possibleBirthdayYear.push(2020 - i)
 }
 function AttributeEntryField(props: AttributeEntryFieldProps): VNode {
-  const errorMessage = props.isValid()
 
   return (
     <div>
@@ -108,14 +92,14 @@ function AttributeEntryField(props: AttributeEntryFieldProps): VNode {
           grabFocus={props.isFirst}
           label={props.spec.label}
           years={possibleBirthdayYear}
-          error={errorMessage}
+          error={props.errorMessage}
           bind={[props.value, props.setValue]}
         />}
       {props.spec.type === 'number' &&
         <NumberInput
           grabFocus={props.isFirst}
           label={props.spec.label}
-          error={errorMessage}
+          error={props.errorMessage}
           bind={[props.value, props.setValue]}
         />
       }
@@ -123,7 +107,7 @@ function AttributeEntryField(props: AttributeEntryFieldProps): VNode {
         <TextInput
           grabFocus={props.isFirst}
           label={props.spec.label}
-          error={errorMessage}
+          error={props.errorMessage}
           bind={[props.value, props.setValue]}
         />
       }
@@ -136,3 +120,21 @@ function AttributeEntryField(props: AttributeEntryFieldProps): VNode {
     </div>
   );
 }
+
+function checkIfValid(value: string, spec: UserAttributeSpec): string | undefined {
+  const pattern = spec['validation-regex']
+  if (pattern) {
+    const re = new RegExp(pattern)
+    if (!re.test(value)) return 'The value is invalid'
+  }
+  const logic = spec['validation-logic']
+  if (logic) {
+    const func = (validators as any)[logic];
+    if (func && typeof func === 'function' && !func(value)) return 'Please check the value'
+  }
+  const optional = spec.optional
+  if (!optional && !value) {
+    return 'This value is required'
+  }
+  return undefined
+}
diff --git a/packages/anastasis-webui/src/pages/home/AuthMethodEmailSetup.tsx b/packages/anastasis-webui/src/pages/home/AuthMethodEmailSetup.tsx
deleted file mode 100644
index c3783ea6c..000000000
--- a/packages/anastasis-webui/src/pages/home/AuthMethodEmailSetup.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-/* eslint-disable @typescript-eslint/camelcase */
-import {
-  encodeCrock,
-  stringToBytes
-} from "@gnu-taler/taler-util";
-import { h, VNode } from "preact";
-import { useState } from "preact/hooks";
-import { AuthMethodSetupProps } from "./AuthenticationEditorScreen";
-import { AnastasisClientFrame } from "./index";
-import { TextInput } from "../../components/fields/TextInput";
-
-export function AuthMethodEmailSetup(props: AuthMethodSetupProps): VNode {
-  const [email, setEmail] = useState("");
-  return (
-    <AnastasisClientFrame hideNav title="Add email authentication">
-      <p>
-        For email authentication, you need to provide an email address. When
-        recovering your secret, you will need to enter the code you receive by
-        email.
-      </p>
-      <div>
-        <TextInput
-          label="Email address"
-          grabFocus
-          bind={[email, setEmail]} />
-      </div>
-      <div>
-        <button onClick={() => props.cancel()}>Cancel</button>
-        <button
-          onClick={() => props.addAuthMethod({
-            authentication_method: {
-              type: "email",
-              instructions: `Email to ${email}`,
-              challenge: encodeCrock(stringToBytes(email)),
-            },
-          })}
-        >
-          Add
-        </button>
-      </div>
-    </AnastasisClientFrame>
-  );
-}
diff --git a/packages/anastasis-webui/src/pages/home/AuthMethodPostSetup.tsx b/packages/anastasis-webui/src/pages/home/AuthMethodPostSetup.tsx
deleted file mode 100644
index c4ddeff91..000000000
--- a/packages/anastasis-webui/src/pages/home/AuthMethodPostSetup.tsx
+++ /dev/null
@@ -1,69 +0,0 @@
-/* eslint-disable @typescript-eslint/camelcase */
-import {
-  canonicalJson, encodeCrock,
-  stringToBytes
-} from "@gnu-taler/taler-util";
-import { h, VNode } from "preact";
-import { useState } from "preact/hooks";
-import { AuthMethodSetupProps } from "./AuthenticationEditorScreen";
-import { TextInput } from "../../components/fields/TextInput";
-
-export function AuthMethodPostSetup(props: AuthMethodSetupProps): VNode {
-  const [fullName, setFullName] = useState("");
-  const [street, setStreet] = useState("");
-  const [city, setCity] = useState("");
-  const [postcode, setPostcode] = useState("");
-  const [country, setCountry] = useState("");
-
-  const addPostAuth = () => {
-    const challengeJson = {
-      full_name: fullName,
-      street,
-      city,
-      postcode,
-      country,
-    };
-    props.addAuthMethod({
-      authentication_method: {
-        type: "email",
-        instructions: `Letter to address in postal code ${postcode}`,
-        challenge: encodeCrock(stringToBytes(canonicalJson(challengeJson))),
-      },
-    });
-  };
-
-  return (
-    <div class="home"> 
-      <h1>Add {props.method} authentication</h1>
-      <div>
-        <p>
-          For postal letter authentication, you need to provide a postal
-          address. When recovering your secret, you will be asked to enter a
-          code that you will receive in a letter to that address.
-        </p>
-        <div>
-          <TextInput
-            grabFocus
-            label="Full Name"
-            bind={[fullName, setFullName]} />
-        </div>
-        <div>
-          <TextInput label="Street" bind={[street, setStreet]} />
-        </div>
-        <div>
-          <TextInput label="City" bind={[city, setCity]} />
-        </div>
-        <div>
-          <TextInput label="Postal Code" bind={[postcode, setPostcode]} />
-        </div>
-        <div>
-          <TextInput label="Country" bind={[country, setCountry]} />
-        </div>
-        <div>
-          <button onClick={() => props.cancel()}>Cancel</button>
-          <button onClick={() => addPostAuth()}>Add</button>
-        </div>
-      </div>
-    </div>
-  );
-}
diff --git a/packages/anastasis-webui/src/pages/home/AuthMethodQuestionSetup.tsx b/packages/anastasis-webui/src/pages/home/AuthMethodQuestionSetup.tsx
deleted file mode 100644
index f1bab94ab..000000000
--- a/packages/anastasis-webui/src/pages/home/AuthMethodQuestionSetup.tsx
+++ /dev/null
@@ -1,47 +0,0 @@
-/* eslint-disable @typescript-eslint/camelcase */
-import {
-  encodeCrock,
-  stringToBytes
-} from "@gnu-taler/taler-util";
-import { h, VNode } from "preact";
-import { useState } from "preact/hooks";
-import { AuthMethodSetupProps } from "./AuthenticationEditorScreen";
-import { AnastasisClientFrame } from "./index";
-import { TextInput } from "../../components/fields/TextInput";
-
-export function AuthMethodQuestionSetup(props: AuthMethodSetupProps): VNode {
-  const [questionText, setQuestionText] = useState("");
-  const [answerText, setAnswerText] = useState("");
-  const addQuestionAuth = (): void => props.addAuthMethod({
-    authentication_method: {
-      type: "question",
-      instructions: questionText,
-      challenge: encodeCrock(stringToBytes(answerText)),
-    },
-  });
-  return (
-    <AnastasisClientFrame hideNav title="Add Security Question">
-      <div>
-        <p>
-          For security question authentication, you need to provide a question
-          and its answer. When recovering your secret, you will be shown the
-          question and you will need to type the answer exactly as you typed it
-          here.
-        </p>
-        <div>
-          <TextInput
-            label="Security question"
-            grabFocus
-            bind={[questionText, setQuestionText]} />
-        </div>
-        <div>
-          <TextInput label="Answer" bind={[answerText, setAnswerText]} />
-        </div>
-        <div>
-          <button onClick={() => props.cancel()}>Cancel</button>
-          <button onClick={() => addQuestionAuth()}>Add</button>
-        </div>
-      </div>
-    </AnastasisClientFrame>
-  );
-}
diff --git a/packages/anastasis-webui/src/pages/home/AuthMethodSmsSetup.tsx b/packages/anastasis-webui/src/pages/home/AuthMethodSmsSetup.tsx
deleted file mode 100644
index 6f4797275..000000000
--- a/packages/anastasis-webui/src/pages/home/AuthMethodSmsSetup.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-/* eslint-disable @typescript-eslint/camelcase */
-import {
-  encodeCrock,
-  stringToBytes
-} from "@gnu-taler/taler-util";
-import { h, VNode } from "preact";
-import { useState, useRef, useLayoutEffect } from "preact/hooks";
-import { AuthMethodSetupProps } from "./AuthenticationEditorScreen";
-import { AnastasisClientFrame } from "./index";
-
-export function AuthMethodSmsSetup(props: AuthMethodSetupProps): VNode {
-  const [mobileNumber, setMobileNumber] = useState("");
-  const addSmsAuth = (): void => {
-    props.addAuthMethod({
-      authentication_method: {
-        type: "sms",
-        instructions: `SMS to ${mobileNumber}`,
-        challenge: encodeCrock(stringToBytes(mobileNumber)),
-      },
-    });
-  };
-  const inputRef = useRef<HTMLInputElement>(null);
-  useLayoutEffect(() => {
-    inputRef.current?.focus();
-  }, []);
-  return (
-    <AnastasisClientFrame hideNav title="Add SMS authentication">
-      <div>
-        <p>
-          For SMS authentication, you need to provide a mobile number. When
-          recovering your secret, you will be asked to enter the code you
-          receive via SMS.
-        </p>
-        <label>
-          Mobile number:{" "}
-          <input
-            value={mobileNumber}
-            ref={inputRef}
-            style={{ display: "block" }}
-            autoFocus
-            onChange={(e) => setMobileNumber((e.target as any).value)}
-            type="text" />
-        </label>
-        <div>
-          <button onClick={() => props.cancel()}>Cancel</button>
-          <button onClick={() => addSmsAuth()}>Add</button>
-        </div>
-      </div>
-    </AnastasisClientFrame>
-  );
-}
diff --git a/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.stories.tsx
index 8f86831a9..5077c3eb0 100644
--- a/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.stories.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/camelcase */
 /*
  This file is part of GNU Taler
  (C) 2021 Taler Systems S.A.
@@ -19,6 +20,7 @@
 * @author Sebastian Javier Marchano (sebasjm)
 */
 
+import { ReducerState } from 'anastasis-core';
 import { createExample, reducerStatesExample } from '../../utils';
 import { AuthenticationEditorScreen as TestedComponent } from './AuthenticationEditorScreen';
 
@@ -36,3 +38,56 @@ export default {
 };
 
 export const Example = createExample(TestedComponent, reducerStatesExample.authEditing);
+export const OneAuthMethodConfigured = createExample(TestedComponent, {
+  ...reducerStatesExample.authEditing,
+  authentication_methods: [{
+    type: 'question',
+    instructions: 'what time is it?',
+    challenge: 'asd',
+  }]
+} as ReducerState);
+
+
+export const SomeMoreAuthMethodConfigured = createExample(TestedComponent, {
+  ...reducerStatesExample.authEditing,
+  authentication_methods: [{
+    type: 'question',
+    instructions: 'what time is it?',
+    challenge: 'asd',
+  },{
+    type: 'question',
+    instructions: 'what time is it?',
+    challenge: 'qwe',
+  },{
+    type: 'sms',
+    instructions: 'what time is it?',
+    challenge: 'asd',
+  },{
+    type: 'email',
+    instructions: 'what time is it?',
+    challenge: 'asd',
+  },{
+    type: 'email',
+    instructions: 'what time is it?',
+    challenge: 'asd',
+  },{
+    type: 'email',
+    instructions: 'what time is it?',
+    challenge: 'asd',
+  },{
+    type: 'email',
+    instructions: 'what time is it?',
+    challenge: 'asd',
+  }]
+} as ReducerState);
+
+export const NoAuthMethodProvided = createExample(TestedComponent, {
+  ...reducerStatesExample.authEditing,
+  authentication_providers: {},
+  authentication_methods: []
+} as ReducerState);
+
+  // type: string;
+  // instructions: string;
+  // challenge: string;
+  // mime_type?: string;
diff --git a/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx
index e9ffccbac..f4d2aee58 100644
--- a/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx
@@ -1,19 +1,19 @@
 /* eslint-disable @typescript-eslint/camelcase */
-import { AuthMethod, ReducerStateBackup } from "anastasis-core";
-import { h, VNode } from "preact";
+import { AuthMethod } from "anastasis-core";
+import { ComponentChildren, h, VNode } from "preact";
 import { useState } from "preact/hooks";
 import { useAnastasisContext } from "../../context/anastasis";
-import { AnastasisReducerApi } from "../../hooks/use-anastasis-reducer";
-import { AuthMethodEmailSetup } from "./AuthMethodEmailSetup";
-import { AuthMethodPostSetup } from "./AuthMethodPostSetup";
-import { AuthMethodQuestionSetup } from "./AuthMethodQuestionSetup";
-import { AuthMethodSmsSetup } from "./AuthMethodSmsSetup";
+import { authMethods, KnownAuthMethods } from "./authMethodSetup";
 import { AnastasisClientFrame } from "./index";
 
+
+
+const getKeys = Object.keys as <T extends object>(obj: T) => Array<keyof T>
+
 export function AuthenticationEditorScreen(): VNode {
-  const [selectedMethod, setSelectedMethod] = useState<string | undefined>(
-    undefined
-  );
+  const [noProvidersAck, setNoProvidersAck] = useState(false)
+  const [selectedMethod, setSelectedMethod] = useState<KnownAuthMethods | undefined>(undefined);
+
   const reducer = useAnastasisContext()
   if (!reducer) {
     return <div>no reducer in context</div>
@@ -21,7 +21,29 @@ export function AuthenticationEditorScreen(): VNode {
   if (!reducer.currentReducerState || reducer.currentReducerState.backup_state === undefined) {
     return <div>invalid state</div>
   }
+  const configuredAuthMethods: AuthMethod[] = reducer.currentReducerState.authentication_methods ?? [];
+  const haveMethodsConfigured = configuredAuthMethods.length > 0;
+
+  function removeByIndex(index: number): void {
+    if (reducer) reducer.transition("delete_authentication", {
+      authentication_method: index,
+    })
+  }
+
+  const camByType: { [s: string]: AuthMethodWithRemove[] } = {}
+  for (let index = 0; index < configuredAuthMethods.length; index++) {
+    const cam = {
+      ...configuredAuthMethods[index],
+      remove: () => removeByIndex(index)
+    }
+    const prevValue = camByType[cam.type] || []
+    prevValue.push(cam)
+    camByType[cam.type] = prevValue;
+  }
+
+
   const providers = reducer.currentReducerState.authentication_providers!;
+
   const authAvailableSet = new Set<string>();
   for (const provKey of Object.keys(providers)) {
     const p = providers[provKey];
@@ -31,79 +53,106 @@ export function AuthenticationEditorScreen(): VNode {
       }
     }
   }
+
   if (selectedMethod) {
     const cancel = (): void => setSelectedMethod(undefined);
     const addMethod = (args: any): void => {
       reducer.transition("add_authentication", args);
       setSelectedMethod(undefined);
     };
-    const methodMap: Record<
-      string, (props: AuthMethodSetupProps) => h.JSX.Element
-    > = {
-      sms: AuthMethodSmsSetup,
-      question: AuthMethodQuestionSetup,
-      email: AuthMethodEmailSetup,
-      post: AuthMethodPostSetup,
-    };
-    const AuthSetup = methodMap[selectedMethod] ?? AuthMethodNotImplemented;
+
+    const AuthSetup = authMethods[selectedMethod].screen ?? AuthMethodNotImplemented;
     return (
       <AuthSetup
         cancel={cancel}
+        configured={camByType[selectedMethod] || []}
         addAuthMethod={addMethod}
         method={selectedMethod} />
     );
   }
-  function MethodButton(props: { method: string; label: string }): VNode {
+  function MethodButton(props: { method: KnownAuthMethods }): VNode {
     return (
-      <button
-        disabled={!authAvailableSet.has(props.method)}
-        onClick={() => {
-          setSelectedMethod(props.method);
-          if (reducer) reducer.dismissError();
-        }}
-      >
-        {props.label}
-      </button>
+      <div class="block">
+        <button
+          style={{ justifyContent: 'space-between' }}
+          class="button is-fullwidth"
+          onClick={() => {
+            if (!authAvailableSet.has(props.method)) {
+              //open add sms dialog
+            } else {
+              setSelectedMethod(props.method);
+            }
+            if (reducer) reducer.dismissError();
+          }}
+        >
+          <div style={{ display: 'flex' }}>
+            <span class="icon ">
+              {authMethods[props.method].icon}
+            </span>
+            <span>
+              {authMethods[props.method].label}
+            </span>
+          </div>
+          {!authAvailableSet.has(props.method) &&
+            <span class="icon has-text-danger" >
+              <i class="mdi mdi-exclamation-thick" />
+            </span>
+          }
+          {camByType[props.method] &&
+            <span class="tag is-info" >
+              {camByType[props.method].length}
+            </span>
+          }
+        </button>
+      </div>
     );
   }
-  const configuredAuthMethods: AuthMethod[] = reducer.currentReducerState.authentication_methods ?? [];
-  const haveMethodsConfigured = configuredAuthMethods.length;
+  const errors = !haveMethodsConfigured ? "There is not enough authentication methods." : undefined;
   return (
-    <AnastasisClientFrame title="Backup: Configure Authentication Methods">
-      <div>
-        <MethodButton method="sms" label="SMS" />
-        <MethodButton method="email" label="Email" />
-        <MethodButton method="question" label="Question" />
-        <MethodButton method="post" label="Physical Mail" />
-        <MethodButton method="totp" label="TOTP" />
-        <MethodButton method="iban" label="IBAN" />
-      </div>
-      <h2>Configured authentication methods</h2>
-      {haveMethodsConfigured ? (
-        configuredAuthMethods.map((x, i) => {
-          return (
-            <p key={i}>
-              {x.type} ({x.instructions}){" "}
-              <button
-                onClick={() => reducer.transition("delete_authentication", {
-                  authentication_method: i,
-                })}
-              >
-                Delete
-              </button>
+    <AnastasisClientFrame title="Backup: Configure Authentication Methods" hideNext={errors}>
+      <div class="columns">
+        <div class="column is-half">
+          <div>
+            {getKeys(authMethods).map(method => <MethodButton key={method} method={method} />)}
+          </div>
+          {authAvailableSet.size === 0 && <ConfirmModal active={!noProvidersAck} onCancel={() => setNoProvidersAck(true)} description="No providers founds" label="Add a provider manually">
+            We have found no trusted cloud providers for your recovery secret. You can add a provider manually.
+            To add a provider you must know the provider URL (e.g. https://provider.com)
+            <p>
+              <a>More about cloud providers</a>
             </p>
-          );
-        })
-      ) : (
-        <p>No authentication methods configured yet.</p>
-      )}
+          </ConfirmModal>}
+
+          {/* {haveMethodsConfigured && (
+            configuredAuthMethods.map((x, i) => {
+              return (
+                <p key={i}>
+                  {x.type} ({x.instructions}){" "}
+                  <button class="button is-danger is-small"
+                    onClick={() => reducer.transition("delete_authentication", {
+                      authentication_method: i,
+                    })}
+                  >
+                    Remove
+                  </button>
+                </p>
+              );
+            })
+          )} */}
+        </div>
+        <div class="column is-half">
+          When recovering your wallet, you will be asked to verify your identity via the methods you configure here.
+        </div>
+      </div>
     </AnastasisClientFrame>
   );
 }
 
+type AuthMethodWithRemove = AuthMethod & { remove: () => void }
 export interface AuthMethodSetupProps {
   method: string;
   addAuthMethod: (x: any) => void;
+  configured: AuthMethodWithRemove[];
   cancel: () => void;
 }
 
@@ -116,8 +165,36 @@ function AuthMethodNotImplemented(props: AuthMethodSetupProps): VNode {
   );
 }
 
-interface AuthenticationEditorProps {
-  reducer: AnastasisReducerApi;
-  backupState: ReducerStateBackup;
+
+function ConfirmModal({ active, description, onCancel, onConfirm, children, danger, disabled, label = 'Confirm' }: Props): VNode {
+  return <div class={active ? "modal is-active" : "modal"}>
+    <div class="modal-background " onClick={onCancel} />
+    <div class="modal-card" style={{ maxWidth: 700 }}>
+      <header class="modal-card-head">
+        {!description ? null : <p class="modal-card-title"><b>{description}</b></p>}
+        <button class="delete " aria-label="close" onClick={onCancel} />
+      </header>
+      <section class="modal-card-body">
+        {children}
+      </section>
+      <footer class="modal-card-foot">
+        <button class="button" onClick={onCancel} >Dismiss</button>
+        <div class="buttons is-right" style={{ width: '100%' }}>
+          <button class={danger ? "button is-danger " : "button is-info "} disabled={disabled} onClick={onConfirm} >{label}</button>
+        </div>
+      </footer>
+    </div>
+    <button class="modal-close is-large " aria-label="close" onClick={onCancel} />
+  </div>
 }
 
+interface Props {
+  active?: boolean;
+  description?: string;
+  onCancel?: () => void;
+  onConfirm?: () => void;
+  label?: string;
+  children?: ComponentChildren;
+  danger?: boolean;
+  disabled?: boolean;
+}
diff --git a/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx
index 0c9d007bc..b71a79727 100644
--- a/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx
@@ -37,7 +37,7 @@ export default {
   },
 };
 
-export const Simple = createExample(TestedComponent, reducerStatesExample.backupFinished);
+export const WithoutName = createExample(TestedComponent, reducerStatesExample.backupFinished);
 
 export const WithName = createExample(TestedComponent, {...reducerStatesExample.backupFinished,
   secret_name: 'super_secret',
diff --git a/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.tsx b/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.tsx
index 218f1d1fd..70ac8157d 100644
--- a/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.tsx
@@ -1,3 +1,4 @@
+import { format } from "date-fns";
 import { h, VNode } from "preact";
 import { useAnastasisContext } from "../../context/anastasis";
 import { AnastasisClientFrame } from "./index";
@@ -11,23 +12,30 @@ export function BackupFinishedScreen(): VNode {
     return <div>invalid state</div>
   }
   const details = reducer.currentReducerState.success_details
-  return (<AnastasisClientFrame hideNext title="Backup finished">
-    <p>
-      Your backup of secret "{reducer.currentReducerState.secret_name ?? "??"}" was
+
+  return (<AnastasisClientFrame hideNav title="Backup finished">
+    {reducer.currentReducerState.secret_name ? <p>
+      Your backup of secret <b>"{reducer.currentReducerState.secret_name}"</b> was
       successful.
-    </p>
-    <p>The backup is stored by the following providers:</p>
+    </p> :
+      <p>
+        Your secret was successfully backed up.
+      </p>}
 
-    {details && <ul>
+    {details && <div class="block">
+    <p>The backup is stored by the following providers:</p>
       {Object.keys(details).map((x, i) => {
         const sd = details[x];
         return (
-          <li key={i}>
-            {x} (Policy version {sd.policy_version})
-          </li>
+          <div key={i} class="box">
+            {x}
+            <p>
+              version {sd.policy_version}
+              {sd.policy_expiration.t_ms !== 'never' ? ` expires at: ${format(sd.policy_expiration.t_ms, 'dd/MM/yyyy')}` : ' without expiration date'}
+            </p>
+          </div>
         );
       })}
-    </ul>}
-    <button onClick={() => reducer.reset()}>Back to start</button>
+    </div>}
   </AnastasisClientFrame>);
 }
diff --git a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx
index 3bb3fb837..cf44d5bf4 100644
--- a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx
@@ -47,8 +47,9 @@ export function ChallengeOverviewScreen(): VNode {
 
   const atLeastThereIsOnePolicySolved = policiesWithInfo.find(p => p.isPolicySolved) !== undefined
 
+  const errors = !atLeastThereIsOnePolicySolved ? "Solve one policy before proceeding" : undefined;
   return (
-    <AnastasisClientFrame hideNext={!atLeastThereIsOnePolicySolved} title="Recovery: Solve challenges">
+    <AnastasisClientFrame hideNext={errors} title="Recovery: Solve challenges">
       {!policies.length ? <p>
         No policies found, try with another version of the secret
       </p> : (policies.length === 1 ? <p>
diff --git a/packages/anastasis-webui/src/pages/home/ChallengePayingScreen.tsx b/packages/anastasis-webui/src/pages/home/ChallengePayingScreen.tsx
index d87afdf46..84896a2ec 100644
--- a/packages/anastasis-webui/src/pages/home/ChallengePayingScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/ChallengePayingScreen.tsx
@@ -13,7 +13,7 @@ export function ChallengePayingScreen(): VNode {
   const payments = ['']; //reducer.currentReducerState.payments ?? 
   return (
     <AnastasisClientFrame
-      hideNext
+      hideNav
       title="Recovery: Challenge Paying"
     >
       <p>
diff --git a/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx b/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx
index 94c0409da..713655625 100644
--- a/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx
@@ -1,20 +1,108 @@
+/* eslint-disable @typescript-eslint/camelcase */
+import { BackupStates, ContinentInfo, RecoveryStates } from "anastasis-core";
 import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
 import { useAnastasisContext } from "../../context/anastasis";
 import { AnastasisClientFrame, withProcessLabel } from "./index";
 
 export function ContinentSelectionScreen(): VNode {
   const reducer = useAnastasisContext()
+
+  //FIXME: remove this when #7056 is fixed
+  const [countryCode, setCountryCode] = useState("")
+
   if (!reducer || !reducer.currentReducerState || !("continents" in reducer.currentReducerState)) {
     return <div />
   }
-  const select = (continent: string) => (): void => reducer.transition("select_continent", { continent });
+  const selectContinent = (continent: string): void => {
+    reducer.transition("select_continent", { continent })
+  };
+  const selectCountry = (country: string): void => {
+    setCountryCode(country)
+  };
+  
+  
+  const continentList = reducer.currentReducerState.continents || [];
+  const countryList = reducer.currentReducerState.countries || [];
+  const theContinent = reducer.currentReducerState.selected_continent || ""
+  // const cc = reducer.currentReducerState.selected_country || "";
+  const theCountry = countryList.find(c => c.code === countryCode)
+  const selectCountryAction = () => {
+    //selection should be when the select box changes it value
+    if (!theCountry) return;
+    reducer.transition("select_country", {
+      country_code: countryCode,
+      currencies: [theCountry.currency],
+    })
+  }
+
+  const step1 = reducer.currentReducerState.backup_state === BackupStates.ContinentSelecting ||
+    reducer.currentReducerState.recovery_state === RecoveryStates.ContinentSelecting;
+
+  const errors = !theCountry ? "Select a country" : undefined 
+
   return (
-    <AnastasisClientFrame hideNext title={withProcessLabel(reducer, "Select Continent")}>
-      {reducer.currentReducerState.continents.map((x: any) => (
-        <button class="button" onClick={select(x.name)} key={x.name}>
-          {x.name}
-        </button>
-      ))}
+    <AnastasisClientFrame hideNext={errors} title={withProcessLabel(reducer, "Select location")} onNext={selectCountryAction}>
+      <div class="columns">
+        <div class="column is-half">
+          <div class="field">
+            <label class="label">Continent</label>
+            <div class="control has-icons-left">
+              <div class="select " >
+                <select onChange={(e) => selectContinent(e.currentTarget.value)} value={theContinent} disabled={!step1}>
+                  <option key="none" disabled selected value=""> Choose a continent </option>
+                  {continentList.map(prov => (
+                    <option key={prov.name} value={prov.name}>
+                      {prov.name}
+                    </option>
+                  ))}
+                </select>
+                <div class="icon is-small is-left">
+                  <i class="mdi mdi-earth" />
+                </div>
+              </div>
+              {!step1 && <span class="control">
+                <a class="button is-danger" onClick={() => reducer.back()}>
+                  X
+                </a>
+              </span>}
+            </div>
+          </div>
+
+          <div class="field">
+            <label class="label">Country</label>
+            <div class="control has-icons-left">
+              <div class="select" >
+                <select onChange={(e) => selectCountry((e.target as any).value)} disabled={!theContinent} value={theCountry?.code || ""}>
+                  <option key="none" disabled selected value=""> Choose a country </option>
+                  {countryList.map(prov => (
+                    <option key={prov.name} value={prov.code}>
+                      {prov.name}
+                    </option>
+                  ))}
+                </select>
+                <div class="icon is-small is-left">
+                  <i class="mdi mdi-earth" />
+                </div>
+              </div>
+            </div>
+          </div>
+
+          {theCountry && <div class="field">
+            <label class="label">Available currencies:</label>
+            <div class="control">
+              <input class="input is-small" type="text" readonly value={theCountry.currency} />
+            </div>
+          </div>}
+        </div>
+        <div class="column is-half">
+          <p>
+            A location will help to define a common information that will be use to locate your secret and a currency
+            for payments if needed.
+          </p>
+        </div>
+      </div>
+
     </AnastasisClientFrame>
   );
 }
diff --git a/packages/anastasis-webui/src/pages/home/CountrySelectionScreen.tsx b/packages/anastasis-webui/src/pages/home/CountrySelectionScreen.tsx
index 417c08633..77329f4fa 100644
--- a/packages/anastasis-webui/src/pages/home/CountrySelectionScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/CountrySelectionScreen.tsx
@@ -18,7 +18,7 @@ export function CountrySelectionScreen(): VNode {
   return (
     <AnastasisClientFrame hideNext title={withProcessLabel(reducer, "Select Country")} >
       <div style={{ display: 'flex', flexDirection: 'column' }}>
-        {reducer.currentReducerState.countries.map((x: any) => (
+        {reducer.currentReducerState.countries!.map((x: any) => (
           <div key={x.name}>
             <button class="button" onClick={() => sel(x)} >
               {x.name} ({x.currency})
diff --git a/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.tsx b/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.tsx
index 8a39cf0e4..a470f5155 100644
--- a/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.tsx
@@ -13,7 +13,7 @@ export function PoliciesPayingScreen(): VNode {
   const payments = reducer.currentReducerState.policy_payment_requests ?? [];
   
   return (
-    <AnastasisClientFrame hideNext title="Backup: Recovery Document Payments">
+    <AnastasisClientFrame hideNav title="Backup: Recovery Document Payments">
       <p>
         Some of the providers require a payment to store the encrypted
         recovery document.
diff --git a/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx b/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx
index 8c8a2c7c8..bbcaa10a5 100644
--- a/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx
@@ -17,7 +17,7 @@ export function RecoveryFinishedScreen(): VNode {
   }
   const encodedSecret = reducer.currentReducerState.core_secret?.value
   if (!encodedSecret) {
-    return <AnastasisClientFrame title="Recovery Problem" hideNext>
+    return <AnastasisClientFrame title="Recovery Problem" hideNav>
       <p>
         Secret not found
       </p>
@@ -25,7 +25,7 @@ export function RecoveryFinishedScreen(): VNode {
   }
   const secret = bytesToString(decodeCrock(encodedSecret))
   return (
-    <AnastasisClientFrame title="Recovery Finished" hideNext>
+    <AnastasisClientFrame title="Recovery Finished" hideNav>
       <p>
         Secret: {secret}
       </p>
diff --git a/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.stories.tsx
index 91855b023..007011326 100644
--- a/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.stories.tsx
@@ -43,11 +43,11 @@ export const HasPoliciesButMethodListIsEmpty = createExample(TestedComponent, {
     methods: [{
       authentication_method: 0,
       provider: 'asd'
-    },{
+    }, {
       authentication_method: 1,
       provider: 'asd'
     }]
-  },{
+  }, {
     methods: [{
       authentication_method: 1,
       provider: 'asd'
@@ -58,27 +58,191 @@ export const HasPoliciesButMethodListIsEmpty = createExample(TestedComponent, {
 
 export const SomePoliciesWithMethods = createExample(TestedComponent, {
   ...reducerStatesExample.policyReview,
-  policies: [{
-    methods: [{
-      authentication_method: 0,
-      provider: 'asd'
-    },{
-      authentication_method: 1,
-      provider: 'asd'
-    }]
-  },{
-    methods: [{
-      authentication_method: 1,
-      provider: 'asd'
-    }]
-  }],
+  policies: [
+    {
+      methods: [
+        {
+          authentication_method: 0,
+          provider: "https://kudos.demo.anastasis.lu/"
+        },
+        {
+          authentication_method: 1,
+          provider: "https://kudos.demo.anastasis.lu/"
+        },
+        {
+          authentication_method: 2,
+          provider: "https://kudos.demo.anastasis.lu/"
+        }
+      ]
+    },
+    {
+      methods: [
+        {
+          authentication_method: 0,
+          provider: "https://kudos.demo.anastasis.lu/"
+        },
+        {
+          authentication_method: 1,
+          provider: "https://kudos.demo.anastasis.lu/"
+        },
+        {
+          authentication_method: 3,
+          provider: "https://anastasis.demo.taler.net/"
+        }
+      ]
+    },
+    {
+      methods: [
+        {
+          authentication_method: 0,
+          provider: "https://kudos.demo.anastasis.lu/"
+        },
+        {
+          authentication_method: 1,
+          provider: "https://kudos.demo.anastasis.lu/"
+        },
+        {
+          authentication_method: 4,
+          provider: "https://anastasis.demo.taler.net/"
+        }
+      ]
+    },
+    {
+      methods: [
+        {
+          authentication_method: 0,
+          provider: "https://kudos.demo.anastasis.lu/"
+        },
+        {
+          authentication_method: 2,
+          provider: "https://kudos.demo.anastasis.lu/"
+        },
+        {
+          authentication_method: 3,
+          provider: "https://anastasis.demo.taler.net/"
+        }
+      ]
+    },
+    {
+      methods: [
+        {
+          authentication_method: 0,
+          provider: "https://kudos.demo.anastasis.lu/"
+        },
+        {
+          authentication_method: 2,
+          provider: "https://kudos.demo.anastasis.lu/"
+        },
+        {
+          authentication_method: 4,
+          provider: "https://anastasis.demo.taler.net/"
+        }
+      ]
+    },
+    {
+      methods: [
+        {
+          authentication_method: 0,
+          provider: "https://kudos.demo.anastasis.lu/"
+        },
+        {
+          authentication_method: 3,
+          provider: "https://anastasis.demo.taler.net/"
+        },
+        {
+          authentication_method: 4,
+          provider: "https://anastasis.demo.taler.net/"
+        }
+      ]
+    },
+    {
+      methods: [
+        {
+          authentication_method: 1,
+          provider: "https://kudos.demo.anastasis.lu/"
+        },
+        {
+          authentication_method: 2,
+          provider: "https://kudos.demo.anastasis.lu/"
+        },
+        {
+          authentication_method: 3,
+          provider: "https://anastasis.demo.taler.net/"
+        }
+      ]
+    },
+    {
+      methods: [
+        {
+          authentication_method: 1,
+          provider: "https://kudos.demo.anastasis.lu/"
+        },
+        {
+          authentication_method: 2,
+          provider: "https://kudos.demo.anastasis.lu/"
+        },
+        {
+          authentication_method: 4,
+          provider: "https://anastasis.demo.taler.net/"
+        }
+      ]
+    },
+    {
+      methods: [
+        {
+          authentication_method: 1,
+          provider: "https://kudos.demo.anastasis.lu/"
+        },
+        {
+          authentication_method: 3,
+          provider: "https://anastasis.demo.taler.net/"
+        },
+        {
+          authentication_method: 4,
+          provider: "https://anastasis.demo.taler.net/"
+        }
+      ]
+    },
+    {
+      methods: [
+        {
+          authentication_method: 2,
+          provider: "https://kudos.demo.anastasis.lu/"
+        },
+        {
+          authentication_method: 3,
+          provider: "https://anastasis.demo.taler.net/"
+        },
+        {
+          authentication_method: 4,
+          provider: "https://anastasis.demo.taler.net/"
+        }
+      ]
+    }
+  ],
   authentication_methods: [{
-    challenge: 'asd',
-    instructions: 'ins',
-    type: 'type',
+    type: "email",
+    instructions: "Email to qwe@asd.com",
+    challenge: "E5VPA"
+  }, {
+    type: "sms",
+    instructions: "SMS to 555-555",
+    challenge: ""
+  }, {
+    type: "question",
+    instructions: "Does P equal NP?",
+    challenge: "C5SP8"
   },{
-    challenge: 'asd2',
-    instructions: 'ins2',
-    type: 'type2',
+    type: "email",
+    instructions: "Email to qwe@asd.com",
+    challenge: "E5VPA"
+  }, {
+    type: "sms",
+    instructions: "SMS to 555-555",
+    challenge: ""
+  }, {
+    type: "question",
+    instructions: "Does P equal NP?",
+    challenge: "C5SP8"
   }]
 } as ReducerState);
diff --git a/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx
index b360ccaf0..6d5220a05 100644
--- a/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx
@@ -2,6 +2,7 @@
 import { h, VNode } from "preact";
 import { useAnastasisContext } from "../../context/anastasis";
 import { AnastasisClientFrame } from "./index";
+import { authMethods, KnownAuthMethods } from "./authMethodSetup";
 
 export function ReviewPoliciesScreen(): VNode {
   const reducer = useAnastasisContext()
@@ -11,43 +12,50 @@ export function ReviewPoliciesScreen(): VNode {
   if (!reducer.currentReducerState || reducer.currentReducerState.backup_state === undefined) {
     return <div>invalid state</div>
   }
-  const authMethods = reducer.currentReducerState.authentication_methods ?? [];
+  const configuredAuthMethods = reducer.currentReducerState.authentication_methods ?? [];
   const policies = reducer.currentReducerState.policies ?? [];
 
+  const errors = policies.length < 1 ? 'Need more policies' : undefined
   return (
-    <AnastasisClientFrame title="Backup: Review Recovery Policies">
+    <AnastasisClientFrame hideNext={errors} title="Backup: Review Recovery Policies">
+      {policies.length > 0 && <p class="block">
+        Based on your configured authentication method you have created, some policies
+        have been configured. In order to recover your secret you have to solve all the 
+        challenges of at least one policy.
+      </p> }
+      {policies.length < 1 && <p class="block">
+        No policies had been created. Go back and add more authentication methods.
+      </p> }
       {policies.map((p, policy_index) => {
         const methods = p.methods
-          .map(x => authMethods[x.authentication_method] && ({ ...authMethods[x.authentication_method], provider: x.provider }))
+          .map(x => configuredAuthMethods[x.authentication_method] && ({ ...configuredAuthMethods[x.authentication_method], provider: x.provider }))
           .filter(x => !!x)
 
         const policyName = methods.map(x => x.type).join(" + ");
 
         return (
-          <div key={policy_index} class="policy">
-            <h3>
-              Policy #{policy_index + 1}: {policyName}
-            </h3>
-            Required Authentications:
-            {!methods.length && <p>
-              No auth method found
-            </p>}
-            <ul>
+          <div key={policy_index} class="box" style={{ display: 'flex', justifyContent: 'space-between' }}>
+            <div>
+              <h3 class="subtitle">
+                Policy #{policy_index + 1}: {policyName}
+              </h3>
+              {!methods.length && <p>
+                No auth method found
+              </p>}
               {methods.map((m, i) => {
                 return (
-                  <li key={i}>
-                    {m.type} ({m.instructions}) at provider {m.provider}
-                  </li>
+                  <p key={i} class="block" style={{display:'flex', alignItems:'center'}}>
+                      <span class="icon">
+                        {authMethods[m.type as KnownAuthMethods]?.icon}
+                      </span>
+                      <span>
+                        {m.instructions} recovery provided by <a href={m.provider}>{m.provider}</a>
+                      </span>
+                    </p>
                 );
               })}
-            </ul>
-            <div>
-              <button
-                onClick={() => reducer.transition("delete_policy", { policy_index })}
-              >
-                Delete Policy
-              </button>
             </div>
+            <div style={{ marginTop: 'auto', marginBottom: 'auto' }}><button class="button is-danger" onClick={() => reducer.transition("delete_policy", { policy_index })}>Delete</button></div>
           </div>
         );
       })}
diff --git a/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx b/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx
index 79a46761c..915465c3f 100644
--- a/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx
@@ -6,6 +6,7 @@ import { useAnastasisContext } from "../../context/anastasis";
 import {
   AnastasisClientFrame} from "./index";
 import { TextInput } from "../../components/fields/TextInput";
+import { FileInput } from "../../components/fields/FileInput";
 
 export function SecretEditorScreen(): VNode {
   const reducer = useAnastasisContext()
@@ -57,6 +58,10 @@ export function SecretEditorScreen(): VNode {
         <TextInput
           label="Secret Value:"
           bind={[secretValue, setSecretValue]}
+        /> or import a file
+        <FileInput 
+          label="Open file from your device"
+          bind={[secretValue, setSecretValue]}
         />
       </div>
     </AnastasisClientFrame>
diff --git a/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx b/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx
index 5d67ee472..d0b83bda5 100644
--- a/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx
@@ -37,7 +37,7 @@ export function SecretSelectionScreen(): VNode {
   const recoveryDocument = reducer.currentReducerState.recovery_document
   if (!recoveryDocument) {
     return (
-      <AnastasisClientFrame hideNext title="Recovery: Problem">
+      <AnastasisClientFrame hideNext="Recovery document not found" title="Recovery: Problem">
         <p>No recovery document found, try with another provider</p>
         <table class="table">
           <tr>
diff --git a/packages/anastasis-webui/src/pages/home/SolveScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/SolveScreen.stories.tsx
index c05c36b07..cb6561b3f 100644
--- a/packages/anastasis-webui/src/pages/home/SolveScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/SolveScreen.stories.tsx
@@ -44,7 +44,7 @@ export const NotSupportedChallenge = createExample(TestedComponent, {
   recovery_information: {
     challenges: [{
       cost: 'USD:1',
-      instructions: 'follow htis instructions',
+      instructions: 'does P equals NP?',
       type: 'chall-type',
       uuid: 'ASDASDSAD!1'
     }],
@@ -58,7 +58,7 @@ export const MismatchedChallengeId = createExample(TestedComponent, {
   recovery_information: {
     challenges: [{
       cost: 'USD:1',
-      instructions: 'follow htis instructions',
+      instructions: 'does P equals NP?',
       type: 'chall-type',
       uuid: 'ASDASDSAD!1'
     }],
@@ -72,7 +72,7 @@ export const SmsChallenge = createExample(TestedComponent, {
   recovery_information: {
     challenges: [{
       cost: 'USD:1',
-      instructions: 'follow htis instructions',
+      instructions: 'SMS to 555-5555',
       type: 'sms',
       uuid: 'ASDASDSAD!1'
     }],
@@ -86,7 +86,7 @@ export const QuestionChallenge = createExample(TestedComponent, {
   recovery_information: {
     challenges: [{
       cost: 'USD:1',
-      instructions: 'follow htis instructions',
+      instructions: 'does P equals NP?',
       type: 'question',
       uuid: 'ASDASDSAD!1'
     }],
@@ -100,7 +100,7 @@ export const EmailChallenge = createExample(TestedComponent, {
   recovery_information: {
     challenges: [{
       cost: 'USD:1',
-      instructions: 'follow htis instructions',
+      instructions: 'Email to sebasjm@some-domain.com',
       type: 'email',
       uuid: 'ASDASDSAD!1'
     }],
@@ -114,7 +114,7 @@ export const PostChallenge = createExample(TestedComponent, {
   recovery_information: {
     challenges: [{
       cost: 'USD:1',
-      instructions: 'follow htis instructions',
+      instructions: 'Letter to address in postal code ABC123',
       type: 'post',
       uuid: 'ASDASDSAD!1'
     }],
diff --git a/packages/anastasis-webui/src/pages/home/SolveScreen.tsx b/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
index 077726e02..b0cfa9bb0 100644
--- a/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
@@ -8,26 +8,26 @@ import { useAnastasisContext } from "../../context/anastasis";
 export function SolveScreen(): VNode {
   const reducer = useAnastasisContext()
   const [answer, setAnswer] = useState("");
-  
+
   if (!reducer) {
-    return <AnastasisClientFrame hideNext title="Recovery problem">
+    return <AnastasisClientFrame hideNav title="Recovery problem">
       <div>no reducer in context</div>
     </AnastasisClientFrame>
   }
   if (!reducer.currentReducerState || reducer.currentReducerState.recovery_state === undefined) {
-    return <AnastasisClientFrame hideNext title="Recovery problem">
+    return <AnastasisClientFrame hideNav title="Recovery problem">
       <div>invalid state</div>
     </AnastasisClientFrame>
   }
 
   if (!reducer.currentReducerState.recovery_information) {
-    return <AnastasisClientFrame hideNext title="Recovery problem">
+    return <AnastasisClientFrame hideNext="Recovery document not found" title="Recovery problem">
       <div>no recovery information found</div>
     </AnastasisClientFrame>
   }
   if (!reducer.currentReducerState.selected_challenge_uuid) {
-    return <AnastasisClientFrame hideNext title="Recovery problem">
-      <div>no selected uuid</div>
+    return <AnastasisClientFrame hideNav title="Recovery problem">
+      <div>invalid state</div>
     </AnastasisClientFrame>
   }
 
@@ -55,7 +55,7 @@ export function SolveScreen(): VNode {
   function onCancel(): void {
     reducer?.back()
   }
-  
+
 
   return (
     <AnastasisClientFrame
@@ -70,9 +70,9 @@ export function SolveScreen(): VNode {
         feedback={challengeFeedback[selectedUuid]} />
 
       <div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
-          <button class="button" onClick={onCancel}>Cancel</button>
-          <button class="button is-info" onClick={onNext} >Confirm</button>
-        </div>
+        <button class="button" onClick={onCancel}>Cancel</button>
+        <button class="button is-info" onClick={onNext} >Confirm</button>
+      </div>
     </AnastasisClientFrame>
   );
 }
@@ -82,13 +82,13 @@ export interface SolveEntryProps {
   challenge: ChallengeInfo;
   feedback?: ChallengeFeedback;
   answer: string;
-  setAnswer: (s:string) => void;
+  setAnswer: (s: string) => void;
 }
 
 function SolveSmsEntry({ challenge, answer, setAnswer }: SolveEntryProps): VNode {
   return (<Fragment>
-      <p>An sms has been sent to "<b>{challenge.instructions}</b>". Type the code below</p>
-      <TextInput label="Answer" grabFocus bind={[answer, setAnswer]} />
+    <p>An sms has been sent to "<b>{challenge.instructions}</b>". Type the code below</p>
+    <TextInput label="Answer" grabFocus bind={[answer, setAnswer]} />
   </Fragment>
   );
 }
diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodEmailSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodEmailSetup.stories.tsx
new file mode 100644
index 000000000..e178a4955
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodEmailSetup.stories.tsx
@@ -0,0 +1,66 @@
+/* eslint-disable @typescript-eslint/camelcase */
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { createExample, reducerStatesExample } from '../../../utils';
+import { authMethods as TestedComponent, KnownAuthMethods } from './index';
+
+
+export default {
+  title: 'Pages/backup/authMethods/email',
+  component: TestedComponent,
+  args: {
+    order: 5,
+  },
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+const type: KnownAuthMethods = 'email'
+
+export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: []
+});
+
+export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: [{
+    challenge: 'qwe',
+    type,
+    instructions: 'Email to sebasjm@email.com ',
+    remove: () => null
+  }]
+});
+
+export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: [{
+    challenge: 'qwe',
+    type,
+    instructions: 'Email to sebasjm@email.com',
+    remove: () => null
+  },{
+    challenge: 'qwe',
+    type,
+    instructions: 'Email to someone@sebasjm.com',
+    remove: () => null
+  }]
+});
diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodEmailSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodEmailSetup.tsx
new file mode 100644
index 000000000..e8cee9cb4
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodEmailSetup.tsx
@@ -0,0 +1,62 @@
+/* eslint-disable @typescript-eslint/camelcase */
+import {
+  encodeCrock,
+  stringToBytes
+} from "@gnu-taler/taler-util";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { AuthMethodSetupProps } from "../AuthenticationEditorScreen";
+import { AnastasisClientFrame } from "../index";
+import { TextInput } from "../../../components/fields/TextInput";
+import { EmailInput } from "../../../components/fields/EmailInput";
+
+const EMAIL_PATTERN = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
+
+export function AuthMethodEmailSetup({ cancel, addAuthMethod, configured }: AuthMethodSetupProps): VNode {
+  const [email, setEmail] = useState("");
+  const addEmailAuth = (): void => addAuthMethod({
+    authentication_method: {
+      type: "email",
+      instructions: `Email to ${email}`,
+      challenge: encodeCrock(stringToBytes(email)),
+    },
+  });
+  const emailError = !EMAIL_PATTERN.test(email) ? 'Email address is not valid' : undefined
+  const errors = !email ? 'Add your email' : emailError
+
+  return (
+    <AnastasisClientFrame hideNav title="Add email authentication">
+      <p>
+        For email authentication, you need to provide an email address. When
+        recovering your secret, you will need to enter the code you receive by
+        email.
+      </p>
+      <div>
+        <EmailInput
+          label="Email address"
+          error={emailError}
+          placeholder="email@domain.com"
+          bind={[email, setEmail]} />
+      </div>
+      {configured.length > 0 && <section class="section">
+        <div class="block">
+          Your emails:
+        </div><div class="block">
+          {configured.map((c, i) => {
+            return <div key={i} class="box" style={{ display: 'flex', justifyContent: 'space-between' }}>
+              <p style={{ marginBottom: 'auto', marginTop: 'auto' }}>{c.instructions}</p>
+              <div><button class="button is-danger" onClick={c.remove} >Delete</button></div>
+            </div>
+          })}
+        </div></section>}
+      <div>
+        <div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
+          <button class="button" onClick={cancel}>Canceul</button>
+          <span data-tooltip={errors}>
+            <button class="button is-info" disabled={errors !== undefined} onClick={addEmailAuth}>Add</button>
+          </span>
+        </div>
+      </div>
+    </AnastasisClientFrame>
+  );
+}
diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodIbanSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodIbanSetup.stories.tsx
new file mode 100644
index 000000000..71f618646
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodIbanSetup.stories.tsx
@@ -0,0 +1,65 @@
+/* eslint-disable @typescript-eslint/camelcase */
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { createExample, reducerStatesExample } from '../../../utils';
+import { authMethods as TestedComponent, KnownAuthMethods } from './index';
+
+
+export default {
+  title: 'Pages/backup/authMethods/IBAN',
+  component: TestedComponent,
+  args: {
+    order: 5,
+  },
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+const type: KnownAuthMethods = 'iban'
+
+export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: []
+});
+
+export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: [{
+    challenge: 'qwe',
+    type,
+    instructions: 'Wire transfer from QWEASD123123 with holder Sebastian',
+    remove: () => null
+  }]
+});
+export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: [{
+    challenge: 'qwe',
+    type,
+    instructions: 'Wire transfer from QWEASD123123 with holder Javier',
+    remove: () => null
+  },{
+    challenge: 'qwe',
+    type,
+    instructions: 'Wire transfer from QWEASD123123 with holder Sebastian',
+    remove: () => null
+  }]
+},);
diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodIbanSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodIbanSetup.tsx
new file mode 100644
index 000000000..c9edbfa07
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodIbanSetup.tsx
@@ -0,0 +1,68 @@
+/* eslint-disable @typescript-eslint/camelcase */
+import {
+  canonicalJson,
+  encodeCrock,
+  stringToBytes
+} from "@gnu-taler/taler-util";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { TextInput } from "../../../components/fields/TextInput";
+import { AuthMethodSetupProps } from "../AuthenticationEditorScreen";
+import { AnastasisClientFrame } from "../index";
+
+export function AuthMethodIbanSetup({ addAuthMethod, cancel, configured }: AuthMethodSetupProps): VNode {
+  const [name, setName] = useState("");
+  const [account, setAccount] = useState("");
+  const addIbanAuth = (): void => addAuthMethod({
+    authentication_method: {
+      type: "iban",
+      instructions: `Wire transfer from ${account} with holder ${name}`,
+      challenge: encodeCrock(stringToBytes(canonicalJson({
+        name, account
+      }))),
+    },
+  });
+  const errors = !name ? 'Add an account name' : (
+    !account ? 'Add an account IBAN number' : undefined
+  )
+  return (
+    <AnastasisClientFrame hideNav title="Add bank transfer authentication">
+      <p>
+        For bank transfer authentication, you need to provide a bank
+        account (account holder name and IBAN). When recovering your
+        secret, you will be asked to pay the recovery fee via bank
+        transfer from the account you provided here.
+      </p>
+      <div>
+        <TextInput
+          label="Bank account holder name"
+          grabFocus
+          placeholder="John Smith"
+          bind={[name, setName]} />
+        <TextInput
+          label="IBAN"
+          placeholder="DE91100000000123456789"
+          bind={[account, setAccount]} />
+      </div>
+      {configured.length > 0 && <section class="section">
+        <div class="block">
+          Your bank accounts:
+        </div><div class="block">
+          {configured.map((c, i) => {
+            return <div key={i} class="box" style={{ display: 'flex', justifyContent: 'space-between' }}>
+              <p style={{ marginBottom: 'auto', marginTop: 'auto' }}>{c.instructions}</p>
+              <div><button class="button is-danger" onClick={c.remove} >Delete</button></div>
+            </div>
+          })}
+        </div></section>}
+      <div>
+        <div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
+          <button class="button" onClick={cancel}>Cancel</button>
+          <span data-tooltip={errors}>
+            <button class="button is-info" disabled={errors !== undefined} onClick={addIbanAuth}>Add</button>
+          </span>
+        </div>
+      </div>
+    </AnastasisClientFrame>
+  );
+}
diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodPostSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodPostSetup.stories.tsx
new file mode 100644
index 000000000..0f1c17495
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodPostSetup.stories.tsx
@@ -0,0 +1,66 @@
+/* eslint-disable @typescript-eslint/camelcase */
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { createExample, reducerStatesExample } from '../../../utils';
+import { authMethods as TestedComponent, KnownAuthMethods } from './index';
+
+
+export default {
+  title: 'Pages/backup/authMethods/Post',
+  component: TestedComponent,
+  args: {
+    order: 5,
+  },
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+const type: KnownAuthMethods = 'post'
+
+export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: []
+});
+
+export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: [{
+    challenge: 'qwe',
+    type,
+    instructions: 'Letter to address in postal code QWE456',
+    remove: () => null
+  }]
+});
+
+export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: [{
+    challenge: 'qwe',
+    type,
+    instructions: 'Letter to address in postal code QWE456',
+    remove: () => null
+  },{
+    challenge: 'qwe',
+    type,
+    instructions: 'Letter to address in postal code ABC123',
+    remove: () => null
+  }]
+});
diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodPostSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodPostSetup.tsx
new file mode 100644
index 000000000..bfeaaa832
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodPostSetup.tsx
@@ -0,0 +1,102 @@
+/* eslint-disable @typescript-eslint/camelcase */
+import {
+  canonicalJson, encodeCrock,
+  stringToBytes
+} from "@gnu-taler/taler-util";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { AuthMethodSetupProps } from "../AuthenticationEditorScreen";
+import { TextInput } from "../../../components/fields/TextInput";
+import { AnastasisClientFrame } from "..";
+
+export function AuthMethodPostSetup({ addAuthMethod, cancel, configured }: AuthMethodSetupProps): VNode {
+  const [fullName, setFullName] = useState("");
+  const [street, setStreet] = useState("");
+  const [city, setCity] = useState("");
+  const [postcode, setPostcode] = useState("");
+  const [country, setCountry] = useState("");
+
+  const addPostAuth = () => {
+    const challengeJson = {
+      full_name: fullName,
+      street,
+      city,
+      postcode,
+      country,
+    };
+    addAuthMethod({
+      authentication_method: {
+        type: "post",
+        instructions: `Letter to address in postal code ${postcode}`,
+        challenge: encodeCrock(stringToBytes(canonicalJson(challengeJson))),
+      },
+    });
+  };
+
+  const errors = !fullName ? 'The full name is missing' : (
+    !street ? 'The street is missing' : (
+      !city ? 'The city is missing' : (
+        !postcode ? 'The postcode is missing' : (
+          !country ? 'The country is missing' : undefined
+        )
+      )
+    )
+  )
+  return (
+    <AnastasisClientFrame hideNav title="Add postal authentication">
+      <p>
+        For postal letter authentication, you need to provide a postal
+        address. When recovering your secret, you will be asked to enter a
+        code that you will receive in a letter to that address.
+      </p>
+      <div>
+        <TextInput
+          grabFocus
+          label="Full Name"
+          bind={[fullName, setFullName]}
+        />
+      </div>
+      <div>
+        <TextInput
+          label="Street"
+          bind={[street, setStreet]}
+        />
+      </div>
+      <div>
+        <TextInput
+          label="City" bind={[city, setCity]}
+        />
+      </div>
+      <div>
+        <TextInput
+          label="Postal Code" bind={[postcode, setPostcode]}
+        />
+      </div>
+      <div>
+        <TextInput
+          label="Country"
+          bind={[country, setCountry]}
+        />
+      </div>
+
+      {configured.length > 0 && <section class="section">
+        <div class="block">
+          Your postal code:
+        </div><div class="block">
+          {configured.map((c, i) => {
+            return <div key={i} class="box" style={{ display: 'flex', justifyContent: 'space-between' }}>
+              <p style={{ marginBottom: 'auto', marginTop: 'auto' }}>{c.instructions}</p>
+              <div><button class="button is-danger" onClick={c.remove} >Delete</button></div>
+            </div>
+          })}
+        </div>
+      </section>}
+      <div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
+        <button class="button" onClick={cancel}>Cancel</button>
+        <span data-tooltip={errors}>
+          <button class="button is-info" disabled={errors !== undefined} onClick={addPostAuth}>Add</button>
+        </span>
+      </div>
+    </AnastasisClientFrame>
+  );
+}
diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodQuestionSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodQuestionSetup.stories.tsx
new file mode 100644
index 000000000..3ba4a84ca
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodQuestionSetup.stories.tsx
@@ -0,0 +1,66 @@
+/* eslint-disable @typescript-eslint/camelcase */
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { createExample, reducerStatesExample } from '../../../utils';
+import { authMethods as TestedComponent, KnownAuthMethods } from './index';
+
+
+export default {
+  title: 'Pages/backup/authMethods/Question',
+  component: TestedComponent,
+  args: {
+    order: 5,
+  },
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+const type: KnownAuthMethods = 'question'
+
+export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: []
+});
+
+export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: [{
+    challenge: 'qwe',
+    type,
+    instructions: 'Is integer factorization polynomial? (non-quantum computer)',
+    remove: () => null
+  }]
+});
+
+export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: [{
+    challenge: 'qwe',
+    type,
+    instructions: 'Does P equal NP?',
+    remove: () => null
+  },{
+    challenge: 'asd',
+    type,
+    instructions: 'Are continuous groups automatically differential groups?',
+    remove: () => null
+  }]
+});
diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodQuestionSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodQuestionSetup.tsx
new file mode 100644
index 000000000..eab800e35
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodQuestionSetup.tsx
@@ -0,0 +1,70 @@
+/* eslint-disable @typescript-eslint/camelcase */
+import {
+  encodeCrock,
+  stringToBytes
+} from "@gnu-taler/taler-util";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { AuthMethodSetupProps } from "../AuthenticationEditorScreen";
+import { AnastasisClientFrame } from "../index";
+import { TextInput } from "../../../components/fields/TextInput";
+
+export function AuthMethodQuestionSetup({ cancel, addAuthMethod, configured }: AuthMethodSetupProps): VNode {
+  const [questionText, setQuestionText] = useState("");
+  const [answerText, setAnswerText] = useState("");
+  const addQuestionAuth = (): void => addAuthMethod({
+    authentication_method: {
+      type: "question",
+      instructions: questionText,
+      challenge: encodeCrock(stringToBytes(answerText)),
+    },
+  });
+
+  const errors = !questionText ? "Add your security question" : (
+    !answerText ? 'Add the answer to your question' : undefined
+  )
+  return (
+    <AnastasisClientFrame hideNav title="Add Security Question">
+      <div>
+        <p>
+          For security question authentication, you need to provide a question
+          and its answer. When recovering your secret, you will be shown the
+          question and you will need to type the answer exactly as you typed it
+          here.
+        </p>
+        <div>
+          <TextInput
+            label="Security question"
+            grabFocus
+            placeholder="Your question"
+            bind={[questionText, setQuestionText]} />
+        </div>
+        <div>
+          <TextInput
+            label="Answer"
+            placeholder="Your answer"
+            bind={[answerText, setAnswerText]}
+          />
+        </div>
+
+        {configured.length > 0 && <section class="section">
+          <div class="block">
+            Your security questions:
+          </div><div class="block">
+            {configured.map((c, i) => {
+              return <div key={i} class="box" style={{ display: 'flex', justifyContent: 'space-between' }}>
+                <p style={{ marginBottom: 'auto', marginTop: 'auto' }}>{c.instructions}</p>
+                <div><button class="button is-danger" onClick={c.remove} >Delete</button></div>
+              </div>
+            })}
+          </div></section>}
+        <div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
+          <button class="button" onClick={cancel}>Cancel</button>
+          <span data-tooltip={errors}>
+            <button class="button is-info" disabled={errors !== undefined} onClick={addQuestionAuth}>Add</button>
+          </span>
+        </div>
+      </div>
+    </AnastasisClientFrame >
+  );
+}
diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodSmsSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodSmsSetup.stories.tsx
new file mode 100644
index 000000000..ae8297ef7
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodSmsSetup.stories.tsx
@@ -0,0 +1,66 @@
+/* eslint-disable @typescript-eslint/camelcase */
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { createExample, reducerStatesExample } from '../../../utils';
+import { authMethods as TestedComponent, KnownAuthMethods } from './index';
+
+
+export default {
+  title: 'Pages/backup/authMethods/Sms',
+  component: TestedComponent,
+  args: {
+    order: 5,
+  },
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+const type: KnownAuthMethods = 'sms'
+
+export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: []
+});
+
+export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: [{
+    challenge: 'qwe',
+    type,
+    instructions: 'SMS to +11-1234-2345',
+    remove: () => null
+  }]
+});
+
+export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: [{
+    challenge: 'qwe',
+    type,
+    instructions: 'SMS to +11-1234-2345',
+    remove: () => null
+  },{
+    challenge: 'qwe',
+    type,
+    instructions: 'SMS to +11-5555-2345',
+    remove: () => null
+  }]
+});
diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodSmsSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodSmsSetup.tsx
new file mode 100644
index 000000000..9e85af2b2
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodSmsSetup.tsx
@@ -0,0 +1,63 @@
+/* eslint-disable @typescript-eslint/camelcase */
+import {
+  encodeCrock,
+  stringToBytes
+} from "@gnu-taler/taler-util";
+import { Fragment, h, VNode } from "preact";
+import { useLayoutEffect, useRef, useState } from "preact/hooks";
+import { NumberInput } from "../../../components/fields/NumberInput";
+import { AuthMethodSetupProps } from "../AuthenticationEditorScreen";
+import { AnastasisClientFrame } from "../index";
+
+export function AuthMethodSmsSetup({ addAuthMethod, cancel, configured }: AuthMethodSetupProps): VNode {
+  const [mobileNumber, setMobileNumber] = useState("");
+  const addSmsAuth = (): void => {
+    addAuthMethod({
+      authentication_method: {
+        type: "sms",
+        instructions: `SMS to ${mobileNumber}`,
+        challenge: encodeCrock(stringToBytes(mobileNumber)),
+      },
+    });
+  };
+  const inputRef = useRef<HTMLInputElement>(null);
+  useLayoutEffect(() => {
+    inputRef.current?.focus();
+  }, []);
+  const errors = !mobileNumber ? 'Add a mobile number' : undefined
+  return (
+    <AnastasisClientFrame hideNav title="Add SMS authentication">
+      <div>
+        <p>
+          For SMS authentication, you need to provide a mobile number. When
+          recovering your secret, you will be asked to enter the code you
+          receive via SMS.
+        </p>
+        <div class="container">
+          <NumberInput
+            label="Mobile number"
+            placeholder="Your mobile number"
+            grabFocus
+            bind={[mobileNumber, setMobileNumber]} />
+        </div>
+        {configured.length > 0 && <section class="section">
+          <div class="block">
+            Your mobile numbers:
+          </div><div class="block">
+            {configured.map((c, i) => {
+              return <div key={i} class="box" style={{ display: 'flex', justifyContent: 'space-between' }}>
+                <p style={{ marginTop: 'auto', marginBottom: 'auto' }}>{c.instructions}</p>
+                <div><button class="button is-danger" onClick={c.remove}>Delete</button></div>
+              </div>
+            })}
+          </div></section>}
+        <div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
+          <button class="button" onClick={cancel}>Cancel</button>
+          <span data-tooltip={errors}>
+            <button class="button is-info" disabled={errors !== undefined} onClick={addSmsAuth}>Add</button>
+          </span>
+        </div>
+      </div>
+    </AnastasisClientFrame>
+  );
+}
diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodTotpSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodTotpSetup.stories.tsx
new file mode 100644
index 000000000..3447e3d61
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodTotpSetup.stories.tsx
@@ -0,0 +1,64 @@
+/* eslint-disable @typescript-eslint/camelcase */
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { createExample, reducerStatesExample } from '../../../utils';
+import { authMethods as TestedComponent, KnownAuthMethods } from './index';
+
+
+export default {
+  title: 'Pages/backup/authMethods/TOTP',
+  component: TestedComponent,
+  args: {
+    order: 5,
+  },
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+const type: KnownAuthMethods = 'totp'
+
+export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: []
+});
+export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: [{
+    challenge: 'qwe',
+    type,
+    instructions: 'instr',
+    remove: () => null
+  }]
+});
+export const WithMoreExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: [{
+    challenge: 'qwe',
+    type,
+    instructions: 'instr',
+    remove: () => null
+  },{
+    challenge: 'qwe',
+    type,
+    instructions: 'instr',
+    remove: () => null
+  }]
+});
diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodTotpSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodTotpSetup.tsx
new file mode 100644
index 000000000..bbffedad6
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodTotpSetup.tsx
@@ -0,0 +1,47 @@
+/* eslint-disable @typescript-eslint/camelcase */
+import {
+  encodeCrock,
+  stringToBytes
+} from "@gnu-taler/taler-util";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { AuthMethodSetupProps } from "../AuthenticationEditorScreen";
+import { AnastasisClientFrame } from "../index";
+import { TextInput } from "../../../components/fields/TextInput";
+import { QR } from "../../../components/QR";
+
+export function AuthMethodTotpSetup({addAuthMethod, cancel, configured}: AuthMethodSetupProps): VNode {
+  const [name, setName] = useState("");
+  const addTotpAuth = (): void => addAuthMethod({
+    authentication_method: {
+      type: "totp",
+      instructions: `Enter code for ${name}`,
+      challenge: encodeCrock(stringToBytes(name)),
+    },
+  });
+  const errors = !name ? 'The TOTP name is missing' : undefined;
+  return (
+    <AnastasisClientFrame hideNav title="Add TOTP authentication">
+      <p>
+        For Time-based One-Time Password (TOTP) authentication, you need to set 
+        a name for the TOTP secret. Then, you must scan the generated QR code 
+        with your TOTP App to import the TOTP secret into your TOTP App.
+      </p>
+      <div>
+        <TextInput
+          label="TOTP Name"
+          grabFocus
+          bind={[name, setName]} />
+      </div>
+      <QR text={`sometext ${name}`} />
+      <div>
+        <div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
+          <button class="button" onClick={cancel}>Cancel</button>
+          <span data-tooltip={errors}>
+            <button class="button is-info" disabled={errors !== undefined} onClick={addTotpAuth}>Add</button>
+          </span>
+        </div>
+      </div>
+    </AnastasisClientFrame>
+  );
+}
diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodVideoSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodVideoSetup.stories.tsx
new file mode 100644
index 000000000..3c4c7bf39
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodVideoSetup.stories.tsx
@@ -0,0 +1,66 @@
+/* eslint-disable @typescript-eslint/camelcase */
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { createExample, reducerStatesExample } from '../../../utils';
+import { authMethods as TestedComponent, KnownAuthMethods } from './index';
+import logoImage from '../../../assets/logo.jpeg'
+
+export default {
+  title: 'Pages/backup/authMethods/Video',
+  component: TestedComponent,
+  args: {
+    order: 5,
+  },
+  argTypes: {
+    onUpdate: { action: 'onUpdate' },
+    onBack: { action: 'onBack' },
+  },
+};
+
+const type: KnownAuthMethods = 'video'
+
+export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: []
+});
+
+export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: [{
+    challenge: 'qwe',
+    type,
+    instructions: logoImage,
+    remove: () => null
+  }]
+});
+
+export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, {
+  configured: [{
+    challenge: 'qwe',
+    type,
+    instructions: logoImage,
+    remove: () => null
+  },{
+    challenge: 'qwe',
+    type,
+    instructions: logoImage,
+    remove: () => null
+  }]
+});
diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodVideoSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodVideoSetup.tsx
new file mode 100644
index 000000000..d292a9d24
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodVideoSetup.tsx
@@ -0,0 +1,56 @@
+/* eslint-disable @typescript-eslint/camelcase */
+import {
+  encodeCrock,
+  stringToBytes
+} from "@gnu-taler/taler-util";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { ImageInput } from "../../../components/fields/ImageInput";
+import { AuthMethodSetupProps } from "../AuthenticationEditorScreen";
+import { AnastasisClientFrame } from "../index";
+
+export function AuthMethodVideoSetup({cancel, addAuthMethod, configured}: AuthMethodSetupProps): VNode {
+  const [image, setImage] = useState("");
+  const addVideoAuth = (): void => {
+    addAuthMethod({
+      authentication_method: {
+        type: "video",
+        instructions: image,
+        challenge: encodeCrock(stringToBytes(image)),
+      },
+    })
+  };
+  return (
+    <AnastasisClientFrame hideNav title="Add video authentication">
+      <p>
+        For video identification, you need to provide a passport-style 
+        photograph. When recovering your secret, you will be asked to join a 
+        video call. During that  call, a human will use the photograph to 
+        verify your identity.
+      </p>
+      <div style={{textAlign:'center'}}>
+        <ImageInput
+          label="Choose photograph"
+          grabFocus
+          bind={[image, setImage]} />
+      </div>
+      {configured.length > 0 && <section class="section">
+          <div class="block">
+            Your photographs:
+          </div><div class="block">
+            {configured.map((c, i) => {
+              return <div key={i} class="box" style={{ display: 'flex', justifyContent: 'space-between' }}>
+                <img style={{ marginTop: 'auto', marginBottom: 'auto', width: 100, height:100, border: 'solid 1px black' }} src={c.instructions} />
+                <div style={{marginTop: 'auto', marginBottom: 'auto'}}><button class="button is-danger" onClick={c.remove}>Delete</button></div>
+              </div>
+            })}
+          </div></section>}
+      <div>
+        <div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
+          <button class="button" onClick={cancel}>Cancel</button>
+          <button class="button is-info" onClick={addVideoAuth}>Add</button>
+        </div>
+      </div>
+    </AnastasisClientFrame>
+  );
+}
diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/index.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/index.tsx
new file mode 100644
index 000000000..1e1d7bc03
--- /dev/null
+++ b/packages/anastasis-webui/src/pages/home/authMethodSetup/index.tsx
@@ -0,0 +1,68 @@
+import { h, VNode } from "preact";
+import { AuthMethodSetupProps } from "../AuthenticationEditorScreen";
+
+import { AuthMethodEmailSetup as EmailScreen } from "./AuthMethodEmailSetup";
+import { AuthMethodIbanSetup as IbanScreen } from "./AuthMethodIbanSetup";
+import { AuthMethodPostSetup as PostalScreen } from "./AuthMethodPostSetup";
+import { AuthMethodQuestionSetup as QuestionScreen } from "./AuthMethodQuestionSetup";
+import { AuthMethodSmsSetup as SmsScreen } from "./AuthMethodSmsSetup";
+import { AuthMethodTotpSetup as TotpScreen } from "./AuthMethodTotpSetup";
+import { AuthMethodVideoSetup as VideScreen } from "./AuthMethodVideoSetup";
+import postalIcon from '../../../assets/icons/auth_method/postal.svg';
+import questionIcon from '../../../assets/icons/auth_method/question.svg';
+import smsIcon from '../../../assets/icons/auth_method/sms.svg';
+import videoIcon from '../../../assets/icons/auth_method/video.svg';
+
+interface AuthMethodConfiguration {
+  icon: VNode;
+  label: string;
+  screen: (props: AuthMethodSetupProps) => VNode;
+}
+export type KnownAuthMethods = "sms" | "email" | "post" | "question" | "video" | "totp" | "iban";
+
+type KnowMethodConfig = {
+  [name in KnownAuthMethods]: AuthMethodConfiguration;
+};
+
+export const authMethods: KnowMethodConfig = {
+  question: {
+    icon: <img src={questionIcon} />,
+    label: "Question",
+    screen: QuestionScreen
+  },
+  sms: {
+    icon: <img src={smsIcon} />,
+    label: "SMS",
+    screen: SmsScreen
+  },
+  email: {
+    icon: <i class="mdi mdi-email" />,
+    label: "Email",
+    screen: EmailScreen
+    
+  },
+  iban: {
+    icon: <i class="mdi mdi-bank" />,
+    label: "IBAN",
+    screen: IbanScreen
+    
+  },
+  post: {
+    icon: <img src={postalIcon} />,
+    label: "Physical mail",
+    screen: PostalScreen
+    
+  },
+  totp: {
+    icon: <i class="mdi mdi-devices" />,
+    label: "TOTP",
+    screen: TotpScreen
+    
+  },
+  video: {
+    icon: <img src={videoIcon} />,
+    label: "Video",
+    screen: VideScreen
+    
+  }
+}
\ No newline at end of file
diff --git a/packages/anastasis-webui/src/pages/home/index.tsx b/packages/anastasis-webui/src/pages/home/index.tsx
index 5cef4ee9c..fefaa184c 100644
--- a/packages/anastasis-webui/src/pages/home/index.tsx
+++ b/packages/anastasis-webui/src/pages/home/index.tsx
@@ -11,7 +11,8 @@ import {
   VNode
 } from "preact";
 import {
-  useErrorBoundary} from "preact/hooks";
+  useErrorBoundary
+} from "preact/hooks";
 import { Menu } from "../../components/menu";
 import { AnastasisProvider, useAnastasisContext } from "../../context/anastasis";
 import {
@@ -59,7 +60,7 @@ interface AnastasisClientFrameProps {
   /**
    * Hide only the "next" button.
    */
-  hideNext?: boolean;
+  hideNext?: string;
 }
 
 function ErrorBoundary(props: {
@@ -112,13 +113,15 @@ export function AnastasisClientFrame(props: AnastasisClientFrameProps): VNode {
       <Menu title="Anastasis" />
       <div>
         <div class="home" onKeyPress={(e) => handleKeyPress(e)}>
-          <h1>{props.title}</h1>
+          <h1 class="title">{props.title}</h1>
           <ErrorBanner />
           {props.children}
           {!props.hideNav ? (
-            <div style={{marginTop: '2em', display:'flex', justifyContent:'space-between'}}>
+            <div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
               <button class="button" onClick={() => reducer.back()}>Back</button>
-              {!props.hideNext ? <button class="button is-info"onClick={next}>Next</button> : null}
+              <span data-tooltip={props.hideNext}>
+                <button class="button is-info" onClick={next} disabled={props.hideNext !== undefined}>Next</button>
+              </span>
             </div>
           ) : null}
         </div>
@@ -151,18 +154,12 @@ const AnastasisClientImpl: FunctionalComponent = () => {
 
   if (
     state.backup_state === BackupStates.ContinentSelecting ||
-    state.recovery_state === RecoveryStates.ContinentSelecting
-  ) {
-    return (
-      <ContinentSelectionScreen />
-    );
-  }
-  if (
+    state.recovery_state === RecoveryStates.ContinentSelecting ||
     state.backup_state === BackupStates.CountrySelecting ||
     state.recovery_state === RecoveryStates.CountrySelecting
   ) {
     return (
-      <CountrySelectionScreen />
+      <ContinentSelectionScreen />
     );
   }
   if (
diff --git a/packages/anastasis-webui/src/scss/main.scss b/packages/anastasis-webui/src/scss/main.scss
index 2e60bf6f9..1e0d3fded 100644
--- a/packages/anastasis-webui/src/scss/main.scss
+++ b/packages/anastasis-webui/src/scss/main.scss
@@ -198,10 +198,10 @@ div[data-tooltip]::before {
   max-width: 40em;
 }
 
-.home div {
-  margin-top: 0.5em;
-  margin-bottom: 0.5em;
-}
+// .home div {
+//   margin-top: 0.5em;
+//   margin-bottom: 0.5em;
+// }
 
 .policy {
   padding: 0.5em;
diff --git a/packages/anastasis-webui/src/utils/index.tsx b/packages/anastasis-webui/src/utils/index.tsx
index 670e229cd..48ac47544 100644
--- a/packages/anastasis-webui/src/utils/index.tsx
+++ b/packages/anastasis-webui/src/utils/index.tsx
@@ -86,7 +86,13 @@ const base = {
         {
           type: "question",
           usage_fee: "COL:0"
-        }
+        },{
+          type: "sms",
+          usage_fee: "COL:0"
+        },{
+          type: "email",
+          usage_fee: "COL:0"
+        },
       ],
       salt: "WBMDD76BR1E90YQ5AHBMKPH7GW",
       storage_limit_in_megabytes: 16,
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 283dafaf2..e38b0e856 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -61,6 +61,7 @@ importers:
       preact-cli: ^3.2.2
       preact-render-to-string: ^5.1.4
       preact-router: ^3.2.1
+      qrcode-generator: ^1.4.4
       sass: ^1.32.13
       sass-loader: ^10.1.1
       sirv-cli: ^1.0.0-next.3
@@ -73,6 +74,7 @@ importers:
       preact: 10.5.14
       preact-render-to-string: 5.1.19_preact@10.5.14
       preact-router: 3.2.1_preact@10.5.14
+      qrcode-generator: 1.4.4
     devDependencies:
       '@creativebulma/bulma-tooltip': 1.2.0
       '@storybook/addon-a11y': 6.3.7
-- 
cgit v1.2.3

