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
2d06cb9b
Commit
2d06cb9b
authored
Jun 02, 2021
by
Doan Andreas Nathanael
Browse files
Pbi 15 read only report integrate api
parent
d44b5a68
Changes
12
Hide whitespace changes
Inline
Side-by-side
src/scenes/navigation/ClientNavigation/index.tsx
View file @
2d06cb9b
...
...
@@ -75,14 +75,14 @@ export const ExtQuestionnaireStackScreen: FC = () => (
);
const
reportClientNavigation
:
NavRoute
[]
=
[
{
name
:
ROUTES
.
weeklyReportReadOnly
,
component
:
ReadOnlyWeeklyReport
,
},
{
name
:
ROUTES
.
weeklyReportForm
,
component
:
WeeklyReport
,
},
{
name
:
ROUTES
.
weeklyReportReadOnly
,
component
:
ReadOnlyWeeklyReport
,
},
{
name
:
ROUTES
.
weeklyReportChooseWeek
,
component
:
ComingSoonPage
,
...
...
src/scenes/report/ReadOnlyWeeklyReport/components/WeeklyReportPage/utils.ts
0 → 100644
View file @
2d06cb9b
const
physicalActivity
=
[
'
Hampir tidak pernah olahraga dan/atau duduk lebih dari 9 jam perhari
'
,
'
Jalan kaki santai
'
,
'
Jalan kaki cepat
'
,
'
Pemanasan
'
,
'
Naik turun tangga
'
,
'
Jogging
'
,
'
Treadmill
'
,
'
Senam Aerobic/cardio, Recovery/Scratching, Dance dll
'
,
'
Latihan penguatan otot (strength workout, weight workout)
'
,
'
Other
'
,
];
export
const
getPhysicalActivity
=
(
activity
:
number
[])
=>
{
return
activity
.
map
((
act
,
i
)
=>
i
===
activity
.
length
-
1
?
`-
${
physicalActivity
[
act
-
1
]}
`
:
`-
${
physicalActivity
[
act
-
1
]}
\n`
,
);
};
const
timeForActivity
=
[
'
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
'
,
];
export
const
getTimeForActivity
=
(
time
:
number
)
=>
timeForActivity
[
time
-
1
];
const
feeling
=
[
'
Rasanya mau menyerah saja
'
,
'
Capek, susah, bosen, males, repot, sibuk
'
,
'
Biasa aja, meski ada kendala tapi semua bisa diatur
'
,
'
Lancar terus, semangat cukup stabil, gak ada masalah
'
,
'
Super seneng, semangat banget, worry-free lah
'
,
];
export
const
getFeeling
=
(
f
:
number
)
=>
feeling
[
f
-
1
];
src/scenes/report/ReadOnlyWeeklyReport/index.test.tsx
deleted
100644 → 0
View file @
d44b5a68
import
React
from
'
react
'
;
import
{
render
}
from
'
@testing-library/react-native
'
;
import
ReadOnlyWeeklyReport
from
'
.
'
;
describe
(
'
ReadOnlyWeeklyReport
'
,
()
=>
{
it
(
'
renders correctly
'
,
()
=>
{
render
(<
ReadOnlyWeeklyReport
/>);
});
});
src/scenes/report/ReadOnlyWeeklyReport/index.tsx
View file @
2d06cb9b
import
{
CarouselPagination
}
from
'
components/core
'
;
import
{
useRoute
}
from
'
@react-navigation/core
'
;
import
{
CarouselPagination
,
EmptyDataPage
,
Loader
}
from
'
components/core
'
;
import
{
useApi
}
from
'
hooks
'
;
import
React
,
{
FC
,
useState
}
from
'
react
'
;
import
{
Dimensions
,
StyleSheet
,
View
}
from
'
react-native
'
;
import
Carousel
from
'
react-native-snap-carousel
'
;
import
{
retrieveUserReportCommentByReportId
}
from
'
services/progress
'
;
import
{
UserReportResponse
}
from
'
services/progress/models
'
;
import
WeeklyReportPage
from
'
./components/WeeklyReportPage
'
;
import
{
page1
}
from
'
./pages/Page1
'
;
import
{
page2
}
from
'
./pages/Page2
'
;
...
...
@@ -10,16 +14,30 @@ import { page4 } from './pages/Page4';
const
ReadOnlyWeeklyReport
:
FC
=
()
=>
{
const
[
activeSlide
,
setActiveSlide
]
=
useState
(
0
);
const
route
=
useRoute
();
const
data
=
route
.
params
as
UserReportResponse
[];
const
{
isLoading
,
data
:
commentData
}
=
useApi
(()
=>
retrieveUserReportCommentByReportId
(
data
[
0
].
id
),
);
const
pageComponents
=
[
<
WeeklyReportPage
questions
=
{
page1
}
title
=
"Laporan Diet Anda"
/>,
<
WeeklyReportPage
questions
=
{
page2
}
/>,
<
WeeklyReportPage
questions
=
{
page1
(
data
[
0
])
}
title
=
"Laporan Diet Anda"
/>,
<
WeeklyReportPage
questions
=
{
page2
(
data
[
0
])
}
/>,
<
WeeklyReportPage
questions
=
{
page3
}
questions
=
{
page3
(
data
[
0
])
}
title
=
"Selama 1 minggu terakhir, berapa rata-rata Anda mengonsumsi jenis makanan dibawah ini selama seharian?"
/>,
<
WeeklyReportPage
questions
=
{
page4
}
/>,
<
WeeklyReportPage
questions
=
{
page4
(
data
[
0
])
}
/>,
];
if
(
isLoading
)
{
return
<
Loader
/>;
}
if
(
commentData
.
length
===
0
)
{
return
<
EmptyDataPage
text
=
"Belum ada komentar dari nutrisionis"
/>;
}
return
(
<>
<
View
style
=
{
[
styles
.
flexContainer
]
}
>
...
...
src/scenes/report/ReadOnlyWeeklyReport/pages/Page1/index.ts
View file @
2d06cb9b
import
{
UserReportResponse
}
from
'
services/progress/models
'
;
import
{
QuestionComment
}
from
'
../types
'
;
export
const
page1
:
QuestionComment
[]
=
[
export
const
page1
=
(
reportData
:
UserReportResponse
)
:
QuestionComment
[]
=
>
[
{
questions
:
[
{
question
:
'
Berat badan (kg)
'
,
answer
:
'
155
'
,
answer
:
`
${
reportData
.
weight
}
`
,
},
],
comment
:
'
keren bingits
'
,
...
...
@@ -14,7 +15,7 @@ export const page1: QuestionComment[] = [
questions
:
[
{
question
:
'
Tinggi badan (cm)
'
,
answer
:
'
188
'
,
answer
:
`
${
reportData
.
height
}
`
,
},
],
comment
:
'
pertahankan
\n
nak
'
,
...
...
@@ -23,7 +24,7 @@ export const page1: QuestionComment[] = [
questions
:
[
{
question
:
'
Lingkar pinggang (cm)
'
,
answer
:
'
100
'
,
answer
:
`
${
reportData
.
waist_size
}
`
,
},
],
comment
:
'
gils
'
,
...
...
src/scenes/report/ReadOnlyWeeklyReport/pages/Page2/index.ts
View file @
2d06cb9b
import
{
UserReportResponse
}
from
'
services/progress/models
'
;
import
{
QuestionComment
}
from
'
../types
'
;
export
const
page2
:
QuestionComment
[]
=
[
export
const
page2
=
(
reportData
:
UserReportResponse
)
:
QuestionComment
[]
=
>
[
{
questions
:
[
{
...
...
@@ -10,7 +11,7 @@ export const page2: QuestionComment[] = [
one
:
'
1. Belum terasa sama sekali
'
,
two
:
'
5. Sudah sangat berubah
'
,
},
answer
:
'
1
'
,
answer
:
`
${
reportData
.
changes_felt
}
`
,
},
],
comment
:
'
keren bingits
'
,
...
...
@@ -24,7 +25,7 @@ export const page2: QuestionComment[] = [
one
:
'
1. Sangat kelaparan
'
,
two
:
'
10. Sangat begah (kenyang berlebihan)
'
,
},
answer
:
'
1
'
,
answer
:
`
${
reportData
.
hunger_level
}
`
,
},
],
comment
:
'
keren bingits
'
,
...
...
@@ -38,7 +39,7 @@ export const page2: QuestionComment[] = [
one
:
'
1. Sangat kelaparan
'
,
two
:
'
10. Sangat begah (kenyang berlebihan)
'
,
},
answer
:
'
1
'
,
answer
:
`
${
reportData
.
fullness_level
}
`
,
},
],
comment
:
'
keren bingits
'
,
...
...
@@ -48,17 +49,17 @@ export const page2: QuestionComment[] = [
{
question
:
'
Selama 1 minggu terakhir, secara rata-rata, berapa kali Anda makan berat atau makan utama dalam 1 hari?
'
,
answer
:
'
1
x/hari
'
,
answer
:
`
${
reportData
.
heavy_meal
}
x/hari
`
,
},
],
comment
:
'
k
ere
n bingits
'
,
comment
:
'
l
ere
'
,
},
{
questions
:
[
{
question
:
'
Selama 1 minggu terakhir, secara rata-rata, berapa kali Anda makan cemilan dalam 1 hari?
'
,
answer
:
'
1
x/hari
'
,
answer
:
`
${
reportData
.
snacks
}
x/hari
`
,
},
],
comment
:
'
keren bingits
'
,
...
...
@@ -68,7 +69,7 @@ export const page2: QuestionComment[] = [
{
question
:
'
Selama 1 minggu terakhir, berapa rata-rata total gelas air putih yang Anda minum?
'
,
answer
:
'
1
'
,
answer
:
`
${
reportData
.
water_consumption
}
`
,
},
],
comment
:
'
keren bingits
'
,
...
...
src/scenes/report/ReadOnlyWeeklyReport/pages/Page3/index.ts
View file @
2d06cb9b
import
{
UserReportResponse
}
from
'
services/progress/models
'
;
import
{
QuestionComment
}
from
'
../types
'
;
export
const
page3
:
QuestionComment
[]
=
[
export
const
page3
=
(
responseData
:
UserReportResponse
)
:
QuestionComment
[]
=
>
[
{
questions
:
[
{
question
:
'
Minuman manis (satuan: gelas)
'
,
answer
:
'
0
'
,
answer
:
`
${
responseData
.
sweet_beverages
}
`
,
},
{
question
:
'
Gula pasir, gula aren, sirup, selai, atau madu (satuan: sendok makan)
'
,
answer
:
'
0
'
,
answer
:
`
${
responseData
.
sugary_ingredients
}
`
,
},
{
question
:
'
Cemilan digoreng (satuan: potong)
'
,
answer
:
'
0
'
,
answer
:
`
${
responseData
.
fried_snacks
}
`
,
},
{
question
:
'
Makanan ringan asin atau gurih (seperti makanan ringan kemasan, ciki-cikian, keripik) (satuan: bungkus)
'
,
answer
:
'
0
'
,
answer
:
`
${
responseData
.
umami_snacks
}
`
,
},
{
question
:
'
Cemilan manis (seperti kue-kue manis, brownis, cake, biskuit, cokelat, wafer) (satuan: potong)
'
,
answer
:
'
0
'
,
answer
:
`
${
responseData
.
sweet_snacks
}
`
,
},
{
question
:
'
Porsi buah
'
,
answer
:
'
0
'
,
answer
:
`
${
responseData
.
fruits_portion
}
`
,
},
{
question
:
'
Porsi sayur
'
,
answer
:
'
0
'
,
answer
:
`
${
responseData
.
vegetables_portion
}
`
,
},
],
comment
:
'
hey b0s
s
'
,
comment
:
'
nai
s
'
,
},
];
src/scenes/report/ReadOnlyWeeklyReport/pages/Page4/index.ts
View file @
2d06cb9b
import
{
UserReportResponse
}
from
'
services/progress/models
'
;
import
{
getFeeling
,
getPhysicalActivity
,
getTimeForActivity
,
}
from
'
../../components/WeeklyReportPage/utils
'
;
import
{
QuestionComment
}
from
'
../types
'
;
export
const
page4
:
QuestionComment
[]
=
[
export
const
page4
=
(
responseData
:
UserReportResponse
)
:
QuestionComment
[]
=
>
[
{
questions
:
[
{
question
:
'
Selama 1 minggu terakhir, pilih semua jenis aktivitas atau olahraga yang sudah Anda lakukan
'
,
answer
:
'
- Hampir tidak pernah olahraga
\n
- Jogging
'
,
answer
:
getPhysicalActivity
(
responseData
.
physical_activity
)
,
},
],
comment
:
'
keren bingits
'
,
...
...
@@ -16,7 +22,7 @@ export const page4: QuestionComment[] = [
{
question
:
'
Selama 1 minggu (7 hari) terakhir, berapa total menit yang Anda habiskan untuk melakukan bergerak aktif dan olahraga di atas dalam seminggu?
'
,
answer
:
'
0 - 60 menit
'
,
answer
:
getTimeForActivity
(
responseData
.
time_for_activity
)
,
},
],
comment
:
'
keren bingits
'
,
...
...
@@ -26,7 +32,7 @@ export const page4: QuestionComment[] = [
{
question
:
'
Sejauh ini, bagaimana perasaan Anda dalam mengikuti program?
'
,
answer
:
'
Bintang 2: Capek, susah, bosen, males, repot, sibuk
'
,
answer
:
getFeeling
(
responseData
.
feeling_rating
)
,
},
],
comment
:
'
keren bingits
'
,
...
...
@@ -36,8 +42,7 @@ export const page4: QuestionComment[] = [
{
question
:
'
Dalam 1 minggu terakhir, Apa saja yang sudah bisa Anda pelajari dari program ini?
'
,
answer
:
'
Tidur cukup, pola makan seimbang, olahraga rutin 30 menit per hari
'
,
answer
:
`
${
responseData
.
lesson_learned
}
`
,
},
],
comment
:
'
keren bingits
'
,
...
...
@@ -47,7 +52,7 @@ export const page4: QuestionComment[] = [
{
question
:
'
Silahkan sampaikan disini, jika Anda mempunyai kendala atau keluhan atau kesulitan dalam mengikuti program.
'
,
answer
:
'
Tidak ada
'
,
answer
:
`
${
responseData
.
problem_faced_and_feedbacks
}
`
,
},
],
comment
:
'
keren bingits
'
,
...
...
src/scenes/report/WeeklyReport/index.test.tsx
deleted
100644 → 0
View file @
d44b5a68
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
View file @
2d06cb9b
import
React
,
{
FC
,
useState
}
from
'
react
'
;
import
React
,
{
FC
,
useContext
,
useState
}
from
'
react
'
;
import
{
useNavigation
}
from
'
@react-navigation/native
'
;
import
*
as
ROUTES
from
'
constants/routes
'
;
import
{
WizardContainer
,
Toast
}
from
'
components/core
'
;
import
{
WizardContainer
,
Toast
,
Loader
}
from
'
components/core
'
;
import
{
dietReportTextFields
,
dietReportSelectFields
,
}
from
'
constants/weeklyReport
'
;
import
{
useForm
}
from
'
hooks
'
;
import
{
useApi
,
useForm
}
from
'
hooks
'
;
import
{
generateValidationSchema
}
from
'
utils/form
'
;
import
{
createUserReportApi
}
from
'
services/progress
'
;
import
{
createUserReportApi
,
retrieveUserReportById
}
from
'
services/progress
'
;
import
{
initialValues
,
fieldValidations
,
convertPayload
}
from
'
./schema
'
;
import
{
pages
}
from
'
./components
'
;
import
{
UserContext
}
from
'
provider
'
;
const
WeeklyReport
:
FC
=
()
=>
{
const
[
currentPage
,
setCurrentPage
]
=
useState
(
1
);
const
{
user
}
=
useContext
(
UserContext
);
const
{
isLoading
,
data
}
=
useApi
(()
=>
retrieveUserReportById
(
user
.
id
!
));
const
navigation
=
useNavigation
();
const
{
...
...
@@ -58,6 +61,16 @@ const WeeklyReport: FC = () => {
)
);
};
console
.
log
(
'
diluar if
'
);
if
(
isLoading
)
{
return
<
Loader
/>;
}
else
if
(
data
?.
length
>
0
)
{
navigation
.
reset
({
index
:
0
,
routes
:
[{
name
:
ROUTES
.
weeklyReportReadOnly
,
params
:
data
}],
});
}
return
(
<
WizardContainer
...
...
src/services/progress/index.ts
View file @
2d06cb9b
...
...
@@ -20,6 +20,10 @@ export const createUserReportApi = (
return
api
(
RequestMethod
.
POST
,
apiUrls
.
userReport
,
payload
);
};
export
const
retrieveUserReportCommentByReportId
=
(
reportId
:
number
)
=>
{
return
api
(
RequestMethod
.
GET
,
apiUrls
.
userReportCommentByReportId
(
reportId
));
};
export
const
createNutritionistCommentApi
=
(
payload
:
NutritionistCommentRequest
,
):
ApiResponse
<
NutritionistCommentResponse
>
=>
{
...
...
src/services/progress/urls.ts
View file @
2d06cb9b
...
...
@@ -3,5 +3,7 @@ export const progress = 'progress/';
export
const
userReport
=
`
${
progress
}
user_report/`
;
export
const
userReportByClientId
=
(
id
:
number
)
=>
`
${
userReport
}
?client_id=
${
id
}
`
;
export
const
userReportCommentByReportId
=
(
id
:
number
)
=>
`
${
progress
}
nutritionist_comment/?weekly_report_id=
${
id
}
`
;
export
const
nutritionistComment
=
`
${
progress
}
nutritionist_comment/`
;
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