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 logo_white_small = require('./logo_white_small.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 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 { View, Text } from 'react-native';
import { typographyStyles } from 'styles';
import { styles } from './styles';
interface Props {
title: string;
title?: string;
emote: string;
content: string;
testID?: string;
......@@ -13,18 +14,20 @@ interface Props {
const Statistic: FC<Props> = ({ title, emote, content, testID }) => {
return (
<View testID={testID}>
<Text style={[typographyStyles.overlineBig, styles.title]}>{title}</Text>
{title && (
<Text style={[typographyStyles.overlineBig, styles.title]}>
{title}
</Text>
)}
<View>
<Text style={typographyStyles.bodyMedium}>
<View style={styles.emote}>
<Column>
<View style={styles.row}>
<Text style={[typographyStyles.bodyMedium, styles.emote]}>
{emote}
</Text>
</View>
<View>
<Text style={typographyStyles.bodyMedium}>{content}</Text>
</View>
</Text>
</Column>
</View>
</View>
);
......
......@@ -10,4 +10,8 @@ export const styles = StyleSheet.create({
emote: {
marginRight: 8,
},
row: {
flexDirection: 'row',
width: '90%',
},
});
......@@ -9,6 +9,7 @@ import {
ManualRegistrationPage,
LoginPage,
ProgramDetail,
NutritionistDetail,
} from 'scenes';
import { FC } from 'react';
......@@ -50,7 +51,7 @@ export const navigation: NavRoute[] = [
},
{
name: ROUTES.nutritionistDetail,
component: ComingSoonPage,
component: NutritionistDetail,
header: 'Nutrisionis',
},
{
......
......@@ -73,9 +73,6 @@ describe('Checkout', () => {
const readMoreButton = getAllByText(/Baca selengkapnya/i)[1];
expect(readMoreButton).toBeTruthy();
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 () => {
......
......@@ -48,7 +48,7 @@ const Checkout: FC = () => {
type="nutritionist"
onReadMore={() =>
navigation.navigate(ROUTES.nutritionistDetail, {
id: data?.nutritionist.id,
ntr: data?.nutritionist,
})
}
/>
......
......@@ -9,23 +9,13 @@ import CACHE_KEYS from 'constants/cacheKeys';
import { mockProgramRecommendations } from '__mocks__/quizResult';
import { dietPrograms } from 'constants/dietelaProgram';
import { setCache } from 'utils/cache';
import { nutritionistDummy } from '__mocks__/cart';
jest.mock('axios');
const mockAxios = axios as jest.Mocked<typeof axios>;
describe('ChoosePlan', () => {
const nutritionists = [
{
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',
},
];
describe('ChoosePlanPalingKeren', () => {
const nutritionists = [nutritionistDummy];
const retrieveNutritionistsApi = () =>
Promise.resolve({
status: 200,
......@@ -170,8 +160,10 @@ describe('ChoosePlan', () => {
expect(readMoreButton).toBeTruthy();
fireEvent.press(readMoreButton);
const nutritionistDetailPage = getByText(/Coming Soon/i);
expect(nutritionistDetailPage).toBeTruthy();
// const nutritionistDetailPage = getByText(
// nutritionistDummy.full_name_and_degree,
// );
// expect(nutritionistDetailPage).toBeTruthy();
});
afterAll(() => {
......
......@@ -109,7 +109,7 @@ const ChoosePlan: FC = () => {
.slice(0, 3),
onReadMore: () =>
navigation.navigate(ROUTES.nutritionistDetail, {
id: nutritionist.id,
ntr: 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'
export { default as Checkout } from './cart/Checkout';
export { default as ChoosePlan } from './cart/ChoosePlan';
export { default as ProgramDetail } from './cart/ProgramDetail';
export { default as NutritionistDetail } from './cart/NutritionistDetail';
......@@ -7,4 +7,5 @@ export interface Nutritionist {
handled_age_group: string;
another_practice_place: 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