Fakultas Ilmu Komputer UI
Skip to content
GitLab
Menu
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
b6c6e618
Commit
b6c6e618
authored
Jun 01, 2021
by
Wulan Mantiri
Browse files
Integrate client weekly report API and implement bottom navbar
parent
f7e12547
Changes
52
Show whitespace changes
Inline
Side-by-side
src/scenes/report/WeeklyReport/components/Report4/index.test.tsx
0 → 100644
View file @
b6c6e618
import
React
from
'
react
'
;
import
{
render
}
from
'
@testing-library/react-native
'
;
import
Report4
from
'
.
'
;
describe
(
'
Report4
'
,
()
=>
{
it
(
'
renders correctly
'
,
()
=>
{
render
(
<
Report4
getTextInputProps
=
{
()
=>
({
value
:
'
hello
'
,
onChangeText
:
jest
.
fn
(),
})
}
getFormFieldProps
=
{
()
=>
({
value
:
[],
onChange
:
jest
.
fn
(),
})
}
/>,
);
});
});
src/scenes/
questionnaire
/WeeklyReport/components/Report4/index.tsx
→
src/scenes/
report
/WeeklyReport/components/Report4/index.tsx
View file @
b6c6e618
import
React
,
{
FC
}
from
'
react
'
;
import
{
ScrollView
,
StyleSheet
,
View
}
from
'
react-native
'
;
import
{
StyleSheet
,
View
}
from
'
react-native
'
;
import
{
TextField
,
CheckboxGroup
,
RadioButtonGroup
}
from
'
components/form
'
;
import
{
...
...
@@ -8,15 +8,9 @@ import {
}
from
'
constants/weeklyReport
'
;
import
{
ReportProps
}
from
'
../../types
'
;
import
{
layoutStyles
}
from
'
styles
'
;
import
{
BigButton
}
from
'
components/core
'
;
const
Report4
:
FC
<
ReportProps
>
=
({
getTextInputProps
,
getFormFieldProps
,
handleSubmit
,
isSubmitting
,
})
=>
(
<
ScrollView
contentContainerStyle
=
{
layoutStyles
}
>
const
Report4
:
FC
<
ReportProps
>
=
({
getTextInputProps
,
getFormFieldProps
})
=>
(
<
View
style
=
{
layoutStyles
}
>
{
dietReportSelectFields
.
dietReportPage4
.
filter
((
item
)
=>
item
.
checkbox
)
.
map
((
props
,
i
)
=>
{
...
...
@@ -60,8 +54,7 @@ const Report4: FC<ReportProps> = ({
key
=
{
`report4-textfield
${
i
}
`
}
/>
))
}
<
BigButton
title
=
"simpan"
onPress
=
{
handleSubmit
}
loading
=
{
isSubmitting
}
/>
</
ScrollView
>
</
View
>
);
export
const
styles
=
StyleSheet
.
create
({
...
...
src/scenes/
questionnaire
/WeeklyReport/components/index.ts
→
src/scenes/
report
/WeeklyReport/components/index.ts
View file @
b6c6e618
File moved
src/scenes/report/WeeklyReport/index.test.tsx
0 → 100644
View file @
b6c6e618
import
React
from
'
react
'
;
import
{
render
,
fireEvent
}
from
'
@testing-library/react-native
'
;
import
axios
from
'
axios
'
;
import
WeeklyReport
from
'
.
'
;
import
{
dietReportTextFields
}
from
'
constants/weeklyReport
'
;
jest
.
mock
(
'
react-native-toast-message
'
);
jest
.
mock
(
'
axios
'
);
const
mockAxios
=
axios
as
jest
.
Mocked
<
typeof
axios
>
;
const
mockedNavigate
=
jest
.
fn
();
jest
.
mock
(
'
@react-navigation/native
'
,
()
=>
{
return
{
useNavigation
:
()
=>
({
reset
:
mockedNavigate
,
}),
};
});
describe
(
'
WeeklyReport
'
,
()
=>
{
const
validFormValues
:
{
[
_
:
string
]:
any
}
=
{
weight
:
'
52
'
,
height
:
'
90
'
,
waist_size
:
'
190
'
,
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
:
'
80
'
,
physical_activity
:
[
1
],
physical_activity_other
:
''
,
time_for_activity
:
1
,
feeling_rating
:
1
,
lesson_learned
:
'
hai
'
,
problem_faced_and_feedbacks
:
'
feedback
'
,
};
it
(
'
initially has disabled next button
'
,
()
=>
{
const
{
getByText
,
queryByText
}
=
render
(<
WeeklyReport
/>);
const
weightTextField
=
queryByText
(
/Berat Badan/i
);
expect
(
weightTextField
).
toBeTruthy
();
const
nextButton
=
getByText
(
/Lanjut/i
);
expect
(
nextButton
).
toBeTruthy
();
fireEvent
.
press
(
nextButton
);
expect
(
queryByText
(
/Berat Badan/i
)).
toBeTruthy
();
});
it
(
'
redirects to choose week for report if all form values are valid and submit success
'
,
async
()
=>
{
const
createUserReportApi
=
()
=>
Promise
.
resolve
({
status
:
201
,
data
:
validFormValues
,
});
mockAxios
.
request
.
mockImplementationOnce
(
createUserReportApi
);
const
{
getByText
,
getByPlaceholderText
}
=
render
(<
WeeklyReport
/>);
dietReportTextFields
.
dietReportPage1
.
forEach
(({
name
,
placeholder
})
=>
{
const
formField
=
getByPlaceholderText
(
placeholder
as
string
);
fireEvent
.
changeText
(
formField
,
validFormValues
[
name
]);
});
fireEvent
.
press
(
getByText
(
/Lanjut/i
));
// dietReportTextFields.dietReportPage2.forEach(({ name, placeholder }) => {
// const formField = getByPlaceholderText(placeholder as string);
// fireEvent.changeText(formField, validFormValues[name]);
// });
// dietReportSelectFields.dietReportPage2.forEach(
// ({ choiceList, scaleDescription, label }) => {
// if (scaleDescription) {
// const firstChoice = getByTestId(`${label}-1`);
// fireEvent.press(firstChoice);
// } else {
// const firstChoice = getByText(choiceList[0]);
// act(() => fireEvent.press(firstChoice));
// }
// },
// );
// fireEvent.press(getByText(/Lanjut/i));
// dietReportSelectFields.dietReportPage3.forEach(({ label }) => {
// const firstChoice = getByTestId(`${label}-1`);
// act(() => fireEvent.press(firstChoice));
// });
// fireEvent.press(getByText(/Lanjut/i));
// dietReportSelectFields.dietReportPage4.forEach(({ choiceList }) => {
// const firstChoice = getByText(choiceList[0]);
// fireEvent.press(firstChoice);
// });
// dietReportTextFields.dietReportPage4.forEach(({ name, placeholder }) => {
// const formField = getByPlaceholderText(placeholder as string);
// fireEvent.changeText(formField, validFormValues[name]);
// });
// fireEvent.press(getByText(/Lanjut/i));
// const submitButton = getByText('Selesai');
// await waitFor(() => fireEvent.press(submitButton));
// expect(mockedNavigate).toHaveBeenCalledTimes(1);
});
// it('does not redirect to choose week for report if all form values are valid but submit fails', async () => {
// const createUserReportApi = () =>
// Promise.reject({
// status: 400,
// response: {
// data: 'error',
// },
// });
// mockAxios.request.mockImplementationOnce(createUserReportApi);
// const { getByText, getByPlaceholderText, getByTestId } = render(
// <WeeklyReport />,
// );
// dietReportTextFields.dietReportPage1.forEach(({ name, placeholder }) => {
// const formField = getByPlaceholderText(placeholder as string);
// fireEvent.changeText(formField, validFormValues[name]);
// });
// fireEvent.press(getByText(/Lanjut/i));
// dietReportSelectFields.dietReportPage2.forEach(
// ({ choiceList, scaleDescription, label }) => {
// if (scaleDescription) {
// const firstChoice = getByTestId(`${label}-1`);
// fireEvent.press(firstChoice);
// } else {
// const firstChoice = getByText(choiceList[0]);
// fireEvent.press(firstChoice);
// }
// },
// );
// dietReportTextFields.dietReportPage2.forEach(({ name, placeholder }) => {
// const formField = getByPlaceholderText(placeholder as string);
// fireEvent.changeText(formField, validFormValues[name]);
// });
// fireEvent.press(getByText(/Lanjut/i));
// dietReportSelectFields.dietReportPage3.forEach(({ label }) => {
// const firstChoice = getByTestId(`${label}-1`);
// fireEvent.press(firstChoice);
// });
// fireEvent.press(getByText(/Lanjut/i));
// dietReportSelectFields.dietReportPage4.forEach(({ choiceList }) => {
// const firstChoice = getByText(choiceList[0]);
// fireEvent.press(firstChoice);
// });
// dietReportTextFields.dietReportPage4.forEach(({ name, placeholder }) => {
// const formField = getByPlaceholderText(placeholder as string);
// fireEvent.changeText(formField, validFormValues[name]);
// });
// fireEvent.press(getByText(/Lanjut/i));
// const submitButton = getByText('Selesai');
// await waitFor(() => fireEvent.press(submitButton));
// expect(mockedNavigate).toHaveBeenCalledTimes(1);
// });
afterAll
(()
=>
{
jest
.
clearAllMocks
();
});
});
src/scenes/report/WeeklyReport/index.tsx
0 → 100644
View file @
b6c6e618
import
React
,
{
FC
,
useState
}
from
'
react
'
;
import
{
useNavigation
}
from
'
@react-navigation/native
'
;
import
*
as
ROUTES
from
'
constants/routes
'
;
import
{
WizardContainer
,
Toast
}
from
'
components/core
'
;
import
{
dietReportTextFields
,
dietReportSelectFields
,
}
from
'
constants/weeklyReport
'
;
import
{
useForm
}
from
'
hooks
'
;
import
{
generateValidationSchema
}
from
'
utils/form
'
;
import
{
createUserReportApi
}
from
'
services/progress
'
;
import
{
initialValues
,
fieldValidations
,
convertPayload
}
from
'
./schema
'
;
import
{
pages
}
from
'
./components
'
;
const
WeeklyReport
:
FC
=
()
=>
{
const
[
currentPage
,
setCurrentPage
]
=
useState
(
1
);
const
navigation
=
useNavigation
();
const
{
getTextInputProps
,
getFormFieldProps
,
isFormUntouched
,
isFieldError
,
handleSubmit
,
isSubmitting
,
}
=
useForm
({
initialValues
,
validationSchema
:
generateValidationSchema
(
fieldValidations
),
onSubmit
:
async
(
values
)
=>
{
const
response
=
await
createUserReportApi
(
convertPayload
(
values
));
if
(
response
.
success
&&
response
.
data
)
{
navigation
.
reset
({
index
:
0
,
routes
:
[{
name
:
ROUTES
.
weeklyReportChooseWeek
}],
});
}
else
{
Toast
.
show
({
type
:
'
error
'
,
text1
:
'
Gagal menyimpan data
'
,
text2
:
'
Terjadi kesalahan pada sisi kami. Silakan coba lagi
'
,
});
}
},
});
const
isCurrentPageError
=
():
boolean
=>
{
const
fields
=
[
...(
dietReportTextFields
[
`dietReportPage
${
currentPage
}
`
]
||
[]),
...(
dietReportSelectFields
[
`dietReportPage
${
currentPage
}
`
]
||
[]),
];
return
(
isFormUntouched
()
||
fields
.
reduce
(
(
acc
:
boolean
,
item
)
=>
acc
||
isFieldError
(
item
.
name
),
false
,
)
);
};
return
(
<
WizardContainer
currentStep
=
{
currentPage
}
setCurrentStep
=
{
setCurrentPage
}
onFinish
=
{
handleSubmit
}
isLoading
=
{
isSubmitting
}
isNextDisabled
=
{
isCurrentPageError
()
}
components
=
{
pages
.
map
((
Component
)
=>
(
<
Component
getFormFieldProps
=
{
getFormFieldProps
}
getTextInputProps
=
{
getTextInputProps
}
/>
))
}
/>
);
};
export
default
WeeklyReport
;
src/scenes/
questionnaire
/WeeklyReport/schema.ts
→
src/scenes/
report
/WeeklyReport/schema.ts
View file @
b6c6e618
...
...
@@ -3,6 +3,7 @@ import {
dietReportTextFields
,
dietReportSelectFields
,
}
from
'
constants/weeklyReport
'
;
import
{
UserReportRequest
}
from
'
services/progress/models
'
;
export
const
initialValues
=
{
weight
:
''
,
...
...
@@ -14,6 +15,7 @@ export const initialValues = {
heavy_meal
:
0
,
snacks
:
0
,
sweet_beverages
:
0
,
sugary_ingredients
:
0
,
fried_snacks
:
0
,
umami_snacks
:
0
,
sweet_snacks
:
0
,
...
...
@@ -47,3 +49,13 @@ export const fieldValidations: FieldValidation[] = [
type
:
field
.
checkbox
?
FieldType
.
CHECKBOX
:
FieldType
.
RADIO_BUTTON
,
})),
];
export
const
convertPayload
=
(
values
:
typeof
initialValues
,
):
UserReportRequest
=>
({
...
values
,
weight
:
parseInt
(
values
.
weight
,
10
),
height
:
parseInt
(
values
.
height
,
10
),
waist_size
:
parseInt
(
values
.
waist_size
,
10
),
water_consumption
:
parseInt
(
values
.
water_consumption
,
10
),
});
src/scenes/
questionnaire
/WeeklyReport/styles.ts
→
src/scenes/
report
/WeeklyReport/styles.ts
View file @
b6c6e618
File moved
src/scenes/
questionnaire
/WeeklyReport/types.ts
→
src/scenes/
report
/WeeklyReport/types.ts
View file @
b6c6e618
export
interface
ReportProps
{
getTextInputProps
:
(
_
:
string
)
=>
any
;
getFormFieldProps
:
(
_
:
string
)
=>
any
;
isSubmitting
:
boolean
;
handleSubmit
:
()
=>
void
;
}
src/services/payment/index.ts
View file @
b6c6e618
...
...
@@ -32,7 +32,7 @@ export const updateCartApi = (
};
export
const
payWithMidtransApi
=
(
cartId
?:
number
,
cartId
?:
number
|
null
,
):
ApiResponse
<
MidtransResponse
>
=>
{
if
(
cartId
)
{
return
api
(
RequestMethod
.
POST
,
apiUrls
.
midtrans
,
{
cart_id
:
cartId
});
...
...
src/services/progress/index.ts
View file @
b6c6e618
import
{
api
,
RequestMethod
,
ApiResponse
}
from
'
../api
'
;
import
*
as
apiUrls
from
'
./urls
'
;
import
{
UserReportResponse
}
from
'
./models
'
;
import
{
UserReportResponse
,
UserReportRequest
}
from
'
./models
'
;
export
const
retrieveUserReportById
=
(
i
d
:
number
,
clientI
d
:
number
,
):
ApiResponse
<
UserReportResponse
[]
>
=>
{
return
api
(
RequestMethod
.
GET
,
apiUrls
.
userReportById
(
id
));
return
api
(
RequestMethod
.
GET
,
apiUrls
.
userReportByClientId
(
clientId
));
};
export
const
createUserReportApi
=
(
payload
:
UserReportRequest
,
):
ApiResponse
<
UserReportResponse
>
=>
{
return
api
(
RequestMethod
.
POST
,
apiUrls
.
userReport
,
payload
);
};
src/services/progress/urls.ts
View file @
b6c6e618
export
const
progress
=
'
progress/
'
;
export
const
userReportById
=
(
id
:
number
)
=>
`
${
progress
}${
id
}
`
;
export
const
userReport
=
`
${
progress
}
user_report/`
;
export
const
userReportByClientId
=
(
id
:
number
)
=>
`
${
userReport
}
?client_id=
${
id
}
`
;
yarn.lock
View file @
b6c6e618
...
...
@@ -1170,6 +1170,14 @@
resolved "https://registry.yarnpkg.com/@react-native-picker/picker/-/picker-1.15.0.tgz#f571a8b013e001a840db905b21ec18e9d205f01b"
integrity sha512-TYdhavldt3ami860fVgYv2mf0d1u5YhMQ6kTw+soX/a1rYbpRCRjdz01sEQXwCW8oL7/lzHakOFnwqCo6JazDw==
"@react-navigation/bottom-tabs@^5.11.11":
version "5.11.11"
resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-5.11.11.tgz#ad4dfee4316522d8c05b5a8ad460f597bddb9e3c"
integrity sha512-hThj6Vfw+ITzAVj5TgLEoxkVEcBD+gYeieWOe6FryBRgokgKNCzFQzqArJ5UCmNMxklNH0rstJfcdyHflLuPtw==
dependencies:
color "^3.1.3"
react-native-iphone-x-helper "^1.3.0"
"@react-navigation/core@^5.15.2":
version "5.15.2"
resolved "https://registry.npmjs.org/@react-navigation/core/-/core-5.15.2.tgz"
...
...
Prev
1
2
3
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment