Fakultas Ilmu Komputer UI
Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
ppl-fasilkom-ui
2021
Kelas D
PT Gizi Sehat - Dietela
Dietela Mobile
Commits
5d91ad27
Commit
5d91ad27
authored
May 11, 2021
by
Wulan Mantiri
Browse files
Merge branch 'PBI-9-diet_questionnaire_api_integration' into 'staging'
Integrate extended questionnaire API See merge request
!47
parents
7711189a
617addc6
Pipeline
#76392
passed with stages
in 48 minutes and 55 seconds
Changes
48
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
src/__mocks__/dietQuestionnaire.ts
0 → 100644
View file @
5d91ad27
import
{
DietQuestionnaireResponse
,
DietQuestionnaireRequest
,
}
from
'
services/dietQuestionnaire/models
'
;
const
validFormValues
:
DietQuestionnaireRequest
=
{
agree_to_all_statements_consent
:
1
,
personal_data_consent
:
1
,
general_purpose
:
1
,
date_of_birth
:
'
1995-12-30
'
,
city_and_area_of_residence
:
'
yang jauh disana
'
,
handphone_no
:
'
081234567890
'
,
whatsapp_no
:
'
080987654321
'
,
profession
:
4
,
last_education
:
5
,
meal_preference
:
2
,
waist_size
:
60
,
dietary_change
:
2
,
has_weigher
:
1
,
breakfast_frequency
:
3
,
breakfast_meal_type
:
2
,
sweet_tea_consumption_frequency
:
9
,
coffee_consumption_frequency
:
9
,
milk_consumption_frequency
:
9
,
other_drink_consumption_frequency
:
9
,
additional_sugar_in_a_day
:
7
,
liquid_consumption_frequency
:
3
,
meal_consumed_almost_every_day
:
'
gaada
'
,
unliked_food
:
'
semua
'
,
preferred_food_taste
:
'
gaada
'
,
expected_food_on_breakfast
:
'
makanan mahal
'
,
expected_food_on_lunch_dinner
:
'
makanan murah
'
,
breakfast_meal_explanation
:
'
jadi, makan pagi saya tuh ga teratur hehe bye
'
,
morning_snack_explanation
:
'
ga nyemil
'
,
lunch_meal_explanation
:
'
yg penting enak
'
,
evening_snack_explanation
:
'
gtw
'
,
dinner_meal_explanation
:
'
makan enak
'
,
night_snack_explanation
:
'
indomi
'
,
food_alergies
:
'
kl banyak mo apa hah
'
,
diet_drinks
:
'
hah
'
,
meal_provider
:
[
1
,
2
,
3
],
cigarette_alcohol_condition
:
[],
multivitamin_tablet_suplement
:
'
gatau
'
,
physical_activity
:
[
1
,
2
],
other_physical_activity
:
'
another one
'
,
diet_and_life_style_story
:
'
kepo bgt si
'
,
disease
:
[
17
],
complaint
:
[
1
,
2
,
3
,
4
,
5
],
regular_drug_consumption
:
'
obatobatan
'
,
other_disease
:
'
dis-ease
'
,
motivation_using_dietela
:
'
biar kurus
'
,
dietela_nutritionist_expectation
:
'
yg jago ya
'
,
dietela_program_expectation
:
'
bikin sy kurus ya, kl gagal balikin duit lho
'
,
};
export
const
mockDietQuestionnaire
:
DietQuestionnaireResponse
=
{
id
:
7
,
...
validFormValues
,
finished_steps
:
[],
user
:
30
,
};
src/app/schema.ts
View file @
5d91ad27
...
...
@@ -2,13 +2,15 @@ import * as ROUTES from 'constants/routes';
import
{
publicNavigation
,
unpaidClientNavigation
,
onboardingClientNavigation
,
clientNavigation
,
}
from
'
constants/navigation
'
;
import
{
User
,
UserRol
e
}
from
'
services/auth/models
'
;
import
{
User
Role
,
AuthUserRespons
e
}
from
'
services/auth/models
'
;
import
{
TransactionStatus
}
from
'
services/payment/models
'
;
export
const
getNavigation
=
(
isAuthenticated
:
boolean
,
user
:
User
)
=>
{
export
const
getNavigation
=
(
isAuthenticated
:
boolean
,
user
:
AuthUserResponse
,
)
=>
{
if
(
isAuthenticated
)
{
if
(
user
.
role
===
UserRole
.
CLIENT
)
{
if
(
user
.
transaction_status
===
TransactionStatus
.
UNPAID
)
{
...
...
@@ -16,14 +18,11 @@ export const getNavigation = (isAuthenticated: boolean, user: User) => {
initialRoute
:
ROUTES
.
checkout
,
navigation
:
unpaidClientNavigation
,
};
}
else
if
(
!
user
.
has_profile
)
{
return
{
initialRoute
:
ROUTES
.
extendedQuestionnaire
,
navigation
:
onboardingClientNavigation
,
};
}
return
{
initialRoute
:
ROUTES
.
clientProfile
,
initialRoute
:
user
.
is_finished_onboarding
?
ROUTES
.
clientProfile
:
ROUTES
.
extendedQuestionnaire
,
navigation
:
clientNavigation
,
};
}
...
...
src/components/form/CheckboxGroup/index.test.tsx
View file @
5d91ad27
...
...
@@ -2,7 +2,6 @@ import React from 'react';
import
{
render
,
fireEvent
}
from
'
@testing-library/react-native
'
;
import
CheckboxGroup
from
'
.
'
;
import
{
checkbox
}
from
'
constants/options
'
;
describe
(
'
CheckboxGroup component
'
,
()
=>
{
const
props
=
{
...
...
@@ -64,6 +63,7 @@ describe('CheckboxGroup component', () => {
value
=
{
value
}
onChange
=
{
(
v
:
typeof
value
)
=>
(
value
=
v
)
}
hasOtherChoice
otherChoiceValue
=
{
1
}
/>,
);
...
...
@@ -71,6 +71,6 @@ describe('CheckboxGroup component', () => {
expect
(
otherChoice
).
toBeTruthy
();
fireEvent
.
press
(
otherChoice
);
expect
(
value
).
toContain
(
checkbox
.
OTHER
);
expect
(
value
).
toContain
(
1
);
});
});
src/components/form/CheckboxGroup/index.tsx
View file @
5d91ad27
...
...
@@ -6,7 +6,6 @@ import { typographyStyles } from 'styles';
import
{
styles
}
from
'
./styles
'
;
import
{
Props
}
from
'
./types
'
;
import
FormLabel
from
'
../FormLabel
'
;
import
{
checkbox
}
from
'
constants/options
'
;
const
CheckboxGroup
:
FC
<
Props
>
=
({
label
,
...
...
@@ -14,10 +13,11 @@ const CheckboxGroup: FC<Props> = ({
value
,
onChange
,
hasOtherChoice
,
otherChoiceValue
,
otherValue
,
setOtherValue
,
})
=>
{
const
handlePress
=
(
choiceValue
:
string
|
number
)
=>
{
const
handlePress
=
(
choiceValue
?
:
string
|
number
)
=>
{
if
(
value
.
includes
(
choiceValue
))
{
onChange
(
value
.
filter
((
item
:
number
|
string
)
=>
item
!==
choiceValue
));
}
else
{
...
...
@@ -53,8 +53,8 @@ const CheckboxGroup: FC<Props> = ({
/>
</
View
>
}
checked
=
{
value
.
includes
(
checkbox
.
OTHER
)
}
onPress
=
{
()
=>
handlePress
(
checkbox
.
OTHER
)
}
checked
=
{
value
.
includes
(
otherChoiceValue
)
}
onPress
=
{
()
=>
handlePress
(
otherChoiceValue
)
}
/>
)
:
null
}
</
View
>
...
...
src/components/form/CheckboxGroup/types.ts
View file @
5d91ad27
...
...
@@ -6,6 +6,7 @@ export interface Props extends FormLabelProps {
value
:
any
;
onChange
:
(
_
:
any
)
=>
void
;
hasOtherChoice
?:
boolean
;
otherChoiceValue
?:
number
|
string
;
otherValue
?:
string
;
setOtherValue
?:
(
_
:
string
|
number
)
=>
void
;
}
src/components/form/StepByStepForm/index.test.tsx
View file @
5d91ad27
...
...
@@ -9,6 +9,7 @@ jest.mock('@react-navigation/native', () => {
return
{
useNavigation
:
()
=>
({
navigate
:
mockedNavigate
,
reset
:
mockedNavigate
,
}),
};
});
...
...
@@ -24,9 +25,9 @@ describe('StepByStepForm component', () => {
finishRedirectRoute
:
'
finishroute
'
,
};
it
(
'
only has "
Lanjut
" button when form is never filled
'
,
()
=>
{
it
(
'
only has "
Isi
" button when form is never filled
'
,
()
=>
{
const
{
getByText
,
queryByText
}
=
render
(<
StepByStepForm
{
...
props
}
/>);
const
nextButton
=
getByText
(
/
Lanjut
/i
);
const
nextButton
=
getByText
(
/
Isi
/i
);
expect
(
nextButton
).
toBeTruthy
();
expect
(
queryByText
(
/Ubah/i
)).
toBeFalsy
();
});
...
...
@@ -38,9 +39,9 @@ describe('StepByStepForm component', () => {
expect
(
queryByText
(
/Ubah/i
)).
toBeTruthy
();
});
it
(
'
redirects to designated route when button "Ubah" or "
Lanjut
" is pressed
'
,
()
=>
{
it
(
'
redirects to designated route when button "Ubah" or "
Isi
" is pressed
'
,
()
=>
{
const
{
getByText
}
=
render
(<
StepByStepForm
{
...
props
}
currentPage
=
{
1
}
/>);
const
nextButton
=
getByText
(
/
Lanjut
/i
);
const
nextButton
=
getByText
(
/
Isi
/i
);
expect
(
nextButton
).
toBeTruthy
();
fireEvent
.
press
(
nextButton
);
...
...
src/components/form/StepByStepForm/index.tsx
View file @
5d91ad27
...
...
@@ -23,7 +23,7 @@ const StepByStepForm: FC<Props> = ({
if
(
i
<
currentPage
)
{
buttonLabel
=
'
Ubah
'
;
}
else
if
(
i
===
currentPage
)
{
buttonLabel
=
'
Lanjut
'
;
buttonLabel
=
'
Isi
'
;
}
return
buttonLabel
?
(
<
Button
...
...
@@ -63,7 +63,12 @@ const StepByStepForm: FC<Props> = ({
<
View
style
=
{
styles
.
bottomContainer
}
>
<
Button
title
=
"Selesai"
onPress
=
{
()
=>
navigation
.
navigate
(
finishRedirectRoute
)
}
onPress
=
{
()
=>
navigation
.
reset
({
index
:
0
,
routes
:
[{
name
:
finishRedirectRoute
}],
})
}
buttonStyle
=
{
styles
.
finishButton
}
titleStyle
=
{
styles
.
buttonTitle
}
disabled
=
{
currentPage
!==
pages
.
length
}
...
...
src/constants/navigation.ts
View file @
5d91ad27
...
...
@@ -27,9 +27,9 @@ import {
}
from
'
scenes
'
;
import
{
FC
}
from
'
react
'
;
export
interface
NavRoute
{
export
interface
NavRoute
<
T
=
any
>
{
name
:
string
;
component
:
FC
;
component
:
FC
<
T
>
;
header
?:
string
;
}
...
...
@@ -121,7 +121,12 @@ export const unpaidClientNavigation: NavRoute[] = [
...
navigation
,
];
export
const
onboardingClientNavigation
:
NavRoute
[]
=
[
export
const
clientNavigation
:
NavRoute
[]
=
[
{
name
:
ROUTES
.
clientProfile
,
component
:
ClientProfile
,
header
:
'
Profil Saya
'
,
},
{
name
:
ROUTES
.
extendedQuestionnaire
,
component
:
ExtendedQuestionnaire
,
...
...
@@ -158,15 +163,6 @@ export const onboardingClientNavigation: NavRoute[] = [
})),
];
export
const
clientNavigation
:
NavRoute
[]
=
[
{
name
:
ROUTES
.
clientProfile
,
component
:
ClientProfile
,
header
:
'
Profil Saya
'
,
},
...
onboardingClientNavigation
,
];
export
const
adminNavigation
:
NavRoute
[]
=
[
{
name
:
ROUTES
.
clientProfile
,
...
...
@@ -177,7 +173,8 @@ export const adminNavigation: NavRoute[] = [
export
const
testNavigation
:
NavRoute
[]
=
[
...
navigation
,
...
onboardingClientNavigation
,
...
clientNavigation
,
...
nutritionistNavigation
,
{
name
:
ROUTES
.
initial
,
component
:
InitialPage
,
...
...
src/constants/options.ts
View file @
5d91ad27
...
...
@@ -11,7 +11,3 @@ export const drinkFrequency = [
'
2 gelas (500 ml) per hari
'
,
'
Lebih dari 2 gelas per hari
'
,
];
export
const
checkbox
=
{
OTHER
:
'
OTHER
'
,
};
src/constants/questionnaire.ts
View file @
5d91ad27
...
...
@@ -313,6 +313,7 @@ export const selectFields = {
label
:
'
Apakah Anda melakukan salah satu dari aktivitas fisik atau olahraga berikut?
'
,
hasOtherChoice
:
true
,
otherChoiceValue
:
9
,
choiceList
:
[
'
Hampir tidak pernah olahraga
'
,
'
Jogging
'
,
...
...
src/hooks/useApi/index.ts
View file @
5d91ad27
...
...
@@ -8,16 +8,14 @@ const useApi = <T>(
):
{
isLoading
:
boolean
;
}
&
Response
<
T
>
=>
{
const
[
isLoading
,
setIsLoading
]
=
useState
(
false
);
const
[
response
,
setResponse
]
=
useState
({
isLoading
:
true
,
success
:
false
,
});
useEffect
(()
=>
{
const
fetchData
=
async
()
=>
{
setIsLoading
(
true
);
const
apiResponse
=
await
fetchApi
();
setResponse
(
apiResponse
);
if
(
!
apiResponse
.
success
)
{
Toast
.
show
({
type
:
'
error
'
,
...
...
@@ -25,16 +23,16 @@ const useApi = <T>(
text2
:
'
Terjadi kesalahan pada sisi kami.
'
,
});
}
setIsLoading
(
false
);
setResponse
({
isLoading
:
false
,
...
apiResponse
,
});
};
fetchData
();
},
[
fetchApi
]);
return
{
isLoading
,
...
response
,
};
return
response
;
};
export
default
useApi
;
src/provider/UserContext/index.ts
View file @
5d91ad27
...
...
@@ -13,10 +13,10 @@ import {
linkUserDataApi
,
}
from
'
services/auth
'
;
import
{
User
,
RegistrationRequest
,
LoginRequest
,
LoginResponse
,
AuthUserResponse
,
}
from
'
services/auth/models
'
;
import
{
setAuthHeader
,
resetAuthHeader
}
from
'
services/api
'
;
...
...
@@ -29,7 +29,7 @@ export const initialUser = {
name
:
''
,
role
:
null
,
transaction_status
:
TransactionStatus
.
UNPAID
,
has_profile
:
false
,
is_finished_onboarding
:
false
,
};
export
const
UserContext
=
createContext
<
iUserContext
>
({
...
...
@@ -45,7 +45,7 @@ export const UserContext = createContext<iUserContext>({
});
export
const
useUserContext
=
():
iUserContext
=>
{
const
[
user
,
setUser
]
=
useState
<
User
>
(
initialUser
);
const
[
user
,
setUser
]
=
useState
<
AuthUserResponse
>
(
initialUser
);
const
[
isLoading
,
setIsLoading
]
=
useState
(
false
);
const
[
isFirstLoading
,
setIsFirstLoading
]
=
useState
(
false
);
...
...
@@ -64,11 +64,7 @@ export const useUserContext = (): iUserContext => {
setAuthHeader
(
token
);
const
response
=
await
retrieveUserApi
();
if
(
response
.
success
&&
response
.
data
)
{
const
{
cart
,
...
userData
}
=
response
.
data
;
setUser
({
...
userData
,
transaction_status
:
cart
.
transaction_status
,
});
setUser
(
response
.
data
);
}
else
{
await
logout
();
Toast
.
show
({
...
...
src/provider/UserContext/types.ts
View file @
5d91ad27
...
...
@@ -3,12 +3,12 @@ import {
LoginRequest
,
LoginResponse
,
RegistrationRequest
,
User
,
LinkUserDataResponse
,
AuthUserResponse
,
}
from
'
services/auth/models
'
;
export
interface
iUserContext
{
user
:
User
;
user
:
AuthUserResponse
;
isAuthenticated
:
boolean
;
isLoading
:
boolean
;
isFirstLoading
:
boolean
;
...
...
src/scenes/nutritionist/ClientListNutritionist/index.test.tsx
View file @
5d91ad27
import
React
from
'
react
'
;
import
{
render
}
from
'
utils/testing
'
;
import
{
render
,
waitFor
}
from
'
utils/testing
'
;
import
*
as
ROUTES
from
'
constants/routes
'
;
import
axios
from
'
axios
'
;
import
ClientListNutritionist
from
'
.
'
;
jest
.
mock
(
'
axios
'
);
const
mockAxios
=
axios
as
jest
.
Mocked
<
typeof
axios
>
;
describe
(
'
ClientListNutritionist
'
,
()
=>
{
it
(
'
renders correctly
'
,
()
=>
{
it
(
'
renders correctly
'
,
async
()
=>
{
mockAxios
.
request
.
mockImplementationOnce
(()
=>
Promise
.
resolve
({
status
:
200
,
data
:
[],
}),
);
render
(<
ClientListNutritionist
/>,
ROUTES
.
clientListNutritionist
);
await
waitFor
(()
=>
expect
(
mockAxios
.
request
).
toBeCalled
());
});
});
src/scenes/nutritionist/ClientListNutritionist/index.tsx
View file @
5d91ad27
...
...
@@ -5,13 +5,18 @@ import { ClientCardNutritionist } from './components';
import
{
useNavigation
}
from
'
@react-navigation/native
'
;
import
*
as
ROUTES
from
'
constants/routes
'
;
import
{
retrieveClientListApi
}
from
'
services/profiles
'
;
import
{
useApi
}
from
'
hooks
'
;
import
{
Loader
}
from
'
components/core
'
;
const
ClientListNutritionist
:
FC
=
()
=>
{
const
navigation
=
useNavigation
();
const
clients
=
retrieveClientListApi
(
);
const
{
isLoading
,
data
:
clients
=
[]
}
=
useApi
(
retrieveClientListApi
);
if
(
isLoading
)
{
return
<
Loader
/>;
}
return
(
<
ScrollView
s
tyle
=
{
layoutStyles
}
>
<
ScrollView
contentContainerS
tyle
=
{
layoutStyles
}
>
{
clients
.
map
((
client
,
idx
)
=>
(
<
ClientCardNutritionist
key
=
{
idx
}
...
...
src/scenes/nutritionist/ClientListNutritionist/styles.tsx
deleted
100644 → 0
View file @
7711189a
import
{
StyleSheet
}
from
'
react-native
'
;
export
const
styles
=
StyleSheet
.
create
({});
src/scenes/questionnaire/AllAccessQuestionnaire/index.tsx
View file @
5d91ad27
...
...
@@ -116,7 +116,7 @@ const AllAccessQuestionnaire: FC = () => {
helperText
=
{
question
.
helperText
}
choices
=
{
question
.
choiceList
.
map
((
choice
,
choiceId
)
=>
({
label
:
choice
,
value
:
choiceId
+
1
,
value
:
choiceId
+
(
question
.
multiple
?
2
:
1
)
,
}))
}
{
...
getFormFieldProps
(
question
.
fieldName
)
}
/>
...
...
src/scenes/questionnaire/AllAccessQuestionnaire/schema.ts
View file @
5d91ad27
import
{
FieldValidation
,
FieldType
}
from
'
utils/form
'
;
import
{
FieldValidation
,
FieldType
,
filterArr
}
from
'
utils/form
'
;
import
{
TextFieldSchema
,
RadioButtonGroupSchema
}
from
'
types/form
'
;
import
{
DietProfileRequest
}
from
'
services/dietelaQuiz/models
'
;
...
...
@@ -290,5 +290,7 @@ export const convertPayload = (
weight
:
parseInt
(
values
.
weight
,
10
),
special_condition
:
values
.
gender
===
1
?
1
:
values
.
special_condition
,
health_problem
:
values
.
health_problem
.
length
===
0
?
[
1
]
:
values
.
health_problem
,
values
.
health_problem
.
length
===
0
?
[
1
]
:
filterArr
(
values
.
health_problem
,
1
),
});
src/scenes/questionnaire/ExtendedQuestionnaire/components/ConsentForm/index.test.tsx
View file @
5d91ad27
...
...
@@ -2,19 +2,20 @@ import React from 'react';
import
{
render
}
from
'
@testing-library/react-native
'
;
import
ConsentForm
from
'
.
'
;
import
{
mockDietQuestionnaire
}
from
'
__mocks__/dietQuestionnaire
'
;
const
mockedNavigate
=
jest
.
fn
();
jest
.
mock
(
'
@react-navigation/native
'
,
()
=>
{
return
{
useNavigation
:
()
=>
({
navigate
:
mockedNavigate
,
reset
:
mockedNavigate
,
}),
};
});
describe
(
'
ConsentForm
'
,
()
=>
{
it
(
'
renders correctly
'
,
()
=>
{
render
(<
ConsentForm
/>);
render
(<
ConsentForm
route
=
{
{
params
:
mockDietQuestionnaire
}
}
/>);
});
});
src/scenes/questionnaire/ExtendedQuestionnaire/components/ConsentForm/index.tsx
View file @
5d91ad27
import
React
,
{
FC
}
from
'
react
'
;
import
{
View
,
ScrollView
}
from
'
react-native
'
;
import
{
View
}
from
'
react-native
'
;
import
{
Text
}
from
'
react-native-elements
'
;
import
{
useNavigation
}
from
'
@react-navigation/native
'
;
import
{
InfoCard
,
BigButton
}
from
'
components/core
'
;
import
{
InfoCard
}
from
'
components/core
'
;
import
{
RadioButtonGroup
}
from
'
components/form
'
;
import
{
Section
}
from
'
components/layout
'
;
import
*
as
ROUTES
from
'
constants/routes
'
;
import
{
useForm
}
from
'
hooks
'
;
import
{
layoutStyles
,
typographyStyles
}
from
'
styles
'
;
import
{
typographyStyles
}
from
'
styles
'
;
import
{
styles
}
from
'
./styles
'
;
import
{
consentQuestions
,
termsAndConditions
,
initialValues
}
from
'
./schema
'
;
const
ConsentForm
:
FC
=
()
=>
{
const
navigation
=
useNavigation
()
;
import
QuestionnaireWrapper
from
'
../QuestionnaireWrapper
'
;
import
{
NavProps
}
from
'
../QuestionnaireWrapper/types
'
;
const
{
getFormFieldProps
,
handleSubmit
,
isSubmitting
,
values
:
formValues
,
}
=
useForm
({
initialValues
,
onSubmit
:
async
(
values
)
=>
{
console
.
log
(
values
);
navigation
.
navigate
(
ROUTES
.
extendedQuestionnaire
);
},
});
const
isValid
=
formValues
.
agree_to_all_statements_consent
&&
formValues
.
personal_data_consent
;
return
(
<
ScrollView
contentContainerStyle
=
{
layoutStyles
}
>
<
View
style
=
{
styles
.
tnc
}
>
<
Text
style
=
{
[
typographyStyles
.
bodyMedium
,
styles
.
spacing
]
}
>
Pelayanan gizi di Dietela, dilakukan dalam bentuk program perubah
an
pola makan dan gaya hidup menjadi lebih sehat yang berlangsung mulai
dari 3 hari sampai dengan 6 bulan. Selama program berlangsung Anda
sebagai klien akan didampingi oleh seorang Nutrisionis atau Dietisien
yang didelegasikan oleh Dietela.
</
Text
>
<
Text
style
=
{
[
typographyStyles
.
bodyMedium
,
styles
.
spacing
]
}
>
Dalam program tersebut akan diberikan servis berupa, “pengecekan gizi”
secara langsung atau online, “konseling gizi” via pesan elektronik
atau telepon atau video call, “diet coaching” via pesan elektronik,
“monitoring rutin” melalui pesan elektronik, “kunjungan gizi ke
lokasi” klien (hanya untuk layanan tertentu), “follow-up” (hanya untuk
klien layanan berjangka 1 bulan atau lebih) melalui telepon atau video
call, dan “exit counseling” atau konseling akhir (hanya untuk klien
layanan berjangka 1 bulan atau lebih) yang dilakukan 1 bulan sekali
melalui telepon atau video call.
</
Text
>
<
Text
style
=
{
[
typographyStyles
.
bodyMedium
,
styles
.
spacing
]
}
>
Se
luruh data dan informasi klien akan disimpan pada lokasi penyimpanan
yang aman dan tidak akan kami berikan kepada pihak manapun.
</
Text
>
<
Text
style
=
{
[
typographyStyles
.
bodyMedium
,
styles
.
spacing
]
}
>
Dengan menceklis kolom dibawah ini, maka klien setuju untuk:
</
Text
>
{
termsAndConditions
.
map
((
condition
,
i
)
=>
(
<
Section
key
=
{
`condition
${
i
}
`
}
>
<
InfoCard
content
=
{
`
${
i
+
1
}
.
${
condition
}
`
}
/>
const
ConsentForm
:
FC
<
NavProps
>
=
(
navProps
)
=>
(
<
QuestionnaireWrapper
{
...
navProps
}
Questionnaire
=
{
({
getFormFieldProps
})
=>
(
<
View
>
<
View
style
=
{
styles
.
tnc
}
>
<
Text
style
=
{
[
typographyStyles
.
bodyMedium
,
styles
.
spacing
]
}
>
Pelayanan gizi di Dietela, dilakukan dalam bentuk program perubahan
pola makan dan gaya hidup menjadi lebih sehat yang berlangsung mulai
dari 3 hari sampai dengan 6 bulan. Selama program berlangsung Anda
sebagai klien akan didampingi oleh seorang Nutrisionis atau
Dietisien yang didelegasikan oleh Dietela.
</
Text
>
<
Text
style
=
{
[
typographyStyles
.
bodyMedium
,
styles
.
spacing
]
}
>
Dalam program tersebut akan diberikan servis berupa, “pengecekan