Feat/implement cats gallery app#33
Conversation
Set up the initial project using Next.js as the React framework and Tailwind CSS for styling. Added the custom styling theme based on the neo-brutalist design.
This commit introduces the Cat list view, where we fetch and display 10 cats at a time. Users can load more cats when reaching the end of the list. Additionally, we’ve introduced several reusable UI components for broader use across the application: - Button - Alert - ServerSideError
This commit introduces a new modal that displays detailed information about a cat when its image is clicked. If breed data is available, it is shown alongside the image. Users can also now mark images as favorite or unfavorite. New hooks and components added: * useDebounce hook * Modal component * IconButton component * Star rating component
This commit introduces a new breeds page that displays a list of available cat breeds. Users can: - Click on a breed to open a modal showing images of that breed. - Click on any image to navigate to the image detail modal, which includes a larger version of the image and breed information.
This commit introduces a new favourites page, allowing users to view their favourite cat images and unfavourite them if desired. To support this feature, we implemented persistent user identification: - When a new user opens the browser, a unique userId is generated. - The ID is stored in a cookie (for server-side access) and in localStorage (for easier access on the client).
…nd error handling * Rename favorite => favourite * Improve modal rendering strategy with parallel routes of nextjs * Enabled Next.js cache to improve performance * Replaced inline alert handling with a reusable alert hook * Made useFetch more scalable by allowing custom props to be passed to the execute function * Improved error handling across the app * Added skeleton loaders throughout the app for a better loading experience * Now the cat card is immediately removed after unfavourite * Move fetching of favourites on the server side
In this commit we are improving the docs on how to setup the env variables for the app, we also include a script to make it automatically. We also add some clarification on the docs regarding the tests
This commit addresses an issue where the uuid on client side could be different on server side and on client side.
In this commit we address two comments of of cursor: - We simplify the "authentication" of the user by setting the userID on the middleware, this will guarantee that the user id will always be there and we will not need to fallback to default value. - We enhance the condition regarding if we call or not the delete cat from favourite
In this commit we are creating a new server function to favourite/unfavourite an image, by moving the logic in server function is easier to handle the response in the client,\ making a more simple implementation.
We are making this change to address a possible bug where we where increasing the page number,\ in the beginning of the function. This could cause issues where the server returned an error or the request failed for any reason. Now we are increasing the page after the success of the request. We have also added a comment regarding the setHasMore logic to provide more clarity around it.
We are making a change where in some components we where navigating to cats-gallery instead the root of the application "/". This is not breaking change, as the "/" is equal to "cats-gallery" as we have modified nextjs to treat as root the "cats-gallery". The reason of this change is to make it more obvious to the reviewer that the navigation leads to cats-gallery.
gpositive
left a comment
There was a problem hiding this comment.
Hey @AlexNti - Thanks a lot for your effort mate! :)
I've checked your assignment and I have some questions for you:
- Why did you choose Next.js over plain React (e.g., Vite + React Router etc)? Could you walk me through the trade-offs for this project’s needs?
- I noticed that for some requests (ie
getCatsImagesList) you're using a time based invalidation (ie: 600s) but for some others (ie:favourites) you're using a tag based invalidation. What was the reason behind this decision? How would you scale invalidation in general? - What are the pros/cons of calling the
NEXT_PUBLIC_API_KEYfrom the client vs proxying it through server actions/routes? - I've tried running the tests but this failed. Do you have any guidelines on how can I run them?
- If you had some more time, what would you have done differently?
Again thanks for your submission and looking forward to your answers!
| type TabItem = { | ||
| label: string; | ||
| href: string; | ||
| icon?: string; |
There was a problem hiding this comment.
Nice catch, its not used my intention was to add icon to the tabs but I forgot 🙃.
| fetchFn: (args: Args) => Promise<ApiSuccessOrError<T>>, | ||
| options: UseFetchOptions = {} | ||
| ) { | ||
| const { fetchOnMount } = options; |
There was a problem hiding this comment.
Noticed that this option is not used anywhere in the source code. Can you verify if this is correct?
Could you help me with the reasoning behind this option? What does this do and what are the pros/cons?
There was a problem hiding this comment.
Indeed this is no longer used, Initially i was using it, but after making a small rethink e.x in the favourites component in the code I decided to follow a different strategy and all the initial fetches to happen on the server, so the fetchOnMount prop became lets say deprecated by that decision.
The fetchOnMount prop gives developers the flexibility to choose whether or not a query should be executed on mount. The standard behavior of this hook is to not execute the query automatically users need to trigger it manually by calling the execute function. This is the approach used in components that implement pagination.
Hey @gpositive , thank for your review! In the following section I am addressing your questions.
I chose Next.js over Vite + React router because it includes React features built in, like RSC and server actions. My goal was to move as much logic as possible to the server and keep components simple for example, the Next.js also has a file-based routing system, which I find easy to use. Another benefit is its caching pages that don’t change often, like the breeds page, can be cached and served faster. As the cats gallery app is an app that uses alot of images we can benefit from the image optimazation that nextjs offers. For the trade-offs, if I had used Vite + React Router, I would need to move the server logic to the frontend. I would also need to set up my own caching (e.g., tanstack query) and handle image optimization myself if needed.
Correct those two are different revalidation strategies. Using tags allows us to create a more complex cache key and easily revalidate all content associated with that key, simply by knowing the key itself. In our case, we generate the tag key based on the user ID, and when the user adds something to favourites we invalidate the cache. When it comes to scaling, we should treat each situation as a standalone case. Sometimes we need to trigger cache invalidation on demand, while other times it’s fine to let it expire automatically after a set period.
By moving it to the server we are hiding the API key from the users, so this offer more protection. To be honest i shouldn have omited the
As the tests are e2e, and depend on a running server you need have an application that runs on
I would change the way the modal works in the cats-gallery by adding a carousel/swipe, now you click an image and a modal pops up, if you want to see the next cat you need to close the modal and click the next image from the grid, with the swipe/carousel view a user would be able to move easily to next/previous cat images without having to close the modal. |
🚀 What’s New
This PR adds three new pages to the cats application:
Cats Gallery: Displays a list of cat images with pagination. Users can load more images as they scroll and view details or favorite an image by clicking on it.
Breeds Page: Shows a list of all available cat breeds. Clicking on a breed shows related images. Selecting an image opens a modal with breed details.
Favourites Page: Displays all the user’s favorite images. Users can remove favorites from this page.
❗ Please read the README.md for setup instructions, design decisions, architecture details, and general project information.