mirror of
https://github.com/FranP-code/spooky-spotify-showcase.git
synced 2025-10-13 00:02:36 +00:00
Add Swiper component and AlbumImage for enhanced album display
This commit is contained in:
98
src/app/_components/album-image.tsx
Normal file
98
src/app/_components/album-image.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
import React from "react";
|
||||
import Tilt from "react-parallax-tilt";
|
||||
|
||||
interface AlbumImageProps {
|
||||
showSpookyImage: boolean;
|
||||
imageSource: string;
|
||||
spookyImageSource: string | null;
|
||||
album: { name: string };
|
||||
generateSpookyImageData: string | null;
|
||||
lastSpookyImageLoaded: number;
|
||||
place: number;
|
||||
spookyImageLoaded: boolean;
|
||||
onImageLoad: () => void;
|
||||
}
|
||||
|
||||
export function AlbumImage({
|
||||
showSpookyImage,
|
||||
imageSource,
|
||||
spookyImageSource,
|
||||
album,
|
||||
generateSpookyImageData,
|
||||
lastSpookyImageLoaded,
|
||||
place,
|
||||
spookyImageLoaded,
|
||||
onImageLoad,
|
||||
}: AlbumImageProps) {
|
||||
return (
|
||||
<Tilt tiltMaxAngleX={10} tiltMaxAngleY={10} transitionSpeed={200}>
|
||||
<img
|
||||
className="h-36 w-36 cursor-pointer rounded"
|
||||
style={{
|
||||
display: showSpookyImage ? "none" : "block",
|
||||
}}
|
||||
src={imageSource}
|
||||
alt={album.name}
|
||||
/>
|
||||
{spookyImageSource &&
|
||||
(generateSpookyImageData
|
||||
? lastSpookyImageLoaded >= place ||
|
||||
lastSpookyImageLoaded + 1 === place
|
||||
: true) && (
|
||||
<img
|
||||
className="h-36 w-36 cursor-pointer rounded"
|
||||
style={{
|
||||
display: showSpookyImage && spookyImageLoaded ? "block" : "none",
|
||||
}}
|
||||
src={spookyImageSource}
|
||||
alt={album.name}
|
||||
onLoad={onImageLoad}
|
||||
onError={() => {
|
||||
onImageLoad();
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{showSpookyImage && !spookyImageLoaded && (
|
||||
<div className="flex h-36 w-36 items-center justify-center rounded bg-slate-300 bg-opacity-10">
|
||||
<div>
|
||||
{(() => {
|
||||
if (generateSpookyImageData) {
|
||||
if (lastSpookyImageLoaded < place - 1) {
|
||||
return (
|
||||
<>
|
||||
<l-pulsar
|
||||
size="100"
|
||||
speed="1.75"
|
||||
color="white"
|
||||
></l-pulsar>{" "}
|
||||
<p className="text-center">On queue...</p>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<l-quantum
|
||||
size="100"
|
||||
speed="1.75"
|
||||
color="white"
|
||||
></l-quantum>
|
||||
<p className="text-center">Generating...</p>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<>
|
||||
<l-ring-2 size="100" speed="1.75" color="white"></l-ring-2>
|
||||
<p className="text-center">Getting image...</p>
|
||||
</>
|
||||
);
|
||||
}
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Tilt>
|
||||
);
|
||||
}
|
||||
|
||||
export default AlbumImage;
|
||||
@@ -1,12 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { use, useEffect, useState } from "react";
|
||||
import Tilt from "react-parallax-tilt";
|
||||
import { useEffect, useState } from "react";
|
||||
import { TrackByAlbum } from "./spotify-data";
|
||||
import { api } from "@/trpc/react";
|
||||
import { quantum } from "ldrs";
|
||||
import { ring2 } from "ldrs";
|
||||
import { pulsar } from "ldrs";
|
||||
import Swiper from "./swiper";
|
||||
import { SwiperSlide } from "swiper/react";
|
||||
import AlbumImage from "./album-image";
|
||||
|
||||
pulsar.register();
|
||||
ring2.register();
|
||||
@@ -104,80 +106,36 @@ export default function AlbumShowcase({
|
||||
>
|
||||
<div
|
||||
onClick={() => setShowSpookyImage(!showSpookyImage)}
|
||||
className="cursor-pointer"
|
||||
className="cursor-pointer *:select-none"
|
||||
>
|
||||
<Tilt tiltMaxAngleX={10} tiltMaxAngleY={10} transitionSpeed={200}>
|
||||
<img
|
||||
className="h-36 w-36 cursor-pointer rounded"
|
||||
style={{
|
||||
display: showSpookyImage ? "none" : "block",
|
||||
}}
|
||||
src={imageSource}
|
||||
alt={album.name}
|
||||
/>
|
||||
{spookyImageSource &&
|
||||
(generateSpookyImage.data
|
||||
? lastSpookyImageLoaded >= place ||
|
||||
lastSpookyImageLoaded + 1 === place
|
||||
: true) && (
|
||||
<img
|
||||
className="h-36 w-36 cursor-pointer rounded"
|
||||
style={{
|
||||
display:
|
||||
showSpookyImage && spookyImageLoaded ? "block" : "none",
|
||||
}}
|
||||
src={spookyImageSource}
|
||||
alt={album.name}
|
||||
onLoad={onImageLoad}
|
||||
onError={() => {
|
||||
onImageLoad();
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{showSpookyImage && !spookyImageLoaded && (
|
||||
<div className="flex h-36 w-36 items-center justify-center rounded bg-slate-300 bg-opacity-10">
|
||||
<div>
|
||||
{(() => {
|
||||
if (generateSpookyImage.data) {
|
||||
if (lastSpookyImageLoaded < place - 1) {
|
||||
return (
|
||||
<>
|
||||
<l-pulsar
|
||||
size="100"
|
||||
speed="1.75"
|
||||
color="white"
|
||||
></l-pulsar>{" "}
|
||||
<p className="text-center">On queue...</p>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<l-quantum
|
||||
size="100"
|
||||
speed="1.75"
|
||||
color="white"
|
||||
></l-quantum>
|
||||
<p className="text-center">Generating...</p>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<>
|
||||
<l-ring-2
|
||||
size="100"
|
||||
speed="1.75"
|
||||
color="white"
|
||||
></l-ring-2>
|
||||
<p className="text-center">Getting image...</p>
|
||||
</>
|
||||
);
|
||||
}
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Tilt>
|
||||
<Swiper>
|
||||
<SwiperSlide>
|
||||
<AlbumImage
|
||||
showSpookyImage={showSpookyImage}
|
||||
imageSource={imageSource}
|
||||
spookyImageSource={spookyImageSource}
|
||||
album={album}
|
||||
generateSpookyImageData={generateSpookyImage.data as string}
|
||||
lastSpookyImageLoaded={lastSpookyImageLoaded}
|
||||
place={place}
|
||||
spookyImageLoaded={spookyImageLoaded}
|
||||
onImageLoad={onImageLoad}
|
||||
/>
|
||||
</SwiperSlide>
|
||||
<SwiperSlide>
|
||||
<AlbumImage
|
||||
showSpookyImage={showSpookyImage}
|
||||
imageSource={imageSource}
|
||||
spookyImageSource={spookyImageSource}
|
||||
album={album}
|
||||
generateSpookyImageData={generateSpookyImage.data as string}
|
||||
lastSpookyImageLoaded={lastSpookyImageLoaded}
|
||||
place={place}
|
||||
spookyImageLoaded={spookyImageLoaded}
|
||||
onImageLoad={onImageLoad}
|
||||
/>
|
||||
</SwiperSlide>
|
||||
</Swiper>
|
||||
</div>
|
||||
<section className="flex h-36 flex-grow flex-col">
|
||||
<h4 className="mb-2 text-lg font-semibold leading-none">
|
||||
|
||||
9
src/app/_components/swiper.css
Normal file
9
src/app/_components/swiper.css
Normal file
@@ -0,0 +1,9 @@
|
||||
.swiper-slide {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 18px;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
}
|
||||
26
src/app/_components/swiper.tsx
Normal file
26
src/app/_components/swiper.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
"use client";
|
||||
import React, { useRef, useState } from "react";
|
||||
import { Swiper as SwiperReact, SwiperSlide } from "swiper/react";
|
||||
import "swiper/css";
|
||||
import "swiper/css/effect-cards";
|
||||
import "./swiper.css";
|
||||
import { EffectCards } from "swiper/modules";
|
||||
|
||||
export function Swiper({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<SwiperReact
|
||||
style={{
|
||||
width: "144px",
|
||||
height: "144px",
|
||||
}}
|
||||
effect={"cards"}
|
||||
grabCursor={true}
|
||||
modules={[EffectCards]}
|
||||
className="mySwiper"
|
||||
>
|
||||
{children}
|
||||
</SwiperReact>
|
||||
);
|
||||
}
|
||||
|
||||
export default Swiper;
|
||||
Reference in New Issue
Block a user