Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
14525e9
chore: initialize Vite React+TS app with Tailwind v4 and React Router…
emirbayrakt Aug 23, 2025
182aaf3
feat(api): add TMDB client with auth and image url helpers; load keys…
emirbayrakt Aug 23, 2025
cec9ded
feat(ui): add loading spinners, skeletons, and error/empty state comp…
emirbayrakt Aug 23, 2025
9803155
feat(search): debounced search bar with URL-synced query (?q=)
emirbayrakt Aug 23, 2025
4961403
feat(search): movie grid backed by /search/movie with paged β€œLoad mor…
emirbayrakt Aug 23, 2025
c032204
feat(ui): add MovieCard hover overlay with truncated overview and sub…
emirbayrakt Aug 23, 2025
5adcedb
feat(home): add Trending/Popular
emirbayrakt Aug 23, 2025
ad97edb
feat(detail): movie details page and cinematic hero (uses backdrop + …
emirbayrakt Aug 23, 2025
ea07680
feat(detail): add Overview/Videos/Photos tabs with URL state; handle …
emirbayrakt Aug 23, 2025
9826646
feat(detail): add Cast section using /movie/{id}/credits with profile…
emirbayrakt Aug 23, 2025
f3ec503
feat(detail): add β€œMore like this” rail via /movie/{id}/similar
emirbayrakt Aug 23, 2025
40f3a0b
feat(core): add 404 page and robust error handling for API failures w…
emirbayrakt Aug 23, 2025
9fd1c3b
feat: enhance layout and loading states; add skeletons and improve st…
emirbayrakt Aug 23, 2025
a15ec07
feat: update layout with new header and footer components; enhance se…
emirbayrakt Aug 23, 2025
4813895
feat: enhance layout and styling of footer and header; improve search…
emirbayrakt Aug 23, 2025
5a13445
feat: enhance footer with copyright and author information; add Scrol…
emirbayrakt Aug 23, 2025
8e3d6ee
feat: refactor HomePage component; introduce SearchHeaderSection and …
emirbayrakt Aug 23, 2025
082173e
feat: adjust layout and styling across multiple components; refine ma…
emirbayrakt Aug 23, 2025
7075c25
feat: enhance Footer and Header components; add navigation links and …
emirbayrakt Aug 23, 2025
58ff781
fix not found text
emirbayrakt Aug 23, 2025
67946dd
feat: add testing setup with Vitest and Playwright
emirbayrakt Aug 23, 2025
000f207
feat: enhance test coverage with new unit and e2e tests
emirbayrakt Aug 23, 2025
6614d90
Remove unused React dependencies and their source maps to clean up th…
emirbayrakt Aug 23, 2025
c6c9e55
feat: update grid layout classes for consistency across components; a…
emirbayrakt Aug 23, 2025
0369706
refactor: streamline Playwright config by removing unused browser pro…
emirbayrakt Aug 23, 2025
45ed5c8
docs: update README to enhance project overview, add deployment instr…
emirbayrakt Aug 23, 2025
df1cc5e
docs: add Live Demo section with project link to README
emirbayrakt Aug 23, 2025
e054306
fix: correct placeholder text in SearchBar component and update test …
emirbayrakt Aug 24, 2025
e6ec763
fix: update text color to white for better visibility in MovieCard an…
emirbayrakt Aug 24, 2025
eda4759
fix: replace anchor tag with span for title in MovieCard component to…
emirbayrakt Aug 24, 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 emir-assignment/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_TMDB_API_KEY=YOUR_API_KEY
30 changes: 30 additions & 0 deletions emir-assignment/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# 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

test-results

.vite
155 changes: 155 additions & 0 deletions emir-assignment/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# 🎬 CinEmir β€” TMDB Movie Explorer

A sleek, fast movie browser built with React + TypeScript + Vite, styled with Tailwind, and powered by TMDB. It features a dynamic, cinematic UI, smooth navigation, rich details, and a polished mobile experience.

> β€œFind your next favorite film faster β€” with style.”

---

## 🌐 Live Demo

πŸ‘‰ [cinemir.vercel.app](https://cinemir.vercel.app)

---

## ✨ Highlights

- Smart search with debounce, grid results, and β€œLoad more”
- Cinematic detail page: hero with backdrop + gradient, ratings, and key facts
- **Tabbed details** (synced to URL): _Overview_ / _Videos_ / _Photos_
- Cast grid (with profile placeholders) & **More like this** rail (drag-to-scroll)
- Robust states: skeletons, graceful errors (with retry), and empty views
- A11y & UX polish: keyboard focus, CLS‑safe images
- Sticky header & well-designed footer
- Document title hook (tab shows the movie title)
- Scroll behavior: scroll-to-top on route change, but not on β€œLoad more” or tab switch
- Decent amount of tests (limited due to time constraints): **Vitest** unit tests + **Playwright** E2E

---

## 🧱 Tech Stack

- **Frontend:** React, TypeScript, Vite
- **Routing:** React Router
- **Styles:** Tailwind CSS, lucide-react icons
- **API:** TMDB (The Movie Database)
- **Testing:** Vitest + @testing-library/react + Playwright

---

## πŸ“¦ Getting Started

```bash
# 1) Install deps
npm install

# 2) Set env (see next section)
cp .env.example .env
# then set VITE_TMDB_API_KEY=your_key_here

# 3) Run dev server
npm run dev

# 4) Build & preview
npm run build
npm run preview
```

---

## πŸ” Environment Variables

Create `.env` from the example and add your TMDB key:

```env
VITE_TMDB_API_KEY=YOUR_TMDB_KEY
```

_This product uses the TMDB API but is not endorsed or certified by TMDB._

---

## πŸ§ͺ Testing

### Unit: Vitest + Testing Library

- Configured JSDOM environment
- Global test utils (RTL, user-event), JSX transform, and strict TypeScript

**Run:**

```bash
npm run test # watch
npm run test:run # single run (CI)
npm run test:ui # if using the Vitest UI
```

**Folder convention:**

```
tests/
unit/
*.test.tsx
e2e/
*.spec.ts
```

### E2E: Playwright

- Headless-stable tests with API mocking (routes for TMDB endpoints)
- Local dev server bootstrapped via Playwright `webServer`

**Run:**

```bash
npm run e2e # headless
npm run e2e:open # headed (debug)
```

> Tip: For headless reliability, don’t use arbitrary timeouts β€” mock network and assert on locators (we do).

---

## 🌐 Deployment (Vercel)

This is a client-side SPA; add a rewrite so all routes serve `index.html`:

`vercel.json`

```json
{
"rewrites": [{ "source": "/(.*)", "destination": "/" }]
}
```

Then:

1. Push your branch to GitHub (e.g., `assignment`).
2. In Vercel, import the repo and select the **assignment** branch (Project β†’ Settings β†’ Git β†’ Production Branch) or create a Preview for the branch.
3. Set `VITE_TMDB_API_KEY` in **Project β†’ Settings β†’ Environment Variables**.
4. **Build Command:** `vite build` β€’ **Output:** `dist`

If you saw the Vercel default 404 page, you were missing the rewrite above.

---

## πŸ”§ Developer Notes

- Reduced CLS: explicit image width/height; reserved spaces in skeletons; hero has fixed height
- URL tab sync: `?tab=overview|videos|photos` (resets to overview when navigating to a new movie)
- Images endpoint & language: the images API can return empty arrays when language filters; we fetch without forcing language there to always get assets.
- Scroll restoration: customized so pagination/tab switches don’t yank the viewport.

---

## πŸ‘ Credits

- **Data/API:** TMDB
- _This product uses the TMDB API but is not endorsed or certified by TMDB._
- **Icons:** [lucide.dev](https://lucide.dev)

---

## πŸ“„ License

**MIT** β€” do what you love. πŸ’š
23 changes: 23 additions & 0 deletions emir-assignment/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
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'
import { globalIgnores } from 'eslint/config'

export default tseslint.config([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs['recommended-latest'],
reactRefresh.configs.vite,
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
},
])
13 changes: 13 additions & 0 deletions emir-assignment/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CinEmir | Where every movie begins with you.</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Loading