aboutsummaryrefslogtreecommitdiff
path: root/packages/anastasis-webui/src/hooks/use-anastasis-reducer.ts
blob: 30bab96d17e49380f36fa4d0fc06ca68075d4f0d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import { useState } from "preact/hooks";

type ReducerState = any;

interface AnastasisState {
  reducerState: ReducerState | undefined;
  currentError: any;
}

export enum BackupStates {
  ContinentSelecting = "CONTINENT_SELECTING",
  CountrySelecting = "COUNTRY_SELECTING",
}

export enum RecoveryStates {
  ContinentSelecting = "CONTINENT_SELECTING",
  CountrySelecting = "COUNTRY_SELECTING",
}

const reducerBaseUrl = "http://localhost:5000/";

async function getBackupStartState(): Promise<ReducerState> {
  const resp = await fetch(new URL("start-backup", reducerBaseUrl).href);
  return await resp.json();
}

async function getRecoveryStartState(): Promise<ReducerState> {
  const resp = await fetch(new URL("start-recovery", reducerBaseUrl).href);
  return await resp.json();
}

async function reduceState(
  state: any,
  action: string,
  args: any,
): Promise<ReducerState> {
  const resp = await fetch(new URL("action", reducerBaseUrl).href, {
    method: "POST",
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      state,
      action,
      arguments: args,
    }),
  });
  return resp.json();
}

export interface AnastasisReducerApi {
  currentReducerState: ReducerState;
  currentError: any;
  startBackup: () => void;
  startRecover: () => void;
  back: () => void;
  transition(action: string, args: any): void;
}

export function useAnastasisReducer(): AnastasisReducerApi {
  const [anastasisState, setAnastasisState] = useState<AnastasisState>({
    reducerState: undefined,
    currentError: undefined,
  });

  async function doTransition(action: string, args: any) {
    console.log("reducing with", action, args);
    const s = await reduceState(anastasisState.reducerState, action, args);
    console.log("got new state from reducer", s);
    if (s.code) {
      setAnastasisState({ ...anastasisState, currentError: s });
    } else {
      setAnastasisState({
        ...anastasisState,
        currentError: undefined,
        reducerState: s,
      });
    }
  }

  return {
    currentReducerState: anastasisState.reducerState,
    currentError: anastasisState.currentError,
    async startBackup() {
      const s = await getBackupStartState();
      setAnastasisState({
        ...anastasisState,
        currentError: undefined,
        reducerState: s,
      });
    },
    async startRecover() {
      const s = await getRecoveryStartState();
      setAnastasisState({
        ...anastasisState,
        currentError: undefined,
        reducerState: s,
      });
    },
    transition(action: string, args: any) {
      doTransition(action, args);
    },
    back() {
      if (
        anastasisState.reducerState.backup_state ===
          BackupStates.ContinentSelecting ||
        anastasisState.reducerState.recovery_state ===
          RecoveryStates.ContinentSelecting
      ) {
        setAnastasisState({
          ...anastasisState,
          currentError: undefined,
          reducerState: undefined,
        });
      } else if (
        anastasisState.reducerState.backup_state ===
        BackupStates.CountrySelecting
      ) {
        doTransition("unselect_continent", {});
      } else if (
        anastasisState.reducerState.recovery_state ===
        RecoveryStates.CountrySelecting
      ) {
        doTransition("unselect_continent", {});
      } else {
        doTransition("back", {});
      }
    },
  };
}