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/SolveQuestionEntry.tsx | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

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

diff --git a/packages/anastasis-webui/src/pages/home/SolveQuestionEntry.tsx b/packages/anastasis-webui/src/pages/home/SolveQuestionEntry.tsx
index 72dadbe89..319289381 100644
--- a/packages/anastasis-webui/src/pages/home/SolveQuestionEntry.tsx
+++ b/packages/anastasis-webui/src/pages/home/SolveQuestionEntry.tsx
@@ -1,7 +1,8 @@
 import { h, VNode } from "preact";
 import { useState } from "preact/hooks";
 import { useAnastasisContext } from "../../context/anastasis";
-import { AnastasisClientFrame, LabeledInput } from "./index";
+import { AnastasisClientFrame } from "./index";
+import { LabeledInput } from "../../components/fields/LabeledInput";
 import { SolveEntryProps } from "./SolveScreen";
 
 export function SolveQuestionEntry({ challenge, feedback }: SolveEntryProps): VNode {
-- 
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/SolveQuestionEntry.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

