Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_CAT_API_KEY=live_wYrhpsJfULRUbN2LjKMkocqw7XRuy6Nzn4WIsnMTmJUU2uw3Vbx1hdWiYjHrkRw8
30 changes: 30 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Test

on:
pull_request:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run linting
run: npm run lint

- name: Type check
run: npm run type-check

- name: Run tests
run: npm test
26 changes: 26 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
.env
coverage
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
23.11.0
7 changes: 7 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"singleQuote": true,
"trailingComma": "es5",
"printWidth": 100,
"tabWidth": 2,
"semi": true
}
144 changes: 131 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,139 @@
# GlobalWebIndex Engineering Challenge
<div align="center">
<img src="src/assets/logo.svg" alt="CatLover Logo" width="45" height="45" />
</div>

## Exercise: CatLover
<h1 align="center">CatLover App</h1>

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.
A React application for to browse random cats, favorite, and learn about different cat breeds.

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.
## Features

The **third** view allows you do the following things:
- Browse and view cat images
- Explore different cat breeds and their details
- Save your favorite cats
- Responsive design

- Display your favourite cats
- Remove an image from your favourites (use any UX option you like)
## API Integration

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.
This application uses The Cat API (https://thecatapi.com/) to fetch:

## Submission
- Random cat images
- Cat breed information
- Favorite cats management

Once you have built your app, share your code in the mean suits you best
Good luck, potential colleague!
To run the application:

1. Sign up for a free API key at https://thecatapi.com/
2. Copy `.env.sample` to `.env`:

```bash
cp .env.sample .env
```

3. Add your API key to the `.env` file:

```
VITE_CAT_API_KEY=your_api_key_here
```

## Tech Stack

- React 19
- TypeScript
- Vite
- React Router v7
- React Query
- TailwindCSS
- Vitest for testing
- ESLint & Prettier for code quality

## Prerequisites

- Node.js (version specified in .nvmrc)
- npm or yarn

## Getting Started

1. Clone the repository and go to project folder:

```bash
git clone [repository-url]
cd platform-react-challenge
```

2. Install dependencies:
> [!INFO]
> We suggest to use [nvm](https://github.com/nvm-sh/nvm) for better compatibility and run `nvm use` before installing

```bash
npm install
```

3. Start the development server:

```bash
npm run dev
```

The application should be available at `http://localhost:5173`

## Available Scripts

- `npm run dev` - Start development server
- `npm run build` - Build for production
- `npm run preview` - Preview production build
- `npm run test` - Run tests
- `npm run test:coverage` - Run tests with coverage
- `npm run lint` - Run ESLint
- `npm run type-check` - Run TypeScript type checking

## Project Structure

```
src/
├── assets/ # Static assets
├── components/ # Reusable UI components
├── constants/ # Application constants
├── contexts/ # React contexts
├── hooks/ # Custom React hooks
├── layouts/ # Page layouts
├── providers/ # Context providers
├── services/ # API services
├── testing/ # Test configuration
└── types/ # TypeScript type definitions
```

## Testing

The project uses Vitest for testing. Run tests with:

```bash
npm run test
```

For test coverage:

```bash
npm run test:coverage
```

> [INFO]
> Github actions are used to run the tests with each PR

### Adding Tests

To add new tests:

1. Create test files with the `.test.ts` or `.test.tsx` extension
2. Place test files next to the files they test or in a `__tests__` directory

For testing API calls, use the `MSW` package and mock the API responses. Feel free to check existing tests if you are not familiar with it or the package's [documentation](https://mswjs.io/docs). Please keep global endpoints mocking into the [./src/testing/mocks/handlers.ts](./src/testing/mocks/handlers.ts) file

## Contributing

1. Fork the repository
2. Create your feature branch (`git checkout -b amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin amazing-feature`)
5. Open a Pull Request
6. GitHub Actions workflow runs `lint`, `type-check`, and `test` on every PR
25 changes: 25 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import js from '@eslint/js';
import globals from 'globals';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
import tseslint from 'typescript-eslint';

export default tseslint.config(
{ ignores: ['dist'] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
},
}
);
13 changes: 13 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en" class="bg-gray-50">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Cat Lovers</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Loading