Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
033111c
Initialize project using Create React App
meletisnikolaidisswiss Jul 10, 2025
a13edab
Initial setup
meletisnikolaidisswiss Jul 10, 2025
47ed261
Added routes and redux reducers and store for fetching breeds and cats
meletisnikolaidisswiss Jul 10, 2025
dfb8089
Refactored code, added modal component and new route for details view
meletisnikolaidisswiss Jul 11, 2025
c301bd5
Refactored code, added modal component and new route for details view
meletisnikolaidisswiss Jul 11, 2025
3fdb41f
Added custom hooks, added cat details functionality, added Modal
meletisnikolaidisswiss Jul 11, 2025
d83f6b2
Added components for Navigation and Footer, added styles for mobile a…
meletisnikolaidisswiss Jul 11, 2025
1e04a78
Added select breed functionality and load images per breed
meletisnikolaidisswiss Jul 12, 2025
049da5e
Added FavouriteButton with animation, added new feature for favourite…
meletisnikolaidisswiss Jul 12, 2025
26f93e3
Added favourites for displaying favourites
meletisnikolaidisswiss Jul 12, 2025
af0b208
Added favourites for displaying favourites
meletisnikolaidisswiss Jul 12, 2025
59fec10
Added user_id for favourites list
meletisnikolaidisswiss Jul 13, 2025
84d63fd
Added limit for favourites list
meletisnikolaidisswiss Jul 16, 2025
9cecc31
Refactored context, added some extra info
meletisnikolaidisswiss Jul 16, 2025
b4d5f51
Refactored context, added some extra info
meletisnikolaidisswiss Jul 16, 2025
93300b3
Added rating component, add and remove from FavouritesList.tsx, .env.…
meletisnikolaidisswiss Jul 16, 2025
7bad8b2
Fixed README.md
meletisnikolaidisswiss Jul 16, 2025
a9ba99b
Merge remote-tracking branch 'upstream/main' into safe-branch
meletisnikolaidisswiss Jul 16, 2025
59f828c
Fixed some errors
meletisnikolaidisswiss Jul 16, 2025
71e17ee
Added Error message component in case of an error
meletisnikolaidisswiss Jul 16, 2025
7107e10
Added an E2E test example for home page
meletisnikolaidisswiss Jul 16, 2025
7b595c5
Added an E2E test example for home page
meletisnikolaidisswiss Jul 16, 2025
5f434ce
Fixed some errors
meletisnikolaidisswiss Jul 16, 2025
4edb84a
Fixed some errors
meletisnikolaidisswiss Jul 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
REACT_APP_MAX_FAVOURITES=10
28 changes: 28 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
.idea
# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

#testing
/cypress/downloads/*
/cypress/screenshots/*
67 changes: 54 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,62 @@
# GlobalWebIndex Engineering Challenge
# 🐱 Catlover's App

## Exercise: CatLover
Welcome to **Catlover's App** – a simple and adorable platform made for cat enthusiasts!

Create a React application for cat lovers which is going to build upon thecatapi.com and will have 3 views.
The **first** view displays a list of 10 random cat images and a button to load more. Clicking on any of those images opens a modal view with the image and the information about the cat’s breed if available. This would be a link to the second view below - the breed detail. The modal should also contain a form to mark the image as your favourite (a part of the third view as well). Make sure you can copy-paste the URL of the modal and send it to your friends - they should see the same image as you can see.
This app allows you to:

The **second** view displays a list of cat breeds. Each breed opens a modal again with a list of cat images of that breed. Each of those images must be a link to the image detail from the previous point.
- 🖼 View **random cat images**
- 🧬 Select a cat to see detailed **breed information**
- 📚 Explore a list of **all available breeds** with images related to each
- ❤️ Save your favourite cats to a **favourites view**

The **third** view allows you do the following things:
---

- Display your favourite cats
- Remove an image from your favourites (use any UX option you like)
## 🚀 Tech Stack

You can find the API documentation here: https://developers.thecatapi.com/
We give you a lot of freedom in technologies and ways of doing things. We only insist on you using React.js. Get creative as much as you want, we WILL appreciate it. You will not be evaluated based on how well you follow these instructions, but based on how sensible your solution will be. In case you are not able to implement something you would normally implement for time reasons, make it clear with a comment.
Built with the following technologies:

- ⚛️ **React** (using Create React App)
- 🟦 **TypeScript**
- 🧠 **Redux** for state management
- 🎨 **Tailwind CSS** for UI styling

---

## 🛠 Getting Started

### Steps for running the app in development mode

```bash
1. Clone the project

git clone https://github.com/melnikolaidis86/catlover.git
cd catlovers-app

2. Install dependencies

# In root folder
npm install

# Then in server folder
cd server
npm install

3. Copy env files

# In root folder
cp .env.example .env

# Then in server folder
cd server
cp .env.example .env

4. You can get a free API key from:

#👉 https://developers.thecatapi.com/

5. Run the in development mode

# In root folder
npm run dev

## Submission

Once you have built your app, share your code in the mean suits you best
Good luck, potential colleague!
9 changes: 9 additions & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { defineConfig } from "cypress";

export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
},
baseUrl: "http://localhost:3000/",
},
});
24 changes: 24 additions & 0 deletions cypress/e2e/home.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
describe('Cat Lovers App', () => {
beforeEach(() => {
cy.visit('/');
});

it('loads the homepage', () => {
cy.getByTestId('load-more-button').contains('Load More');
});

it('loads more cats on click', () => {
cy.getByTestId('load-more-button').click();
cy.getByTestId('cat-card').should('have.length.greaterThan', 10);
});

it('opens modal when a cat card is clicked', () => {
cy.getByTestId('cat-card').first().click();
cy.getByTestId('cat-details-modal').should('be.visible');
cy.getByTestId('cat-name').should('exist');
cy.getByTestId('cat-description').should('exist');
});
});


export {};
13 changes: 13 additions & 0 deletions cypress/support/commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
declare global {
namespace Cypress {
interface Chainable {
getByTestId(testId: string): Chainable;
}
}
}

Cypress.Commands.add('getByTestId', (testId: string) =>
cy.get(`[data-test-id="${testId}"]`)
);

export {};
12 changes: 12 additions & 0 deletions cypress/support/component-index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Components App</title>
</head>
<body>
<div data-cy-root></div>
</body>
</html>
36 changes: 36 additions & 0 deletions cypress/support/component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// ***********************************************************
// This example support/component.ts is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************

// Import commands.js using ES2015 syntax:
import './commands'

import { mount } from 'cypress/react'

// Augment the Cypress namespace to include type definitions for
// your custom command.
// Alternatively, can be defined in cypress/support/component.d.ts
// with a <reference path="./component" /> at the top of your spec.
declare global {
namespace Cypress {
interface Chainable {
mount: typeof mount
}
}
}

Cypress.Commands.add('mount', mount)

// Example use:
// cy.mount(<MyComponent />)
17 changes: 17 additions & 0 deletions cypress/support/e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// ***********************************************************
// This example support/e2e.ts is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************

// Import commands.js using ES2015 syntax:
import './commands'
Loading