Skip to content

Commit b0dba0c

Browse files
committed
Add cover art inspector
1 parent 498e31f commit b0dba0c

File tree

6 files changed

+130
-3
lines changed

6 files changed

+130
-3
lines changed

app/javascript/components/CoverArt.jsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { useState } from "react";
2+
import { Link } from "react-router-dom";
23

3-
const CoverArt = ({ coverArtUrls, albumCoverUrl, openAppModal, size = "small", css, selectedOption }) => {
4+
const CoverArt = ({ coverArtUrls, albumCoverUrl, openAppModal, closeAppModal, size = "small", css, selectedOption }) => {
45
const [isLoaded, setIsLoaded] = useState(false);
56

67
const handleOpenModal = () => {
@@ -26,7 +27,8 @@ const CoverArt = ({ coverArtUrls, albumCoverUrl, openAppModal, size = "small", c
2627
)}
2728

2829
<div className="box mt-2">
29-
Images generated by DALL-E with prompt assistance from ChatGPT.
30+
Images generated by DALL-E with prompt assistance from ChatGPT.<br />
31+
<Link to="/cover-art" onClick={closeAppModal} className="button mt-2">Browse All Art</Link>
3032
</div>
3133
</>
3234
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
export const coverArtInspectorLoader = async ({ request }) => {
2+
const url = new URL(request.url);
3+
const page = url.searchParams.get("page") || 1;
4+
const perPage = url.searchParams.get("per_page") || 50;
5+
6+
try {
7+
const response = await fetch(`/api/v2/shows?page=${page}&per_page=${perPage}`);
8+
if (!response.ok) throw response;
9+
const data = await response.json();
10+
return {
11+
shows: data.shows,
12+
totalPages: data.total_pages,
13+
totalEntries: data.total_entries,
14+
page: parseInt(page, 10) - 1,
15+
perPage: parseInt(perPage)
16+
};
17+
} catch (error) {
18+
throw new Response("Error fetching data", { status: 500 });
19+
}
20+
};
21+
22+
import React, { useState } from "react";
23+
import { useLoaderData, useNavigate, useOutletContext } from "react-router-dom";
24+
import { Helmet } from "react-helmet-async";
25+
import LayoutWrapper from "./layout/LayoutWrapper";
26+
import CoverArt from "./CoverArt";
27+
import Pagination from "./controls/Pagination";
28+
import { paginationHelper } from "./helpers/pagination";
29+
import { formatNumber } from "./helpers/utils";
30+
31+
const CoverArtInspector = () => {
32+
const { shows, totalPages, totalEntries, page, perPage } = useLoaderData();
33+
const { openAppModal, closeAppModal } = useOutletContext();
34+
const [selectedOption, setSelectedOption] = useState("coverArt");
35+
const {
36+
tempPerPage,
37+
handlePageClick,
38+
handlePerPageInputChange,
39+
handlePerPageBlurOrEnter
40+
} = paginationHelper(page, "", perPage);
41+
42+
const handleOptionChange = (e) => {
43+
setSelectedOption(e.target.value);
44+
};
45+
46+
const sidebarContent = (
47+
<div className="sidebar-content">
48+
<p className="sidebar-title">Cover Art</p>
49+
<p className="sidebar-subtitle">{formatNumber(totalEntries)} total</p>
50+
<div className="dropdown mt-3">
51+
<select id="coverArtOption" value={selectedOption} onChange={handleOptionChange} className="input">
52+
<option value="coverArt">Raw Cover Art</option>
53+
<option value="albumCover">Album Covers</option>
54+
</select>
55+
</div>
56+
</div>
57+
);
58+
59+
return (
60+
<>
61+
<Helmet>
62+
<title>Cover Art - Phish.in</title>
63+
</Helmet>
64+
<LayoutWrapper sidebarContent={sidebarContent}>
65+
<div className="cover-art-inspector-container">
66+
{shows.map((show) => (
67+
<CoverArt
68+
key={show.id}
69+
coverArtUrls={show.cover_art_urls}
70+
albumCoverUrl={show.album_cover_url}
71+
openAppModal={openAppModal}
72+
closeAppModal={closeAppModal}
73+
size="medium"
74+
css="cover-art-inspector"
75+
selectedOption={selectedOption}
76+
/>
77+
))}
78+
</div>
79+
<Pagination
80+
totalPages={totalPages}
81+
handlePageClick={handlePageClick}
82+
currentPage={page}
83+
perPage={tempPerPage}
84+
handlePerPageInputChange={handlePerPageInputChange}
85+
handlePerPageBlurOrEnter={handlePerPageBlurOrEnter}
86+
/>
87+
</LayoutWrapper>
88+
</>
89+
);
90+
};
91+
92+
export default CoverArtInspector;

app/javascript/components/Show.jsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const Show = ({ trackSlug }) => {
3232
const show = useLoaderData();
3333
const [tracks, setTracks] = useState(show.tracks);
3434
const trackRefs = useRef([]);
35-
const { playTrack, mapboxToken, openAppModal } = useOutletContext();
35+
const { playTrack, mapboxToken, openAppModal, closeAppModal } = useOutletContext();
3636
const [matchedTrack, setMatchedTrack] = useState(tracks[0]);
3737
const [showIncompleteNotification, setShowIncompleteNotification] = useState(show.incomplete);
3838
const [showAdminNotesNotification, setShowAdminNotesNotification] = useState(!!show.admin_notes);
@@ -89,6 +89,7 @@ const Show = ({ trackSlug }) => {
8989
coverArtUrls={show.cover_art_urls}
9090
albumCoverUrl={show.album_cover_url}
9191
openAppModal={openAppModal}
92+
closeAppModal={closeAppModal}
9293
size="medium"
9394
/>
9495
</div>

app/javascript/components/pages/Faq.jsx

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ const Faq = () => {
8181

8282
<h3>How is album cover art created?</h3>
8383
<p>Album covers are generated with a combination of automation scripts and the assistance of ChatGPT and Dall-E.</p>
84+
<Link to="/cover-art" className="button mt-2">Browse All Art</Link>
8485

8586
<h3>How can I contribute?</h3>
8687
<p>

app/javascript/components/routes/routes.js

+6
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import TopShows, { topShowsLoader } from "../TopShows";
2222
import TopTracks, { topTracksLoader } from "../TopTracks";
2323
import VenueIndex, { venueIndexLoader } from "../VenueIndex";
2424
import VenueShows, { venueShowsLoader } from "../VenueShows";
25+
import CoverArtInspector, { coverArtInspectorLoader } from "../CoverArtInspector";
2526

2627
// Simple pages with no sidebar
2728
import ApiDocs from "../pages/ApiDocs";
@@ -181,6 +182,11 @@ const routes = (props) => [
181182
path: "/settings",
182183
element: <Settings />,
183184
},
185+
{
186+
path: "/cover-art",
187+
element: <CoverArtInspector />,
188+
loader: coverArtInspectorLoader,
189+
},
184190
{
185191
path: "*",
186192
element: <DynamicRoute />,

app/javascript/stylesheets/content.css.scss

+25
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,31 @@ main {
439439
}
440440
}
441441

442+
.cover-art-inspector-container {
443+
display: grid;
444+
grid-template-columns: repeat(auto-fill, minmax(128px, 1fr));
445+
gap: 1rem;
446+
padding: 1rem;
447+
width: 100%;
448+
449+
.cover-art-inspector {
450+
width: 128px;
451+
height: 128px;
452+
border-radius: 8px;
453+
object-fit: cover;
454+
transition: transform 0.2s ease;
455+
456+
&:hover {
457+
transform: scale(1.05);
458+
cursor: pointer;
459+
}
460+
}
461+
462+
.cover-art {
463+
background-color: transparent !important;
464+
}
465+
}
466+
442467
.grid-view {
443468
display: grid;
444469
grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));

0 commit comments

Comments
 (0)