Fakultas Ilmu Komputer UI

Commit b256c31c authored by Doan Andreas Nathanael's avatar Doan Andreas Nathanael
Browse files

Integrate Quiz Result UI with backend API

parent 1cd4ad49
......@@ -6,16 +6,24 @@ import ResultCard from '.';
describe('ResultCard', () => {
const info = [
{
title: 'Energi per hari',
label: 'Energi per hari',
content: '1953 kkal',
},
{
title: 'Protein per hari',
label: 'Protein per hari',
content: '23 kkal',
},
];
it('renders correctly', () => {
it('renders correctly when healthy', () => {
render(<ResultCard status="healthy" infos={info} />);
});
it('renders correctly when warning', () => {
render(<ResultCard status="warning" infos={info} />);
});
it('renders correctly when danger', () => {
render(<ResultCard status="danger" infos={info} />);
});
});
......@@ -5,14 +5,14 @@ import { typographyStyles } from 'styles';
import { styles } from './styles';
interface Props {
infos: { title: string; content: string }[];
infos: { label: string; content: string }[];
status: 'healthy' | 'warning' | 'danger';
testID?: string;
}
const ResultCard: FC<Props> = ({ infos, status, testID }) => {
const getColorFromStatus = (status: string) => {
if (status === 'healthy') {
const getColorFromStatus = (cardStatus: string) => {
if (cardStatus === 'healthy') {
return '#1DD1A1';
} else if (status === 'warning') {
return '#FF9A3E';
......@@ -33,21 +33,18 @@ const ResultCard: FC<Props> = ({ infos, status, testID }) => {
{infoPairs.map((pair, ii) => (
<View style={styles.row} key={ii}>
{pair.map((info, jj) => {
const padding =
jj % 2 === 0
? { flex: 1, paddingRight: 10 }
: { flex: 1, paddingLeft: 10 };
const padding = jj % 2 === 0 ? styles.leftSide : styles.rightSide;
return (
<View style={[styles.content, padding]} key={info.title}>
<View style={[styles.content, padding]} key={info.label}>
<Text style={[typographyStyles.overlineBig, styles.text]}>
{info.title}
{info.label}
</Text>
<Text
style={[
typographyStyles.headingMedium,
styles.text,
{ marginTop: 4 },
styles.marginTop,
]}>
{info.content}
</Text>
......
......@@ -15,4 +15,15 @@ export const styles = StyleSheet.create({
text: {
color: colors.neutralLight,
},
marginTop: {
marginTop: 4,
},
leftSide: {
flex: 1,
paddingRight: 10,
},
rightSide: {
flex: 1,
paddingLeft: 10,
},
});
import React from 'react';
import { render } from '@testing-library/react-native';
import MakanPagi from '.';
import Column from '.';
describe('MakanPagi', () => {
describe('Column', () => {
it('renders correctly', () => {
render(<MakanPagi />);
render(<Column />);
});
});
import React, { FC } from 'react';
import { View } from 'react-native';
import { styles } from './styles';
const Column: FC = ({ children }) => (
<View style={styles.column}>{children}</View>
);
export default Column;
import { StyleSheet } from 'react-native';
export const styles = StyleSheet.create({
view: {
column: {
flex: 1,
},
resultImage: {
width: '100%',
resizeMode: 'contain',
},
sectionHeader: {
marginBottom: 8,
},
});
import React from 'react';
import { render } from '@testing-library/react-native';
import AsupanGGL from '.';
import Row from '.';
describe('AsupanGGL', () => {
describe('Row', () => {
it('renders correctly', () => {
render(<AsupanGGL />);
render(<Row />);
});
});
import React, { FC } from 'react';
import { View } from 'react-native';
import { styles } from './styles';
const Row: FC = ({ children }) => <View style={styles.row}>{children}</View>;
export default Row;
import { StyleSheet } from 'react-native';
export const styles = StyleSheet.create({
row: {
flexDirection: 'row',
},
});
export { default as Section } from './Section';
export { default as Row } from './Row';
export { default as Column } from './Column';
......@@ -3,7 +3,7 @@ import { View, Text, ImageBackground, Image } from 'react-native';
import { layoutStyles, typographyStyles } from '../../../styles';
import { styles } from './styles';
import { banner_girl_eating, logo_white_small } from '../../../assets/images';
import { banner_girl_eating, logo_white_small } from 'assets/images';
import * as ROUTES from 'constants/routes';
import BigButton from 'components/core/Button';
......
......@@ -39,6 +39,7 @@ const AllAccessQuestionnaire: FC = () => {
validationSchema: generateValidationSchema(fieldValidations),
onSubmit: async (values) => {
const response = await createDietProfileApi(convertPayload(values));
if (response.success) {
await AsyncStorage.setItem(
CACHE_KEYS.dietProfileId,
......
import React from 'react';
import { render } from '@testing-library/react-native';
import { render } from 'utils/testing';
import * as ROUTES from 'constants/routes';
import DietelaQuizResult from '.';
describe('DietelaQuizResult', () => {
it('renders correctly', () => {
render(<DietelaQuizResult />);
render(<DietelaQuizResult />, ROUTES.dietelaQuizResult);
});
});
......@@ -3,18 +3,9 @@ import { View, Dimensions } from 'react-native';
import Carousel from 'react-native-snap-carousel';
import { CarouselPagination } from 'components/core';
import {
AktivitasFisik,
AsupanGGL,
DetailEnergiSehari,
KebutuhanEnergiZatGizi,
KecukupanSayurBuah,
MakanBesar,
MakanCemilan,
MakanPagi,
StatusBeratBadan,
} from './pages';
import { ResultPage, pages } from './pages';
import { styles } from './styles';
import { exampleResult } from 'services/dietelaQuiz/quizResult';
const DietelaQuizResult: FC = () => {
const [activeSlide, setActiveSlide] = useState(0);
......@@ -22,17 +13,13 @@ const DietelaQuizResult: FC = () => {
return (
<View style={styles.view}>
<Carousel
data={[
<StatusBeratBadan />,
<KebutuhanEnergiZatGizi />,
<KecukupanSayurBuah />,
<AsupanGGL />,
<MakanBesar />,
<MakanCemilan />,
<MakanPagi />,
<AktivitasFisik />,
<DetailEnergiSehari />,
]}
data={pages.map((page, idx) =>
idx === 8 ? (
<ResultPage content={page(exampleResult)} cta />
) : (
<ResultPage content={page(exampleResult)} />
),
)}
renderItem={({ item }) => item}
sliderWidth={Dimensions.get('window').width}
itemWidth={Dimensions.get('window').width}
......
import React from 'react';
import { render } from '@testing-library/react-native';
import AktivitasFisik from '.';
describe('AktivitasFisik', () => {
it('renders correctly', () => {
render(<AktivitasFisik />);
});
});
import { DietProfileResponse } from 'services/dietelaQuiz/models';
import { aktivitasFisikStatus } from 'services/dietelaQuiz/quizResult';
import { ResultPageContent } from '../types';
import { genericResult, getAnswerString, getInfos } from '../utils';
const aktivitasFisik = (response: DietProfileResponse): ResultPageContent => {
const result = response.quiz_result;
const recommendation = result.physical_activity_recommendation;
const { infosContent, infoStatus } = getInfos(
aktivitasFisikStatus[recommendation],
);
// body_activity
const activity = getAnswerString('body_activity', response.body_activity);
return genericResult(
'Aktivitas fisik',
'status aktivitas fisik',
infosContent,
infoStatus,
recommendation,
[activity],
);
};
export default aktivitasFisik;
import React, { FC } from 'react';
import { View, Text } from 'react-native';
import { AutoImage, InfoCard, ResultCard } from 'components/core';
import { Section } from 'components/layout';
import { layoutStyles, typographyStyles } from 'styles';
import { styles } from '../styles';
import { status_berat_badan } from '../../../../../assets/images';
import { ScrollView } from 'react-native-gesture-handler';
const info = [
{
title: 'status aktivitas fisik',
content: 'Perbanyak olahraga',
},
];
const AktivitasFisik: FC = () => (
<View style={layoutStyles}>
<ScrollView>
<Text style={typographyStyles.headingLarge}>Porsi Makan Pagi</Text>
<Section>
<AutoImage source={status_berat_badan} ratio={0.5} />
</Section>
<Section>
<ResultCard status="warning" infos={info} />
</Section>
<Section>
<Text style={[typographyStyles.bodySmall, styles.sectionHeader]}>
Ini rekomendasi yang Dietela berikan untukmu:
</Text>
<InfoCard
content={
'Hayooo kok duduk-duduk aja? Yuk ah mulai lakukan aktivitas fisik, dimulai dari aktivitas yang ringan seperti jalan kaki, jogging, senam, atau naik turun tangga 15 menit per hari. Tingkatkan perlahan hingga mencapai 30 menit per hari. Konsultasikan kebutuhan gizi harianmu kepada Dietela agar asupan makan kamu seimbang dengan energi yang kamu keluarkan setiap harinya'
}
/>
</Section>
<Section>
<Section>
<Text style={[typographyStyles.bodySmall, styles.sectionHeader]}>
Berdasarkan jawaban kuis kamu:
</Text>
<InfoCard content="3 porsi sayur per hari" />
</Section>
</Section>
</ScrollView>
</View>
);
export default AktivitasFisik;
import { gglStatus } from 'services/dietelaQuiz/quizResult';
import { DietProfileResponse } from 'services/dietelaQuiz/models';
import { ResultPageContent } from '../types';
import { genericResult, getAnswerString } from '../utils';
const asupanGGL = (response: DietProfileResponse): ResultPageContent => {
const result = response.quiz_result;
const infosContent = result.sugar_salt_fat_problem;
const infoStatus = gglStatus[infosContent].status;
const recommendation = result.sugar_salt_fat_diet_recommendation;
const fried = getAnswerString(
'fried_food_in_one_day',
response.fried_food_in_one_day,
);
const snack = getAnswerString(
'sweet_snacks_in_one_day',
response.sweet_snacks_in_one_day,
);
const drink = getAnswerString(
'sweet_drinks_in_one_day',
response.sweet_drinks_in_one_day,
);
const packaged = getAnswerString(
'packaged_food_in_one_day',
response.packaged_food_in_one_day,
);
const questions = [fried, snack, drink, packaged];
return genericResult(
'Asupan Gula, Garam, dan Lemak (GGL)',
'status asupan ggl',
infosContent,
infoStatus,
recommendation,
questions,
);
};
export default asupanGGL;
import React, { FC } from 'react';
import { View, Text } from 'react-native';
import { AutoImage, InfoCard, ResultCard } from 'components/core';
import { Section } from 'components/layout';
import { layoutStyles, typographyStyles } from 'styles';
import { styles } from '../styles';
import { status_berat_badan } from '../../../../../assets/images';
import { ScrollView } from 'react-native-gesture-handler';
const info = [
{
title: 'status asupan ggl',
content: 'Kelebihan makan gula, garam, dan lemak',
},
];
const AsupanGGL: FC = () => (
<View style={layoutStyles}>
<ScrollView>
<Text style={typographyStyles.headingLarge}>
Asupan Gula, Garam, dan Lemak (GGL)
</Text>
<Section>
<AutoImage source={status_berat_badan} ratio={0.5} />
</Section>
<Section>
<ResultCard status="warning" infos={info} />
</Section>
<Section>
<Text style={[typographyStyles.bodySmall, styles.sectionHeader]}>
Ini rekomendasi yang Dietela berikan untukmu:
</Text>
<InfoCard
content={
'Duh, asupan gula, garam, dan lemak kamu kebanyakan nih. Asupan gula, garam, dan lemak juga ada batasannya lho. Kamu harus hati-hati dalam memilih jenis makanan. Kalau konsumsi kamu berlebih berisiko menimbulkan masalah kesehatan juga Lho. '
}
/>
</Section>
<Section>
<Section>
<Text style={[typographyStyles.bodySmall, styles.sectionHeader]}>
Berdasarkan jawaban kuis kamu:
</Text>
<InfoCard content="3 porsi sayur per hari" />
</Section>
</Section>
</ScrollView>
</View>
);
export default AsupanGGL;
import React from 'react';
import { render, fireEvent } from '@testing-library/react-native';
import DetailEnergiSehari from '.';
describe('DetailEnergiSehari', () => {
it('renders correctly', () => {
render(<DetailEnergiSehari />);
});
test('has call-to-action button', () => {
const { queryByTestId } = render(<DetailEnergiSehari />);
const button = queryByTestId('cta-button');
fireEvent.press(button);
expect(button).toBeTruthy();
});
});
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