Fakultas Ilmu Komputer UI

index.tsx 9.38 KB
Newer Older
Nandhika Prayoga's avatar
Nandhika Prayoga committed
1
import React, {useState, useEffect, useReducer, useRef} from 'react';
Josh Sudung's avatar
Josh Sudung committed
2
import styled, {ThemeProvider} from 'styled-components/native';
Nandhika Prayoga's avatar
Nandhika Prayoga committed
3
import {NavigationContainer, DefaultTheme} from '@react-navigation/native';
Josh Sudung's avatar
Josh Sudung committed
4
import {createStackNavigator} from '@react-navigation/stack';
5

Josh Sudung's avatar
Josh Sudung committed
6
import {AppContext} from 'contexts';
7
import {
Josh Sudung's avatar
Josh Sudung committed
8
9
10
11
12
13
14
15
16
  Home,
  LoginPage,
  OfficerSignupForm,
  OfficerSignupFormFinishPage,
  ContactInvestigationFormFinishPage,
  ContactInvestigationFormStep1,
  ContactInvestigationFormStep2,
  ContactInvestigationFormStep3,
  ContactInvestigationFormStep4,
jahnsmichael's avatar
jahnsmichael committed
17
  EditProfileForm,
18
  ProfilePage,
jahnsmichael's avatar
jahnsmichael committed
19
  ForgetPasswordPage,
20
21
22
23
24
25
26
  MonitoringSelection,
  MonitoringMedicalReference,
  MonitoringFormFinishPage,
  Splash,
  MonitoringMedicalIntake,
  MonitoringMedicalCheck,
  MonitoringMedicalResume
Josh Sudung's avatar
Josh Sudung committed
27
} from 'scenes';
Nandhika Prayoga's avatar
Nandhika Prayoga committed
28
import {Dimensions, Modal, ActivityIndicator, Image, ImageSourcePropType} from 'react-native';
Josh Sudung's avatar
Josh Sudung committed
29
import initialCacheState, {
30
  CacheType
Josh Sudung's avatar
Josh Sudung committed
31
} from 'contexts/AppContext/cache';
Nandhika Prayoga's avatar
Nandhika Prayoga committed
32
import { useMainService } from 'services'
Nandhika Prayoga's avatar
Nandhika Prayoga committed
33
import { Box, Text, Button, Gap } from 'components';
Nandhika Prayoga's avatar
Nandhika Prayoga committed
34
35
36
37

const StyledApp = styled.SafeAreaView`
  height: 100%;
  width: 100%;
Nandhika Prayoga's avatar
Nandhika Prayoga committed
38
  background: white;
Nandhika Prayoga's avatar
Nandhika Prayoga committed
39
  flex-flow: column nowrap;
40
`;
Josh Sudung's avatar
Josh Sudung committed
41

Nandhika Prayoga's avatar
Nandhika Prayoga committed
42
43
44
45
46
47
48
const StyledAlert = styled.View`
  max-height: 400px;
  padding: 24px;
  background: white;
  border-radius: 3px;
`

Josh Sudung's avatar
Josh Sudung committed
49
50
51
52
53
54
55
56
57
58
59
declare global {
  interface ThemeProps {
    colors: {
      readonly totallyWhite: string;
      readonly almostWhite: string;
      readonly gray: string;
      readonly mediumGray: string;
      readonly lightGray: string;
      readonly red: string;
      readonly green: string;
      readonly black: string;
Nandhika Prayoga's avatar
Nandhika Prayoga committed
60
      readonly deepOcean: string;
Josh Sudung's avatar
Josh Sudung committed
61
62
63
64
65
66
67
68
    };
    vw: number;
    vh: number;
  }

  type TokenType = string;
  type SetTokenType = React.Dispatch<React.SetStateAction<TokenType>>;

Nandhika Prayoga's avatar
Nandhika Prayoga committed
69
70
71
72
73
74
75
76
  type SetShouldLoadingType = React.Dispatch<React.SetStateAction<boolean>>;

  type AlertType = {
    illustration?: ImageSourcePropType;
    message?: string;
  }
  type SetAlertType = React.Dispatch<React.SetStateAction<AlertType>>

Josh Sudung's avatar
Josh Sudung committed
77
78
79
80
81
82
83
84
  interface GlobalProps {
    vw: number;
    vh: number;
    services: {
      main: any;
    };
    setToken: SetTokenType;
    cache: CacheType;
85
    setCache: (object) => void;
Nandhika Prayoga's avatar
Nandhika Prayoga committed
86
87
88
    shouldLoading: boolean;
    setShouldLoading: SetShouldLoadingType;
    setAlert: SetAlertType;
Josh Sudung's avatar
Josh Sudung committed
89
90
91
92
93
    isAuthenticated: boolean;
  }
}

const Stack = createStackNavigator();
94
95
96
97
98
99
100
101
102
103
const theme: ThemeProps = {
  colors: {
    totallyWhite: '#FFFFFF',
    almostWhite: '#FAFAFA',
    gray: '#5F5F5F',
    mediumGray: '#C2C2C2',
    lightGray: '#EFEFEF',
    red: '#9A3838',
    green: '#0DCE66',
    black: '#454545',
Nandhika Prayoga's avatar
Nandhika Prayoga committed
104
    deepOcean: "#424598",
105
106
107
108
  },
  vw: Dimensions.get('window').width,
  vh: Dimensions.get('window').height,
};
109

110
111
112
113
114
115
116
117
118
119
120
enum CacheActionType{
  Update = "Update"
}

type CacheAction =
 | {
    type: CacheActionType.Update;
    data: object;
  }

function cacheReducer(oldCache: CacheType, action: CacheAction): CacheType {
Nandhika Prayoga's avatar
Nandhika Prayoga committed
121
122
123
124
125
  if (action.type === CacheActionType.Update) {
    return {
      ...oldCache,
      ...action.data,
    }
126
  }
Nandhika Prayoga's avatar
Nandhika Prayoga committed
127
  return oldCache
128
129
}

Nandhika Prayoga's avatar
Nandhika Prayoga committed
130
131
132
133
134
135
136
137
const navigationTheme = {
  ...DefaultTheme,
  colors: {
    ...DefaultTheme.colors,
    background: 'white',
  }
}

138
const App = () => {
139
  console.disableYellowBox = true;
Nandhika Prayoga's avatar
Nandhika Prayoga committed
140
  const [cache, cacheDispatch] = useReducer(cacheReducer, initialCacheState);
Nandhika Prayoga's avatar
Nandhika Prayoga committed
141
  const [token, setToken] = useState();
142
  const [user, setUser] = useState();
Nandhika Prayoga's avatar
Nandhika Prayoga committed
143
144
145
146
147
148

  const [shouldLoading, setShouldLoading] = useState<boolean>(false);

  const [shouldShowAlert, setShouldShowAlert] = useState<boolean>(false);
  const [alert, setAlert] = useState<AlertType>({});

Nandhika Prayoga's avatar
Nandhika Prayoga committed
149
  const navigatorRef = useRef()
Josh Sudung's avatar
Josh Sudung committed
150
151
152
153
154
155
156

  const mainService = useMainService(token);
  const global: GlobalProps = {
    // For services
    services: {
      main: mainService,
    },
157
158
    user,
    setUser,
Josh Sudung's avatar
Josh Sudung committed
159
    setToken,
Nandhika Prayoga's avatar
Nandhika Prayoga committed
160
161
162
    shouldLoading,
    setShouldLoading,
    setAlert,
Josh Sudung's avatar
Josh Sudung committed
163
164
165
166
167
168
    isAuthenticated: !!token,
    // For device size
    vw: Dimensions.get('window').width,
    vh: Dimensions.get('window').height,
    // For caching
    cache,
169
170
171
172
173
174
    setCache: (data) => {
      cacheDispatch({
        type: CacheActionType.Update,
        data,
      })
    },
Josh Sudung's avatar
Josh Sudung committed
175
  };
Nandhika Prayoga's avatar
Nandhika Prayoga committed
176
  
177
  useEffect(() => {
Nandhika Prayoga's avatar
Nandhika Prayoga committed
178
179
    if (token) {
      const getUser = async () => {
180
        const response = await mainService.me()
181
        if (response.status === 200) {
Nandhika Prayoga's avatar
Nandhika Prayoga committed
182
          // Token is valid
183
          setUser(response.data)
184
185
186
187
          navigatorRef.current?.reset({
            index: 0,
            routes: [{name: 'home'}]
          });
Nandhika Prayoga's avatar
Nandhika Prayoga committed
188
189
190
        } else {
          // Token is not valid
          setToken('')
191
192
        }
      }
Nandhika Prayoga's avatar
Nandhika Prayoga committed
193
194
      getUser()
    } else if (token === '') {
195
196
197
198
      navigatorRef.current?.reset({
        index: 0,
        routes: [{name: 'login'}]
      });
199
    }
Nandhika Prayoga's avatar
Nandhika Prayoga committed
200
  }, [token])
201

Nandhika Prayoga's avatar
Nandhika Prayoga committed
202
203
204
205
206
207
208
209
  useEffect(() => {
    if (alert.message) {
      setShouldShowAlert(true);
    } else {
      setShouldShowAlert(false);
    }
  }, [alert])

210
  return (
Josh Sudung's avatar
Josh Sudung committed
211
212
213
    <AppContext.Provider value={global}>
      <ThemeProvider theme={theme}>
        <StyledApp>
Nandhika Prayoga's avatar
Nandhika Prayoga committed
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
        <Modal
          animationType="fade"
          transparent={true}
          visible={shouldLoading}
        >
          <Box
            grow={1}
            axis={Box.Axis.Vertical}
            mainAxis="center"
            crossAxis="center"
            background="#00000080"
          >
            <ActivityIndicator
              animating={shouldLoading}
              size="large"
              color="#fff"
            />
          </Box>
        </Modal>
        <Modal
          id="error-modal"
          animationType="fade"
          transparent={true}
          visible={shouldShowAlert}
          onDismiss={() => {}}
        >
          <Box
            grow={1}
            axis={Box.Axis.Vertical}
            mainAxis="center"
            crossAxis="center"
            height="100%"
            width="100%"
            background="#00000080"
          >
            <StyledAlert>
              <Box
                width="250px"
                height="250px"
                mainAxis="center"
              >
                <Image
                  resizeMode="contain"
                  style={{width: "100%", height: "100%"}}
                  source={alert.illustration || {}}
                />
              </Box>
              <Text
                width="100%"
                align="center"
                isBold={true}
                type={Text.StyleType.Medium}
              >
                {alert.message || ""}
              </Text>
              <Gap gap={32} axis={Gap.Axis.Vertical} />
              <Box>
                <Button
                  type={Button.Type.Filled}
                  id="modalBack"
                  onPress={() => setShouldShowAlert(false)}
                >
                  Kembali
                </Button>
              </Box>
            </StyledAlert>
          </Box>
        </Modal>
          <NavigationContainer ref={navigatorRef} theme={navigationTheme}>
Josh Sudung's avatar
Josh Sudung committed
283
284
285
286
287
            <Stack.Navigator
              screenOptions={{
                // Empty header
                header: () => <></>,
              }}>
Nandhika Prayoga's avatar
Nandhika Prayoga committed
288
              <Stack.Screen name="splash" component={Splash} />
Josh Sudung's avatar
Josh Sudung committed
289
              <Stack.Screen name="login" component={LoginPage} />
jahnsmichael's avatar
jahnsmichael committed
290
              <Stack.Screen name="forget-password" component={ForgetPasswordPage} />
Josh Sudung's avatar
Josh Sudung committed
291
              <Stack.Screen name="home" component={Home} />
292
              <Stack.Screen name="profile" component={ProfilePage} />
jahnsmichael's avatar
jahnsmichael committed
293
              <Stack.Screen name="edit-profile" component={EditProfileForm} />
Josh Sudung's avatar
Josh Sudung committed
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
              <Stack.Screen
                name="contact-investigation-form/1"
                component={ContactInvestigationFormStep1}
              />
              <Stack.Screen
                name="contact-investigation-form/2"
                component={ContactInvestigationFormStep2}
              />
              <Stack.Screen
                name="contact-investigation-form/3"
                component={ContactInvestigationFormStep3}
              />
              <Stack.Screen
                name="contact-investigation-form/4"
                component={ContactInvestigationFormStep4}
              />
              <Stack.Screen
                name="contact-investigation-finish"
                component={ContactInvestigationFormFinishPage}
              />
              <Stack.Screen
                name="officer-signup-form"
                component={OfficerSignupForm}
              />
              <Stack.Screen
319
                name="officer-signup-finish"
Josh Sudung's avatar
Josh Sudung committed
320
321
                component={OfficerSignupFormFinishPage}
              />
322
323
324
325
326
327
328
329
              <Stack.Screen
                name="monitoring-select"
                component={MonitoringSelection}
              />
              <Stack.Screen
                name="monitoring-medical-reference"
                component={MonitoringMedicalReference}
              />
Nandhika Prayoga's avatar
Nandhika Prayoga committed
330
              <Stack.Screen
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
                name="monitoring-medical-check"
                component={MonitoringMedicalCheck}
              />
              <Stack.Screen
                name="monitoring-medical-intake"
                component={MonitoringMedicalIntake}
              />
              <Stack.Screen
                name="monitoring-medical-resume"
                component={MonitoringMedicalResume}
              />
              <Stack.Screen
                name="monitoring-finish"
                component={MonitoringFormFinishPage}
              />
Josh Sudung's avatar
Josh Sudung committed
346
347
348
349
350
            </Stack.Navigator>
          </NavigationContainer>
        </StyledApp>
      </ThemeProvider>
    </AppContext.Provider>
351
352
353
354
  );
};

export default App;