Spookify switch

This commit is contained in:
2024-10-11 20:42:30 -03:00
parent a20d5e3d09
commit 540b13c958
6 changed files with 121 additions and 17 deletions

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import { useEffect, useState } from "react"; import { use, useEffect, useState } from "react";
import Tilt from "react-parallax-tilt"; import Tilt from "react-parallax-tilt";
import { TrackByAlbum } from "./spotify-data"; import { TrackByAlbum } from "./spotify-data";
import { api } from "@/trpc/react"; import { api } from "@/trpc/react";
@@ -11,17 +11,22 @@ ring2.register();
quantum.register(); quantum.register();
export default function AlbumShowcase({ export default function AlbumShowcase({
spookify,
album, album,
position, position,
tracks, tracks,
}: TrackByAlbum) { }: TrackByAlbum & { spookify: boolean }) {
const imageSource = album.images[0] const imageSource = album.images[0]
? album.images[0].url ? album.images[0].url
: "https://via.placeholder.com/150"; : "https://via.placeholder.com/150";
const [showSpookyImage, setShowSpookyImage] = useState(false); const [showSpookyImage, setShowSpookyImage] = useState(spookify);
const [spookyImageLoaded, setSpookyImageLoaded] = useState(false); const [spookyImageLoaded, setSpookyImageLoaded] = useState(false);
useEffect(() => {
setShowSpookyImage(spookify);
}, [spookify]);
const entry = api.entry.get.useQuery({ const entry = api.entry.get.useQuery({
type: "album", type: "album",
name: album.name, name: album.name,
@@ -72,14 +77,17 @@ export default function AlbumShowcase({
)?.match(/https:\/\/res.cloudinary.com\/[^"]+/); )?.match(/https:\/\/res.cloudinary.com\/[^"]+/);
const spookyImageSource = spookyImageMatch ? spookyImageMatch[0] : null; const spookyImageSource = spookyImageMatch ? spookyImageMatch[0] : null;
console.log(spookyImageSource);
return ( return (
<div <div
onClick={() => setShowSpookyImage(!showSpookyImage)}
key={album.id} key={album.id}
className="flex w-full flex-wrap gap-3 rounded-xl bg-white bg-opacity-10 p-5 backdrop-blur-lg backdrop-filter" className="flex w-full flex-wrap gap-3 rounded-xl bg-white bg-opacity-10 p-5 backdrop-blur-lg backdrop-filter"
> >
<div className="cursor-pointer"> <div
onClick={() => setShowSpookyImage(!showSpookyImage)}
className="cursor-pointer"
>
<Tilt tiltMaxAngleX={10} tiltMaxAngleY={10} transitionSpeed={200}> <Tilt tiltMaxAngleX={10} tiltMaxAngleY={10} transitionSpeed={200}>
<img <img
className="h-36 w-36 cursor-pointer rounded" className="h-36 w-36 cursor-pointer rounded"
@@ -99,7 +107,7 @@ export default function AlbumShowcase({
src={spookyImageSource} src={spookyImageSource}
alt={album.name} alt={album.name}
onLoad={() => { onLoad={() => {
if (!spookyImageLoaded && generateSpookyImage.data) { if (!spookyImageLoaded) {
setSpookyImageLoaded(true); setSpookyImageLoaded(true);
} }
}} }}
@@ -120,7 +128,7 @@ export default function AlbumShowcase({
) : ( ) : (
<> <>
<l-ring-2 size="100" speed="1.75" color="white"></l-ring-2> <l-ring-2 size="100" speed="1.75" color="white"></l-ring-2>
<p className="text-center">Generating...</p> <p className="text-center">Getting image...</p>
</> </>
)} )}
</div> </div>

View File

@@ -10,17 +10,23 @@ ring2.register();
quantum.register(); quantum.register();
export default function ArtistShowcase({ export default function ArtistShowcase({
spookify,
images, images,
name, name,
id, id,
}: { }: {
spookify: boolean;
images: { url: string }[]; images: { url: string }[];
name: string; name: string;
id: string; id: string;
}) { }) {
const [showSpookyImage, setShowSpookyImage] = useState(false); const [showSpookyImage, setShowSpookyImage] = useState(spookify);
const [spookyImageLoaded, setSpookyImageLoaded] = useState(false); const [spookyImageLoaded, setSpookyImageLoaded] = useState(false);
useEffect(() => {
setShowSpookyImage(spookify);
}, [spookify]);
const imageSource = images[0] const imageSource = images[0]
? images[0].url ? images[0].url
: "https://via.placeholder.com/150"; : "https://via.placeholder.com/150";

View File

@@ -0,0 +1,49 @@
"use client";
import React, { useState } from "react";
import Switch from "./switch";
import AlbumShowcase from "./album-showcase";
import ArtistShowcase from "./artist-showcase";
export function Showcase({
tracksByAlbum,
artists,
}: {
tracksByAlbum: Record<string, any>;
artists: any[];
}) {
const [spookify, setSpookify] = useState(false);
return (
<>
<div className="flex gap-2 self-start">
<label className="flex items-center gap-2 text-lg font-semibold leading-6 text-white">
Spookify
</label>
<Switch isChecked={spookify} setIsChecked={setSpookify} />
</div>
<h3>Tracks by album</h3>
{Object.values(tracksByAlbum)
.sort((a, b) => b.position - a.position)
.map(
(album, index) =>
!index && <AlbumShowcase spookify={spookify} {...album} />,
)}
<h3>Artists images</h3>
<div
style={{
display: "flex",
flexWrap: "wrap",
justifyContent: "space-evenly",
}}
>
{[artists[0]].map((artist) => {
return (
<ArtistShowcase spookify={spookify} key={artist.id} {...artist} />
);
})}
</div>
</>
);
}
export default Showcase;

View File

@@ -1,7 +1,5 @@
import SpotifyWebApi from "spotify-web-api-node"; import SpotifyWebApi from "spotify-web-api-node";
import AlbumShowcase from "./album-showcase"; import Showcase from "./showcase";
import ArtistShowcase from "./artist-showcase";
import { TRPCReactProvider } from "@/trpc/react";
const TRACKS_LIMIT = 20; const TRACKS_LIMIT = 20;
const ARTISTS_LIMIT = 21; const ARTISTS_LIMIT = 21;
@@ -141,12 +139,12 @@ export default async function SpotifyData({
</div> */} </div> */}
{/* TODO CHECK IF NEEDED */} {/* TODO CHECK IF NEEDED */}
<TRPCReactProvider> {/* <TRPCReactProvider>
<h3>Tracks by album</h3> <h3>Tracks by album</h3>
{Object.values(tracksByAlbum) {Object.values(tracksByAlbum)
.sort((a, b) => b.position - a.position) .sort((a, b) => b.position - a.position)
.map((album, index) => !index && <AlbumShowcase {...album} />)} .map((album, index) => !index && <AlbumShowcase {...album} />)}
</TRPCReactProvider> </TRPCReactProvider> */}
{/* <h3>Albums images</h3> {/* <h3>Albums images</h3>
<div <div
@@ -175,7 +173,7 @@ export default async function SpotifyData({
})} })}
</div> */} </div> */}
<h3>Artists images</h3> {/* <h3>Artists images</h3>
<div <div
style={{ style={{
display: "flex", display: "flex",
@@ -183,10 +181,12 @@ export default async function SpotifyData({
justifyContent: "space-evenly", justifyContent: "space-evenly",
}} }}
> >
{artists.map((artist) => { {[artists[0]].map((artist) => {
return <ArtistShowcase key={artist.id} {...artist} />; return <ArtistShowcase key={artist.id} {...artist} />;
})} })}
</div> </div> */}
<Showcase tracksByAlbum={tracksByAlbum} artists={artists} />
</> </>
); );
} }

View File

@@ -0,0 +1,41 @@
"use client";
import React, { useState } from "react";
const Switch = ({
isChecked,
setIsChecked,
}: {
isChecked: boolean;
setIsChecked: (isChecked: boolean) => void;
}) => {
const handleCheckboxChange = () => {
setIsChecked(!isChecked);
};
return (
<>
<label className={`flex cursor-pointer select-none items-center`}>
<div className="relative">
<input
type="checkbox"
checked={isChecked}
onChange={handleCheckboxChange}
className="sr-only"
/>
<div
className={`box block h-8 w-14 rounded-full ${
isChecked ? "bg-purple-800" : "bg-gray-700"
}`}
></div>
<div
className={`absolute left-1 top-1 flex h-6 w-6 items-center justify-center rounded-full bg-orange-500 transition ${
isChecked ? "translate-x-full" : ""
} `}
></div>
</div>
</label>
</>
);
};
export default Switch;

View File

@@ -39,7 +39,7 @@ export default async function Home({
return ( return (
<HydrateClient> <HydrateClient>
<main className="justify-centerbg-gradient-to-r flex min-h-screen flex-col items-center bg-gradient-to-r from-slate-900 to-slate-700 text-slate-200"> <main className="justify-centerbg-gradient-to-r flex min-h-screen flex-col items-center bg-gradient-to-r from-slate-900 to-slate-700 text-slate-200">
<div className="container flex flex-col items-center justify-center gap-8 px-4 py-16"> <div className="container flex flex-col items-center justify-center gap-8 px-4 pb-16 pt-8">
{userIsLogged ? ( {userIsLogged ? (
<SpotifyData <SpotifyData
accessToken={access_token as string} accessToken={access_token as string}