To run this project locally, follow these steps:
-
Clone the repository:
git clone https://github.com/andynullwong/loan-tracker-fullstack.git
-
Install the dependencies:
pnpm install
-
Start the development server:
pnpm run dev
- Create a User: Users can create an account to access the app.
- Create a Loan: Users can create a new loan, specifying the initial principal balance, interest rate, and amortization term.
- Fetch all User’s Loans: Users can view a list of all their saved loans.
- Fetch the Amortization Term for a Loan: Users can retrieve the amortization schedule for a specific loan.
- Share a Loan with another User: Users can share their loan details with other users.
- Manage Current User State: Users can switch between profiles (User Ids) to perform operations on Loans that the specific users have access to.
- Edit Loan Details: Was not specified in the scoring rubric but was well documented. There was a minor bug discovered with this endpoint which I mitigated away with form validation. Documented in
API Bug 1
- Form Validation: Notifies end users when an input does not match the specified rule(s) and returns an error message.
- Proper error handling: All async functions have a catch and will throw a pop-up error message, render the error message in the ErrorMessage component, or provide a
console.error
at minimum. - Good style: Leveraged Ant Design component library for faster velocity. For long term projects my preference is either TailwindCSS or at minimum Material UI.
- State & component testing: Included Jest & React Testing Library support to the application and included some testing for key React Components that rely on state.
- React: A JavaScript library for building user interfaces.
- Next.js: A Web Application framework.
- Ant Design: React UI component library.
- Jest & React Testing Library: For some simple snapshot testing of React Components.
-
An
.env
file containing the URL of the external API is included in the root of the project strictly for convenience and should otherwise never be included in the repository. I decided to use API Routes as a simple API proxy for several reasons:- Since the API is semi-private and is not protected with an API key, the API routes will mask the API host.
- Without visibility into how the external API will handle fetch requests on the client side, I wanted to reduce the risk of unforeseen issues like CORS errors.
- Scalability: While this is just an assessment of the front-end, any application that relies on user scopes/permissions and other services will deal with sensitive or increasingly complex data. Introducing the API route now will allow for additional business logic or middleware functions to be added without cluttering the front-end components.
- API Bug 1: When editing an existing Loan, assigning an
Owner ID
that is different that the currentUser ID
does not throw an error on the API side and instead behaves as if I just shared the Loan to the newly assigned Owner. This issue is prevented on the Front-End using form validations. - API Bug 2: The
One-Many
orMany-Many
relation betweenUser
andLoan
is not enforced on the database. I was able to insert invalid User IDs, such as0
or999
. This risk is mitgated on the front end with form validations or limiting the options to valid users using theSelectDropdown
Component of all Users. - Documentation:
POST: /loans/{loan_id}/share
is stating that a200
response is astring
type while the API is actually returning[string]
. For now I prevented this issue by checking the 0th element's value inSelectDropdown
L51 - Documentation:
LoanSchemaBase.status
is stated as astring
but should more accurately be described as anenum
ofactive
andinactive
. I only discovered this while testing invalid inputs.