Skip to content

Commit

Permalink
MRKT-27: Single Item for play - Initial Item Page (#577)
Browse files Browse the repository at this point in the history
* feat: Create initial single Item page with card

* feat: Move Single Item page for dynamic route

* feat: Implement with static test data
  • Loading branch information
dmkirshon authored Mar 29, 2024
1 parent d9f54f7 commit 44beb6d
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 50 deletions.
16 changes: 16 additions & 0 deletions apps/marketplace/src/app/item/[songId]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { FunctionComponent, ReactNode } from "react";
import { mockSongs } from "../../../temp/data";

interface SongLayoutProps {
readonly children: ReactNode;
}

export const generateStaticParams = async () => {
return mockSongs.map(({ id }) => ({ songId: id }));
};

const Layout: FunctionComponent<SongLayoutProps> = ({ children }) => {
return children;
};

export default Layout;
51 changes: 51 additions & 0 deletions apps/marketplace/src/app/item/[songId]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"use client";
import { Container, Stack } from "@mui/material";
import { SongCard } from "@newm-web/components";
import { FunctionComponent, useEffect, useState } from "react";
import { mockSongs } from "../../../temp/data";
import { ItemSkeleton } from "../../../components";

interface SingleSongProps {
readonly params: {
readonly songId: string;
};
}

const SingleSong: FunctionComponent<SingleSongProps> = ({ params }) => {
// TEMP: simulate data loading
const [isLoading, setIsLoading] = useState(true);

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

if (isLoading) {
return <ItemSkeleton />;
}

return (
<Container sx={ { flexGrow: 1, mt: 5 } }>
<Stack alignItems="center" mt={ 2.5 }>
<SongCard
coverArtUrl={
mockSongs.find((song) => song.id === params.songId)?.coverArtUrl
}
isPlayable={ true }
price="3.0"
size="Large"
// eslint-disable-next-line @typescript-eslint/no-empty-function
onPriceClick={ () => {} }
// eslint-disable-next-line @typescript-eslint/no-empty-function
onSubtitleClick={ () => {} }
// eslint-disable-next-line @typescript-eslint/no-empty-function
onTitleClick={ () => {} }
/>
</Stack>
</Container>
);
};

export default SingleSong;
9 changes: 8 additions & 1 deletion apps/marketplace/src/components/Songs.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import { FunctionComponent } from "react";
import { Stack, Typography } from "@mui/material";
import { SongCard } from "@newm-web/components";
import { useRouter } from "next/navigation";
import { mockSongs } from "../temp/data";
/**
* TODO: Implement useGetSongsQuery and playback functionality,
* see studio/src/pages/home/owners/Songs.tsx
*/

const Songs: FunctionComponent = () => {
const router = useRouter();

const handleTitleClick = (id: string) => {
router.push(`/item/${id}`);
};

return (
<Stack alignItems="center" mt={ [7.5, 5.5, 10] }>
{ mockSongs.length ? (
Expand Down Expand Up @@ -44,7 +51,7 @@ const Songs: FunctionComponent = () => {
// eslint-disable-next-line @typescript-eslint/no-empty-function
onSubtitleClick={ () => {} }
// eslint-disable-next-line @typescript-eslint/no-empty-function
onTitleClick={ () => {} }
onTitleClick={ () => handleTitleClick(song.id) }
/>
);
}) }
Expand Down
1 change: 1 addition & 0 deletions apps/marketplace/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from "./Artist";
export * from "./skeletons/index";
export { default as Artist } from "./Artist";
export { default as ArtistSpotlight } from "./ArtistSpotlight";
export { default as Footer } from "./footer/Footer";
Expand Down
15 changes: 15 additions & 0 deletions apps/marketplace/src/components/skeletons/ItemSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Container, Skeleton, Stack } from "@mui/material";
import { FunctionComponent } from "react";

const ItemSkeleton: FunctionComponent = () => (
<Container sx={ { flexGrow: 1, mt: 5 } }>
<Stack alignItems="center" mt={ 2.5 }>
<Skeleton
sx={ { height: [150, 150, 400], width: [150, 150, 400] } }
variant="rectangular"
/>
</Stack>
</Container>
);

export default ItemSkeleton;
2 changes: 2 additions & 0 deletions apps/marketplace/src/components/skeletons/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as ArtistSkeleton } from "./ArtistSkeleton";
export { default as ItemSkeleton } from "./ItemSkeleton";
117 changes: 68 additions & 49 deletions packages/components/src/lib/SongCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,17 @@ interface SongCardProps {
onSubtitleClick?: () => void;
onTitleClick?: () => void;
price?: string;
subtitle: string;
title: string;
size?: "Small" | "Large";
subtitle?: string;
title?: string;
}

// create a record for the song card size, small is 260 x 260, large is 400 x 400
const songCardSize: Record<string, number> = {
Large: 400,
Small: 260,
};

export const SongCard = ({
coverArtUrl,
title,
Expand All @@ -33,6 +40,7 @@ export const SongCard = ({
onSubtitleClick,
price,
subtitle,
size = "Small",
}: SongCardProps) => {
const theme = useTheme();
const windowWidth = useWindowDimensions()?.width;
Expand Down Expand Up @@ -89,16 +97,21 @@ export const SongCard = ({
}

return (
<Stack sx={ { maxWidth: ["150px", "150px", "260px"], rowGap: 0.5 } }>
<Stack
sx={ {
maxWidth: ["150px", "150px", `${songCardSize[size]}px`],
rowGap: 0.5,
} }
>
<Stack alignItems="center" display="grid" justifyItems="center">
<img
alt="Song cover art"
height={ isWidthAboveMd ? 260 : 150 }
height={ isWidthAboveMd ? songCardSize[size] : 150 }
src={
coverArtUrl
? resizeCloudinaryImage(coverArtUrl, {
height: 200,
width: 200,
height: songCardSize[size],
width: songCardSize[size],
})
: getImageSrc(bgImage)
}
Expand All @@ -107,7 +120,7 @@ export const SongCard = ({
gridArea: "1 / 1 / 2 / 2",
objectFit: "cover",
} }
width={ isWidthAboveMd ? 260 : 150 }
width={ isWidthAboveMd ? songCardSize[size] : 150 }
/>
{ isPlayable && (
<IconButton
Expand Down Expand Up @@ -159,48 +172,54 @@ export const SongCard = ({
</Stack>
) }
</Stack>
<Typography
fontWeight={ 700 }
mt={ 0.5 }
role={ onTitleClick ? "button" : undefined }
sx={
onTitleClick
? {
"&:hover": { textDecoration: "underline" },
cursor: "pointer",
width: "fit-content",
}
: undefined
}
tabIndex={ onTitleClick ? 0 : undefined }
variant="h4"
onClick={ onTitleClick ? handleTitleClick : undefined }
onKeyDown={ onTitleClick ? handleKeyPress(handleTitleClick) : undefined }
>
{ title }
</Typography>
<Typography
fontWeight={ 500 }
mt={ 0.5 }
role={ onSubtitleClick ? "button" : undefined }
sx={
onSubtitleClick
? {
"&:hover": { textDecoration: "underline" },
cursor: "pointer",
width: "fit-content",
}
: undefined
}
tabIndex={ onSubtitleClick ? 0 : undefined }
variant="subtitle1"
onClick={ onSubtitleClick ? handleSubtitleClick : undefined }
onKeyDown={
onSubtitleClick ? handleKeyPress(handleSubtitleClick) : undefined
}
>
{ subtitle }
</Typography>
{ title && (
<Typography
fontWeight={ 700 }
mt={ 0.5 }
role={ onTitleClick ? "button" : undefined }
sx={
onTitleClick
? {
"&:hover": { textDecoration: "underline" },
cursor: "pointer",
width: "fit-content",
}
: undefined
}
tabIndex={ onTitleClick ? 0 : undefined }
variant="h4"
onClick={ onTitleClick ? handleTitleClick : undefined }
onKeyDown={
onTitleClick ? handleKeyPress(handleTitleClick) : undefined
}
>
{ title }
</Typography>
) }
{ subtitle && (
<Typography
fontWeight={ 500 }
mt={ 0.5 }
role={ onSubtitleClick ? "button" : undefined }
sx={
onSubtitleClick
? {
"&:hover": { textDecoration: "underline" },
cursor: "pointer",
width: "fit-content",
}
: undefined
}
tabIndex={ onSubtitleClick ? 0 : undefined }
variant="subtitle1"
onClick={ onSubtitleClick ? handleSubtitleClick : undefined }
onKeyDown={
onSubtitleClick ? handleKeyPress(handleSubtitleClick) : undefined
}
>
{ subtitle }
</Typography>
) }
</Stack>
);
};

0 comments on commit 44beb6d

Please sign in to comment.