Skip to content

Commit

Permalink
feat: add popular items page for movies and shows (#153)
Browse files Browse the repository at this point in the history
* feat: add popular items page for movies and shows

* chore: remove unused html
  • Loading branch information
davidemarcoli authored Oct 28, 2024
1 parent 261b69b commit a6cc1a7
Show file tree
Hide file tree
Showing 6 changed files with 299 additions and 5 deletions.
8 changes: 5 additions & 3 deletions src/lib/components/home-items.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
import { goto } from '$app/navigation';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export let data: any;
export let trending: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export let popular: any;
export let name: string;
export let type: string;
Expand Down Expand Up @@ -38,7 +40,7 @@
</div>

<div class="no-scrollbar flex flex-wrap overflow-x-auto px-1 lg:p-0">
{#each data.results as item}
{#each trending.results as item}
<div
class="group relative mb-2 flex w-1/2 flex-shrink-0 flex-col gap-2 rounded-lg p-2 sm:w-1/4 lg:w-1/6 xl:p-[.4rem]"
role="button"
Expand Down Expand Up @@ -98,7 +100,7 @@
</a>
</div>
<div class="flex flex-col gap-2 overflow-hidden">
{#each data.results as item, i}
{#each popular.results as item, i}
{#if i <= 9}
<a
class="group flex aspect-[4.3/1] w-full gap-1 overflow-hidden rounded-lg 2xl:aspect-[5.33/1]"
Expand Down
4 changes: 2 additions & 2 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,6 @@
</Carousel.Root>
</div>

<HomeItems name="Movies" data={data.trendingMovies} type="movie" />
<HomeItems name="Movies" trending={data.trendingMovies} popular={data.moviesPopular} type="movie" />

<HomeItems name="Shows" data={data.trendingShows} type="tv" />
<HomeItems name="Shows" trending={data.trendingShows} popular={data.showsPopular} type="tv" />
131 changes: 131 additions & 0 deletions src/routes/movie/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<script lang="ts">
import { roundOff } from '$lib/helpers';
import { Star } from 'lucide-svelte';
import type { PageData } from './$types';
import ItemRequest from '$lib/components/item-request.svelte';
import Header from '$lib/components/header.svelte';
import * as Pagination from '$lib/components/ui/pagination';
import { getMoviesPopular } from '$lib/tmdb';
import { writable } from 'svelte/store';
import { goto } from '$app/navigation';
export let data: PageData;
let items = data.movies.results;
let totalItems = data.movies.total_results;
let pageNumber = data.page;
$: totalDataItems = writable(totalItems);
async function fetchItems() {
let data = await getMoviesPopular(fetch, 'en-US', pageNumber);
if (data) {
items = data.results;
totalItems = data.total_results;
$totalDataItems = totalItems;
} else {
//pass
}
}
const limit = 20;
const hoveredItem = writable(null);
</script>

<svelte:head>
<title>Movies | Riven</title>
</svelte:head>

<div class="!text-zinc-100">
<Header />
</div>

<div class="mt-32 p-8 md:px-24 lg:px-32">
<h1 class="mb-8 text-center text-4xl text-zinc-50 md:text-left">Popular Movies</h1>

<div class="grid grid-cols-2 gap-6 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6">
{#each items as item (item.id)}
<div
class="group relative mb-2 flex flex-shrink-0 flex-col gap-2 rounded-lg p-2"
role="button"
tabindex="0"
on:mouseenter={() => ($hoveredItem = item.id)}
on:mouseleave={() => ($hoveredItem = null)}
on:focus={() => ($hoveredItem = item.id)}
on:blur={() => ($hoveredItem = null)}
on:keydown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
$hoveredItem = item.id;
}
}}
on:click={() => goto(`/movie/${item.id}`)}
>
<div class="relative aspect-[1/1.5] w-full overflow-hidden rounded-lg">
<img
src="https://image.tmdb.org/t/p/w342{item.poster_path}"
alt={item.title || item.name}
loading="lazy"
class="h-full w-full object-cover object-center transition-all duration-300 ease-in-out group-hover:scale-105"
/>
<div
class="absolute right-0 top-1 flex items-center justify-center gap-1 rounded-l-md bg-slate-900/70 px-[5px] py-1"
>
<Star class="size-3 text-yellow-400" />
<span class="text-xs font-light text-white">
{roundOff(item.vote_average)}
</span>
</div>
<div
class="absolute inset-0 hidden flex-col justify-end from-zinc-900/70 p-2 group-hover:flex group-hover:bg-gradient-to-t"
>
{#if $hoveredItem === item.id}
<ItemRequest data={item} type="movie" />
{/if}
</div>
</div>
</div>
{/each}
</div>

<div class="mt-8 flex flex-wrap overflow-x-auto px-1 lg:p-0">
<Pagination.Root
count={$totalDataItems}
perPage={limit}
let:pages
let:currentPage
onPageChange={(page) => {
pageNumber = page;
fetchItems();
}}
>
<Pagination.Content class="flex items-center justify-center space-x-2">
<Pagination.Item>
<Pagination.PrevButton class="rounded-md bg-primary px-4 py-2 text-primary-foreground" />
</Pagination.Item>
{#each pages as page (page.key)}
{#if page.type === 'ellipsis'}
<Pagination.Item>
<Pagination.Ellipsis class="px-4 py-2" />
</Pagination.Item>
{:else}
<Pagination.Item>
<Pagination.Link
{page}
isActive={currentPage === page.value}
class="rounded-md px-4 py-2"
>
{page.value}
</Pagination.Link>
</Pagination.Item>
{/if}
{/each}
<Pagination.Item>
<Pagination.NextButton class="rounded-md bg-primary px-4 py-2 text-primary-foreground" />
</Pagination.Item>
</Pagination.Content>
</Pagination.Root>
</div>
</div>
15 changes: 15 additions & 0 deletions src/routes/movie/+page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { PageLoad } from './$types';
import { getMoviesPopular } from '$lib/tmdb';

export const load = (async ({ fetch }) => {
const page = 1;

async function getMovies() {
return await getMoviesPopular(fetch, 'en-US', page);
}

return {
movies: await getMovies(),
page
};
}) satisfies PageLoad;
131 changes: 131 additions & 0 deletions src/routes/tv/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<script lang="ts">
import { roundOff } from '$lib/helpers';
import { Star } from 'lucide-svelte';
import type { PageData } from './$types';
import ItemRequest from '$lib/components/item-request.svelte';
import Header from '$lib/components/header.svelte';
import * as Pagination from '$lib/components/ui/pagination';
import { getTVPopular } from '$lib/tmdb';
import { writable } from 'svelte/store';
import { goto } from '$app/navigation';
export let data: PageData;
let items = data.shows.results;
let totalItems = data.shows.total_results;
let pageNumber = data.page;
$: totalDataItems = writable(totalItems);
async function fetchItems() {
let data = await getTVPopular(fetch, 'en-US', pageNumber);
if (data) {
items = data.results;
totalItems = data.total_results;
$totalDataItems = totalItems;
} else {
//pass
}
}
const limit = 20;
const hoveredItem = writable(null);
</script>

<svelte:head>
<title>Movies | Riven</title>
</svelte:head>

<div class="!text-zinc-100">
<Header />
</div>

<div class="mt-32 p-8 md:px-24 lg:px-32">
<h1 class="mb-8 text-center text-4xl text-zinc-50 md:text-left">Popular Shows</h1>

<div class="grid grid-cols-2 gap-6 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6">
{#each items as item (item.id)}
<div
class="group relative mb-2 flex flex-shrink-0 flex-col gap-2 rounded-lg p-2"
role="button"
tabindex="0"
on:mouseenter={() => ($hoveredItem = item.id)}
on:mouseleave={() => ($hoveredItem = null)}
on:focus={() => ($hoveredItem = item.id)}
on:blur={() => ($hoveredItem = null)}
on:keydown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
$hoveredItem = item.id;
}
}}
on:click={() => goto(`/tv/${item.id}`)}
>
<div class="relative aspect-[1/1.5] w-full overflow-hidden rounded-lg">
<img
src="https://image.tmdb.org/t/p/w342{item.poster_path}"
alt={item.title || item.name}
loading="lazy"
class="h-full w-full object-cover object-center transition-all duration-300 ease-in-out group-hover:scale-105"
/>
<div
class="absolute right-0 top-1 flex items-center justify-center gap-1 rounded-l-md bg-slate-900/70 px-[5px] py-1"
>
<Star class="size-3 text-yellow-400" />
<span class="text-xs font-light text-white">
{roundOff(item.vote_average)}
</span>
</div>
<div
class="absolute inset-0 hidden flex-col justify-end from-zinc-900/70 p-2 group-hover:flex group-hover:bg-gradient-to-t"
>
{#if $hoveredItem === item.id}
<ItemRequest data={item} type="tv" />
{/if}
</div>
</div>
</div>
{/each}
</div>

<div class="mt-8 flex flex-wrap overflow-x-auto px-1 lg:p-0">
<Pagination.Root
count={$totalDataItems}
perPage={limit}
let:pages
let:currentPage
onPageChange={(page) => {
pageNumber = page;
fetchItems();
}}
>
<Pagination.Content class="flex items-center justify-center space-x-2">
<Pagination.Item>
<Pagination.PrevButton class="rounded-md bg-primary px-4 py-2 text-primary-foreground" />
</Pagination.Item>
{#each pages as page (page.key)}
{#if page.type === 'ellipsis'}
<Pagination.Item>
<Pagination.Ellipsis class="px-4 py-2" />
</Pagination.Item>
{:else}
<Pagination.Item>
<Pagination.Link
{page}
isActive={currentPage === page.value}
class="rounded-md px-4 py-2"
>
{page.value}
</Pagination.Link>
</Pagination.Item>
{/if}
{/each}
<Pagination.Item>
<Pagination.NextButton class="rounded-md bg-primary px-4 py-2 text-primary-foreground" />
</Pagination.Item>
</Pagination.Content>
</Pagination.Root>
</div>
</div>
15 changes: 15 additions & 0 deletions src/routes/tv/+page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { PageLoad } from './$types';
import { getTVPopular } from '$lib/tmdb';

export const load = (async ({ fetch }) => {
const page = 1;

async function getShows() {
return await getTVPopular(fetch, 'en-US', page);
}

return {
shows: await getShows(),
page
};
}) satisfies PageLoad;

0 comments on commit a6cc1a7

Please sign in to comment.