This project was my final assignment for the General Assembly Software Engineering Immersive course. The objective was to develop a full-stack app using React for the frontend and Django REST Framework for managing data from a Postgres database. Inspired by my love for books and frequent usage of Goodreads, I chose to create a simplified version of a book-related app.
https://goodreads-project.herokuapp.com/
The following credentials can be used:
- email: ivana@email.com
- password: lozinkaa123!
To set up the project, follow these steps:
- Go to the root directory of the project.
- Install the backend dependencies:
pipenv install
- Enter the project shell:
pipenv shell
- Start the server:
python manage.py runserver
- Go to the client folder:
cd client
- Install the frontend dependencies:
npm i
- Run the frontend server:
npm run start
This was a solo project, completed within a 1.5-week timeframe.
- React
- JavaScript
- Python
- Django
- PostgreSQL
- Axios
- SASS
- JSX
- HTML
- Build a full-stack application by making your own backend and your own front-end
- Use a Python Django API using Django REST Framework to serve your data from a Postgres database
- Consume your API with a separate front-end built with React
- Be a complete product which most likely means multiple relationships and CRUD functionality for at least a couple of models
- Implement thoughtful user stories/wireframes that are significant enough to help you know which features are core MVP and which you can cut
- Have a visually impressive design to kick your portfolio up a notch and have something to wow future clients & employers. ALLOW time for this.
- Be deployed online so it's publicly accessible.
I Started the project by drawing a wireframe on Excalidraw. The app consists of the following pages:
- Login: Allows users to log in to their accounts.
- Register: Enables new users to create an account.
- Browse Books: Displays book categories and the books belonging to each category.
- Single Book: Shows detailed information about a specific book. Users can add books to their library by clicking the "Add to Library" button and categorize them as "Read," "Currently Reading," or "Wishlist." If a book is already in the library, the user can view its current category instead of the default "Add to Library" button.
- My Books: Allows logged-in users to manage their book library. They can view all the books they have added to a specific category (Read, Currently Reading, Wishlist) and also see the books in the "All" section that includes all categories combined.
- Profile: Shows the user's profile photo, bookshelves with links to different library categories, and the number of books in each category. It also includes recent updates for the user.
In order to keep track of the tasks I need to do, I created a Trello board.
In the backend, I have implemented the Book
, Review
, and User
models and their views, serializers, and URL paths.
After creating the Login and Register page, I created the BrowseBooks
component that fetches the book data from the server, filters the books by genre, and renders them in separate sections based on the categories.
This frontend component was the most complex one because it handles the linking of the user and the book once the user has added a specific book to their library.
Also, I made sure that users could add books to their library only if they are logged in.
Moreover, this component also handles the reviews CRUD logic as well. Leaving reviews is also limited to only logged-in users.
The MyBooks
component is responsible for displaying the user's list of books categorized into "all," "read," "reading," and "wishlist." I decided to add queries in the URLs, so the user can switch between these categories and have distinct URLs for each category. This allows users to easily share or bookmark specific category links, such as the link to only "read" books or "wishlist" books. This approach improves navigation and makes it easier for users to share or bookmark specific book categories.
Besides showing other profile-related information, the profile page also shows the user's bookshelves. Each shelf is represented as a clickable link, utilizing query parameters in the URLs to filter and display specific book categories. The number of books on each shelf is also shown next to the shelf name.
Despite time constraints, I managed to add a "reading challenge" section. In order to create a dynamic progress bar, I designed it to retrieve the user's reading progress by checking the length of their "read" list (user.read.length
) \in the user model. This ensures that the progress bar accurately reflects the number of books the user has read. Additionally, the reading goal can be updated at any time, allowing users to adjust their target as needed.
One of the most challenging aspects of the implementation was establishing a mechanism to track the books added by users to their read, reading, and wishlist categories. This tracking was crucial for dynamically displaying the appropriate category name instead of the "add to library" text on the SingleBook page. If a book had not been categorized before, the "add to library" text would remain unchanged. When a book is updated from one category to another, I wanted the button text to reflect the new category, ensuring consistency between the user interface and the database.
In order to achieve that, I added reading, reading, and wishlist custom fields to the User model.
Then I created the put method in the UserDetailView
API view, which updates the user's details, including their book lists (read, reading, wishlist). It compares the updated book lists with the original lists to handle removing books from one list and adding them to another if necessary. Finally, it saves the updated user data and returns the serialized user information.
My biggest win was successfully completing my first solo full-stack project within the deadline while utilizing advanced server-side functionality to manipulate the database with complex conditions.
- I gained valuable insights into the functioning of models and serializers.
- I learned how to define and manipulate data structures, establish relationships between different entities, and ensure the smooth transfer of data between the application and the database.
I haven't noticed any bugs.
- During registration, instead of displaying "Request failed with status code 422" when the password is too simple, it would be preferable to display a more specific message like "Password too simple."
- Add a search bar.
- Add book ratings.
- Add dates (when a book is added to the library, when a book is read, etc.).
- Add reading progress.
- Add a rating option.
- Display the average rating.
- Add a search bar
- Implement an "Add" button next to a book cover.