Fakultas Ilmu Komputer UI

Commit d64578e1 authored by Kefas Satrio Bangkit Solidedantyo's avatar Kefas Satrio Bangkit Solidedantyo
Browse files

integrate choose weekly report page with backend

parent bbff4370
...@@ -23,6 +23,7 @@ import { ...@@ -23,6 +23,7 @@ import {
ClientListAdmin, ClientListAdmin,
LoginChoosePlan, LoginChoosePlan,
ClientNavigation, ClientNavigation,
ChooseWeekForNutritionist,
} from 'scenes'; } from 'scenes';
import { FC } from 'react'; import { FC } from 'react';
import DietReportForNutritionist from 'scenes/nutritionist/DietReportForNutritionist'; import DietReportForNutritionist from 'scenes/nutritionist/DietReportForNutritionist';
...@@ -131,6 +132,11 @@ export const nutritionistNavigation: NavRoute[] = [ ...@@ -131,6 +132,11 @@ export const nutritionistNavigation: NavRoute[] = [
component: ComingSoonPage, component: ComingSoonPage,
header: 'Chat Klien', header: 'Chat Klien',
}, },
{
name: ROUTES.weeklyReportChooseWeekForNutritionist,
component: ChooseWeekForNutritionist,
header: 'Riwayat Laporan Diet Klien',
},
{ {
name: ROUTES.clientDietReportNutritionist, name: ROUTES.clientDietReportNutritionist,
component: DietReportForNutritionist, component: DietReportForNutritionist,
......
...@@ -47,4 +47,5 @@ export const clientDietRecommendation = `${admin}/client-diet-recommendation`; ...@@ -47,4 +47,5 @@ export const clientDietRecommendation = `${admin}/client-diet-recommendation`;
const weeklyReport = 'weekly-report'; const weeklyReport = 'weekly-report';
export const weeklyReportForm = `${weeklyReport}/form`; export const weeklyReportForm = `${weeklyReport}/form`;
export const weeklyReportChooseWeek = `${weeklyReport}/choose-week`; export const weeklyReportChooseWeek = `${weeklyReport}/choose-week`;
export const weeklyReportChooseWeekForNutritionist = `${weeklyReport}/choose-week-for-nutritionist`;
export const weeklyReportReadOnly = `${weeklyReport}/read-only`; export const weeklyReportReadOnly = `${weeklyReport}/read-only`;
...@@ -42,11 +42,10 @@ export const mockUserReportResponse: UserReportResponse = { ...@@ -42,11 +42,10 @@ export const mockUserReportResponse: UserReportResponse = {
...mockUserReportRequest, ...mockUserReportRequest,
}; };
// TODO: to be adjusted
export const mockUserReportHistory = { export const mockUserReportHistory = {
has_not_filled_form: true, has_submitted_this_week: false,
current_week_num: 14, today_week: 14,
reports: [ data: [
{ {
...mockUserReportResponse, ...mockUserReportResponse,
week_num: 12, week_num: 12,
......
...@@ -8,7 +8,7 @@ const ClientListNutritionist: FC = () => { ...@@ -8,7 +8,7 @@ const ClientListNutritionist: FC = () => {
<ClientList <ClientList
role={UserRole.NUTRITIONIST} role={UserRole.NUTRITIONIST}
clientProfileRoute={ROUTES.clientProfileNutritionist} clientProfileRoute={ROUTES.clientProfileNutritionist}
clientDietReportRoute={ROUTES.clientDietReportNutritionist} clientDietReportRoute={ROUTES.weeklyReportChooseWeekForNutritionist}
clientChatRoute={ROUTES.clientChatNutritionist} clientChatRoute={ROUTES.clientChatNutritionist}
/> />
); );
......
...@@ -11,23 +11,16 @@ jest.mock('axios'); ...@@ -11,23 +11,16 @@ jest.mock('axios');
const mockAxios = axios as jest.Mocked<typeof axios>; const mockAxios = axios as jest.Mocked<typeof axios>;
describe('DietReportForNutritionist', () => { describe('DietReportForNutritionist', () => {
const userReports = [mockUserReportResponse]; const data = mockUserReportResponse;
it('renders and submits correctly when given valid comments', async () => { it('renders and submits correctly when given valid comments', async () => {
mockAxios.request.mockImplementationOnce(() =>
Promise.resolve({
status: 200,
data: userReports,
}),
);
const { queryByText, getByText, getAllByPlaceholderText } = render( const { queryByText, getByText, getAllByPlaceholderText } = render(
<DietReportForNutritionist />, <DietReportForNutritionist />,
ROUTES.clientDietReportNutritionist, ROUTES.clientDietReportNutritionist,
{ {
routeParams: { id: 1 }, routeParams: data,
}, },
); );
await waitFor(() => expect(mockAxios.request).toBeCalled());
const textFieldsPage1 = getAllByPlaceholderText(/Tuliskan komentar.../i); const textFieldsPage1 = getAllByPlaceholderText(/Tuliskan komentar.../i);
textFieldsPage1.forEach((field) => { textFieldsPage1.forEach((field) => {
...@@ -68,20 +61,13 @@ describe('DietReportForNutritionist', () => { ...@@ -68,20 +61,13 @@ describe('DietReportForNutritionist', () => {
}); });
it('renders and does not redirect when api fails', async () => { it('renders and does not redirect when api fails', async () => {
mockAxios.request.mockImplementationOnce(() =>
Promise.resolve({
status: 200,
data: userReports,
}),
);
const { queryByText, getByText, getAllByPlaceholderText } = render( const { queryByText, getByText, getAllByPlaceholderText } = render(
<DietReportForNutritionist />, <DietReportForNutritionist />,
ROUTES.clientDietReportNutritionist, ROUTES.clientDietReportNutritionist,
{ {
routeParams: { id: 1 }, routeParams: data,
}, },
); );
await waitFor(() => expect(mockAxios.request).toBeCalled());
const textFieldsPage1 = getAllByPlaceholderText(/Tuliskan komentar.../i); const textFieldsPage1 = getAllByPlaceholderText(/Tuliskan komentar.../i);
textFieldsPage1.forEach((field) => { textFieldsPage1.forEach((field) => {
...@@ -123,28 +109,6 @@ describe('DietReportForNutritionist', () => { ...@@ -123,28 +109,6 @@ describe('DietReportForNutritionist', () => {
expect(queryByText(/Daftar Klien/i)).toBeFalsy(); expect(queryByText(/Daftar Klien/i)).toBeFalsy();
}); });
it('shows empty data page when no data', async () => {
mockAxios.request.mockImplementationOnce(() =>
Promise.resolve({
status: 200,
data: [],
}),
);
const { queryByText } = render(
<DietReportForNutritionist />,
ROUTES.clientDietReportNutritionist,
{
routeParams: { id: 0 },
},
);
await waitFor(() => expect(mockAxios.request).toBeCalled());
expect(
queryByText(/Klien belum mengisi laporan diet mingguan/i),
).toBeTruthy();
});
afterAll(() => { afterAll(() => {
jest.clearAllMocks(); jest.clearAllMocks();
}); });
......
...@@ -2,17 +2,17 @@ import React, { FC, useState } from 'react'; ...@@ -2,17 +2,17 @@ import React, { FC, useState } from 'react';
import { View, StyleSheet } from 'react-native'; import { View, StyleSheet } from 'react-native';
import { layoutStyles } from 'styles'; import { layoutStyles } from 'styles';
import { pages } from './pages'; import { pages } from './pages';
import { WizardContainer, Loader, EmptyDataPage, Toast } from 'components/core'; import { WizardContainer, Toast } from 'components/core';
import { useForm, useApi } from 'hooks'; import { useForm } from 'hooks';
import { dietReportCommentInitialValues, fieldValidations } from './schema'; import { dietReportCommentInitialValues, fieldValidations } from './schema';
import { generateValidationSchema } from 'utils/form'; import { generateValidationSchema } from 'utils/form';
import { DietReportPage } from './components'; import { DietReportPage } from './components';
import { useRoute, useNavigation } from '@react-navigation/native'; import { useRoute, useNavigation } from '@react-navigation/native';
import { createNutritionistCommentApi } from 'services/progress';
import { import {
retrieveUserReportByIdApi, NutritionistCommentRequest,
createNutritionistCommentApi, UserReportResponse,
} from 'services/progress'; } from 'services/progress/models';
import { NutritionistCommentRequest } from 'services/progress/models';
import * as ROUTES from 'constants/routes'; import * as ROUTES from 'constants/routes';
import { import {
dietReportTextFields, dietReportTextFields,
...@@ -26,10 +26,7 @@ interface ParamsDietReport { ...@@ -26,10 +26,7 @@ interface ParamsDietReport {
const DietReportForNutritionist: FC = () => { const DietReportForNutritionist: FC = () => {
const navigation = useNavigation(); const navigation = useNavigation();
const route = useRoute(); const route = useRoute();
const { id } = route.params as ParamsDietReport; const data = route.params as UserReportResponse;
const { isLoading, data: userReports = [] } = useApi(() =>
retrieveUserReportByIdApi(id),
);
const [activeSlide, setActiveSlide] = useState(1); const [activeSlide, setActiveSlide] = useState(1);
...@@ -44,7 +41,7 @@ const DietReportForNutritionist: FC = () => { ...@@ -44,7 +41,7 @@ const DietReportForNutritionist: FC = () => {
validationSchema: generateValidationSchema(fieldValidations), validationSchema: generateValidationSchema(fieldValidations),
onSubmit: async (values) => { onSubmit: async (values) => {
const payload: NutritionistCommentRequest = { const payload: NutritionistCommentRequest = {
weekly_report: userReports[userReports.length - 1].id, weekly_report: data.id,
...values, ...values,
}; };
const response = await createNutritionistCommentApi(payload); const response = await createNutritionistCommentApi(payload);
...@@ -65,15 +62,7 @@ const DietReportForNutritionist: FC = () => { ...@@ -65,15 +62,7 @@ const DietReportForNutritionist: FC = () => {
}, },
}); });
if (isLoading) { const userReport = data;
return <Loader />;
}
if (!userReports.length) {
return <EmptyDataPage text="Klien belum mengisi laporan diet mingguan" />;
}
const userReport = userReports[userReports.length - 1];
const isCurrentPageError = (): boolean => { const isCurrentPageError = (): boolean => {
if (activeSlide === 1) { if (activeSlide === 1) {
......
...@@ -34,7 +34,7 @@ describe('ChooseWeek component', () => { ...@@ -34,7 +34,7 @@ describe('ChooseWeek component', () => {
it('does not have "Isi" button when form is already filled', () => { it('does not have "Isi" button when form is already filled', () => {
const { queryByText } = render( const { queryByText } = render(
<ChooseWeek <ChooseWeek
data={{ ...mockUserReportHistory, has_not_filled_form: false }} data={{ ...mockUserReportHistory, has_submitted_this_week: true }}
/>, />,
); );
expect(queryByText(/Isi/i)).toBeFalsy(); expect(queryByText(/Isi/i)).toBeFalsy();
......
...@@ -7,24 +7,31 @@ import * as ROUTES from 'constants/routes'; ...@@ -7,24 +7,31 @@ import * as ROUTES from 'constants/routes';
import { styles } from './styles'; import { styles } from './styles';
import { Props } from './types'; import { Props } from './types';
import { getDateRange } from 'utils/format'; import { getDateRange } from 'utils/format';
import { EmptyDataPage } from 'components/core';
const ChooseWeek: FC<Props> = ({ data, isNutritionist }) => { const ChooseWeek: FC<Props> = ({ data, isNutritionist }) => {
const redirectViewRoute = isNutritionist ? '' : ROUTES.weeklyReportReadOnly; // TODO const redirectViewRoute = isNutritionist
? ROUTES.clientDietReportNutritionist
: ROUTES.weeklyReportReadOnly;
const navigation = useNavigation(); const navigation = useNavigation();
if (!data) {
return <EmptyDataPage text="Laporan mingguan tidak ditemukan" />;
}
const getDateRangeForWeek = (weekNum: number) => { const getDateRangeForWeek = (weekNum: number) => {
const { mon, sun } = getDateRange(data.current_week_num - weekNum); const { mon, sun } = getDateRange(data.today_week - weekNum);
return `${mon.format('DD MMM YYYY')} - ${sun.format('DD MMM YYYY')}`; return `${mon.format('DD MMM YYYY')} - ${sun.format('DD MMM YYYY')}`;
}; };
return ( return (
<ScrollView contentContainerStyle={styles.container}> <ScrollView contentContainerStyle={styles.container}>
<View style={styles.pageContainer}> <View style={styles.pageContainer}>
{!isNutritionist && data.has_not_filled_form ? ( {!isNutritionist && !data.has_submitted_this_week ? (
<View style={styles.page}> <View style={styles.page}>
<View style={styles.text}> <View style={styles.text}>
<Text style={styles.bold}>Minggu {data.current_week_num}</Text> <Text style={styles.bold}>Minggu {data.today_week}</Text>
<Text>{getDateRangeForWeek(data.current_week_num)}</Text> <Text>{getDateRangeForWeek(data.today_week)}</Text>
</View> </View>
<View style={styles.buttonContainer}> <View style={styles.buttonContainer}>
<Button <Button
...@@ -36,7 +43,7 @@ const ChooseWeek: FC<Props> = ({ data, isNutritionist }) => { ...@@ -36,7 +43,7 @@ const ChooseWeek: FC<Props> = ({ data, isNutritionist }) => {
</View> </View>
</View> </View>
) : null} ) : null}
{data.reports.map((report, i) => ( {data.data.map((report, i) => (
<View style={styles.page} key={i}> <View style={styles.page} key={i}>
<View style={styles.text}> <View style={styles.text}>
<Text style={styles.bold}>Minggu {report.week_num}</Text> <Text style={styles.bold}>Minggu {report.week_num}</Text>
...@@ -46,7 +53,7 @@ const ChooseWeek: FC<Props> = ({ data, isNutritionist }) => { ...@@ -46,7 +53,7 @@ const ChooseWeek: FC<Props> = ({ data, isNutritionist }) => {
<Button <Button
title="Lihat" title="Lihat"
type="outline" type="outline"
onPress={() => navigation.navigate(redirectViewRoute)} onPress={() => navigation.navigate(redirectViewRoute, report)}
buttonStyle={styles.outlineButtonStyle} buttonStyle={styles.outlineButtonStyle}
titleStyle={styles.buttonTitle} titleStyle={styles.buttonTitle}
/> />
......
import { UserReportResponse } from 'services/progress/models'; import { UserReportsResponse } from 'services/progress/models';
export interface Props { export interface Props {
data: { data: UserReportsResponse | undefined;
has_not_filled_form: boolean;
current_week_num: number;
reports: UserReportResponse[];
}; // TODO: Kefas adjust to API response
isNutritionist?: boolean; isNutritionist?: boolean;
} }
import React, { FC } from 'react'; import React, { FC, useContext } from 'react';
import ChooseWeek from '../ChooseWeek'; import ChooseWeek from '../ChooseWeek';
import { mockUserReportHistory } from 'mocks/userReport'; import { Loader } from 'components/core';
import { retrieveUserReportsByIdApi } from 'services/progress';
import { useApi } from 'hooks';
import { UserContext } from 'provider';
const ChooseWeekForClient: FC = () => { const ChooseWeekForClient: FC = () => {
// call for API, get client id from user context? or discuss with backend const { user } = useContext(UserContext);
const data = mockUserReportHistory;
const { isLoading, data } = useApi(() => retrieveUserReportsByIdApi(user.id));
if (isLoading) {
return <Loader />;
}
return <ChooseWeek data={data} />; return <ChooseWeek data={data} />;
}; };
......
...@@ -10,6 +10,11 @@ jest.mock('@react-navigation/native', () => { ...@@ -10,6 +10,11 @@ jest.mock('@react-navigation/native', () => {
useNavigation: () => ({ useNavigation: () => ({
navigate: mockedNavigate, navigate: mockedNavigate,
}), }),
useRoute: () => ({
params: {
id: 1,
},
}),
}; };
}); });
......
import React, { FC } from 'react'; import React, { FC } from 'react';
import ChooseWeek from '../ChooseWeek'; import ChooseWeek from '../ChooseWeek';
import { mockUserReportHistory } from 'mocks/userReport'; import { useApi } from 'hooks';
import { retrieveUserReportsByIdApi } from 'services/progress';
import { Loader } from 'components/core';
import { useRoute } from '@react-navigation/native';
const ChooseWeekForNutritionist: FC = () => { const ChooseWeekForNutritionist: FC = () => {
// call for API, get client id dr yg d pass? const route = useRoute();
const data = mockUserReportHistory; const { id } = route.params as { id: number };
const { isLoading, data } = useApi(() => retrieveUserReportsByIdApi(id));
if (isLoading) {
return <Loader />;
}
return <ChooseWeek data={data} isNutritionist />; return <ChooseWeek data={data} isNutritionist />;
}; };
......
...@@ -15,19 +15,19 @@ import { page4 } from './pages/Page4'; ...@@ -15,19 +15,19 @@ import { page4 } from './pages/Page4';
const ReadOnlyWeeklyReport: FC = () => { const ReadOnlyWeeklyReport: FC = () => {
const [activeSlide, setActiveSlide] = useState(0); const [activeSlide, setActiveSlide] = useState(0);
const route = useRoute(); const route = useRoute();
const data = route.params as UserReportResponse[]; const data = route.params as UserReportResponse;
const { isLoading, data: commentData } = useApi(() => const { isLoading, data: commentData } = useApi(() =>
retrieveUserReportCommentByReportId(data[0].id), retrieveUserReportCommentByReportId(data.id),
); );
const pageComponents = [ const pageComponents = [
<WeeklyReportPage questions={page1(data[0])} title="Laporan Diet Anda" />, <WeeklyReportPage questions={page1(data)} title="Laporan Diet Anda" />,
<WeeklyReportPage questions={page2(data[0])} />, <WeeklyReportPage questions={page2(data)} />,
<WeeklyReportPage <WeeklyReportPage
questions={page3(data[0])} questions={page3(data)}
title="Selama 1 minggu terakhir, berapa rata-rata Anda mengonsumsi jenis makanan dibawah ini selama seharian?" title="Selama 1 minggu terakhir, berapa rata-rata Anda mengonsumsi jenis makanan dibawah ini selama seharian?"
/>, />,
<WeeklyReportPage questions={page4(data[0])} />, <WeeklyReportPage questions={page4(data)} />,
]; ];
if (isLoading) { if (isLoading) {
......
...@@ -6,11 +6,12 @@ import { ...@@ -6,11 +6,12 @@ import {
UserReportRequest, UserReportRequest,
NutritionistCommentRequest, NutritionistCommentRequest,
NutritionistCommentResponse, NutritionistCommentResponse,
UserReportsResponse,
} from './models'; } from './models';
export const retrieveUserReportByIdApi = ( export const retrieveUserReportsByIdApi = (
clientId: number, clientId: number | null,
): ApiResponse<UserReportResponse[]> => { ): ApiResponse<UserReportsResponse> => {
return api(RequestMethod.GET, apiUrls.userReportByClientId(clientId)); return api(RequestMethod.GET, apiUrls.userReportByClientId(clientId));
}; };
......
...@@ -32,6 +32,12 @@ export interface UserReportResponse extends UserReportRequest { ...@@ -32,6 +32,12 @@ export interface UserReportResponse extends UserReportRequest {
week_num: number; week_num: number;
} }
export interface UserReportsResponse {
has_submitted_this_week: boolean;
today_week: number;
data: UserReportResponse[];
}
export interface NutritionistComment { export interface NutritionistComment {
weight: string; weight: string;
height: string; height: string;
......
export const progress = 'progress/'; export const progress = 'progress/';
export const userReport = `${progress}user_report/`; export const userReport = `${progress}user_report/`;
export const userReportByClientId = (id: number) => export const userReportByClientId = (id: number | null) =>
`${userReport}?client_id=${id}`; `${userReport}?client_id=${id}`;
export const userReportCommentByReportId = (id: number) => export const userReportCommentByReportId = (id: number) =>
`${progress}nutritionist_comment/?weekly_report_id=${id}`; `${progress}nutritionist_comment/?weekly_report_id=${id}`;
......
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