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
3f700cb4
Commit
3f700cb4
authored
Jun 01, 2021
by
Kefas Satrio Bangkit Solidedantyo
Browse files
Static Diet Report For Nutritionist
parent
2e0af7c3
Changes
25
Hide whitespace changes
Inline
Side-by-side
src/__mocks__/userReport.ts
0 → 100644
View file @
3f700cb4
import
{
UserReportRequest
,
UserReportResponse
,
}
from
'
services/progress/models
'
;
import
{
UserRole
}
from
'
services/auth/models
'
;
export
const
mockUserReportRequest
:
UserReportRequest
=
{
weight
:
155
,
height
:
188
,
waist_size
:
100
,
changes_felt
:
1
,
hunger_level
:
1
,
fullness_level
:
1
,
heavy_meal
:
1
,
snacks
:
1
,
sweet_beverages
:
1
,
sugary_ingredients
:
1
,
fried_snacks
:
1
,
umami_snacks
:
1
,
sweet_snacks
:
1
,
fruits_portion
:
1
,
vegetables_portion
:
1
,
water_consumption
:
1
,
physical_activity
:
[
1
,
2
],
physical_activity_other
:
'
n
'
,
time_for_activity
:
1
,
feeling_rating
:
2
,
lesson_learned
:
'
a
'
,
problem_faced_and_feedbacks
:
'
x
'
,
};
export
const
mockUserReportResponse
:
UserReportResponse
=
{
id
:
4
,
nutritionist
:
1
,
week_num
:
2
,
client
:
{
id
:
9
,
name
:
'
Shin Ryujin
'
,
email
:
'
ryujin@itzy.com
'
,
role
:
UserRole
.
CLIENT
,
},
...
mockUserReportRequest
,
};
src/components/core/ClientList/index.tsx
View file @
3f700cb4
...
...
@@ -7,7 +7,9 @@ import { useNavigation } from '@react-navigation/native';
import
{
retrieveClientListApi
}
from
'
services/profiles
'
;
import
{
useApi
,
useDownloadFiles
}
from
'
hooks
'
;
import
{
getAbsoluteUrl
}
from
'
utils/format
'
;
import
{
BigButton
,
Loader
,
EmptyDataPage
}
from
'
components/core
'
;
import
BigButton
from
'
../../core/BigButton
'
;
import
Loader
from
'
../../core/Loader
'
;
import
EmptyDataPage
from
'
../../core/EmptyDataPage
'
;
import
{
Section
}
from
'
components/layout
'
;
import
{
UserRole
}
from
'
services/auth/models
'
;
import
{
FileType
}
from
'
hooks/useDownloadFiles/schema
'
;
...
...
src/constants/navigation.ts
View file @
3f700cb4
...
...
@@ -35,6 +35,7 @@ import {
WeeklyReport
,
}
from
'
scenes
'
;
import
{
FC
}
from
'
react
'
;
import
DietReportForNutritionist
from
'
scenes/nutritionist/DietReportForNutritionist
'
;
export
interface
NavRoute
<
T
=
any
>
{
name
:
string
;
...
...
@@ -195,7 +196,7 @@ export const nutritionistNavigation: NavRoute[] = [
},
{
name
:
ROUTES
.
clientDietReportNutritionist
,
component
:
ComingSoonPage
,
component
:
DietReportForNutritionist
,
header
:
'
Laporan Klien
'
,
},
{
...
...
src/constants/routes.ts
View file @
3f700cb4
...
...
@@ -40,3 +40,6 @@ export const clientProfileAdmin = `${admin}/client-profile`;
export
const
clientDietReportAdmin
=
`
${
admin
}
/client-diet-report`
;
export
const
clientChatAdmin
=
`
${
admin
}
/client-chat`
;
export
const
clientDietRecommendation
=
`
${
admin
}
/client-diet-recommendation`
;
const
progress
=
'
progress
'
;
export
const
userReport
=
`
${
progress
}
/user-report`
;
src/constants/userReport.ts
0 → 100644
View file @
3f700cb4
import
{
TextFieldSchema
}
from
'
types/form
'
;
import
{
likertScale5
,
likertScale10
,
averageConsumptionOptions
,
}
from
'
./options
'
;
export
const
dietReportTextFields
:
{
[
_
:
string
]:
TextFieldSchema
[]
}
=
{
dietReportPage1
:
[
{
label
:
'
Berat Badan (kg)
'
,
placeholder
:
'
Masukan berat badan yang terakhir anda ukur
'
,
name
:
'
weight
'
,
required
:
true
,
keyboardType
:
'
numeric
'
,
},
{
label
:
'
Tinggi Badan (cm)
'
,
placeholder
:
'
Masukan tinggi badan yang terakhir anda ukur
'
,
name
:
'
height
'
,
required
:
true
,
keyboardType
:
'
numeric
'
,
},
{
label
:
'
Lingkar Pinggang (cm)
'
,
placeholder
:
'
Masukan lingkar pinggang yang terakhir anda ukur
'
,
name
:
'
waist_size
'
,
keyboardType
:
'
numeric
'
,
},
],
dietReportPage2
:
[
{
label
:
'
Selama 1 minggu terakhir, berapa rata-rata total gelas air putih yang Anda minum?
'
,
placeholder
:
'
Masukan dalam angka
'
,
name
:
'
water_consumption
'
,
keyboardType
:
'
numeric
'
,
},
],
dietReportPage4
:
[
{
label
:
'
Dalam 1 minggu terakhir, Apa saja yang sudah bisa Anda pelajari dari program ini?
'
,
placeholder
:
'
Masukan pelajarann-pelajaran yang anda dapatkan
'
,
name
:
'
lesson_learned
'
,
},
{
label
:
'
Silahkan sampaikan disini, jika Anda mempunyai kendala atau keluhan atau kesulitan dalam mengikuti program.
'
,
placeholder
:
'
Jika ada masukan, saran, dan komplain terkait layanan sejauh ini, juga bisa disampaikan disini
'
,
name
:
'
problem_faced_and_feedbacks
'
,
},
],
};
export
const
dietReportSelectFields
:
{
[
_
:
string
]:
any
[]
}
=
{
dietReportPage2
:
[
{
label
:
'
Apakah sudah mulai terasa ada perubahan ukuran baju atau celana?
'
,
placeholder
:
'
Skor 3: jika tidak ada perubahan sama sekali
'
,
name
:
'
changes_felt
'
,
lowestScoreDescription
:
'
1: Belum terasa sama sekali
'
,
highestScoreDescription
:
'
5: Sudah sangat berubah
'
,
choiceList
:
likertScale5
,
},
{
label
:
'
Secara rata-rata, sebelum waktu makan selama 1 minggu terakhir ini, dimana level rasa lapar yang Anda rasakan?
'
,
placeholder
:
'
Cek indikator di program book kamu ya
'
,
name
:
'
hunger_level
'
,
lowestScoreDescription
:
'
1: Sangat kelaparan
'
,
highestScoreDescription
:
'
10: Sangat begah (kenyang berlebihan)
'
,
choiceList
:
likertScale10
,
},
{
label
:
'
Secara rata-rata, saat berhenti makan selama 1 minggu terakhir ini, dimana level rasa kenyang yang Anda rasakan?
'
,
placeholder
:
'
Cek indikator di program book kamu ya
'
,
name
:
'
fullness_level
'
,
lowestScoreDescription
:
'
1: Sangat kelaparan
'
,
highestScoreDescription
:
'
10: Sangat begah (kenyang berlebihan)
'
,
choiceList
:
likertScale10
,
},
{
label
:
'
Selama 1 minggu terakhir, secara rata-rata, berapa kali Anda makan berat atau makan utama dalam 1 hari?
'
,
placeholder
:
'
Pilih salah satu
'
,
name
:
'
heavy_meal
'
,
choiceList
:
[
'
1x/hari
'
,
'
2x/hari
'
,
'
3x/hari
'
,
'
Lebih dari 3x/hari
'
],
},
{
label
:
'
Selama 1 minggu terakhir, secara rata-rata, berapa kali Anda makan cemilan dalam 1 hari?
'
,
placeholder
:
'
Pilih salah satu
'
,
name
:
'
snacks
'
,
choiceList
:
[
'
1x/hari
'
,
'
2x/hari
'
,
'
3x/hari
'
,
'
Lebih dari 3x/hari
'
,
'
Hampir tidak ada
'
,
],
},
],
dietReportPage3
:
[
{
label
:
'
Minuman manis (satuan: gelas)
'
,
placeholder
:
'
Pilih salah satu
'
,
name
:
'
sweet_beverages
'
,
choiceList
:
averageConsumptionOptions
,
},
{
label
:
'
Gula pasir, gula aren, sirup, selai, atau madu (satuan: sendok makan)
'
,
placeholder
:
'
Pilih salah satu
'
,
name
:
'
sugary_ingredients
'
,
choiceList
:
averageConsumptionOptions
,
},
{
label
:
'
Cemilan digoreng (satuan: potong)
'
,
placeholder
:
'
Pilih salah satu
'
,
name
:
'
fried_snacks
'
,
choiceList
:
averageConsumptionOptions
,
},
{
label
:
'
Makanan ringan asin atau gurih (seperti makanan ringan kemasan, ciki-cikian, keripik) (satuan: bungkus)
'
,
placeholder
:
'
Pilih salah satu
'
,
name
:
'
umami_snacks
'
,
choiceList
:
averageConsumptionOptions
,
},
{
label
:
'
Cemilan manis (seperti kue-kue manis, brownis, cake, biskuit, cokelat, wafer) (satuan: potong)
'
,
placeholder
:
'
Pilih salah satu
'
,
name
:
'
sweet_snacks
'
,
choiceList
:
averageConsumptionOptions
,
},
{
label
:
'
Porsi buah
'
,
placeholder
:
'
Pilih salah satu
'
,
name
:
'
fruits_portion
'
,
choiceList
:
averageConsumptionOptions
,
},
{
label
:
'
Porsi sayur
'
,
placeholder
:
'
Pilih salah satu
'
,
name
:
'
vegetables_portion
'
,
choiceList
:
averageConsumptionOptions
,
},
],
dietReportPage4
:
[
{
label
:
'
Selama 1 minggu terakhir, pilih semua jenis aktivitas atau olahraga yang sudah Anda lakukan
'
,
placeholder
:
'
Dapat memilih lebih dari satu
'
,
name
:
'
physical_activity
'
,
hasOtherChoice
:
true
,
otherChoiceValue
:
9
,
choiceList
:
[
'
Hampir tidak pernah olahraga
'
,
'
Jogging
'
,
'
Senam aerobic, zumba, yoga, dan sejenisnya
'
,
'
Sepak bola atau futsal
'
,
'
Renang
'
,
'
Basket
'
,
'
Bulu tangkis
'
,
'
Voli
'
,
],
},
{
label
:
'
Selama 1 minggu (7 hari) terakhir, berapa total menit yang Anda habiskan untuk melakukan bergerak aktif dan olahraga di atas dalam seminggu?
'
,
placeholder
:
'
Pilih salah satu
'
,
name
:
'
time_for_activity
'
,
choiceList
:
[
'
0 - 60 menit
'
,
'
60 - 100 menit
'
,
'
100 - 120 menit
'
,
'
120 - 150 menit
'
,
'
150 - 175 menit
'
,
'
175 - 200 menit
'
,
'
200 - 250 menit
'
,
'
Lebih dari 250 menit
'
,
],
},
{
label
:
'
Sejauh ini, bagaimana perasaan Anda dalam mengikuti program?
'
,
placeholder
:
'
Pilih salah satu
'
,
name
:
'
feeling_rating
'
,
choiceList
:
[
'
Bintang 1: Rasanya mau menyerah saja
'
,
'
Bintang 2: Capek, susah, bosen, males, repot, sibuk
'
,
'
Bintang 3: Biasa aja, meski ada kendala tapi semua bisa diatur
'
,
'
Bintang 4: Lancar terus, semangat cukup stabil, gak ada masalah
'
,
'
Bintang 5: Super seneng, semangat banget, worry-free lah
'
,
],
},
],
};
src/constants/weeklyReport.ts
View file @
3f700cb4
...
...
@@ -123,7 +123,7 @@ export const dietReportSelectFields: { [_: string]: any[] } = {
{
label
:
'
Gula pasir, gula aren, sirup, selai, atau madu
'
,
helperText
:
'
dalam satuan sendok makan
'
,
name
:
'
sugar
'
,
name
:
'
sugar
y_ingredients
'
,
choiceList
:
averageConsumptionOptions
,
},
{
...
...
src/scenes/nutritionist/DietReportForNutritionist/components/DietReportPage/index.tsx
0 → 100644
View file @
3f700cb4
import
{
FC
}
from
'
react
'
;
import
{
ScrollView
,
View
}
from
'
react-native
'
;
import
{
styles
}
from
'
./styles
'
;
import
React
from
'
react
'
;
import
{
DietReportPageContent
,
dietReportPage
}
from
'
../../pages/types
'
;
import
QuestionAnswerCommentCard
from
'
../QuestionAnswerCommentCard
'
;
import
{
Text
}
from
'
react-native-elements
'
;
import
{
typographyStyles
}
from
'
styles
'
;
import
{
TextInput
}
from
'
react-native-gesture-handler
'
;
const
DietReportPage
:
FC
<
{
content
:
DietReportPageContent
;
pageName
:
string
;
getTextInputProps
?:
any
;
}
>
=
({
content
,
pageName
,
getTextInputProps
})
=>
{
return
(
<
ScrollView
style
=
{
styles
.
container
}
>
{
pageName
===
dietReportPage
.
PAGE3
?
(
<
Text
style
=
{
[
typographyStyles
.
headingMedium
,
styles
.
bottomMargin
]
}
>
Selama 1 minggu terakhir, berapa rata-rata Anda mengonsumsi jenis
makanan dibawah ini selama seharian
</
Text
>
)
:
null
}
{
content
.
questions
.
map
((
qst
,
idx
)
=>
{
if
(
pageName
===
dietReportPage
.
PAGE3
)
{
return
(
<
QuestionAnswerCommentCard
key
=
{
idx
}
pageName
=
{
pageName
}
questionName
=
{
qst
.
questionName
}
question
=
{
qst
.
label
}
answer
=
{
qst
.
answer
}
/>
);
}
return
(
<
QuestionAnswerCommentCard
key
=
{
idx
}
pageName
=
{
pageName
}
questionName
=
{
qst
.
questionName
}
question
=
{
qst
.
label
}
answer
=
{
qst
.
answer
}
textInputProps
=
{
qst
.
textInputProps
}
lowestScoreDescription
=
{
qst
.
lowestScoreDescription
}
highestScoreDescription
=
{
qst
.
highestScoreDescription
}
/>
);
})
}
{
pageName
===
dietReportPage
.
PAGE3
?
(
<
View
>
<
Text
style
=
{
[
typographyStyles
.
bodySmall
,
styles
.
topMargin
]
}
>
Komentar:
</
Text
>
<
TextInput
style
=
{
[
typographyStyles
.
bodySmall
,
styles
.
input
]
}
{
...
getTextInputProps
(
'
average_consumption
'
)
}
placeholder
=
"Tuliskan komentar..."
multiline
=
{
true
}
/>
</
View
>
)
:
null
}
</
ScrollView
>
);
};
export
default
DietReportPage
;
src/scenes/nutritionist/DietReportForNutritionist/components/DietReportPage/styles.ts
0 → 100644
View file @
3f700cb4
import
{
StyleSheet
,
Dimensions
}
from
'
react-native
'
;
export
const
styles
=
StyleSheet
.
create
({
nameMargin
:
{
marginBottom
:
15
,
},
container
:
{
width
:
Dimensions
.
get
(
'
window
'
).
width
-
40
,
},
input
:
{
borderWidth
:
1
,
height
:
90
,
borderRadius
:
4
,
marginBottom
:
20
,
padding
:
15
,
marginTop
:
5
,
},
bottomMargin
:
{
marginBottom
:
10
,
},
topMargin
:
{
marginTop
:
10
,
},
});
src/scenes/nutritionist/DietReportForNutritionist/components/QuestionAnswerCommentCard/index.tsx
0 → 100644
View file @
3f700cb4
import
{
FC
}
from
'
react
'
;
import
{
View
,
Text
,
TextInput
}
from
'
react-native
'
;
import
React
from
'
react
'
;
import
{
InfoCard
}
from
'
components/core
'
;
import
{
typographyStyles
}
from
'
styles
'
;
import
{
styles
}
from
'
./styles
'
;
import
{
dietReportPage
}
from
'
../../pages/types
'
;
interface
Props
{
question
:
string
;
pageName
:
string
;
answer
:
string
;
textInputProps
?:
any
;
questionName
?:
string
|
null
;
lowestScoreDescription
?:
string
|
null
;
highestScoreDescription
?:
string
|
null
;
testID
?:
string
;
}
const
QuestionAnswerCommentCard
:
FC
<
Props
>
=
({
questionName
,
pageName
,
question
,
answer
,
textInputProps
,
lowestScoreDescription
,
highestScoreDescription
,
testID
,
})
=>
{
return
(
<
View
style
=
{
styles
.
labelContainer
}
testID
=
{
testID
}
>
{
questionName
===
'
name
'
?
(
<
Text
style
=
{
[
typographyStyles
.
headingLarge
,
styles
.
nameSize
]
}
>
{
answer
}
</
Text
>
)
:
null
}
{
questionName
===
'
email
'
?
(
<
Text
style
=
{
[
typographyStyles
.
bodySmall
,
styles
.
bottomMargin
]
}
>
{
answer
}
</
Text
>
)
:
null
}
{
pageName
===
dietReportPage
.
PAGE3
?
(
<
View
>
<
Text
style
=
{
[
typographyStyles
.
bodyLarge
,
styles
.
topMargin
,
styles
.
smallBottomMargin
,
]
}
>
{
question
}
</
Text
>
<
InfoCard
content
=
{
answer
}
/>
{
/* <Text style={[typographyStyles.bodyMedium, styles.label]}>
{answer}
</Text> */
}
</
View
>
)
:
null
}
{
pageName
!==
dietReportPage
.
PAGE3
&&
questionName
!==
'
name
'
&&
questionName
!==
'
email
'
?
(
<
View
>
<
Text
style
=
{
[
typographyStyles
.
bodyLarge
]
}
>
{
question
}
</
Text
>
{
lowestScoreDescription
?
(
<
Text
style
=
{
[
typographyStyles
.
bodySmall
,
styles
.
descMargin
]
}
>
{
lowestScoreDescription
}
</
Text
>
)
:
null
}
{
highestScoreDescription
?
(
<
Text
style
=
{
[
typographyStyles
.
bodySmall
,
styles
.
smallBottomMargin
]
}
>
{
highestScoreDescription
}
</
Text
>
)
:
null
}
{
/* <Text style={[typographyStyles.bodyMedium, styles.label]}>
{answer}
</Text> */
}
<
InfoCard
content
=
{
answer
}
/>
<
Text
style
=
{
[
typographyStyles
.
bodySmall
,
styles
.
topMargin
]
}
>
Komentar:
</
Text
>
<
TextInput
style
=
{
[
typographyStyles
.
bodySmall
,
styles
.
input
]
}
{
...
textInputProps
}
placeholder
=
"Tuliskan komentar..."
multiline
=
{
true
}
/>
</
View
>
)
:
null
}
</
View
>
);
};
export
default
QuestionAnswerCommentCard
;
src/scenes/nutritionist/DietReportForNutritionist/components/QuestionAnswerCommentCard/styles.ts
0 → 100644
View file @
3f700cb4
import
{
StyleSheet
}
from
'
react-native
'
;
export
const
styles
=
StyleSheet
.
create
({
label
:
{
marginBottom
:
5
,
marginTop
:
5
,
},
labelContainer
:
{
alignSelf
:
'
stretch
'
,
},
answer
:
{
flexDirection
:
'
row
'
,
},
nameSize
:
{
fontSize
:
32
,
},
bottomMargin
:
{
marginBottom
:
20
,
},
smallBottomMargin
:
{
marginBottom
:
10
,
},
topMargin
:
{
marginTop
:
10
,
},
descMargin
:
{
marginTop
:
5
,
},
input
:
{
borderRadius
:
4
,
borderWidth
:
1
,
height
:
90
,
marginTop
:
5
,
marginBottom
:
20
,
padding
:
15
,
},
});
src/scenes/nutritionist/DietReportForNutritionist/components/index.ts
0 → 100644
View file @
3f700cb4
export
{
default
as
DietReportPage
}
from
'
./DietReportPage
'
;
export
{
default
as
QuestionAnswerCommentCard
}
from
'
./QuestionAnswerCommentCard
'
;
src/scenes/nutritionist/DietReportForNutritionist/index.test.tsx
0 → 100644
View file @
3f700cb4
import
React
from
'
react
'
;
import
{
render
}
from
'
utils/testing
'
;
import
*
as
ROUTES
from
'
constants/routes
'
;
import
DietReportForNutritionist
from
'
.
'
;
jest
.
useFakeTimers
();
describe
(
'
DietReportForNutritionist
'
,
()
=>
{
it
(
'
renders correctly
'
,
()
=>
{
render
(<
DietReportForNutritionist
/>,
ROUTES
.
userReport
);
});
});
src/scenes/nutritionist/DietReportForNutritionist/index.tsx
0 → 100644
View file @
3f700cb4
import
React
,
{
FC
,
useState
}
from
'
react
'
;
import
{
View
,
StyleSheet
,
Dimensions
}
from
'
react-native
'
;
import
{
layoutStyles
}
from
'
styles
'
;
import
Carousel
from
'
react-native-snap-carousel
'
;
import
{
pages
}
from
'
./pages
'
;
import
{
CarouselPagination
,
BigButton
}
from
'
components/core
'
;
import
{
useForm
}
from
'
hooks
'
;
import
{
dietReportCommentInitialValues
,
fieldValidations
}
from
'
./schema
'
;
import
{
generateValidationSchema
}
from
'
utils/form
'
;
import
{
DietReportPage
}
from
'
./components
'
;
import
{
mockUserReportResponse
}
from
'
__mocks__/userReport
'
;
const
DietReportForNutritionist
:
FC
=
()
=>
{
const
[
activeSlide
,
setActiveSlide
]
=
useState
(
0
);
const
userReport
=
mockUserReportResponse
;
const
{
getTextInputProps
,
handleSubmit
,
isSubmitting
}
=
useForm
({
initialValues
:
dietReportCommentInitialValues
,
validationSchema
:
generateValidationSchema
(
fieldValidations
),
onSubmit
:
async
(
values
)
=>
{
console
.
log
(
'
masuk
'
);
console
.
log
(
values
);
},
});
return
(
<
View
style
=
{
[
layoutStyles
,
styles
.
reportContainer
]
}
>
<
View
style
=
{
[
styles
.
flexContainer
]
}
>
<
Carousel
data
=
{
pages
.
map
((
page
,
idx
)
=>
(
<
DietReportPage
key
=
{
idx
}
content
=
{
page
.
pageContent
(
userReport
,
getTextInputProps
)
}
pageName
=
{
page
.
pageName
}
getTextInputProps
=
{
getTextInputProps
}