Skip to content

Commit

Permalink
MRKT-26: artist spotlight (#550)
Browse files Browse the repository at this point in the history
* implements artist spotlight on home page

* removes components/index.ts file

* removes getResizedAlbumCoverImageUrl for resizeCloudinaryImage

* renames Artists component

* makes resizeCloudinaryImage url param optional

* removes unused type definition

* updates comment

* improves resizeCloudinaryImage regex

* updates artist spotlight click functionality

* imports components from top level of components directory

* updates artist skeleton spacing

* makes artist spotlight image size responsive

* minor update to artist spotlight styling

* resolves merge conflicts
  • Loading branch information
scandycuz authored Mar 4, 2024
1 parent 824c2ff commit 8d64033
Show file tree
Hide file tree
Showing 18 changed files with 267 additions and 49 deletions.
5 changes: 5 additions & 0 deletions apps/marketplace/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ const nextConfig = {
styledComponents: true
},

images: {
// TODO: remove this setting once non-static site can be deployed
unoptimized: true
},

output: "export"
};

Expand Down
4 changes: 1 addition & 3 deletions apps/marketplace/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ import { AppRouterCacheProvider } from "@mui/material-nextjs/v13-appRouter";
import { FunctionComponent, ReactNode } from "react";
import theme from "@newm-web/theme";
import { Provider } from "react-redux";
import { StyledComponentsRegistry } from "../components";
import Header from "../components/header/Header";
import { Footer, Header, StyledComponentsRegistry } from "../components";
import store from "../store";
import Footer from "../components/footer/Footer";

interface RootLayoutProps {
readonly children: ReactNode;
Expand Down
3 changes: 2 additions & 1 deletion apps/marketplace/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
"use client";
import { FunctionComponent } from "react";
import { Container } from "@mui/material";
import Songs from "../components/Songs";
import { ArtistSpotlight, Songs } from "../components";

const Home: FunctionComponent = () => {
return (
<Container sx={ { flexGrow: 1 } }>
<Songs />
<ArtistSpotlight />
</Container>
);
};
Expand Down
69 changes: 69 additions & 0 deletions apps/marketplace/src/components/Artist.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { Box, Stack, Typography, useTheme } from "@mui/material";
import { resizeCloudinaryImage } from "@newm-web/utils";
import { FunctionComponent } from "react";
import { Clickable } from "@newm-web/elements";
import ArtistSkeleton from "./skeletons/ArtistSkeleton";

interface ArtistProps {
readonly imageUrl: string;
readonly isLoading: boolean;
readonly onSelectArtist: (param: string) => void;
readonly orientation: "row" | "column";
readonly subtitle: string;
readonly title: string;
}

/**
* Image and information for an artist. Can be vertically
* or horizontally aligned.
*/
const Artist: FunctionComponent<ArtistProps> = ({
imageUrl,
title,
isLoading,
subtitle,
orientation,
onSelectArtist,
}) => {
const theme = useTheme();

if (isLoading) {
return <ArtistSkeleton orientation={ orientation } />;
}

return (
<Clickable
aria-label={ `${title}-artist-profile` }
onClick={ () => onSelectArtist(title) }
>
<Stack columnGap={ 3.5 } direction={ orientation } rowGap={ 2 }>
<Box
alt={ `${title}-artist-profile` }
component="img"
height={ [150, 150, 200] }
src={ resizeCloudinaryImage(imageUrl, {
height: 200,
width: 200,
}) }
style={ { borderRadius: "50%", maxWidth: "100%" } }
width={ [150, 150, 200] }
/>
<Stack
justifyContent="center"
spacing={ 0.25 }
textAlign={ orientation === "row" ? "start" : "center" }
>
<Typography variant="h4">{ title }</Typography>
<Typography
sx={ { color: theme.colors.grey100, fontWeight: 400 } }
variant="h4"
>
{ subtitle }
</Typography>
</Stack>
</Stack>
</Clickable>
);
};

export default Artist;
100 changes: 100 additions & 0 deletions apps/marketplace/src/components/ArtistSpotlight.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { FunctionComponent, useEffect, useState } from "react";
import { Grid, Stack, Typography } from "@mui/material";
import Artist from "./Artist";

const ArtistSpotlight: FunctionComponent = () => {
// TEMP: simulate data loading
const [isLoading, setIsLoading] = useState(true);

const handleSelectArtist = (name: string) => {
// placeholder
console.log("artist selected: ", name); // eslint-disable-line
};

// TEMP: simulate data loading
useEffect(() => {
setTimeout(() => {
setIsLoading(false);
}, 1000);
}, []);

return (
<Stack mb={ 8 }>
<Stack alignItems="center" mb={ 5 } mt={ 20 }>
<Typography fontSize={ ["24px", "24px", "32px"] } variant="h3">
ARTIST SPOTLIGHT
</Typography>
</Stack>

<Grid columnGap={ [5, 5, 15] } justifyContent="center" rowGap={ 5 } container>
{ tempArtistData.map(({ imageUrl, name, songCount }, idx) => {
return (
<Grid display="flex" key={ imageUrl } sx={ { cursor: "pointer" } }>
<Artist
imageUrl={ imageUrl }
isLoading={ isLoading }
orientation="column"
subtitle={ `${songCount} songs` }
title={ name }
onSelectArtist={ handleSelectArtist }
/>
</Grid>
);
}) }
</Grid>
</Stack>
);
};

export default ArtistSpotlight;

const tempArtistData = [
{
imageUrl:
"https://res.cloudinary.com/newm/image/upload/v1701715430/pzeo4bcivjouksomeggy.jpg",
name: "Lorem Ipsum",
songCount: 4,
},
{
imageUrl:
"https://res.cloudinary.com/newm/image/upload/c_limit,w_4000,h_4000/v1695587661/mprskynp42oijtpaypeq.jpg",
name: "Lorem Ipsum",
songCount: 4,
},
{
imageUrl:
"https://res.cloudinary.com/newm/image/upload/v1701715430/pzeo4bcivjouksomeggy.jpg",
name: "Lorem Ipsum",
songCount: 4,
},
{
imageUrl:
"https://res.cloudinary.com/newm/image/upload/c_limit,w_4000,h_4000/v1695587661/mprskynp42oijtpaypeq.jpg",
name: "Lorem Ipsum",
songCount: 4,
},
{
imageUrl:
"https://res.cloudinary.com/newm/image/upload/v1701715430/pzeo4bcivjouksomeggy.jpg",
name: "Lorem Ipsum",
songCount: 4,
},
{
imageUrl:
"https://res.cloudinary.com/newm/image/upload/c_limit,w_4000,h_4000/v1695587661/mprskynp42oijtpaypeq.jpg",
name: "Lorem Ipsum",
songCount: 4,
},
{
imageUrl:
"https://res.cloudinary.com/newm/image/upload/v1701715430/pzeo4bcivjouksomeggy.jpg",
name: "Lorem Ipsum",
songCount: 4,
},
{
imageUrl:
"https://res.cloudinary.com/newm/image/upload/c_limit,w_4000,h_4000/v1695587661/mprskynp42oijtpaypeq.jpg",
name: "Lorem Ipsum",
songCount: 4,
},
];
4 changes: 3 additions & 1 deletion apps/marketplace/src/components/StyledComponentsRegistry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import React, { useState } from "react";
import { useServerInsertedHTML } from "next/navigation";
import { ServerStyleSheet, StyleSheetManager } from "styled-components";

export const StyledComponentsRegistry = ({
const StyledComponentsRegistry = ({
children,
}: {
children: React.ReactNode;
Expand All @@ -33,3 +33,5 @@ export const StyledComponentsRegistry = ({
</StyleSheetManager>
);
};

export default StyledComponentsRegistry;
1 change: 0 additions & 1 deletion apps/marketplace/src/components/header/index.ts

This file was deleted.

12 changes: 7 additions & 5 deletions apps/marketplace/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export * from "./header";
export { Header } from "./header";
export * from "./footer/Footer";
export * from "./Songs";
export * from "./StyledComponentsRegistry";
export * from "./Artist";
export { default as Artist } from "./Artist";
export { default as ArtistSpotlight } from "./ArtistSpotlight";
export { default as Footer } from "./footer/Footer";
export { default as Header } from "./header/Header";
export { default as StyledComponentsRegistry } from "./StyledComponentsRegistry";
export { default as Songs } from "./Songs";
30 changes: 30 additions & 0 deletions apps/marketplace/src/components/skeletons/ArtistSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Box, Skeleton, Stack } from "@mui/material";
import { FunctionComponent } from "react";

interface ArtistSkeletonProps {
readonly orientation: "row" | "column";
}

const ArtistSkeleton: FunctionComponent<ArtistSkeletonProps> = ({
orientation,
}) => (
<Stack spacing={ 1.25 }>
<Box>
<Skeleton
sx={ { height: [150, 150, 200], width: [150, 150, 200] } }
variant="circular"
/>
</Box>

<Stack
alignItems={ orientation === "column" ? "center" : "row" }
direction={ orientation }
spacing={ 0.25 }
>
<Skeleton height={ 30 } width={ 100 } />
<Skeleton height={ 20 } width={ 60 } />
</Stack>
</Stack>
);

export default ArtistSkeleton;
4 changes: 2 additions & 2 deletions apps/studio/src/components/invites/InvitesTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import CheckIcon from "@mui/icons-material/Check";
import CloseIcon from "@mui/icons-material/Close";
import { TableCell, TableHeadCell } from "@newm-web/elements";
import { getResizedAlbumCoverImageUrl, useHlsJs } from "@newm-web/utils";
import { resizeCloudinaryImage, useHlsJs } from "@newm-web/utils";
import theme from "@newm-web/theme";
import { PlayerState, Song } from "@newm-web/types";

Expand Down Expand Up @@ -245,7 +245,7 @@ const InvitesTable: FunctionComponent<InvitesTableProps> = ({
{ coverArtUrl ? (
<img
alt="Song cover"
src={ getResizedAlbumCoverImageUrl(coverArtUrl, {
src={ resizeCloudinaryImage(coverArtUrl, {
height: 50,
width: 50,
}) }
Expand Down
4 changes: 2 additions & 2 deletions apps/studio/src/pages/home/library/SongList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import {
Tooltip,
} from "@newm-web/elements";
import {
getResizedAlbumCoverImageUrl,
isMoreThanThresholdSecondsLater,
resizeCloudinaryImage,
useHlsJs,
useWindowDimensions,
} from "@newm-web/utils";
Expand Down Expand Up @@ -363,7 +363,7 @@ export default function SongList({ totalCountOfSongs, query }: SongListProps) {
) }
<img
alt="Album cover"
src={ getResizedAlbumCoverImageUrl(song.coverArtUrl) }
src={ resizeCloudinaryImage(song.coverArtUrl) }
style={ {
borderRadius: "4px",
height: "40px",
Expand Down
7 changes: 2 additions & 5 deletions apps/studio/src/pages/home/owners/Owner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ import {
bgImage,
} from "@newm-web/assets";
import theme from "@newm-web/theme";
import {
getResizedAlbumCoverImageUrl,
useWindowDimensions,
} from "@newm-web/utils";
import { resizeCloudinaryImage, useWindowDimensions } from "@newm-web/utils";
import { Button, Typography } from "@newm-web/elements";
import Songs from "./Songs";
import OwnerModal from "./OwnerModal";
Expand Down Expand Up @@ -100,7 +97,7 @@ const Owner: FunctionComponent = () => {
height={ isWidthAboveSm ? "200px" : "100px" }
src={
pictureUrl
? getResizedAlbumCoverImageUrl(pictureUrl, {
? resizeCloudinaryImage(pictureUrl, {
height: 200,
width: 200,
})
Expand Down
4 changes: 2 additions & 2 deletions apps/studio/src/pages/home/wallet/SongRoyaltiesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
TableRow,
} from "@mui/material";
import theme from "@newm-web/theme";
import { getResizedAlbumCoverImageUrl } from "@newm-web/utils";
import { resizeCloudinaryImage } from "@newm-web/utils";
import { Song } from "@newm-web/types";
import { Dispatch, SetStateAction } from "react";
import { TablePagination, Typography } from "@newm-web/elements";
Expand Down Expand Up @@ -96,7 +96,7 @@ export default function SongRoyaltiesList({
<Box sx={ { alignItems: "center", display: "flex" } }>
<img
alt="Album cover"
src={ getResizedAlbumCoverImageUrl(row.coverArtUrl) }
src={ resizeCloudinaryImage(row.coverArtUrl) }
style={ {
borderRadius: "50%",
} }
Expand Down
4 changes: 2 additions & 2 deletions packages/components/src/lib/SongCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { PlayArrow, Stop } from "@mui/icons-material";
import { bgImage } from "@newm-web/assets";
import {
getImageSrc,
getResizedAlbumCoverImageUrl,
resizeCloudinaryImage,
useWindowDimensions,
} from "@newm-web/utils";
import { SongCardSkeleton } from "@newm-web/elements";
Expand Down Expand Up @@ -96,7 +96,7 @@ export const SongCard = ({
height={ isWidthAboveMd ? 260 : 150 }
src={
coverArtUrl
? getResizedAlbumCoverImageUrl(coverArtUrl, {
? resizeCloudinaryImage(coverArtUrl, {
height: 200,
width: 200,
})
Expand Down
1 change: 1 addition & 0 deletions packages/elements/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export { default as Button } from "./lib/Button";
export * from "./lib/Button";
export { default as Checkbox } from "./lib/Checkbox";
export * from "./lib/Checkbox";
export { default as Clickable } from "./lib/styled/Clickable";
export { default as Dialog } from "./lib/styled/Dialog";
export { default as DropdownSelect } from "./lib/DropdownSelect";
export * from "./lib/DropdownSelect";
Expand Down
16 changes: 16 additions & 0 deletions packages/elements/src/lib/styled/Clickable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { styled } from "@mui/material/styles";

const Clickable = styled("button")`
background: none;
border: none;
color: inherit;
margin: 0;
padding: 0;
cursor: pointer;
border-radius: 8px;
&:hover * {
text-decoration: underline;
}
`;

export default Clickable;
Loading

0 comments on commit 8d64033

Please sign in to comment.