Skip to content

Commit c4490f0

Browse files
committed
feat: add MovieCard component for displaying movie details and refactor MoviesPage to utilize it
1 parent 5b35a10 commit c4490f0

File tree

17 files changed

+208
-175
lines changed

17 files changed

+208
-175
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { href, Link } from 'react-router'
2+
import { type Movie } from './movies-data.ts'
3+
4+
export function MovieCard({ movie }: { movie: Movie }) {
5+
return (
6+
<Link
7+
to={href('/:movieId', { movieId: String(movie.id) })}
8+
className="rr-card transition-shadow hover:shadow-lg"
9+
>
10+
<div className="mb-4">
11+
<img
12+
src={movie.poster}
13+
alt={`${movie.title} poster`}
14+
className="mb-4 h-64 w-full rounded-lg object-cover"
15+
/>
16+
<h3 className="rr-heading text-lg font-semibold">{movie.title}</h3>
17+
<p className="rr-text mb-2">Year: {movie.year}</p>
18+
<p className="rr-text mb-2">Rating: {movie.rating}/10</p>
19+
<p className="rr-text mb-4 text-sm text-gray-600">
20+
{movie.description}
21+
</p>
22+
<div className="flex items-center gap-2">
23+
<span
24+
className={`rr-badge ${movie.isFavorite ? 'rr-badge-red' : ''}`}
25+
>
26+
{movie.isFavorite ? 'Favorite' : 'Not Favorite'}
27+
</span>
28+
</div>
29+
</div>
30+
</Link>
31+
)
32+
}

exercises/01.start/01.problem.vite-plugin/app/routes/index.tsx

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { href, Link } from 'react-router'
1+
import { MovieCard } from '#app/movie-card.tsx'
22
import { getMovies } from '#app/movies-data.ts'
33
import { type Route } from './+types/index'
44

@@ -11,32 +11,7 @@ export default function MoviesPage({ loaderData }: Route.ComponentProps) {
1111
const { movies } = loaderData
1212

1313
const moviesUI = movies.map((movie) => (
14-
<Link
15-
key={movie.id}
16-
to={href('/:movieId', { movieId: String(movie.id) })}
17-
className="rr-card transition-shadow hover:shadow-lg"
18-
>
19-
<div className="mb-4">
20-
<img
21-
src={movie.poster}
22-
alt={`${movie.title} poster`}
23-
className="mb-4 h-64 w-full rounded-lg object-cover"
24-
/>
25-
<h3 className="rr-heading text-lg font-semibold">{movie.title}</h3>
26-
<p className="rr-text mb-2">Year: {movie.year}</p>
27-
<p className="rr-text mb-2">Rating: {movie.rating}/10</p>
28-
<p className="rr-text mb-4 text-sm text-gray-600">
29-
{movie.description}
30-
</p>
31-
<div className="flex items-center gap-2">
32-
<span
33-
className={`rr-badge ${movie.isFavorite ? 'rr-badge-red' : ''}`}
34-
>
35-
{movie.isFavorite ? 'Favorite' : 'Not Favorite'}
36-
</span>
37-
</div>
38-
</div>
39-
</Link>
14+
<MovieCard key={movie.id} movie={movie} />
4015
))
4116

4217
return (
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { href, Link } from 'react-router'
2+
import { type Movie } from './movies-data.ts'
3+
4+
export function MovieCard({ movie }: { movie: Movie }) {
5+
return (
6+
<Link
7+
to={href('/:movieId', { movieId: String(movie.id) })}
8+
className="rr-card transition-shadow hover:shadow-lg"
9+
>
10+
<div className="mb-4">
11+
<img
12+
src={movie.poster}
13+
alt={`${movie.title} poster`}
14+
className="mb-4 h-64 w-full rounded-lg object-cover"
15+
/>
16+
<h3 className="rr-heading text-lg font-semibold">{movie.title}</h3>
17+
<p className="rr-text mb-2">Year: {movie.year}</p>
18+
<p className="rr-text mb-2">Rating: {movie.rating}/10</p>
19+
<p className="rr-text mb-4 text-sm text-gray-600">
20+
{movie.description}
21+
</p>
22+
<div className="flex items-center gap-2">
23+
<span
24+
className={`rr-badge ${movie.isFavorite ? 'rr-badge-red' : ''}`}
25+
>
26+
{movie.isFavorite ? 'Favorite' : 'Not Favorite'}
27+
</span>
28+
</div>
29+
</div>
30+
</Link>
31+
)
32+
}

exercises/01.start/01.solution.vite-plugin/app/root.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {
33
Links,
44
Meta,
55
Outlet,
6-
Scripts,
76
ScrollRestoration,
87
} from 'react-router'
98

@@ -35,7 +34,6 @@ export function Layout({ children }: { children: React.ReactNode }) {
3534
<body>
3635
{children}
3736
<ScrollRestoration />
38-
<Scripts />
3937
</body>
4038
</html>
4139
)

exercises/01.start/01.solution.vite-plugin/app/routes/index.tsx

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { href, Link } from 'react-router'
1+
import { MovieCard } from '#app/movie-card.tsx'
22
import { getMovies } from '#app/movies-data.ts'
33
import { type Route } from './+types/index'
44

@@ -11,32 +11,7 @@ export default function MoviesPage({ loaderData }: Route.ComponentProps) {
1111
const { movies } = loaderData
1212

1313
const moviesUI = movies.map((movie) => (
14-
<Link
15-
key={movie.id}
16-
to={href('/:movieId', { movieId: String(movie.id) })}
17-
className="rr-card transition-shadow hover:shadow-lg"
18-
>
19-
<div className="mb-4">
20-
<img
21-
src={movie.poster}
22-
alt={`${movie.title} poster`}
23-
className="mb-4 h-64 w-full rounded-lg object-cover"
24-
/>
25-
<h3 className="rr-heading text-lg font-semibold">{movie.title}</h3>
26-
<p className="rr-text mb-2">Year: {movie.year}</p>
27-
<p className="rr-text mb-2">Rating: {movie.rating}/10</p>
28-
<p className="rr-text mb-4 text-sm text-gray-600">
29-
{movie.description}
30-
</p>
31-
<div className="flex items-center gap-2">
32-
<span
33-
className={`rr-badge ${movie.isFavorite ? 'rr-badge-red' : ''}`}
34-
>
35-
{movie.isFavorite ? 'Favorite' : 'Not Favorite'}
36-
</span>
37-
</div>
38-
</div>
39-
</Link>
14+
<MovieCard key={movie.id} movie={movie} />
4015
))
4116

4217
return (
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { href, Link } from 'react-router'
2+
import { type Movie } from './movies-data.ts'
3+
4+
export function MovieCard({ movie }: { movie: Movie }) {
5+
return (
6+
<Link
7+
to={href('/:movieId', { movieId: String(movie.id) })}
8+
className="rr-card transition-shadow hover:shadow-lg"
9+
>
10+
<div className="mb-4">
11+
<img
12+
src={movie.poster}
13+
alt={`${movie.title} poster`}
14+
className="mb-4 h-64 w-full rounded-lg object-cover"
15+
/>
16+
<h3 className="rr-heading text-lg font-semibold">{movie.title}</h3>
17+
<p className="rr-text mb-2">Year: {movie.year}</p>
18+
<p className="rr-text mb-2">Rating: {movie.rating}/10</p>
19+
<p className="rr-text mb-4 text-sm text-gray-600">
20+
{movie.description}
21+
</p>
22+
<div className="flex items-center gap-2">
23+
<span
24+
className={`rr-badge ${movie.isFavorite ? 'rr-badge-red' : ''}`}
25+
>
26+
{movie.isFavorite ? 'Favorite' : 'Not Favorite'}
27+
</span>
28+
</div>
29+
</div>
30+
</Link>
31+
)
32+
}

exercises/01.start/02.solution.loader-rsc/app/root.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {
33
Links,
44
Meta,
55
Outlet,
6-
Scripts,
76
ScrollRestoration,
87
} from 'react-router'
98

@@ -35,7 +34,6 @@ export function Layout({ children }: { children: React.ReactNode }) {
3534
<body>
3635
{children}
3736
<ScrollRestoration />
38-
<Scripts />
3937
</body>
4038
</html>
4139
)

exercises/01.start/02.solution.loader-rsc/app/routes/index.tsx

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,14 @@
1-
import { href, Link } from 'react-router'
1+
import { MovieCard } from '#app/movie-card.tsx'
22
import { getMovies } from '#app/movies-data.ts'
33
import { type Route } from './+types/index'
44

55
export async function loader() {
66
const movies = await getMovies()
77

88
const moviesUI = movies.map((movie) => (
9-
<Link
10-
key={movie.id}
11-
to={href('/:movieId', { movieId: String(movie.id) })}
12-
className="rr-card transition-shadow hover:shadow-lg"
13-
>
14-
<div className="mb-4">
15-
<img
16-
src={movie.poster}
17-
alt={`${movie.title} poster`}
18-
className="mb-4 h-64 w-full rounded-lg object-cover"
19-
/>
20-
<h3 className="rr-heading text-lg font-semibold">{movie.title}</h3>
21-
<p className="rr-text mb-2">Year: {movie.year}</p>
22-
<p className="rr-text mb-2">Rating: {movie.rating}/10</p>
23-
<p className="rr-text mb-4 text-sm text-gray-600">
24-
{movie.description}
25-
</p>
26-
<div className="flex items-center gap-2">
27-
<span
28-
className={`rr-badge ${movie.isFavorite ? 'rr-badge-red' : ''}`}
29-
>
30-
{movie.isFavorite ? 'Favorite' : 'Not Favorite'}
31-
</span>
32-
</div>
33-
</div>
34-
</Link>
9+
<MovieCard key={movie.id} movie={movie} />
3510
))
11+
3612
return { moviesUI }
3713
}
3814

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { href, Link } from 'react-router'
2+
import { type Movie } from './movies-data.ts'
3+
4+
export function MovieCard({ movie }: { movie: Movie }) {
5+
return (
6+
<Link
7+
to={href('/:movieId', { movieId: String(movie.id) })}
8+
className="rr-card transition-shadow hover:shadow-lg"
9+
>
10+
<div className="mb-4">
11+
<img
12+
src={movie.poster}
13+
alt={`${movie.title} poster`}
14+
className="mb-4 h-64 w-full rounded-lg object-cover"
15+
/>
16+
<h3 className="rr-heading text-lg font-semibold">{movie.title}</h3>
17+
<p className="rr-text mb-2">Year: {movie.year}</p>
18+
<p className="rr-text mb-2">Rating: {movie.rating}/10</p>
19+
<p className="rr-text mb-4 text-sm text-gray-600">
20+
{movie.description}
21+
</p>
22+
<div className="flex items-center gap-2">
23+
<span
24+
className={`rr-badge ${movie.isFavorite ? 'rr-badge-red' : ''}`}
25+
>
26+
{movie.isFavorite ? 'Favorite' : 'Not Favorite'}
27+
</span>
28+
</div>
29+
</div>
30+
</Link>
31+
)
32+
}

exercises/01.start/03.solution.rsc-route/app/root.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {
33
Links,
44
Meta,
55
Outlet,
6-
Scripts,
76
ScrollRestoration,
87
} from 'react-router'
98

@@ -35,7 +34,6 @@ export function Layout({ children }: { children: React.ReactNode }) {
3534
<body>
3635
{children}
3736
<ScrollRestoration />
38-
<Scripts />
3937
</body>
4038
</html>
4139
)

0 commit comments

Comments
 (0)