mirror of
https://github.com/FranP-code/spooky-spotify-showcase.git
synced 2025-10-13 00:02:36 +00:00
Spookify switch
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { use, useEffect, useState } from "react";
|
||||
import Tilt from "react-parallax-tilt";
|
||||
import { TrackByAlbum } from "./spotify-data";
|
||||
import { api } from "@/trpc/react";
|
||||
@@ -11,17 +11,22 @@ ring2.register();
|
||||
quantum.register();
|
||||
|
||||
export default function AlbumShowcase({
|
||||
spookify,
|
||||
album,
|
||||
position,
|
||||
tracks,
|
||||
}: TrackByAlbum) {
|
||||
}: TrackByAlbum & { spookify: boolean }) {
|
||||
const imageSource = album.images[0]
|
||||
? album.images[0].url
|
||||
: "https://via.placeholder.com/150";
|
||||
|
||||
const [showSpookyImage, setShowSpookyImage] = useState(false);
|
||||
const [showSpookyImage, setShowSpookyImage] = useState(spookify);
|
||||
const [spookyImageLoaded, setSpookyImageLoaded] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setShowSpookyImage(spookify);
|
||||
}, [spookify]);
|
||||
|
||||
const entry = api.entry.get.useQuery({
|
||||
type: "album",
|
||||
name: album.name,
|
||||
@@ -72,14 +77,17 @@ export default function AlbumShowcase({
|
||||
)?.match(/https:\/\/res.cloudinary.com\/[^"]+/);
|
||||
|
||||
const spookyImageSource = spookyImageMatch ? spookyImageMatch[0] : null;
|
||||
console.log(spookyImageSource);
|
||||
|
||||
return (
|
||||
<div
|
||||
onClick={() => setShowSpookyImage(!showSpookyImage)}
|
||||
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"
|
||||
>
|
||||
<div className="cursor-pointer">
|
||||
<div
|
||||
onClick={() => setShowSpookyImage(!showSpookyImage)}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<Tilt tiltMaxAngleX={10} tiltMaxAngleY={10} transitionSpeed={200}>
|
||||
<img
|
||||
className="h-36 w-36 cursor-pointer rounded"
|
||||
@@ -99,7 +107,7 @@ export default function AlbumShowcase({
|
||||
src={spookyImageSource}
|
||||
alt={album.name}
|
||||
onLoad={() => {
|
||||
if (!spookyImageLoaded && generateSpookyImage.data) {
|
||||
if (!spookyImageLoaded) {
|
||||
setSpookyImageLoaded(true);
|
||||
}
|
||||
}}
|
||||
@@ -120,7 +128,7 @@ export default function AlbumShowcase({
|
||||
) : (
|
||||
<>
|
||||
<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>
|
||||
|
||||
@@ -10,17 +10,23 @@ ring2.register();
|
||||
quantum.register();
|
||||
|
||||
export default function ArtistShowcase({
|
||||
spookify,
|
||||
images,
|
||||
name,
|
||||
id,
|
||||
}: {
|
||||
spookify: boolean;
|
||||
images: { url: string }[];
|
||||
name: string;
|
||||
id: string;
|
||||
}) {
|
||||
const [showSpookyImage, setShowSpookyImage] = useState(false);
|
||||
const [showSpookyImage, setShowSpookyImage] = useState(spookify);
|
||||
const [spookyImageLoaded, setSpookyImageLoaded] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setShowSpookyImage(spookify);
|
||||
}, [spookify]);
|
||||
|
||||
const imageSource = images[0]
|
||||
? images[0].url
|
||||
: "https://via.placeholder.com/150";
|
||||
|
||||
49
src/app/_components/showcase.tsx
Normal file
49
src/app/_components/showcase.tsx
Normal 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;
|
||||
@@ -1,7 +1,5 @@
|
||||
import SpotifyWebApi from "spotify-web-api-node";
|
||||
import AlbumShowcase from "./album-showcase";
|
||||
import ArtistShowcase from "./artist-showcase";
|
||||
import { TRPCReactProvider } from "@/trpc/react";
|
||||
import Showcase from "./showcase";
|
||||
|
||||
const TRACKS_LIMIT = 20;
|
||||
const ARTISTS_LIMIT = 21;
|
||||
@@ -141,12 +139,12 @@ export default async function SpotifyData({
|
||||
</div> */}
|
||||
|
||||
{/* TODO CHECK IF NEEDED */}
|
||||
<TRPCReactProvider>
|
||||
{/* <TRPCReactProvider>
|
||||
<h3>Tracks by album</h3>
|
||||
{Object.values(tracksByAlbum)
|
||||
.sort((a, b) => b.position - a.position)
|
||||
.map((album, index) => !index && <AlbumShowcase {...album} />)}
|
||||
</TRPCReactProvider>
|
||||
</TRPCReactProvider> */}
|
||||
|
||||
{/* <h3>Albums images</h3>
|
||||
<div
|
||||
@@ -175,7 +173,7 @@ export default async function SpotifyData({
|
||||
})}
|
||||
</div> */}
|
||||
|
||||
<h3>Artists images</h3>
|
||||
{/* <h3>Artists images</h3>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
@@ -183,10 +181,12 @@ export default async function SpotifyData({
|
||||
justifyContent: "space-evenly",
|
||||
}}
|
||||
>
|
||||
{artists.map((artist) => {
|
||||
{[artists[0]].map((artist) => {
|
||||
return <ArtistShowcase key={artist.id} {...artist} />;
|
||||
})}
|
||||
</div>
|
||||
</div> */}
|
||||
|
||||
<Showcase tracksByAlbum={tracksByAlbum} artists={artists} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
41
src/app/_components/switch.tsx
Normal file
41
src/app/_components/switch.tsx
Normal 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;
|
||||
@@ -39,7 +39,7 @@ export default async function Home({
|
||||
return (
|
||||
<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">
|
||||
<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 ? (
|
||||
<SpotifyData
|
||||
accessToken={access_token as string}
|
||||
|
||||
Reference in New Issue
Block a user