mirror of
https://github.com/FranP-code/spooky-spotify-showcase.git
synced 2025-10-13 00:02:36 +00:00
Added second album image
This commit is contained in:
@@ -1,7 +1,11 @@
|
|||||||
import React from "react";
|
import { api } from "@/trpc/react";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
import Tilt from "react-parallax-tilt";
|
import Tilt from "react-parallax-tilt";
|
||||||
|
import SadFaceIcon from "./sad-face-icon";
|
||||||
|
|
||||||
interface AlbumImageProps {
|
interface AlbumImageProps {
|
||||||
|
number?: number;
|
||||||
|
entry: { data: any; isLoading: boolean };
|
||||||
showSpookyImage: boolean;
|
showSpookyImage: boolean;
|
||||||
imageSource: string;
|
imageSource: string;
|
||||||
spookyImageSource: string | null;
|
spookyImageSource: string | null;
|
||||||
@@ -9,13 +13,27 @@ interface AlbumImageProps {
|
|||||||
generateSpookyImageData: string | null;
|
generateSpookyImageData: string | null;
|
||||||
lastSpookyImageLoaded: number;
|
lastSpookyImageLoaded: number;
|
||||||
place: number;
|
place: number;
|
||||||
spookyImageLoaded: boolean;
|
|
||||||
onImageLoad: () => void;
|
|
||||||
loadGeneratedImage: boolean;
|
loadGeneratedImage: boolean;
|
||||||
onQueue: boolean;
|
onQueue: boolean;
|
||||||
|
saveImage: {
|
||||||
|
mutate: (arg0: {
|
||||||
|
entry: {
|
||||||
|
type: "album" | "artist";
|
||||||
|
image: string;
|
||||||
|
name: string;
|
||||||
|
number?: number;
|
||||||
|
};
|
||||||
|
}) => void;
|
||||||
|
};
|
||||||
|
setLastSpookyImageLoaded: (
|
||||||
|
arg0: number | ((state: number) => number),
|
||||||
|
) => void;
|
||||||
|
error: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AlbumImage({
|
export function AlbumImage({
|
||||||
|
number,
|
||||||
|
entry,
|
||||||
showSpookyImage,
|
showSpookyImage,
|
||||||
imageSource,
|
imageSource,
|
||||||
spookyImageSource,
|
spookyImageSource,
|
||||||
@@ -23,11 +41,42 @@ export function AlbumImage({
|
|||||||
generateSpookyImageData,
|
generateSpookyImageData,
|
||||||
lastSpookyImageLoaded,
|
lastSpookyImageLoaded,
|
||||||
place,
|
place,
|
||||||
spookyImageLoaded,
|
|
||||||
onImageLoad,
|
|
||||||
loadGeneratedImage,
|
loadGeneratedImage,
|
||||||
onQueue,
|
onQueue,
|
||||||
|
saveImage,
|
||||||
|
setLastSpookyImageLoaded,
|
||||||
|
error,
|
||||||
}: AlbumImageProps) {
|
}: AlbumImageProps) {
|
||||||
|
const [spookyImageLoaded, setSpookyImageLoaded] = useState(false);
|
||||||
|
|
||||||
|
const handleSaveImage = async () => {
|
||||||
|
if (!entry.data && !entry.isLoading) {
|
||||||
|
saveImage.mutate({
|
||||||
|
entry: {
|
||||||
|
type: "album",
|
||||||
|
image: imageSource,
|
||||||
|
name: album.name,
|
||||||
|
number,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (spookyImageLoaded) {
|
||||||
|
handleSaveImage();
|
||||||
|
}
|
||||||
|
}, [spookyImageLoaded]);
|
||||||
|
|
||||||
|
const onImageLoad = () => {
|
||||||
|
if (!spookyImageLoaded) {
|
||||||
|
setSpookyImageLoaded(true);
|
||||||
|
setLastSpookyImageLoaded((state: number) =>
|
||||||
|
state > place ? state : place,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tilt tiltMaxAngleX={10} tiltMaxAngleY={10} transitionSpeed={200}>
|
<Tilt tiltMaxAngleX={10} tiltMaxAngleY={10} transitionSpeed={200}>
|
||||||
<img
|
<img
|
||||||
@@ -38,7 +87,7 @@ export function AlbumImage({
|
|||||||
src={imageSource}
|
src={imageSource}
|
||||||
alt={album.name}
|
alt={album.name}
|
||||||
/>
|
/>
|
||||||
{loadGeneratedImage && spookyImageSource && (
|
{loadGeneratedImage && spookyImageSource && !error && (
|
||||||
<img
|
<img
|
||||||
className="h-36 w-36 cursor-pointer rounded"
|
className="h-36 w-36 cursor-pointer rounded"
|
||||||
style={{
|
style={{
|
||||||
@@ -52,7 +101,7 @@ export function AlbumImage({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{showSpookyImage && !spookyImageLoaded && (
|
{showSpookyImage && !spookyImageLoaded && !error && (
|
||||||
<div className="flex h-36 w-36 items-center justify-center rounded bg-slate-300 bg-opacity-10">
|
<div className="flex h-36 w-36 items-center justify-center rounded bg-slate-300 bg-opacity-10">
|
||||||
<div>
|
<div>
|
||||||
{(() => {
|
{(() => {
|
||||||
@@ -91,6 +140,14 @@ export function AlbumImage({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{error && (
|
||||||
|
<div className="flex h-36 w-36 items-center justify-center rounded bg-slate-300 bg-opacity-10">
|
||||||
|
<div>
|
||||||
|
<SadFaceIcon className="h-16 w-16" color="white" />
|
||||||
|
<p className="text-center">Error</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</Tilt>
|
</Tilt>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { TrackByAlbum } from "./spotify-data";
|
import { TrackByAlbum } from "./spotify-data";
|
||||||
import { api } from "@/trpc/react";
|
import { api } from "@/trpc/react";
|
||||||
import { quantum } from "ldrs";
|
import { quantum } from "ldrs";
|
||||||
@@ -19,12 +19,12 @@ export default function AlbumShowcase({
|
|||||||
album,
|
album,
|
||||||
position,
|
position,
|
||||||
tracks,
|
tracks,
|
||||||
place,
|
places,
|
||||||
lastSpookyImageLoaded,
|
lastSpookyImageLoaded,
|
||||||
setLastSpookyImageLoaded,
|
setLastSpookyImageLoaded,
|
||||||
}: TrackByAlbum & {
|
}: TrackByAlbum & {
|
||||||
spookify: boolean;
|
spookify: boolean;
|
||||||
place: number;
|
places: number[];
|
||||||
lastSpookyImageLoaded: number;
|
lastSpookyImageLoaded: number;
|
||||||
setLastSpookyImageLoaded: any;
|
setLastSpookyImageLoaded: any;
|
||||||
}) {
|
}) {
|
||||||
@@ -33,26 +33,34 @@ export default function AlbumShowcase({
|
|||||||
: "https://via.placeholder.com/150";
|
: "https://via.placeholder.com/150";
|
||||||
|
|
||||||
const [showSpookyImage, setShowSpookyImage] = useState(spookify);
|
const [showSpookyImage, setShowSpookyImage] = useState(spookify);
|
||||||
const [spookyImageLoaded, setSpookyImageLoaded] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setShowSpookyImage(spookify);
|
setShowSpookyImage(spookify);
|
||||||
}, [spookify]);
|
}, [spookify]);
|
||||||
|
|
||||||
const entry = api.entry.get.useQuery({
|
const entry = api.entry.get.useQuery(
|
||||||
type: "album",
|
{
|
||||||
name: album.name,
|
type: "album",
|
||||||
image: imageSource,
|
name: album.name,
|
||||||
});
|
image: imageSource,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
refetchInterval: false,
|
||||||
|
refetchOnReconnect: false,
|
||||||
|
refetchOnWindowFocus: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const generateSpookyImage = api.entry.generate.useMutation();
|
const generateSpookyImage = api.entry.generate.useMutation();
|
||||||
const generateSecondSpookyImage = api.entry.generate.useMutation();
|
const generateSecondSpookyImage = api.entry.generate.useMutation();
|
||||||
|
|
||||||
const spookyImageMatch = (
|
const spookyImageSource = useMemo(() => {
|
||||||
(entry.data?.value || generateSpookyImage.data) as null | string
|
const spookyImageMatch = (
|
||||||
)?.match(/https:\/\/res.cloudinary.com\/[^"]+/);
|
(entry.data?.value || generateSpookyImage.data) as null | string
|
||||||
|
)?.match(/<img\s+src='([^']+)'[^>]*>/);
|
||||||
|
|
||||||
const spookyImageSource = spookyImageMatch ? spookyImageMatch[0] : "";
|
return spookyImageMatch && spookyImageMatch[1] ? spookyImageMatch[1] : "";
|
||||||
|
}, [entry.data, generateSpookyImage.data]);
|
||||||
|
|
||||||
const secondEntry = api.entry.get.useQuery(
|
const secondEntry = api.entry.get.useQuery(
|
||||||
{
|
{
|
||||||
@@ -62,13 +70,12 @@ export default function AlbumShowcase({
|
|||||||
number: 2,
|
number: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled: !!spookyImageSource,
|
refetchInterval: false,
|
||||||
|
refetchOnReconnect: false,
|
||||||
|
refetchOnWindowFocus: false,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const saveImage = api.entry.save.useMutation();
|
|
||||||
const saveSecondImage = api.entry.save.useMutation();
|
|
||||||
|
|
||||||
const handleGenerateSpookyImage = async () => {
|
const handleGenerateSpookyImage = async () => {
|
||||||
if (!entry.data && !entry.isLoading) {
|
if (!entry.data && !entry.isLoading) {
|
||||||
generateSpookyImage.mutate({
|
generateSpookyImage.mutate({
|
||||||
@@ -82,61 +89,44 @@ export default function AlbumShowcase({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleSecondGenerateSpookyImage = async () => {
|
const handleSecondGenerateSpookyImage = async () => {
|
||||||
if (!secondEntry.data && !secondEntry.isLoading) {
|
if (!secondEntry.data && !secondEntry.isLoading && spookyImageSource) {
|
||||||
generateSecondSpookyImage.mutate({
|
generateSecondSpookyImage.mutate({
|
||||||
entry: {
|
entry: {
|
||||||
type: "album",
|
type: "album",
|
||||||
name: album.name,
|
name: album.name,
|
||||||
image: spookyImageSource as string,
|
image: spookyImageSource,
|
||||||
|
number: 2,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSaveImage = async () => {
|
const saveImage = api.entry.save.useMutation();
|
||||||
if (!entry.data && !entry.isLoading) {
|
const saveSecondImage = api.entry.save.useMutation();
|
||||||
saveImage.mutate({
|
|
||||||
entry: {
|
|
||||||
type: "album",
|
|
||||||
image: imageSource,
|
|
||||||
name: album.name,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSecondSaveImage = async () => {
|
|
||||||
if (!secondEntry.data && !secondEntry.isLoading) {
|
|
||||||
saveSecondImage.mutate({
|
|
||||||
entry: {
|
|
||||||
type: "album",
|
|
||||||
image: spookyImageSource as string,
|
|
||||||
name: album.name,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleGenerateSpookyImage();
|
handleGenerateSpookyImage();
|
||||||
}, [entry.data]);
|
}, [entry.data]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (spookyImageLoaded) {
|
handleSecondGenerateSpookyImage();
|
||||||
handleSaveImage();
|
}, [secondEntry.data, entry.data]);
|
||||||
}
|
|
||||||
}, [spookyImageLoaded]);
|
|
||||||
|
|
||||||
//TODO ERROR HANDLING
|
const secondSpookyImageMatch = (
|
||||||
|
(secondEntry.data?.value || generateSecondSpookyImage?.data || "") as string
|
||||||
|
).match(/<img\s+src='([^']+)'[^>]*>/);
|
||||||
|
const secondSpookyImageSource =
|
||||||
|
secondSpookyImageMatch && secondSpookyImageMatch[1]
|
||||||
|
? secondSpookyImageMatch[1]
|
||||||
|
: "";
|
||||||
|
|
||||||
const onImageLoad = () => {
|
const firstPlace = places[0] || 0;
|
||||||
if (!spookyImageLoaded) {
|
const secondPlace = places[1] || 0;
|
||||||
setSpookyImageLoaded(true);
|
|
||||||
setLastSpookyImageLoaded((state: number) =>
|
const firstImageError = !!(entry.error || generateSpookyImage.error);
|
||||||
state > place ? state : place,
|
const secondImageError = !!(
|
||||||
);
|
secondEntry.error || generateSecondSpookyImage.error
|
||||||
}
|
);
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -148,49 +138,64 @@ export default function AlbumShowcase({
|
|||||||
className="cursor-pointer *:select-none"
|
className="cursor-pointer *:select-none"
|
||||||
>
|
>
|
||||||
<Swiper>
|
<Swiper>
|
||||||
<SwiperSlide>
|
<SwiperSlide className="shadow-lg">
|
||||||
<AlbumImage
|
<AlbumImage
|
||||||
|
entry={entry}
|
||||||
showSpookyImage={showSpookyImage}
|
showSpookyImage={showSpookyImage}
|
||||||
imageSource={imageSource}
|
imageSource={imageSource}
|
||||||
spookyImageSource={spookyImageSource}
|
spookyImageSource={spookyImageSource}
|
||||||
album={album}
|
album={album}
|
||||||
generateSpookyImageData={generateSpookyImage.data as string}
|
generateSpookyImageData={generateSpookyImage.data as string}
|
||||||
lastSpookyImageLoaded={lastSpookyImageLoaded}
|
lastSpookyImageLoaded={lastSpookyImageLoaded}
|
||||||
place={place}
|
place={firstPlace}
|
||||||
spookyImageLoaded={spookyImageLoaded}
|
|
||||||
onImageLoad={onImageLoad}
|
|
||||||
loadGeneratedImage={
|
loadGeneratedImage={
|
||||||
!!(
|
!!(
|
||||||
spookyImageSource &&
|
spookyImageSource &&
|
||||||
(generateSpookyImage.data
|
(generateSpookyImage.data
|
||||||
? lastSpookyImageLoaded >= place ||
|
? lastSpookyImageLoaded >= firstPlace ||
|
||||||
lastSpookyImageLoaded + 1 === place
|
lastSpookyImageLoaded + 1 === firstPlace
|
||||||
: true)
|
: true)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
onQueue={lastSpookyImageLoaded < place - 1}
|
onQueue={lastSpookyImageLoaded < firstPlace - 1}
|
||||||
|
saveImage={saveImage}
|
||||||
|
setLastSpookyImageLoaded={setLastSpookyImageLoaded}
|
||||||
|
error={firstImageError}
|
||||||
/>
|
/>
|
||||||
</SwiperSlide>
|
</SwiperSlide>
|
||||||
{/* <SwiperSlide>
|
<SwiperSlide>
|
||||||
<AlbumImage
|
<AlbumImage
|
||||||
|
number={2}
|
||||||
|
entry={secondEntry}
|
||||||
showSpookyImage={showSpookyImage}
|
showSpookyImage={showSpookyImage}
|
||||||
imageSource={imageSource}
|
imageSource={imageSource}
|
||||||
spookyImageSource={spookyImageSource}
|
spookyImageSource={secondSpookyImageSource}
|
||||||
album={album}
|
album={album}
|
||||||
generateSpookyImageData={generateSpookyImage.data as string}
|
generateSpookyImageData={generateSecondSpookyImage.data as string}
|
||||||
lastSpookyImageLoaded={lastSpookyImageLoaded}
|
lastSpookyImageLoaded={lastSpookyImageLoaded}
|
||||||
place={place}
|
place={secondPlace}
|
||||||
spookyImageLoaded={spookyImageLoaded}
|
loadGeneratedImage={
|
||||||
onImageLoad={onImageLoad}
|
!!(
|
||||||
|
secondSpookyImageSource &&
|
||||||
|
(generateSecondSpookyImage.data
|
||||||
|
? lastSpookyImageLoaded >= secondPlace ||
|
||||||
|
lastSpookyImageLoaded + 1 === secondPlace
|
||||||
|
: true)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onQueue={lastSpookyImageLoaded < secondPlace - 1}
|
||||||
|
saveImage={saveSecondImage}
|
||||||
|
setLastSpookyImageLoaded={setLastSpookyImageLoaded}
|
||||||
|
error={secondImageError}
|
||||||
/>
|
/>
|
||||||
</SwiperSlide> */}
|
</SwiperSlide>
|
||||||
</Swiper>
|
</Swiper>
|
||||||
</div>
|
</div>
|
||||||
<section className="flex h-36 flex-grow flex-col">
|
<section className="flex h-36 flex-grow flex-col">
|
||||||
<h4 className="mb-2 text-lg font-semibold leading-none">
|
<h4 className="mb-2 text-lg font-semibold leading-none">
|
||||||
{album.name}
|
{album.name}
|
||||||
</h4>
|
</h4>
|
||||||
<ul className="overflow-scroll">
|
<ul className="max-h-[400px] overflow-auto overflow-y-auto [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-gray-300 dark:[&::-webkit-scrollbar-thumb]:bg-neutral-500 [&::-webkit-scrollbar-track]:rounded-full [&::-webkit-scrollbar-track]:bg-gray-100 dark:[&::-webkit-scrollbar-track]:bg-neutral-700 [&::-webkit-scrollbar]:w-2">
|
||||||
{tracks.map((track) => (
|
{tracks.map((track) => (
|
||||||
<li key={track.id}>{track.name}</li>
|
<li key={track.id}>{track.name}</li>
|
||||||
))}
|
))}
|
||||||
|
|||||||
38
src/app/_components/sad-face-icon.tsx
Normal file
38
src/app/_components/sad-face-icon.tsx
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
interface SadFaceIconProps {
|
||||||
|
color: string;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SadFaceIcon({ color, className }: SadFaceIconProps) {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
className={className}
|
||||||
|
fill={color}
|
||||||
|
version="1.1"
|
||||||
|
id="Capa_1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||||
|
width="800px"
|
||||||
|
height="800px"
|
||||||
|
viewBox="0 0 106.059 106.059"
|
||||||
|
xmlSpace="preserve"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<path
|
||||||
|
d="M90.546,15.518C69.858-5.172,36.199-5.172,15.515,15.513C-5.173,36.198-5.171,69.858,15.517,90.547
|
||||||
|
c20.682,20.684,54.341,20.684,75.027-0.004C111.23,69.858,111.229,36.2,90.546,15.518z M84.757,84.758
|
||||||
|
c-17.494,17.494-45.96,17.496-63.455,0.002c-17.498-17.497-17.496-45.966,0-63.46C38.796,3.807,67.261,3.805,84.759,21.302
|
||||||
|
C102.253,38.796,102.251,67.265,84.757,84.758z M77.017,74.001c0.658,1.521-0.042,3.286-1.562,3.943
|
||||||
|
c-1.521,0.66-3.286-0.042-3.944-1.562c-2.893-6.689-9.73-11.012-17.421-11.012c-7.868,0-14.747,4.319-17.522,11.004
|
||||||
|
c-0.479,1.154-1.596,1.851-2.771,1.851c-0.384,0-0.773-0.074-1.15-0.23c-1.53-0.636-2.255-2.392-1.62-3.921
|
||||||
|
c3.71-8.932,12.764-14.703,23.063-14.703C64.174,59.371,73.174,65.113,77.017,74.001z M33.24,38.671
|
||||||
|
c0-3.424,2.777-6.201,6.201-6.201c3.423,0,6.2,2.776,6.2,6.201c0,3.426-2.777,6.202-6.2,6.202
|
||||||
|
C36.017,44.873,33.24,42.097,33.24,38.671z M61.357,38.671c0-3.424,2.779-6.201,6.203-6.201c3.423,0,6.2,2.776,6.2,6.201
|
||||||
|
c0,3.426-2.776,6.202-6.2,6.202S61.357,42.097,61.357,38.671z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SadFaceIcon;
|
||||||
@@ -27,16 +27,18 @@ export function Showcase({
|
|||||||
<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) => (
|
.map((album, index) => {
|
||||||
<AlbumShowcase
|
return (
|
||||||
key={album.id}
|
<AlbumShowcase
|
||||||
place={index}
|
key={album.id}
|
||||||
lastSpookyImageLoaded={lastSpookyImageLoaded}
|
{...album}
|
||||||
setLastSpookyImageLoaded={setLastSpookyImageLoaded}
|
places={[index, albumsQuantity + index]}
|
||||||
spookify={spookify}
|
lastSpookyImageLoaded={lastSpookyImageLoaded}
|
||||||
{...album}
|
setLastSpookyImageLoaded={setLastSpookyImageLoaded}
|
||||||
/>
|
spookify={spookify}
|
||||||
))}
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
<h3>Artists images</h3>
|
<h3>Artists images</h3>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
export const FETCH_TRACKS_LIMIT = 20;
|
export const FETCH_TRACKS_LIMIT = 1;
|
||||||
export const FETCH_ARTISTS_LIMIT = 21;
|
export const FETCH_ARTISTS_LIMIT = 1;
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ export const entryRouter = createTRPCRouter({
|
|||||||
type: z.enum(["artist", "album"]),
|
type: z.enum(["artist", "album"]),
|
||||||
name: z.string().min(1),
|
name: z.string().min(1),
|
||||||
image: z.string().min(1),
|
image: z.string().min(1),
|
||||||
|
number: z.number().optional(),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
@@ -51,7 +52,7 @@ export const entryRouter = createTRPCRouter({
|
|||||||
if (!uploadedImage || typeof uploadedImage !== "string") {
|
if (!uploadedImage || typeof uploadedImage !== "string") {
|
||||||
throw new Error("Failed to upload image");
|
throw new Error("Failed to upload image");
|
||||||
}
|
}
|
||||||
const spookyImage = makeImageSpooky(uploadedImage);
|
const spookyImage = makeImageSpooky(uploadedImage, input.entry.number);
|
||||||
if (!spookyImage || typeof spookyImage !== "string") {
|
if (!spookyImage || typeof spookyImage !== "string") {
|
||||||
throw new Error("Failed to make image spooky");
|
throw new Error("Failed to make image spooky");
|
||||||
}
|
}
|
||||||
@@ -79,6 +80,7 @@ export const entryRouter = createTRPCRouter({
|
|||||||
type: z.enum(["artist", "album"]),
|
type: z.enum(["artist", "album"]),
|
||||||
name: z.string().min(1),
|
name: z.string().min(1),
|
||||||
image: z.string().min(1),
|
image: z.string().min(1),
|
||||||
|
number: z.number().optional(),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -24,11 +24,16 @@ export const uploadImage = async (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const makeImageSpooky = (publicId: string) => {
|
export const makeImageSpooky = (publicId: string, number?: number) => {
|
||||||
const options = {
|
const options: Record<string, string> = {};
|
||||||
effect:
|
|
||||||
"gen_background_replace:prompt_a bizarre and super creepy background acording with main object theme-max creativity",
|
if (number === 2) {
|
||||||
};
|
options.effect =
|
||||||
|
"gen_recolor:prompt_main_object_or_motive_on_image;to-color_green";
|
||||||
|
} else {
|
||||||
|
options.effect =
|
||||||
|
"gen_background_replace:prompt_a bizarre and super creepy background acording with main object theme-max creativity";
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = cloudinary.v2.image(publicId, { ...options });
|
const result = cloudinary.v2.image(publicId, { ...options });
|
||||||
|
|||||||
Reference in New Issue
Block a user