Fakultas Ilmu Komputer UI

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

Implement choose week UI layout

parent 4829bc3b
......@@ -98,4 +98,3 @@ android:
only:
- staging
- master
- fix-build-autistic
......@@ -132,7 +132,7 @@ android {
defaultConfig {
applicationId "com.dietela_mobile"
minSdkVersion 21
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
......@@ -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 plugin: 'com.google.gms.google-services'
......@@ -3,7 +3,7 @@
buildscript {
ext {
buildToolsVersion = "29.0.2"
minSdkVersion = 16
minSdkVersion = 21
compileSdkVersion = 29
targetSdkVersion = 29
}
......
......@@ -18,7 +18,9 @@ const Datepicker: FC<Props> = ({
}) => {
const [show, setShow] = useState(false);
const onPress = () => setShow(true);
const onPress = () => {
setShow(true);
};
const handleChange = (_: any, date?: Date) => {
setShow(false);
......@@ -42,7 +44,7 @@ const Datepicker: FC<Props> = ({
) : null}
{show ? (
<RNDateTimePicker
value={value}
value={new Date(value)}
onChange={handleChange}
locale="id-ID"
/>
......
......@@ -24,9 +24,9 @@ export const paymentResult = `${payment}/result`;
const client = 'client';
export const clientTabNavigation = `${client}/tab-navigation`;
export const clientProfile = `${client}/profile`;
export const clientTabProfile = `${client}/profile`;
export const clientRecommendation = `${client}/recommendation`;
export const clientWeeklyReport = `${client}/report`;
export const clientTabWeeklyReport = `${client}/tab-report`;
export const clientChat = `${client}/chat`;
const nutritionist = 'nutritionist';
......
......@@ -41,3 +41,23 @@ export const mockUserReportResponse: UserReportResponse = {
},
...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';
export { default as ClientRecommendation } from './recommendation/ClientRecommendation';
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 ReadOnlyWeeklyReport } from './report/ReadOnlyWeeklyReport';
......
......@@ -2,9 +2,11 @@ import React, { FC } from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Icon } from 'react-native-elements';
import { colors, typography } from 'styles';
import * as ROUTES from 'constants/routes';
import { screenOptions } from 'app/styles';
import { styles, tabBarOptions } from './styles';
import ClientRecommendation from 'scenes/recommendation/ClientRecommendation';
import WeeklyReport from 'scenes/report/WeeklyReport';
import ComingSoonPage from 'scenes/common/ComingSoonPage';
......@@ -18,9 +20,7 @@ import {
Questionnaire5,
} from 'scenes/questionnaire/ExtendedQuestionnaire/components';
import ReadOnlyWeeklyReport from 'scenes/report/ReadOnlyWeeklyReport';
import { screenOptions } from 'app/styles';
import { styles } from './styles';
import ChooseWeekForClient from 'scenes/report/ChooseWeekForClient';
interface NavRoute<T = any> {
name: string;
......@@ -75,6 +75,10 @@ export const ExtQuestionnaireStackScreen: FC = () => (
);
const reportClientNavigation: NavRoute[] = [
{
name: ROUTES.weeklyReportChooseWeek,
component: ChooseWeekForClient,
},
{
name: ROUTES.weeklyReportForm,
component: WeeklyReport,
......@@ -83,10 +87,6 @@ const reportClientNavigation: NavRoute[] = [
name: ROUTES.weeklyReportReadOnly,
component: ReadOnlyWeeklyReport,
},
{
name: ROUTES.weeklyReportChooseWeek,
component: ComingSoonPage,
},
];
const WeeklyReportStack = createStackNavigator();
......@@ -109,24 +109,11 @@ const ClientTab = createBottomTabNavigator();
const ClientNavigation: FC = () => {
return (
<ClientTab.Navigator
initialRouteName={ROUTES.clientProfile}
initialRouteName={ROUTES.clientTabProfile}
sceneContainerStyle={styles.sceneStyle}
tabBarOptions={{
activeTintColor: colors.primaryVariant,
labelStyle: {
paddingVertical: 0,
marginVertical: 0,
...typography.headingMedium,
fontSize: 14,
},
style: {
height: 66,
paddingTop: 8,
paddingBottom: 8,
},
}}>
tabBarOptions={tabBarOptions}>
<ClientTab.Screen
name={ROUTES.clientProfile}
name={ROUTES.clientTabProfile}
component={ExtQuestionnaireStackScreen}
options={{
tabBarLabel: 'Profil',
......@@ -151,7 +138,7 @@ const ClientNavigation: FC = () => {
}}
/>
<ClientTab.Screen
name={ROUTES.clientWeeklyReport}
name={ROUTES.clientTabWeeklyReport}
component={WeeklyReportStackScreen}
options={{
tabBarLabel: 'Laporan Diet',
......
import { StyleSheet } from 'react-native';
import { colors, typography } from 'styles';
export const styles = StyleSheet.create({
sceneStyle: {
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';
import DietReportPage from '.';
import { dietReportPage1 } from '../../pages/DietReportPage1';
import { mockUserReportResponse } from '__mocks__/userReport';
import { mockUserReportResponse } from 'mocks/userReport';
import { dietReportPage } from '../../pages/types';
import { dietReportPage2 } from '../../pages/DietReportPage2';
import { dietReportPage3 } from '../../pages/DietReportPage3';
......
......@@ -2,7 +2,7 @@ import React from 'react';
import { render, waitFor, fireEvent } from 'utils/testing';
import DietReportForNutritionist from '.';
import { mockUserReportResponse } from '__mocks__/userReport';
import { mockUserReportResponse } from 'mocks/userReport';
import axios from 'axios';
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';
export const convertDate = (dateString?: string): string => {
......@@ -10,3 +10,15 @@ export const dateToString = (date: Date): string =>
export const getAbsoluteUrl = (path?: string | null) =>
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% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment