Fakultas Ilmu Komputer UI

Commit 7f321890 authored by Doan Andreas Nathanael's avatar Doan Andreas Nathanael
Browse files

Merge branch 'PBI-3-nutritionist_detail' into 'staging'

Nutritionist Detail UI & API Integration

See merge request !36
parents 6199efa7 92caf6b4
Pipeline #73613 canceled with stages
in 29 minutes and 20 seconds
export const banner_girl_eating = require('./banner_girl_eating.png'); export const banner_girl_eating = require('./banner_girl_eating.png');
export const logo_white_small = require('./logo_white_small.png'); export const logo_white_small = require('./logo_white_small.png');
export const status_berat_badan = require('./status_berat_badan.png'); export const status_berat_badan = require('./status_berat_badan.png');
export const default_nutritionist = require('./default_nutritionist.png');
export const googleLogo = require('./google_logo.png'); export const googleLogo = require('./google_logo.png');
export const dietelaLogo = require('./dietela_logo.png'); export const dietelaLogo = require('./dietela_logo.png');
import { Nutritionist } from 'services/nutritionists/models';
export const nutritionistDummy: Nutritionist = {
id: 1,
full_name_and_degree: 'Wendy',
registration_certificate_no: '432491859',
university: 'UGM',
mastered_nutritional_problems: 'Manajemen berat badan, hipertensi',
handled_age_group: '12 - 17 tahun (Remaja)',
another_practice_place: 'RSIU',
languages: 'Bahasa Indonesia, Jepang',
};
import { Column } from 'components/layout';
import React, { FC } from 'react'; import React, { FC } from 'react';
import { View, Text } from 'react-native'; import { View, Text } from 'react-native';
import { typographyStyles } from 'styles'; import { typographyStyles } from 'styles';
import { styles } from './styles'; import { styles } from './styles';
interface Props { interface Props {
title: string; title?: string;
emote: string; emote: string;
content: string; content: string;
testID?: string; testID?: string;
...@@ -13,18 +14,20 @@ interface Props { ...@@ -13,18 +14,20 @@ interface Props {
const Statistic: FC<Props> = ({ title, emote, content, testID }) => { const Statistic: FC<Props> = ({ title, emote, content, testID }) => {
return ( return (
<View testID={testID}> <View testID={testID}>
<Text style={[typographyStyles.overlineBig, styles.title]}>{title}</Text> {title && (
<Text style={[typographyStyles.overlineBig, styles.title]}>
{title}
</Text>
)}
<View> <View>
<Text style={typographyStyles.bodyMedium}> <Column>
<View style={styles.emote}> <View style={styles.row}>
<Text style={[typographyStyles.bodyMedium, styles.emote]}> <Text style={[typographyStyles.bodyMedium, styles.emote]}>
{emote} {emote}
</Text> </Text>
</View>
<View>
<Text style={typographyStyles.bodyMedium}>{content}</Text> <Text style={typographyStyles.bodyMedium}>{content}</Text>
</View> </View>
</Text> </Column>
</View> </View>
</View> </View>
); );
......
...@@ -10,4 +10,8 @@ export const styles = StyleSheet.create({ ...@@ -10,4 +10,8 @@ export const styles = StyleSheet.create({
emote: { emote: {
marginRight: 8, marginRight: 8,
}, },
row: {
flexDirection: 'row',
width: '90%',
},
}); });
...@@ -9,6 +9,7 @@ import { ...@@ -9,6 +9,7 @@ import {
ManualRegistrationPage, ManualRegistrationPage,
LoginPage, LoginPage,
ProgramDetail, ProgramDetail,
NutritionistDetail,
} from 'scenes'; } from 'scenes';
import { FC } from 'react'; import { FC } from 'react';
...@@ -50,7 +51,7 @@ export const navigation: NavRoute[] = [ ...@@ -50,7 +51,7 @@ export const navigation: NavRoute[] = [
}, },
{ {
name: ROUTES.nutritionistDetail, name: ROUTES.nutritionistDetail,
component: ComingSoonPage, component: NutritionistDetail,
header: 'Nutrisionis', header: 'Nutrisionis',
}, },
{ {
......
...@@ -73,9 +73,6 @@ describe('Checkout', () => { ...@@ -73,9 +73,6 @@ describe('Checkout', () => {
const readMoreButton = getAllByText(/Baca selengkapnya/i)[1]; const readMoreButton = getAllByText(/Baca selengkapnya/i)[1];
expect(readMoreButton).toBeTruthy(); expect(readMoreButton).toBeTruthy();
fireEvent.press(readMoreButton); fireEvent.press(readMoreButton);
const nutritionistDetailPage = getByText(/Coming Soon/i);
expect(nutritionistDetailPage).toBeTruthy();
}); });
it('redirects to choose plan page when user clicks Ganti Pilihan button', async () => { it('redirects to choose plan page when user clicks Ganti Pilihan button', async () => {
......
...@@ -48,7 +48,7 @@ const Checkout: FC = () => { ...@@ -48,7 +48,7 @@ const Checkout: FC = () => {
type="nutritionist" type="nutritionist"
onReadMore={() => onReadMore={() =>
navigation.navigate(ROUTES.nutritionistDetail, { navigation.navigate(ROUTES.nutritionistDetail, {
id: data?.nutritionist.id, ntr: data?.nutritionist,
}) })
} }
/> />
......
...@@ -9,23 +9,13 @@ import CACHE_KEYS from 'constants/cacheKeys'; ...@@ -9,23 +9,13 @@ import CACHE_KEYS from 'constants/cacheKeys';
import { mockProgramRecommendations } from '__mocks__/quizResult'; import { mockProgramRecommendations } from '__mocks__/quizResult';
import { dietPrograms } from 'constants/dietelaProgram'; import { dietPrograms } from 'constants/dietelaProgram';
import { setCache } from 'utils/cache'; import { setCache } from 'utils/cache';
import { nutritionistDummy } from '__mocks__/cart';
jest.mock('axios'); jest.mock('axios');
const mockAxios = axios as jest.Mocked<typeof axios>; const mockAxios = axios as jest.Mocked<typeof axios>;
describe('ChoosePlan', () => { describe('ChoosePlanPalingKeren', () => {
const nutritionists = [ const nutritionists = [nutritionistDummy];
{
id: 1,
full_name_and_degree: 'Wendy',
registration_certificate_no: '123',
university: 'UI',
mastered_nutritional_problems: 'diet',
handled_age_group: '18',
another_practice_place: '-',
languages: 'English',
},
];
const retrieveNutritionistsApi = () => const retrieveNutritionistsApi = () =>
Promise.resolve({ Promise.resolve({
status: 200, status: 200,
...@@ -170,8 +160,10 @@ describe('ChoosePlan', () => { ...@@ -170,8 +160,10 @@ describe('ChoosePlan', () => {
expect(readMoreButton).toBeTruthy(); expect(readMoreButton).toBeTruthy();
fireEvent.press(readMoreButton); fireEvent.press(readMoreButton);
const nutritionistDetailPage = getByText(/Coming Soon/i); // const nutritionistDetailPage = getByText(
expect(nutritionistDetailPage).toBeTruthy(); // nutritionistDummy.full_name_and_degree,
// );
// expect(nutritionistDetailPage).toBeTruthy();
}); });
afterAll(() => { afterAll(() => {
......
...@@ -109,7 +109,7 @@ const ChoosePlan: FC = () => { ...@@ -109,7 +109,7 @@ const ChoosePlan: FC = () => {
.slice(0, 3), .slice(0, 3),
onReadMore: () => onReadMore: () =>
navigation.navigate(ROUTES.nutritionistDetail, { navigation.navigate(ROUTES.nutritionistDetail, {
id: nutritionist.id, ntr: nutritionist,
}), }),
}))} }))}
value={values.nutritionist} value={values.nutritionist}
......
import React from 'react';
import { render } from 'utils/testing';
import * as ROUTES from 'constants/routes';
import NutritionistDetail from '.';
import { nutritionistDummy } from '__mocks__/cart';
describe('NutritionistDetail', () => {
it('renders correctly', () => {
render(<NutritionistDetail />, ROUTES.nutritionistDetail, {
ntr: nutritionistDummy,
});
});
});
import React, { FC } from 'react';
import { useRoute } from '@react-navigation/core';
import { ScrollView } from 'react-native-gesture-handler';
import { AutoImage, Statistic } from 'components/core';
import { Row, Section } from 'components/layout';
import { Nutritionist } from 'services/nutritionists/models';
import { default_nutritionist } from 'assets/images';
import { layoutStyles } from 'styles';
import { HeadingLarge } from 'components/typography';
import { toStatisticList } from './utils';
const NutritionistDetail: FC = () => {
const route = useRoute();
const nutritionist: Nutritionist = route.params.ntr as Nutritionist;
const ntrStats = toStatisticList(nutritionist);
return (
<ScrollView contentContainerStyle={layoutStyles}>
<HeadingLarge text={nutritionist.full_name_and_degree} />
<Section>
<AutoImage source={default_nutritionist} />
</Section>
{ntrStats.map((stat, ii) =>
stat.label ? (
<Section key={`stat${ii}`}>
<Row>
<Statistic
title={stat.label}
emote={stat.emote}
content={stat.content}
/>
</Row>
</Section>
) : (
<Row key={`stat${ii}`}>
<Statistic
title={stat.label}
emote={stat.emote}
content={stat.content}
/>
</Row>
),
)}
<Section />
</ScrollView>
);
};
export default NutritionistDetail;
import { Nutritionist } from 'services/nutritionists/models';
const splitMastery = (mastery: string) => {
return splitStatistics(mastery, 'ahli menangani', '☑️', ';');
};
const splitAgeRange = (ageRange: string) => {
return splitStatistics(ageRange, 'umur klien ditangani', '🎂', ',');
};
const splitLanguage = (language: string) => {
return splitStatistics(language, 'bahasa dikuasai', '💬', ',');
};
const splitStatistics = (
stats: string,
label: string,
emoji: string,
splitBy: string,
) => {
const statsArr = stats.split(splitBy);
return statsArr.map((statsStr, i) => {
if (i === 0) {
return {
label: label,
emote: emoji,
content: statsStr,
};
} else {
return {
emote: emoji,
content: statsStr.trim(),
};
}
});
};
export const toStatisticList = (nutritionist: Nutritionist) => {
return [
{
label: 'nama lengkap',
emote: '👨‍💼',
content: nutritionist.full_name_and_degree,
},
{
label: 'no. sertifikat',
emote: '📃',
content: nutritionist.registration_certificate_no,
},
{
label: 'universitas',
emote: '🎓',
content: nutritionist.university,
},
...splitMastery(nutritionist.mastered_nutritional_problems),
...splitAgeRange(nutritionist.handled_age_group),
{
label: 'tempat praktek lainnya',
emote: '🏥',
content: nutritionist.another_practice_place,
},
...splitLanguage(nutritionist.languages),
];
};
...@@ -10,3 +10,4 @@ export { default as DietelaQuizResult } from './questionnaire/DietelaQuizResult' ...@@ -10,3 +10,4 @@ export { default as DietelaQuizResult } from './questionnaire/DietelaQuizResult'
export { default as Checkout } from './cart/Checkout'; export { default as Checkout } from './cart/Checkout';
export { default as ChoosePlan } from './cart/ChoosePlan'; export { default as ChoosePlan } from './cart/ChoosePlan';
export { default as ProgramDetail } from './cart/ProgramDetail'; export { default as ProgramDetail } from './cart/ProgramDetail';
export { default as NutritionistDetail } from './cart/NutritionistDetail';
...@@ -7,4 +7,5 @@ export interface Nutritionist { ...@@ -7,4 +7,5 @@ export interface Nutritionist {
handled_age_group: string; handled_age_group: string;
another_practice_place: string; another_practice_place: string;
languages: string; languages: string;
profile_picture?: string;
} }
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