New sexy discover page media cards

This commit is contained in:
Cooper Ransom 2024-04-09 22:21:13 -04:00
parent 81d91fc5bd
commit 8f4e924e57
3 changed files with 87 additions and 96 deletions

View File

@ -45,7 +45,7 @@
"fscreen": "^1.2.0",
"fuse.js": "^7.0.0",
"hls.js": "^1.5.7",
"i18next": "^23.10.1",
"i18next": "^23.11.1",
"immer": "^10.0.4",
"jwt-decode": "^4.0.0",
"lodash.isequal": "^4.5.0",
@ -82,9 +82,9 @@
"@types/lodash.isequal": "^4.5.8",
"@types/lodash.merge": "^4.6.9",
"@types/lodash.throttle": "^4.1.9",
"@types/node": "^20.12.5",
"@types/node": "^20.12.7",
"@types/pako": "^2.0.3",
"@types/react": "^18.2.74",
"@types/react": "^18.2.75",
"@types/react-dom": "^18.2.24",
"@types/react-helmet": "^6.1.11",
"@types/react-lazy-load-image-component": "^1.6.3",

View File

@ -70,8 +70,8 @@ dependencies:
specifier: ^1.5.7
version: 1.5.7
i18next:
specifier: ^23.10.1
version: 23.10.1
specifier: ^23.11.1
version: 23.11.1
immer:
specifier: ^10.0.4
version: 10.0.4
@ -113,7 +113,7 @@ dependencies:
version: 2.0.4(react-dom@18.2.0)(react@18.2.0)
react-i18next:
specifier: ^14.1.0
version: 14.1.0(i18next@23.10.1)(react-dom@18.2.0)(react@18.2.0)
version: 14.1.0(i18next@23.11.1)(react-dom@18.2.0)(react@18.2.0)
react-lazy-with-preload:
specifier: ^2.2.1
version: 2.2.1
@ -140,7 +140,7 @@ dependencies:
version: 2.1.2
zustand:
specifier: ^4.5.2
version: 4.5.2(@types/react@18.2.74)(immer@10.0.4)(react@18.2.0)
version: 4.5.2(@types/react@18.2.75)(immer@10.0.4)(react@18.2.0)
devDependencies:
'@babel/core':
@ -177,14 +177,14 @@ devDependencies:
specifier: ^4.1.9
version: 4.1.9
'@types/node':
specifier: ^20.12.5
version: 20.12.5
specifier: ^20.12.7
version: 20.12.7
'@types/pako':
specifier: ^2.0.3
version: 2.0.3
'@types/react':
specifier: ^18.2.74
version: 18.2.74
specifier: ^18.2.75
version: 18.2.75
'@types/react-dom':
specifier: ^18.2.24
version: 18.2.24
@ -295,7 +295,7 @@ devDependencies:
version: 5.4.4
vite:
specifier: ^5.2.8
version: 5.2.8(@types/node@20.12.5)
version: 5.2.8(@types/node@20.12.7)
vite-plugin-checker:
specifier: ^0.6.4
version: 0.6.4(eslint@8.57.0)(typescript@5.4.4)(vite@5.2.8)
@ -310,7 +310,7 @@ devDependencies:
version: 1.0.2(vite@5.2.8)
vitest:
specifier: ^1.4.0
version: 1.4.0(@types/node@20.12.5)(jsdom@23.2.0)
version: 1.4.0(@types/node@20.12.7)(jsdom@23.2.0)
workbox-window:
specifier: ^7.0.0
version: 7.0.0
@ -2255,11 +2255,11 @@ packages:
/@types/node-forge@1.3.11:
resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==}
dependencies:
'@types/node': 20.12.5
'@types/node': 20.12.7
dev: false
/@types/node@20.12.5:
resolution: {integrity: sha512-BD+BjQ9LS/D8ST9p5uqBxghlN+S42iuNxjsUGjeZobe/ciXzk2qb1B6IXc6AnRLS+yFJRpN2IPEHMzwspfDJNw==}
/@types/node@20.12.7:
resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==}
dependencies:
undici-types: 5.26.5
@ -2273,19 +2273,19 @@ packages:
/@types/react-dom@18.2.24:
resolution: {integrity: sha512-cN6upcKd8zkGy4HU9F1+/s98Hrp6D4MOcippK4PoE8OZRngohHZpbJn1GsaDLz87MqvHNoT13nHvNqM9ocRHZg==}
dependencies:
'@types/react': 18.2.74
'@types/react': 18.2.75
dev: true
/@types/react-helmet@6.1.11:
resolution: {integrity: sha512-0QcdGLddTERotCXo3VFlUSWO3ztraw8nZ6e3zJSgG7apwV5xt+pJUS8ewPBqT4NYB1optGLprNQzFleIY84u/g==}
dependencies:
'@types/react': 18.2.74
'@types/react': 18.2.75
dev: true
/@types/react-lazy-load-image-component@1.6.3:
resolution: {integrity: sha512-HsIsYz7yWWTh/bftdzGnijKD26JyofLRqM/RM80sxs7Gk13G83ew8R/ra2XzXuiZfjNEjAq/Va+NBHFF9ciwxA==}
dependencies:
'@types/react': 18.2.74
'@types/react': 18.2.75
csstype: 3.1.3
dev: true
@ -2293,7 +2293,7 @@ packages:
resolution: {integrity: sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==}
dependencies:
'@types/history': 4.7.11
'@types/react': 18.2.74
'@types/react': 18.2.75
'@types/react-router': 5.1.20
dev: true
@ -2301,23 +2301,23 @@ packages:
resolution: {integrity: sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==}
dependencies:
'@types/history': 4.7.11
'@types/react': 18.2.74
'@types/react': 18.2.75
dev: true
/@types/react-stickynode@4.0.3:
resolution: {integrity: sha512-K7YkwdhXQE4YVxIVweix4nkpdG4onm/dcnKK+qCj0vgUrNiKng+09zOfjF5AlOcC1HQkg5yxVLwp/0AzT84R0w==}
dependencies:
'@types/react': 18.2.74
'@types/react': 18.2.75
dev: true
/@types/react-transition-group@4.4.10:
resolution: {integrity: sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==}
dependencies:
'@types/react': 18.2.74
'@types/react': 18.2.75
dev: true
/@types/react@18.2.74:
resolution: {integrity: sha512-9AEqNZZyBx8OdZpxzQlaFEVCSFUM2YXJH46yPOiOpm078k6ZLOCcuAzGum/zK8YBwY+dbahVNbHrbgrAwIRlqw==}
/@types/react@18.2.75:
resolution: {integrity: sha512-+DNnF7yc5y0bHkBTiLKqXFe+L4B3nvOphiMY3tuA5X10esmjqk7smyBZzbGTy2vsiy/Bnzj8yFIBL8xhRacoOg==}
dependencies:
'@types/prop-types': 15.7.12
csstype: 3.1.3
@ -2325,7 +2325,7 @@ packages:
/@types/resolve@1.17.1:
resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==}
dependencies:
'@types/node': 20.12.5
'@types/node': 20.12.7
dev: true
/@types/semver@7.5.8:
@ -2483,7 +2483,7 @@ packages:
'@babel/plugin-transform-react-jsx-source': 7.24.1(@babel/core@7.24.4)
'@types/babel__core': 7.20.5
react-refresh: 0.14.0
vite: 5.2.8(@types/node@20.12.5)
vite: 5.2.8(@types/node@20.12.7)
transitivePeerDependencies:
- supports-color
dev: true
@ -2750,7 +2750,7 @@ packages:
postcss: '>=8.4.31'
dependencies:
browserslist: 4.23.0
caniuse-lite: 1.0.30001606
caniuse-lite: 1.0.30001607
fraction.js: 4.3.7
normalize-range: 0.1.2
picocolors: 1.0.0
@ -2854,8 +2854,8 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
dependencies:
caniuse-lite: 1.0.30001606
electron-to-chromium: 1.4.729
caniuse-lite: 1.0.30001607
electron-to-chromium: 1.4.731
node-releases: 2.0.14
update-browserslist-db: 1.0.13(browserslist@4.23.0)
@ -2894,8 +2894,8 @@ packages:
engines: {node: '>= 6'}
dev: true
/caniuse-lite@1.0.30001606:
resolution: {integrity: sha512-LPbwnW4vfpJId225pwjZJOgX1m9sGfbw/RKJvw/t0QhYOOaTXHvkjVGFGPpvwEzufrjvTlsULnVTxdy4/6cqkg==}
/caniuse-lite@1.0.30001607:
resolution: {integrity: sha512-WcvhVRjXLKFB/kmOFVwELtMxyhq3iM/MvmXcyCe2PNf166c39mptscOc/45TTS96n2gpNV2z7+NakArTWZCQ3w==}
/chai@4.4.1:
resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==}
@ -3361,8 +3361,8 @@ packages:
jake: 10.8.7
dev: true
/electron-to-chromium@1.4.729:
resolution: {integrity: sha512-bx7+5Saea/qu14kmPTDHQxkp2UnziG3iajUQu3BxFvCOnpAJdDbMV4rSl+EqFDkkpNNVUFlR1kDfpL59xfy1HA==}
/electron-to-chromium@1.4.731:
resolution: {integrity: sha512-+TqVfZjpRz2V/5SPpmJxq9qK620SC5SqCnxQIOi7i/U08ZDcTpKbT7Xjj9FU5CbXTMUb4fywbIr8C7cGv4hcjw==}
/emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
@ -4340,8 +4340,8 @@ packages:
resolution: {integrity: sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==}
dev: false
/i18next@23.10.1:
resolution: {integrity: sha512-NDiIzFbcs3O9PXpfhkjyf7WdqFn5Vq6mhzhtkXzj51aOcNuPNcTwuYNuXCpHsanZGHlHKL35G7huoFeVic1hng==}
/i18next@23.11.1:
resolution: {integrity: sha512-mXw4A24BiPZKRsbb9ewgSvjYd6fxFCNwJyfK6nYfSTIAX2GkCWcb598m3DFkDZmqADatvuASrKo6qwORz3VwTQ==}
dependencies:
'@babel/runtime': 7.24.4
dev: false
@ -4678,7 +4678,7 @@ packages:
resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==}
engines: {node: '>= 10.13.0'}
dependencies:
'@types/node': 20.12.5
'@types/node': 20.12.7
merge-stream: 2.0.0
supports-color: 7.2.0
dev: true
@ -5651,7 +5651,7 @@ packages:
shallowequal: 1.1.0
dev: false
/react-i18next@14.1.0(i18next@23.10.1)(react-dom@18.2.0)(react@18.2.0):
/react-i18next@14.1.0(i18next@23.11.1)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-3KwX6LHpbvGQ+sBEntjV4sYW3Zovjjl3fpoHbUwSgFHf0uRBcbeCBLR5al6ikncI5+W0EFb71QXZmfop+J6NrQ==}
peerDependencies:
i18next: '>= 23.2.3'
@ -5666,7 +5666,7 @@ packages:
dependencies:
'@babel/runtime': 7.24.4
html-parse-stringify: 3.0.1
i18next: 23.10.1
i18next: 23.11.1
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
@ -6748,7 +6748,7 @@ packages:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
dev: true
/vite-node@1.4.0(@types/node@20.12.5):
/vite-node@1.4.0(@types/node@20.12.7):
resolution: {integrity: sha512-VZDAseqjrHgNd4Kh8icYHWzTKSCZMhia7GyHfhtzLW33fZlG9SwsB6CEhgyVOWkJfJ2pFLrp/Gj1FSfAiqH9Lw==}
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
@ -6757,7 +6757,7 @@ packages:
debug: 4.3.4
pathe: 1.1.2
picocolors: 1.0.0
vite: 5.2.8(@types/node@20.12.5)
vite: 5.2.8(@types/node@20.12.7)
transitivePeerDependencies:
- '@types/node'
- less
@ -6813,7 +6813,7 @@ packages:
strip-ansi: 6.0.1
tiny-invariant: 1.3.3
typescript: 5.4.4
vite: 5.2.8(@types/node@20.12.5)
vite: 5.2.8(@types/node@20.12.7)
vscode-languageclient: 7.0.0
vscode-languageserver: 7.0.0
vscode-languageserver-textdocument: 1.0.11
@ -6825,7 +6825,7 @@ packages:
peerDependencies:
vite: '>=2.0.0-beta.69'
dependencies:
vite: 5.2.8(@types/node@20.12.5)
vite: 5.2.8(@types/node@20.12.7)
dev: true
/vite-plugin-pwa@0.17.5(vite@5.2.8)(workbox-build@7.0.0)(workbox-window@7.0.0):
@ -6839,7 +6839,7 @@ packages:
debug: 4.3.4
fast-glob: 3.3.2
pretty-bytes: 6.1.1
vite: 5.2.8(@types/node@20.12.5)
vite: 5.2.8(@types/node@20.12.7)
workbox-build: 7.0.0
workbox-window: 7.0.0
transitivePeerDependencies:
@ -6856,10 +6856,10 @@ packages:
fast-glob: 3.3.2
fs-extra: 11.2.0
picocolors: 1.0.0
vite: 5.2.8(@types/node@20.12.5)
vite: 5.2.8(@types/node@20.12.7)
dev: true
/vite@5.2.8(@types/node@20.12.5):
/vite@5.2.8(@types/node@20.12.7):
resolution: {integrity: sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==}
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
@ -6887,7 +6887,7 @@ packages:
terser:
optional: true
dependencies:
'@types/node': 20.12.5
'@types/node': 20.12.7
esbuild: 0.20.2
postcss: 8.4.38
rollup: /@rollup/wasm-node@4.14.1
@ -6895,7 +6895,7 @@ packages:
fsevents: 2.3.3
dev: true
/vitest@1.4.0(@types/node@20.12.5)(jsdom@23.2.0):
/vitest@1.4.0(@types/node@20.12.7)(jsdom@23.2.0):
resolution: {integrity: sha512-gujzn0g7fmwf83/WzrDTnncZt2UiXP41mHuFYFrdwaLRVQ6JYQEiME2IfEjU3vcFL3VKa75XhI3lFgn+hfVsQw==}
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
@ -6920,7 +6920,7 @@ packages:
jsdom:
optional: true
dependencies:
'@types/node': 20.12.5
'@types/node': 20.12.7
'@vitest/expect': 1.4.0
'@vitest/runner': 1.4.0
'@vitest/snapshot': 1.4.0
@ -6939,8 +6939,8 @@ packages:
strip-literal: 2.1.0
tinybench: 2.6.0
tinypool: 0.8.3
vite: 5.2.8(@types/node@20.12.5)
vite-node: 1.4.0(@types/node@20.12.5)
vite: 5.2.8(@types/node@20.12.7)
vite-node: 1.4.0(@types/node@20.12.7)
why-is-node-running: 2.2.2
transitivePeerDependencies:
- less
@ -7360,7 +7360,7 @@ packages:
engines: {node: '>=12.20'}
dev: true
/zustand@4.5.2(@types/react@18.2.74)(immer@10.0.4)(react@18.2.0):
/zustand@4.5.2(@types/react@18.2.75)(immer@10.0.4)(react@18.2.0):
resolution: {integrity: sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==}
engines: {node: '>=12.7.0'}
peerDependencies:
@ -7375,7 +7375,7 @@ packages:
react:
optional: true
dependencies:
'@types/react': 18.2.74
'@types/react': 18.2.75
immer: 10.0.4
react: 18.2.0
use-sync-external-store: 1.2.0(react@18.2.0)

View File

@ -252,13 +252,13 @@ export function Discover() {
? `${category} Shows`
: `${category} Movies`;
return (
<div className="relative overflow-hidden mt-4 rounded-xl">
<h2 className="text-2xl font-bold text-white sm:text-3xl md:text-2xl mx-auto pl-2">
<div className="relative overflow-hidden mt-2 rounded-xl">
<h2 className="text-2xl font-bold text-white sm:text-3xl md:text-2xl mx-auto pl-5">
{displayCategory}
</h2>
<div
id={`carousel-${categorySlug}`}
className="flex whitespace-nowrap overflow-auto scrollbar pb-6 mb-4 mt-4 rounded-xl"
className="flex whitespace-nowrap overflow-auto scrollbar pb-3 mb-2 rounded-xl"
style={{
scrollbarWidth: "thin",
scrollbarColor: `${bgColor} transparent`,
@ -270,56 +270,47 @@ export function Discover() {
onMouseLeave={handleMouseLeave}
onWheel={(e) => handleWheel(e, categorySlug)}
>
{medias.slice(0, 20).map((media) => (
<Flare.Base
className="group -m-[0.705em] p-[0.2em] rounded-xl bg-background-main transition-colors duration-300 focus:relative focus:z-10 hover:bg-mediaCard-hoverBackground tabbable"
tabIndex={0} // Assuming all items are linkable for simplicity; adjust as needed
onKeyUp={(e) => {
if (e.key === "Enter") {
navigate(
`/media/tmdb-${isTVShow ? "tv" : "movie"}-${media.id}-${
isTVShow ? media.name : media.title
}`,
);
}
}}
{medias.slice(0, 25).map((media) => (
<a
key={media.id}
onClick={() =>
navigate(
`/media/tmdb-${isTVShow ? "tv" : "movie"}-${media.id}-${
isTVShow ? media.name : media.title
}`,
)
}
className="text-center relative mt-4 mb-4 ml-[0.4em] mr-[0.2em]"
style={{ flex: `0 0 ${movieWidth}` }} // Set a fixed width for each movie
>
<Flare.Light
flareSize={300}
cssColorVar="--colors-mediaCard-hoverAccent"
backgroundClass="bg-mediaCard-hoverBackground duration-100"
className="rounded-xl bg-background-main group-hover:opacity-100"
/>
<Flare.Child className="pointer-events-auto relative mb-2 p-3 transition-transform duration-300 group-hover:scale-95">
<a
key={media.id}
onClick={() =>
navigate(
`/media/tmdb-${isTVShow ? "tv" : "movie"}-${media.id}-${
isTVShow ? media.name : media.title
}`,
)
}
rel="noopener noreferrer"
className="block rounded-xl text-center relative overflow-hidden transition-transform transform hover:scale-95 duration-500 mr-5"
style={{ flex: `0 0 ${movieWidth}` }} // Set a fixed width for each movie
>
<div className="relative transition-transform hover:scale-105 duration-[0.45s]">
<Flare.Base className="group rounded-xl relative p-[0.6em] bg-background-main transition-colors duration-300">
<Flare.Light
flareSize={250}
cssColorVar="--colors-mediaCard-hoverAccent"
backgroundClass="bg-mediaCard-hoverBackground duration-200"
className="rounded-xl bg-background-main group-hover:opacity-100"
/>
<img
src={`https://image.tmdb.org/t/p/w500${media.poster_path}`}
alt={isTVShow ? media.name : media.title}
alt="failed to fetch :("
loading="lazy"
className="rounded-xl"
className="rounded-xl relative"
style={{ width: "200px", height: "auto" }}
/>
</a>
</Flare.Child>
</Flare.Base>
<span className="relative items-center justify-center pt-[0.35em] whitespace-normal break-words font-semibold text-white">
{isTVShow ? media.name : media.title}
</span>
</Flare.Base>
</div>
</a>
))}
</div>
<button
type="button"
title="Back"
className="absolute top-1/2 transform -translate-y-1/2 z-10 left-2"
className="absolute top-1/2 transform -translate-y-1/2 z-10 left-5"
onClick={() => scrollCarousel(categorySlug, "left")}
>
<div className="cursor-pointer text-white flex justify-center items-center h-10 w-10 rounded-full bg-search-hoverBackground active:scale-110 transition-[transform,background-color] duration-200">
@ -329,7 +320,7 @@ export function Discover() {
<button
type="button"
title="Next"
className="absolute top-1/2 right-2 transform -translate-y-1/2 z-10"
className="absolute top-1/2 right-5 transform -translate-y-1/2 z-10"
onClick={() => scrollCarousel(categorySlug, "right")}
>
<div className="cursor-pointer text-white flex justify-center items-center h-10 w-10 rounded-full bg-search-hoverBackground active:scale-110 transition-[transform,background-color] duration-200">