Fakultas Ilmu Komputer UI

Commit 298870ed authored by Doan Andreas Nathanael's avatar Doan Andreas Nathanael
Browse files

Diet Program Detail UI Layout + API Integration

parent d775910c
import React, { FC } from 'react';
import { View } from 'react-native';
import { View, StyleSheet } from 'react-native';
const Section: FC = ({ children }) => (
<View style={{ marginTop: 15 }}>{children}</View>
<View style={styles.margin}>{children}</View>
);
const styles = StyleSheet.create({
margin: {
marginTop: 15,
},
});
export default Section;
import React from 'react';
import { render } from '@testing-library/react-native';
import HeadingLarge from '.';
describe('HeadingLarge', () => {
it('renders correctly', () => {
render(<HeadingLarge text="Hai" />);
});
});
import React, { FC } from 'react';
import { Text } from 'react-native-elements';
import { typographyStyles } from 'styles';
const BodyMedium: FC<{ text: String }> = ({ text }) => (
<Text style={typographyStyles.bodyMedium}>{text}</Text>
);
export default BodyMedium;
import React from 'react';
import { render } from '@testing-library/react-native';
import BodyMedium from '.';
describe('BodyMedium', () => {
it('renders correctly', () => {
render(<BodyMedium text="Hai" />);
});
});
import React, { FC } from 'react';
import { Text } from 'react-native-elements';
import { typographyStyles } from 'styles';
const HeadingLarge: FC<{ text: String }> = ({ text }) => (
<Text style={typographyStyles.headingLarge}>{text}</Text>
);
export default HeadingLarge;
export { default as HeadingLarge } from './HeadingLarge';
export { default as BodyMedium } from './BodyMedium';
......@@ -2,6 +2,12 @@ import {
ProgramRecommendations,
DietelaProgram,
} from 'services/dietelaQuiz/quizResult';
import {
babyProgram,
balancedDietProgram,
bodyGoalsProgram,
oneTimeConsultation,
} from './programDetail';
const prices = {
oneWeek: '239,900',
......@@ -14,38 +20,47 @@ export const dietPrograms = {
[DietelaProgram.TRIAL]: {
title: 'One Week Trial (7 Hari)',
price: prices.oneWeek,
details: oneTimeConsultation,
},
[DietelaProgram.BALANCED_1]: {
title: 'Balanced Diet (1 Bulan)',
price: prices.oneMonth,
details: balancedDietProgram,
},
[DietelaProgram.BALANCED_3]: {
title: 'Balanced Diet (3 Bulan)',
price: prices.threeMonths,
details: balancedDietProgram,
},
[DietelaProgram.BALANCED_6]: {
title: 'Balanced Diet (6 Bulan)',
price: prices.sixMonths,
details: balancedDietProgram,
},
[DietelaProgram.GOALS_1]: {
title: 'Body Goals (1 Bulan)',
price: prices.oneMonth,
details: bodyGoalsProgram,
},
[DietelaProgram.GOALS_3]: {
title: 'Body Goals (3 Bulan)',
price: prices.threeMonths,
details: bodyGoalsProgram,
},
[DietelaProgram.GOALS_6]: {
title: 'Body Goals (6 Bulan)',
price: prices.sixMonths,
details: bodyGoalsProgram,
},
[DietelaProgram.BABY_1]: {
title: 'Body for Baby (1 Bulan)',
price: prices.oneMonth,
details: babyProgram,
},
[DietelaProgram.BABY_3]: {
title: 'Body for Baby (3 Bulan)',
price: prices.threeMonths,
details: babyProgram,
},
};
......
......@@ -5,6 +5,7 @@ import {
ComingSoonPage,
DietelaQuizResult,
InitialPage,
ProgramDetail,
} from 'scenes';
import { FC } from 'react';
......@@ -42,7 +43,7 @@ export const navigation: NavRoute[] = [
},
{
name: ROUTES.programDetail,
component: ComingSoonPage,
component: ProgramDetail,
header: 'Program Dietela',
},
{
......
interface ProgramDetails {
description: string;
details: {
title: string;
content: string[];
}[];
}
export const balancedDietProgram: ProgramDetails = {
description:
'Dalam Program yang didesain khusus secara personalised untuk kamu. Sehat bukan hanya diukur dari angka di timbangan. Namun seberapa banyak perubahan kebiasaan sehat yang kamu capai, yang akan merubah pola makan kamu dan hidup lebih sehat untuk jangka panjang! #DietGayaKuSendiri',
details: [
{
title: 'Di akhir program, yang akan kamu rasakan:',
content: [
'Badan terasa lebih fit, bonus turun berat badan atau hasil lab mulai terkontrol',
'Mindset positif terhadap tubuh dan makanan',
'Lebih tau cara memilih jenis makanan yang cocok untuk kamu',
'Bisa mengukur porsi makan sendiri',
'Bisa mengenali sinyal lapar dan kenyang (mindful eating)',
'Lebih bisa menghargai tubuh dan kesehatan',
],
},
{
title: 'Untuk mencapai goal sehat kamu, program ini menyediakan:',
content: [
'Konseling One-on-One melalui video call dengan nutrisionis pribadimu',
'Penilaian Kondisi Gizi',
'Personalized Meal Plan (sesuai kondisi, kebutuhan dan kesukaan kamu)',
'Konsultasi harian (Online Chat) dengan nutrisionis pribadimu',
'Materi coaching selama 1, 3, atau 6 bulan',
'Personalized Menu 10 Hari (di update setiap bulan, selama berlangganan)',
'Evaluasi',
],
},
],
};
export const bodyGoalsProgram: ProgramDetails = {
description:
'Untuk mendapatkan berat badan yang ideal, pola makan yang sehat adalah kunci utama. Tapi bukan berarti kamu harus ninggalin makanan enak yang kamu suka! Kuncinya adalah makan sesuai dengan kebutuhanmu #DietGayaKuSendiri. Pilih tipe program yang sesuai dengan target kamu.',
details: [
{
title: 'Di akhir program, yang akan kamu rasakan:',
content: [
'Berat badan sesuai goal realistis kamu',
'Tetap enjoy makanan yang kamu suka dengan lebih mindful',
'Menghargai tubuh kamu kamu sendiri',
'Berat badan yang bertahan untuk jangka panjang, anti yo-yo diet',
],
},
{
title:
'Dalam Body Goals Program, kamu akan dipandu untuk mendapatkan Berat badan ideal dengan cara yang seimbang, aman dan terbukti secara ilmiah. Program ini menyediakan:',
content: [
'Konseling One-on-One melalui video call dengan nutrisionis pribadimu',
'Penilaian Kondisi Gizi',
'Personalized Meal Plan (sesuai kondisi, kebutuhan dan kesukaan kamu)',
'Konsultasi harian (Online Chat) dengan nutrisionis pribadimu',
'Materi coaching selama 1, 3, atau 6 bulan',
'Personalized Menu 10 Hari (di update setiap bulan, selama berlangganan)',
'Evaluasi',
],
},
],
};
export const babyProgram: ProgramDetails = {
description:
'Program Body for Baby memastikan calon ibu terpenuhi kebutuhan gizinya, lewat program yang mudah diterapkan. Mulai perjalanan kamu menjadi seorang ibu, bersama Dietela!',
details: [
{
title: 'Di akhir program, yang akan kamu rasakan:',
content: [
'Berat badan semakin ideal',
'Gula darah normal',
'Badan yang lebih bugar',
'Perbaikan pola makan dan gaya hidup yang dapat mendukung kesuburan',
],
},
{
title:
'Program Dietela ini akan mendampingi perjalanan kamu mejadi ibu lewat:',
content: [
'Konseling One-on-One melalui video call dengan nutrisionis pribadimu',
'Penilaian Kondisi Gizi',
'Personalized Meal Plan (sesuai kondisi, kebutuhan dan kesukaan kamu)',
'Konsultasi harian (Online Chat) dengan nutrisionis pribadimu',
'Materi coaching selama 1, 3, atau 6 bulan',
'Personalized Menu 10 Hari (di update setiap bulan, selama berlangganan)',
'Evaluasi',
],
},
],
};
export const oneTimeConsultation: ProgramDetails = {
description:
'Kamu belum siap berkomitmen jangka panjang? Program 1 minggu Dietela ini layaknya sneak peak agar kamu bisa lebih kenal pola makan dan gaya hidup sehat yang cocok untukmu.',
details: [
{
title: 'Yang akan kamu dapatkan:',
content: [
'Konseling One-on-One melalui video call dengan nutrisionis pribadimu',
'Penilaian Kondisi Gizi',
'Personalized Meal Plan (sesuai kondisi, kebutuhan dan kesukaan kamu)',
'Konsultasi harian (Online Chat) dengan nutrisionis pribadimu',
'Materi coaching 7 hari',
'Personalized Menu 10 Hari',
],
},
],
};
......@@ -11,6 +11,7 @@ import {
BreakfastReponse,
PhysicalActivityResponse,
} from 'services/dietelaQuiz/quizResult';
import { DietelaProgram } from 'services/dietelaQuiz/quizResult';
import { defaultProgramRecommendations } from 'constants/dietelaProgram';
const validFormValues: DietProfileRequest = {
......@@ -36,6 +37,16 @@ const validFormValues: DietProfileRequest = {
health_problem: [2, 3],
};
export const mockProgramRecommendations = {
priority_1: DietelaProgram.TRIAL,
priority_2: null,
};
export const mockBodyGoals = {
priority_1: DietelaProgram.GOALS_3,
priority_2: DietelaProgram.GOALS_1,
};
export const mockQuizResult: DietProfileResponse = {
id: 1,
...validFormValues,
......
......@@ -4,6 +4,8 @@ import axios from 'axios';
import * as ROUTES from 'constants/routes';
import ChoosePlan from '.';
import { mockProgramRecommendations } from 'mocks/quizResult';
import { dietPrograms } from 'constants/dietelaProgram';
import { defaultProgramRecommendations } from 'constants/dietelaProgram';
jest.mock('axios');
......@@ -132,7 +134,10 @@ describe('ChoosePlan', () => {
expect(readMoreButton).toBeTruthy();
fireEvent.press(readMoreButton);
const programDetailPage = getByText(/Coming Soon/i);
const program = mockProgramRecommendations.priority_1;
const programDetails = dietPrograms[program].details;
const programDetailPage = getByText(programDetails.description);
expect(programDetailPage).toBeTruthy();
});
......
import React from 'react';
import { render } from 'utils/testing';
import * as ROUTES from 'constants/routes';
import ProgramDetail from '.';
import { dietPrograms } from 'constants/dietelaProgram';
import { DietelaProgram } from 'services/dietelaQuiz/quizResult';
describe('ProgramDetail', () => {
const id = DietelaProgram.GOALS_1;
it('shows program details content correctly', () => {
const { getByText } = render(<ProgramDetail />, ROUTES.programDetail, {
id: id,
});
const programDetail = dietPrograms[id].details;
const description = getByText(programDetail.description);
expect(description).toBeTruthy();
const firstDetail = programDetail.details[0];
expect(getByText(firstDetail.title)).toBeTruthy();
const secondDetail = programDetail.details[1];
expect(getByText(secondDetail.title)).toBeTruthy();
});
});
import { useRoute } from '@react-navigation/core';
import { Section } from 'components/layout';
import { BodyMedium, HeadingLarge } from 'components/typography';
import { dietPrograms } from 'constants/dietelaProgram';
import React, { FC } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { Icon, ListItem } from 'react-native-elements';
import { ScrollView } from 'react-native-gesture-handler';
import { DietelaProgram } from 'services/cart/models';
import { colors, layoutStyles } from 'styles';
interface IdProgram {
id: DietelaProgram;
}
const styles = StyleSheet.create({
padding: { padding: 10 },
});
const ProgramDetail: FC = () => {
const route = useRoute();
const { id } = route.params as IdProgram;
const programTitle = dietPrograms[id].title;
const programDetail = dietPrograms[id].details;
return (
<ScrollView contentContainerStyle={layoutStyles}>
<HeadingLarge text={programTitle} />
<Section>
<BodyMedium text={programDetail.description} />
</Section>
{programDetail.details.map((detail, i) => (
<View key={`details${i}`}>
<Section>
<Text>{detail.title}</Text>
</Section>
{detail.content.map((item, j) => (
<ListItem key={`info${j}`} containerStyle={styles.padding}>
<Icon name="check" color={colors.primary} />
<ListItem.Content>
<ListItem.Title>{item}</ListItem.Title>
</ListItem.Content>
</ListItem>
))}
</View>
))}
</ScrollView>
);
};
export default ProgramDetail;
export { default as AllAccessQuestionnaire } from './questionnaire/AllAccessQuestionnaire';
export { default as ChoosePlan } from './cart/ChoosePlan';
export { default as ProgramDetail } from './cart/ProgramDetail';
export { default as ComingSoonPage } from './common/ComingSoonPage';
export { default as DietelaQuizResult } from './questionnaire/DietelaQuizResult';
export { default as InitialPage } from './common/InitialPage';
Supports Markdown
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