Fakultas Ilmu Komputer UI

Commit c62e767e authored by Wulan Mantiri's avatar Wulan Mantiri
Browse files

Merge branch 'PBI-13-choose_week_layout' into 'staging'

Implement choose week UI layout

See merge request !76
parents 4829bc3b ae4f85e3
Pipeline #82965 failed with stages
in 73 minutes and 3 seconds
...@@ -98,4 +98,3 @@ android: ...@@ -98,4 +98,3 @@ android:
only: only:
- staging - staging
- master - master
- fix-build-autistic
...@@ -132,7 +132,7 @@ android { ...@@ -132,7 +132,7 @@ android {
defaultConfig { defaultConfig {
applicationId "com.dietela_mobile" applicationId "com.dietela_mobile"
minSdkVersion 21 minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
...@@ -231,4 +231,3 @@ task copyDownloadableDepsToLibs(type: Copy) { ...@@ -231,4 +231,3 @@ task copyDownloadableDepsToLibs(type: Copy) {
} }
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
// apply plugin: 'com.google.gms.google-services'
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
buildscript { buildscript {
ext { ext {
buildToolsVersion = "29.0.2" buildToolsVersion = "29.0.2"
minSdkVersion = 16 minSdkVersion = 21
compileSdkVersion = 29 compileSdkVersion = 29
targetSdkVersion = 29 targetSdkVersion = 29
} }
......
...@@ -18,7 +18,9 @@ const Datepicker: FC<Props> = ({ ...@@ -18,7 +18,9 @@ const Datepicker: FC<Props> = ({
}) => { }) => {
const [show, setShow] = useState(false); const [show, setShow] = useState(false);
const onPress = () => setShow(true); const onPress = () => {
setShow(true);
};
const handleChange = (_: any, date?: Date) => { const handleChange = (_: any, date?: Date) => {
setShow(false); setShow(false);
...@@ -42,7 +44,7 @@ const Datepicker: FC<Props> = ({ ...@@ -42,7 +44,7 @@ const Datepicker: FC<Props> = ({
) : null} ) : null}
{show ? ( {show ? (
<RNDateTimePicker <RNDateTimePicker
value={value} value={new Date(value)}
onChange={handleChange} onChange={handleChange}
locale="id-ID" locale="id-ID"
/> />
......
...@@ -24,9 +24,9 @@ export const paymentResult = `${payment}/result`; ...@@ -24,9 +24,9 @@ export const paymentResult = `${payment}/result`;
const client = 'client'; const client = 'client';
export const clientTabNavigation = `${client}/tab-navigation`; export const clientTabNavigation = `${client}/tab-navigation`;
export const clientProfile = `${client}/profile`; export const clientTabProfile = `${client}/profile`;
export const clientRecommendation = `${client}/recommendation`; export const clientRecommendation = `${client}/recommendation`;
export const clientWeeklyReport = `${client}/report`; export const clientTabWeeklyReport = `${client}/tab-report`;
export const clientChat = `${client}/chat`; export const clientChat = `${client}/chat`;
const nutritionist = 'nutritionist'; const nutritionist = 'nutritionist';
......
...@@ -41,3 +41,23 @@ export const mockUserReportResponse: UserReportResponse = { ...@@ -41,3 +41,23 @@ export const mockUserReportResponse: UserReportResponse = {
}, },
...mockUserReportRequest, ...mockUserReportRequest,
}; };
// TODO: to be adjusted
export const mockUserReportHistory = {
has_not_filled_form: true,
current_week_num: 14,
reports: [
{
...mockUserReportResponse,
week_num: 12,
},
{
...mockUserReportResponse,
week_num: 2,
},
{
...mockUserReportResponse,
week_num: 1,
},
],
};
...@@ -28,6 +28,8 @@ export { default as ClientListAdmin } from './admin/ClientListAdmin'; ...@@ -28,6 +28,8 @@ export { default as ClientListAdmin } from './admin/ClientListAdmin';
export { default as ClientRecommendation } from './recommendation/ClientRecommendation'; export { default as ClientRecommendation } from './recommendation/ClientRecommendation';
export { default as ClientDietRecommendationForAdmin } from './recommendation/ClientDietRecommendationForAdmin'; export { default as ClientDietRecommendationForAdmin } from './recommendation/ClientDietRecommendationForAdmin';
export { default as ChooseWeekForClient } from './report/ChooseWeekForClient';
export { default as ChooseWeekForNutritionist } from './report/ChooseWeekForNutritionist';
export { default as WeeklyReport } from './report/WeeklyReport'; export { default as WeeklyReport } from './report/WeeklyReport';
export { default as ReadOnlyWeeklyReport } from './report/ReadOnlyWeeklyReport'; export { default as ReadOnlyWeeklyReport } from './report/ReadOnlyWeeklyReport';
......
...@@ -2,9 +2,11 @@ import React, { FC } from 'react'; ...@@ -2,9 +2,11 @@ import React, { FC } from 'react';
import { createStackNavigator } from '@react-navigation/stack'; import { createStackNavigator } from '@react-navigation/stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Icon } from 'react-native-elements'; import { Icon } from 'react-native-elements';
import { colors, typography } from 'styles';
import * as ROUTES from 'constants/routes'; import * as ROUTES from 'constants/routes';
import { screenOptions } from 'app/styles';
import { styles, tabBarOptions } from './styles';
import ClientRecommendation from 'scenes/recommendation/ClientRecommendation'; import ClientRecommendation from 'scenes/recommendation/ClientRecommendation';
import WeeklyReport from 'scenes/report/WeeklyReport'; import WeeklyReport from 'scenes/report/WeeklyReport';
import ComingSoonPage from 'scenes/common/ComingSoonPage'; import ComingSoonPage from 'scenes/common/ComingSoonPage';
...@@ -18,9 +20,7 @@ import { ...@@ -18,9 +20,7 @@ import {
Questionnaire5, Questionnaire5,
} from 'scenes/questionnaire/ExtendedQuestionnaire/components'; } from 'scenes/questionnaire/ExtendedQuestionnaire/components';
import ReadOnlyWeeklyReport from 'scenes/report/ReadOnlyWeeklyReport'; import ReadOnlyWeeklyReport from 'scenes/report/ReadOnlyWeeklyReport';
import { screenOptions } from 'app/styles'; import ChooseWeekForClient from 'scenes/report/ChooseWeekForClient';
import { styles } from './styles';
interface NavRoute<T = any> { interface NavRoute<T = any> {
name: string; name: string;
...@@ -75,6 +75,10 @@ export const ExtQuestionnaireStackScreen: FC = () => ( ...@@ -75,6 +75,10 @@ export const ExtQuestionnaireStackScreen: FC = () => (
); );
const reportClientNavigation: NavRoute[] = [ const reportClientNavigation: NavRoute[] = [
{
name: ROUTES.weeklyReportChooseWeek,
component: ChooseWeekForClient,
},
{ {
name: ROUTES.weeklyReportForm, name: ROUTES.weeklyReportForm,
component: WeeklyReport, component: WeeklyReport,
...@@ -83,10 +87,6 @@ const reportClientNavigation: NavRoute[] = [ ...@@ -83,10 +87,6 @@ const reportClientNavigation: NavRoute[] = [
name: ROUTES.weeklyReportReadOnly, name: ROUTES.weeklyReportReadOnly,
component: ReadOnlyWeeklyReport, component: ReadOnlyWeeklyReport,
}, },
{
name: ROUTES.weeklyReportChooseWeek,
component: ComingSoonPage,
},
]; ];
const WeeklyReportStack = createStackNavigator(); const WeeklyReportStack = createStackNavigator();
...@@ -109,24 +109,11 @@ const ClientTab = createBottomTabNavigator(); ...@@ -109,24 +109,11 @@ const ClientTab = createBottomTabNavigator();
const ClientNavigation: FC = () => { const ClientNavigation: FC = () => {
return ( return (
<ClientTab.Navigator <ClientTab.Navigator
initialRouteName={ROUTES.clientProfile} initialRouteName={ROUTES.clientTabProfile}
sceneContainerStyle={styles.sceneStyle} sceneContainerStyle={styles.sceneStyle}
tabBarOptions={{ tabBarOptions={tabBarOptions}>
activeTintColor: colors.primaryVariant,
labelStyle: {
paddingVertical: 0,
marginVertical: 0,
...typography.headingMedium,
fontSize: 14,
},
style: {
height: 66,
paddingTop: 8,
paddingBottom: 8,
},
}}>
<ClientTab.Screen <ClientTab.Screen
name={ROUTES.clientProfile} name={ROUTES.clientTabProfile}
component={ExtQuestionnaireStackScreen} component={ExtQuestionnaireStackScreen}
options={{ options={{
tabBarLabel: 'Profil', tabBarLabel: 'Profil',
...@@ -151,7 +138,7 @@ const ClientNavigation: FC = () => { ...@@ -151,7 +138,7 @@ const ClientNavigation: FC = () => {
}} }}
/> />
<ClientTab.Screen <ClientTab.Screen
name={ROUTES.clientWeeklyReport} name={ROUTES.clientTabWeeklyReport}
component={WeeklyReportStackScreen} component={WeeklyReportStackScreen}
options={{ options={{
tabBarLabel: 'Laporan Diet', tabBarLabel: 'Laporan Diet',
......
import { StyleSheet } from 'react-native'; import { StyleSheet } from 'react-native';
import { colors, typography } from 'styles';
export const styles = StyleSheet.create({ export const styles = StyleSheet.create({
sceneStyle: { sceneStyle: {
backgroundColor: 'transparent', backgroundColor: 'transparent',
}, },
}); });
export const tabBarOptions = {
activeTintColor: colors.primaryVariant,
labelStyle: {
paddingVertical: 0,
marginVertical: 0,
...typography.headingMedium,
fontSize: 14,
},
style: {
height: 66,
paddingTop: 8,
paddingBottom: 8,
},
};
...@@ -4,7 +4,7 @@ import * as ROUTES from 'constants/routes'; ...@@ -4,7 +4,7 @@ import * as ROUTES from 'constants/routes';
import DietReportPage from '.'; import DietReportPage from '.';
import { dietReportPage1 } from '../../pages/DietReportPage1'; import { dietReportPage1 } from '../../pages/DietReportPage1';
import { mockUserReportResponse } from '__mocks__/userReport'; import { mockUserReportResponse } from 'mocks/userReport';
import { dietReportPage } from '../../pages/types'; import { dietReportPage } from '../../pages/types';
import { dietReportPage2 } from '../../pages/DietReportPage2'; import { dietReportPage2 } from '../../pages/DietReportPage2';
import { dietReportPage3 } from '../../pages/DietReportPage3'; import { dietReportPage3 } from '../../pages/DietReportPage3';
......
...@@ -2,7 +2,7 @@ import React from 'react'; ...@@ -2,7 +2,7 @@ import React from 'react';
import { render, waitFor, fireEvent } from 'utils/testing'; import { render, waitFor, fireEvent } from 'utils/testing';
import DietReportForNutritionist from '.'; import DietReportForNutritionist from '.';
import { mockUserReportResponse } from '__mocks__/userReport'; import { mockUserReportResponse } from 'mocks/userReport';
import axios from 'axios'; import axios from 'axios';
import * as ROUTES from 'constants/routes'; import * as ROUTES from 'constants/routes';
......
import React from 'react';
import { fireEvent, render } from '@testing-library/react-native';
import ChooseWeek from '.';
import { mockUserReportHistory } from 'mocks/userReport';
const mockedNavigate = jest.fn();
jest.mock('@react-navigation/native', () => {
return {
useNavigation: () => ({
navigate: mockedNavigate,
}),
};
});
describe('ChooseWeek component', () => {
it('has "Isi" button when form is never filled and accessed by client', () => {
const { getByText } = render(<ChooseWeek data={mockUserReportHistory} />);
const fillButton = getByText(/Isi/i);
expect(fillButton).toBeTruthy();
fireEvent.press(fillButton);
expect(mockedNavigate).toHaveBeenCalled();
});
it('does not have "Isi" button when form is never filled but accessed by nutritionist', () => {
const { queryByText } = render(
<ChooseWeek data={mockUserReportHistory} isNutritionist />,
);
expect(queryByText(/Isi/i)).toBeFalsy();
});
it('does not have "Isi" button when form is already filled', () => {
const { queryByText } = render(
<ChooseWeek
data={{ ...mockUserReportHistory, has_not_filled_form: false }}
/>,
);
expect(queryByText(/Isi/i)).toBeFalsy();
});
it('redirects to designated route when button "Lihat" is pressed', () => {
const { getAllByText } = render(
<ChooseWeek data={mockUserReportHistory} />,
);
const viewButton = getAllByText(/Lihat/i)[0];
expect(viewButton).toBeTruthy();
fireEvent.press(viewButton);
expect(mockedNavigate).toHaveBeenCalled();
});
});
import React, { FC } from 'react';
import { useNavigation } from '@react-navigation/native';
import { View, ScrollView } from 'react-native';
import { Button, Text } from 'react-native-elements';
import * as ROUTES from 'constants/routes';
import { styles } from './styles';
import { Props } from './types';
import { getDateRange } from 'utils/format';
const ChooseWeek: FC<Props> = ({ data, isNutritionist }) => {
const redirectViewRoute = isNutritionist ? '' : ROUTES.weeklyReportReadOnly; // TODO
const navigation = useNavigation();
const getDateRangeForWeek = (weekNum: number) => {
const { mon, sun } = getDateRange(data.current_week_num - weekNum);
return `${mon.format('DD MMM YYYY')} - ${sun.format('DD MMM YYYY')}`;
};
return (
<ScrollView contentContainerStyle={styles.container}>
<View style={styles.pageContainer}>
{!isNutritionist && data.has_not_filled_form ? (
<View style={styles.page}>
<View style={styles.text}>
<Text style={styles.bold}>Minggu {data.current_week_num}</Text>
<Text>{getDateRangeForWeek(data.current_week_num)}</Text>
</View>
<View style={styles.buttonContainer}>
<Button
title="Isi"
onPress={() => navigation.navigate(ROUTES.weeklyReportForm)}
buttonStyle={styles.button}
titleStyle={styles.buttonTitle}
/>
</View>
</View>
) : null}
{data.reports.map((report, i) => (
<View style={styles.page} key={i}>
<View style={styles.text}>
<Text style={styles.bold}>Minggu {report.week_num}</Text>
<Text>{getDateRangeForWeek(report.week_num)}</Text>
</View>
<View style={styles.buttonContainer}>
<Button
title="Lihat"
type="outline"
onPress={() => navigation.navigate(redirectViewRoute)}
buttonStyle={styles.outlineButtonStyle}
titleStyle={styles.buttonTitle}
/>
</View>
</View>
))}
</View>
</ScrollView>
);
};
export default ChooseWeek;
import { StyleSheet } from 'react-native';
import { colors, typography } from 'styles';
export const styles = StyleSheet.create({
container: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
flex: 1,
paddingHorizontal: 20,
},
pageContainer: {
display: 'flex',
alignItems: 'center',
},
bold: {
color: colors.textBlack,
...typography.headingMedium,
fontSize: 18,
marginBottom: 2,
},
page: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
padding: 14,
borderBottomColor: colors.border,
borderBottomWidth: 1,
},
buttonContainer: {
paddingLeft: 10,
flex: 0.3,
},
text: {
flex: 0.7,
},
button: {
padding: 10,
paddingHorizontal: 0,
backgroundColor: colors.primaryYellow,
},
outlineButtonStyle: {
padding: 10,
paddingHorizontal: 0,
borderColor: colors.buttonYellow,
borderWidth: 1,
},
buttonTitle: {
color: colors.textBlack,
},
});
import { UserReportResponse } from 'services/progress/models';
export interface Props {
data: {
has_not_filled_form: boolean;
current_week_num: number;
reports: UserReportResponse[];
}; // TODO: Kefas adjust to API response
isNutritionist?: boolean;
}
import React from 'react';
import { render } from '@testing-library/react-native';
import ChooseWeekForClient from '.';
const mockedNavigate = jest.fn();
jest.mock('@react-navigation/native', () => {
return {
useNavigation: () => ({
navigate: mockedNavigate,
}),
};
});
describe('ChooseWeekForClient', () => {
it('renders correctly', () => {
render(<ChooseWeekForClient />);
});
});
import React, { FC } from 'react';
import ChooseWeek from '../ChooseWeek';
import { mockUserReportHistory } from 'mocks/userReport';
const ChooseWeekForClient: FC = () => {
// call for API, get client id from user context? or discuss with backend
const data = mockUserReportHistory;
return <ChooseWeek data={data} />;
};
export default ChooseWeekForClient;
import React from 'react';
import { render } from '@testing-library/react-native';
import ChooseWeekForNutritionist from '.';
const mockedNavigate = jest.fn();
jest.mock('@react-navigation/native', () => {
return {
useNavigation: () => ({
navigate: mockedNavigate,
}),
};
});
describe('ChooseWeekForNutritionist', () => {
it('renders correctly', () => {
render(<ChooseWeekForNutritionist />);
});
});
import React, { FC } from 'react';
import ChooseWeek from '../ChooseWeek';
import { mockUserReportHistory } from 'mocks/userReport';
const ChooseWeekForNutritionist: FC = () => {
// call for API, get client id dr yg d pass?
const data = mockUserReportHistory;
return <ChooseWeek data={data} isNutritionist />;
};
export default ChooseWeekForNutritionist;
import dayjs from 'dayjs'; import dayjs, { Dayjs } from 'dayjs';
import { API_BASE_URL } from 'env'; import { API_BASE_URL } from 'env';
export const convertDate = (dateString?: string): string => { export const convertDate = (dateString?: string): string => {
...@@ -10,3 +10,15 @@ export const dateToString = (date: Date): string => ...@@ -10,3 +10,15 @@ export const dateToString = (date: Date): string =>
export const getAbsoluteUrl = (path?: string | null) => export const getAbsoluteUrl = (path?: string | null) =>
path ? API_BASE_URL + path : ''; path ? API_BASE_URL + path : '';
export const getDateRange = (
weekDiff: number,
): {
mon: Dayjs;
sun: Dayjs;
} => {
return {
mon: dayjs().day(1).subtract(weekDiff, 'week'),
sun: dayjs().day(7).subtract(weekDiff, 'week'),
};
};
Markdown is supported
0%