Closed gglinoga closed 4 years ago
@gglinoga apologies for forgetting to make this frontend ticket. Here's the associated backend ticket: https://github.com/omou-org/mainframe/issues/56
Notable things from the backend ticket:
The endpoint should be something like /payments/list-of-unpaid-students
The expected response will be a JSON object with student_id keys, and for each student_id keys, there will be an array of objects describing the enrollment payment status. Only include enrollments that have at most 3 paid sessions left. Example:
{
[student_id]: [
{
student_id: //int,
amount_due: //double <- sum total of unpaid tutitions if paid_sessions < 0,
course_id: //int,
},
...
],
....
}
Make sure you create a new branch off of the current development branch!
We need to create a home tab for the AdminPortal to put our list of unpaid enrollment tuitions.
To do's
<AdminRoute/>
similar to the other ones, except the route will just be <AdminRoute path="/adminportal/"/>
since we want this root AdminRoute to be our homepage. For the render
attribute, render our AdminPortalHome component we made with the first To do. Now, whenever we got to /amdinportal/, we'll go to the AdminPortalHome component. Here, the goal is to prepare our application to accept and process responses from our endpoint with Redux by putting the responses in the Redux store so any component can interact with the data.
Review: Actions are triggers for our Redux workflow to know what we need to do with the data. Typically there are 3 types of triggers: success, fail, and request started. Dispatching an action means to alert Redux that we would like to handle the data in by the action that we dispatch.
To do's
/payments/list-of-unpaid-students
responses. They should be similar to the past actions. Where there's a SUCCESS, FAILED, and _____STARTED. wrapGet()
.
wrapGet()
function, refer to line 19 - 27 on adminActions.js. To look at the deeper implementation of wrapGet()
go to apiActions.js line 15 Review: Reducers are the functions that act on the actions that are dispatched. For instance, we will need to write a reducer for handling receiving a successful GET request. We call this a reducer is because we're "reducing" the raw API response to something the application can use in the Redux state.
To do's
state = initialState.Admin
(line 4). This means, whenever you call on state in the adminReducer function, you will be referencing the "Admin" object in initialState.js (line 80). We also set newState = state
as a reminder that we should be returning a copy of "state" to follow immutable functional programming practices. Review: Now that we've created functions in Redux to handle various API responses from our GET /payments/list-of-unpaid-students
request, we need to allow our component to call on these functions as well as get the data we've received. These items will help you do this.
To do's
const discountList = useSelector(({"Admin":{Discounts}}) => Discounts);
. useSelector is a Redux hook that allows our functional React Hooks to access our Redux state easily. import * as adminActions from "../../../actions/adminActions";
and import the actions into the component by using this code block:
const api = useMemo(
() => ({
...bindActionCreators(adminActions, dispatch),
}),
[dispatch]
);
This is where we need to use critical thinking. You need to answer the question: when do I want to get the list of unpaid enrollment tuitions? Most likely you'll want to call it when the component first renders/loads. In that case, you will likely need to do something similar to line 33 - 35 on ManageCategories.js.
If there's any other cases where you think you'll need to call on the list of unpaid enrollment tuitions, you'll need to create a new useEffect that will respond to when to call on the request. Ask @NeilAllavarpu for feedback on when would be appropriate times.
There's a lot that goes into here, so I won't type everything out. Long story short on what we're doing, when we fire off SUCCESS, ____FAILED, STARTED actions, we want to record which actions have been triggered. To do so, we'll need an additional reducer (apiReducer.js) to record these actions. Refer to this file to see how we're recording the status of our request calls. Also take a look at initialState.js line 90 + to get an idea of where/how we're storing the request status-es (stati? not sure lol).
Ask @NeilAllavarpu If you have any questions on this.
But the big To Do item here is: MAKE THE COMPONENT DISPLAY A LOADING ICON UNTIL YOU HAVE ALL OF YOUR DATA!! otherwise your app will break.
Since you won't be able to get the api endpoint up and running anytime this week, create fake data in redux. Under the "Admin" key in initialState.js and under the new key you created in "2 - Creating Our Redux Reducers", instead of having an empty object as your initial state, put it with fake data that would match the response that you're expecting. I've described what's the response you should expect in the previous comment.
Add component to Admin tab displaying information for students with outstanding tuition payments. Mandatory data: student name, # of sessions taken, course name, $ amount owed. The objective is to give the user the ability to identify at a glance all students who owe tuition, for which courses, and amount student owes.
No current design spec, for the meantime use layout from identical dashboard feature: