Fakultas Ilmu Komputer UI

Commit 27ff03ff authored by Jahns's avatar Jahns
Browse files

Merge branch 'pbi-15-edit-profile' into 'staging'

Pbi 15 edit profile

See merge request !8
parents be0def7a b8c91ecc
Pipeline #82019 passed with stages
in 33 minutes and 52 seconds
......@@ -14,6 +14,9 @@ import {
ContactInvestigationFormStep2,
ContactInvestigationFormStep3,
ContactInvestigationFormStep4,
EditProfileForm,
ProfilePage,
ForgetPasswordPage,
MonitoringSelection,
MonitoringMedicalReference,
MonitoringFormFinishPage,
......@@ -28,7 +31,6 @@ import initialCacheState, {
} from 'contexts/AppContext/cache';
import { useMainService } from 'services'
import { Box, Text, Button, Gap } from 'components';
import ForgetPasswordPage from 'scenes/ForgetPasswordPage';
import OfficerSignupFormGoogleSignin from 'scenes/OfficerSignupFormGoogleSignin';
import WonderingIllustration from 'assets/illustrations/wondering.png';
......@@ -294,6 +296,8 @@ const App = () => {
<Stack.Screen name="login" component={LoginPage} />
<Stack.Screen name="forget-password" component={ForgetPasswordPage} />
<Stack.Screen name="home" component={Home} />
<Stack.Screen name="profile" component={ProfilePage} />
<Stack.Screen name="edit-profile" component={EditProfileForm} />
<Stack.Screen
name="contact-investigation-form/1"
component={ContactInvestigationFormStep1}
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`DatePicker tests renders correctly 1`] = `
<View
axis={2}
style={
Array [
Object {
"alignItems": "flex-start",
"backgroundColor": "transparent",
"borderBottomColor": "black",
"borderBottomWidth": 0,
"borderLeftColor": "black",
"borderLeftWidth": 0,
"borderRadius": 0,
"borderRightColor": "black",
"borderRightWidth": 0,
"borderTopColor": "black",
"borderTopWidth": 0,
"flexDirection": "column",
"flexGrow": 0,
"flexShrink": 0,
"flexWrap": "nowrap",
"height": "auto",
"justifyContent": "flex-start",
"paddingBottom": 0,
"paddingLeft": 0,
"paddingRight": 0,
"paddingTop": 0,
"width": "auto",
},
]
}
>
<View
style={
Array [
Object {
"alignItems": "flex-start",
"backgroundColor": "transparent",
"borderBottomColor": "black",
"borderBottomWidth": 0,
"borderLeftColor": "black",
"borderLeftWidth": 0,
"borderRadius": 0,
"borderRightColor": "black",
"borderRightWidth": 0,
"borderTopColor": "black",
"borderTopWidth": 0,
"flexDirection": "row",
"flexGrow": 0,
"flexShrink": 0,
"flexWrap": "nowrap",
"height": "auto",
"justifyContent": "flex-start",
"paddingBottom": 0,
"paddingLeft": 0,
"paddingRight": 0,
"paddingTop": 0,
"width": "auto",
},
]
}
>
<Text
fontSize="16px"
fontWeight="Bold"
style={
Array [
Object {
"color": "black",
"fontFamily": "Dosis-Bold",
"fontSize": 16,
"textAlign": "left",
"width": "auto",
},
]
}
>
Tanggal Hari Ini
</Text>
</View>
<RNGestureHandlerButton
collapsable={false}
onGestureEvent={[Function]}
onGestureHandlerEvent={[Function]}
onGestureHandlerStateChange={[Function]}
onHandlerStateChange={[Function]}
rippleColor={0}
style={
Array [
Object {
"overflow": "hidden",
},
undefined,
]
}
>
<View
accessible={true}
style={
Object {
"opacity": 1,
}
}
>
<View
style={
Array [
Object {
"borderBottomWidth": 0.75,
"height": 40,
"paddingLeft": 5,
"paddingTop": 6,
"width": 728,
},
]
}
>
<View
style={
Array [
Object {
"alignItems": "flex-start",
"backgroundColor": "transparent",
"borderBottomColor": "black",
"borderBottomWidth": 0,
"borderLeftColor": "black",
"borderLeftWidth": 0,
"borderRadius": 0,
"borderRightColor": "black",
"borderRightWidth": 0,
"borderTopColor": "black",
"borderTopWidth": 0,
"flexDirection": "row",
"flexGrow": 0,
"flexShrink": 0,
"flexWrap": "nowrap",
"height": "auto",
"justifyContent": "flex-start",
"paddingBottom": 0,
"paddingLeft": 0,
"paddingRight": 0,
"paddingTop": 0,
"width": "100%",
},
]
}
width="100%"
>
<Text
fontSize="16px"
fontWeight="Regular"
style={
Array [
Object {
"color": "black",
"fontFamily": "Dosis-Regular",
"fontSize": 16,
"textAlign": "left",
"width": "auto",
},
]
}
>
7/6/2021
</Text>
</View>
<View
style={
Array [
Object {
"alignItems": "flex-start",
"backgroundColor": "transparent",
"borderBottomColor": "black",
"borderBottomWidth": 0,
"borderLeftColor": "black",
"borderLeftWidth": 0,
"borderRadius": 0,
"borderRightColor": "black",
"borderRightWidth": 0,
"borderTopColor": "black",
"borderTopWidth": 0,
"flexDirection": "row",
"flexGrow": 0,
"flexShrink": 0,
"flexWrap": "nowrap",
"height": "auto",
"justifyContent": "flex-start",
"paddingBottom": 0,
"paddingLeft": 0,
"paddingRight": 0,
"paddingTop": 0,
"width": "auto",
},
]
}
/>
</View>
</View>
</RNGestureHandlerButton>
</View>
`;
import {AppContext} from 'contexts';
import { AppContext } from 'contexts';
import { useNavigation } from '@react-navigation/native';
import React, {useContext} from 'react';
import React, { useContext } from 'react';
import styled from 'styled-components/native';
import {Image} from 'react-native';
import {Button, Text, Box} from 'components';
import { Image } from 'react-native';
import { Button, Text, Box } from 'components';
interface HeaderProps {
isHome?: boolean;
......@@ -25,19 +25,24 @@ const Header = ({
<BackgroundMain>
<HeaderMain>
<ChildrenContent>
{isHome? (
{isHome ? (
<>
<Box
grow={1}
/>
<FlexControl>
<FlexControl >
<Image
style={{borderRadius: 100, width: 80, height: 80}}
style={{ borderRadius: 100, width: 80, height: 80 }}
source={require('assets/icons/user-placeholder.png')}
/>
<TextView>
<Text isBold type={Text.StyleType.Larger} >{`Halo, ${greetingName} !`}</Text>
<Text type={Text.StyleType.Medium} >Semangat berantas TB</Text>
<TouchableText
onPress={() => global.isAuthenticated ? navigation.navigate("profile") : navigation.navigate("login")}
>
<Text>Lihat Profile</Text>
</TouchableText>
</TextView>
</FlexControl>
</>
......@@ -51,7 +56,7 @@ const Header = ({
<Button
width="30px"
type={Button.Type.Outline}
onPress={() => global.isAuthenticated? navigation.navigate("home"): navigation.navigate("login")}
onPress={() => global.isAuthenticated ? navigation.navigate("home") : navigation.navigate("login")}
>
Beranda
</Button>
......@@ -126,4 +131,10 @@ const HeaderSecondary = styled.SafeAreaView`
border-top-left-radius: 80px;
`;
const TouchableText = styled.TouchableOpacity`
height: auto;
width: auto;
border-width: 0px;
`;
export default Header;
import 'react-native';
import React from 'react';
import axios from 'axios';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import ReactTestRenderer, { act } from 'react-test-renderer';
import EditProfileForm from '.';
import { AppContext } from 'contexts';
import { useMainService } from 'services';
const Stack = createStackNavigator();
const testProps = {
services: {
main: useMainService('dummyToken'),
},
user: {
name: "test name",
username: "testusername",
email: "test@email.com",
phone_number: "0123456789",
district: "Tapos",
sub_district: "Sukatani",
},
setUser: (data: any) => {
testProps.user = data;
},
cache: {},
}
jest.mock('axios');
jest.useFakeTimers();
const mockedAxios = axios as jest.Mocked<typeof axios>;
describe("EditProfileForm", () => {
it('renders correctly', () => {
const instance = ReactTestRenderer.create(
<AppContext.Provider value={testProps}>
<NavigationContainer>
<Stack.Navigator
screenOptions={{
header: () => <></>,
}}>
<Stack.Screen name="edit-profile" component={EditProfileForm} />
</Stack.Navigator>
</NavigationContainer>,
</AppContext.Provider>
);
expect(instance.toJSON()).toMatchSnapshot();
});
it('success with insert fields with valid values', async () => {
const formPage = ReactTestRenderer.create(
<AppContext.Provider value={testProps}>
<NavigationContainer>
<Stack.Navigator
screenOptions={{
// Empty header
header: () => <></>,
}}>
<Stack.Screen name="edit-profile" component={EditProfileForm} />
</Stack.Navigator>
</NavigationContainer>
</AppContext.Provider>
);
expect(formPage).toBeTruthy()
const nameField = formPage.root.find(elem => elem.props.id === "name")
expect(nameField).toBeTruthy()
const usernameField = formPage.root.find(elem => elem.props.id === "username")
expect(usernameField).toBeTruthy()
const passwordField = formPage.root.find(elem => elem.props.id === "password")
expect(passwordField).toBeTruthy()
const confirmPasswordField = formPage.root.find(elem => elem.props.id === "confirm_password")
expect(confirmPasswordField).toBeTruthy()
const emailField = formPage.root.find(elem => elem.props.id === "email")
expect(emailField).toBeTruthy()
const phoneField = formPage.root.find(elem => elem.props.id === "phone_number")
expect(phoneField).toBeTruthy()
const districtField = formPage.root.find(elem => elem.props.id === "district")
expect(districtField).toBeTruthy()
const sub_districtField = formPage.root.find(elem => elem.props.id === "sub_district")
expect(sub_districtField).toBeTruthy()
// Set value
act(() => {
if (nameField && usernameField && passwordField && confirmPasswordField && emailField && phoneField && districtField && sub_districtField) {
nameField.props.updateValue("your name")
usernameField.props.updateValue("username")
passwordField.props.updateValue("asdQWE123")
confirmPasswordField.props.updateValue("asdQWE123")
emailField.props.updateValue("email@gmail.com")
phoneField.props.updateValue("081802769312")
districtField.props.updateValue("districtku")
sub_districtField.props.updateValue("subdistrictku")
}
})
expect(formPage.toJSON()).toMatchSnapshot()
mockedAxios.request.mockImplementationOnce(
() => new Promise(resolve => {
resolve({
status: 200,
data: {
"message": "success edit profile",
},
});
})
);
const submit = formPage.root.find(elem => elem.props.id === "submit")
await act(async () => {
submit.props.onPress()
})
});
})
\ No newline at end of file
import React, { useState, useContext, useEffect } from 'react';
import styled from 'styled-components/native';
import { ActivityIndicator, ScrollView, View, Modal, Image } from 'react-native';
import { Header, Field, Button, Text } from '../../components';
import error_img from '../OfficerSignupForm/img/folder.png';
import { useFormState } from 'helpers';
import { KECAMATAN_VALUES, KELURAHAN_VALUES } from '../OfficerSignupForm/constants';
import { useNavigation } from '@react-navigation/native';
import { AppContext } from 'contexts';
import translateError from '../OfficerSignupForm/utilities'
const EditProfileForm = () => {
const navigation = useNavigation();
const global = useContext(AppContext);
const headingSize = 0.028 * global.vh;
const imageSize = 0.15 * global.vh;
const [form, setField] = useFormState({
name: { type: 'text' },
username: { type: 'any' },
password: { type: 'password' },
confirm_password: { type: 'password' },
email: { type: 'email' },
phone_number: { type: 'phone' },
district: { type: 'any' },
sub_district: { type: 'any' },
});
const [serverHasError, setServerHasError] = useState(false);
const [messageErrors, setMessageErrors] = useState({
name: '',
username: '',
password: '',
confirm_password: '',
email: '',
phone_number: '',
district: '',
sub_district: '',
})
const [modalVisible, setModalVisible] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const initFieldValue = () => {
setField('name', global.user.name);
setField('username', global.user.username);
setField('email', global.user.email);
setField('phone_number', global.user.phone_number);
setField('district', global.user.district);
setField('sub_district', global.user.sub_district);
}
useEffect(initFieldValue, []);
return (
<View>
<ScrollView>
<Header headerText="Edit Profile" />
<ContainerContent>
<Modal animationType="fade" transparent={true} visible={isLoading}>
<ModalContainer>
<ActivityIndicator
animating={isLoading}
size="large"
color="#fff"
/>
</ModalContainer>
</Modal>
<Modal
id="errorModal"
animationType="fade"
transparent={true}
visible={modalVisible}
onDismiss={() => setServerHasError(false)}>
<ModalContainer>
<ModalInner>
<Image
style={{ width: imageSize, height: imageSize }}
source={error_img}
/>
<HeadingField>
{serverHasError ? (
<>
<Text isBold={true} fontSize={headingSize}>
Unknown Server Error
</Text>
</>
) : (
<>
<Text isBold={true} fontSize={headingSize}>
Terjadi kesalahan, periksa kembali data anda.
</Text>
</>
)}
</HeadingField>
<Button id="modalBack" type={2} onPress={() => setModalVisible(false)}>
Kembali
</Button>
</ModalInner>
</ModalContainer>
</Modal>
<InputField>
<Field
id="name"
name="Nama"
placeholder="Nama Lengkap Anda"
isRequired={true}
information={messageErrors.name}
value={form.fields.name.value}
updateValue={val => setField('name', val)}
/>
</InputField>
<InputField>
<Field
id="username"
name="Username"
placeholder="Username Anda"
isRequired={true}
information={messageErrors.username}
value={form.fields.username.value}
updateValue={val => setField('username', val)}
/>
</InputField>
<InputField>
<Field
id="password"
name="Password"
placeholder="Password Anda"
isRequired={true}
shouldSecure={true}
information={messageErrors.password}
value={form.fields.password.value}
updateValue={val => setField('password', val)}
/>
</InputField>
<InputField>
<Field
id="confirm_password"
name="Konfirmasi Password"
placeholder="Konfirmasi Password Anda"
isRequired={true}
shouldSecure={true}
information={messageErrors.confirm_password}
value={form.fields.confirm_password.value}
updateValue={val => setField('confirm_password', val)}
/>
</InputField>
<InputField>
<Field
id="email"
name="Email"
placeholder="Email Anda"
isRequired={true}
information={messageErrors.email}
value={form.fields.email.value}
updateValue={val => setField('email', val)}
/>
</InputField>
<InputField>
<Field
id="phone_number"
name="Nomor Handphone"
placeholder="No HP Anda"
isRequired={true}
information={messageErrors.phone_number}
value={form.fields.phone_number.value}
updateValue={val => setField('phone_number', val)}
/>