Skip to content

Commit

Permalink
feat(items-list): add new card view
Browse files Browse the repository at this point in the history
  • Loading branch information
Iqro-dev committed Oct 7, 2024
1 parent 4b23cc6 commit a7c0450
Show file tree
Hide file tree
Showing 16 changed files with 2,298 additions and 610 deletions.
41 changes: 25 additions & 16 deletions app/components/items/cards/item-card.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
'use client'

import { ItemImage, ItemName, ItemArtists } from '../misc'
import { ItemArtists, ItemImage, ItemName } from '../misc'

import { Card } from '@app/components/ui/card'
import { SpotifyLink } from '@app/components/common'
import type { AlbumEntity, ArtistEntity, TrackEntity } from '@app/api/types'
import { SpotifyLink } from '@app/components/common'
import { Card } from '@app/components/ui/card'
import { cn } from '@app/utils/cn'

interface ItemCardAlbum
extends Pick<AlbumEntity, 'images' | 'albumType' | 'releaseDate'> {
Expand Down Expand Up @@ -46,27 +47,35 @@ function ItemCard({
<Card className="flex flex-col gap-3 rounded-lg bg-neutral-800 p-4">
<ItemImage images={images ?? album} alt={name} size={200} />

<div>
<div
className={cn(!album && !artists && 'flex flex-row justify-between')}
>
<ItemName
name={name}
href={`/${artists ? (album ? 'track' : 'album') : 'artist'}/${id}`}
className="!max-w-[200px]"
/>

<div className="flex flex-row justify-between">
{albumType ? (
<div>
{new Date(releaseDate).getFullYear()} &bull;&nbsp;
<span className="capitalize">{albumType}</span>
</div>
) : album ? (
<ItemArtists artists={artists} />
) : (
<div />
)}
{(album ?? albumType) ? (
<div className="flex flex-row justify-between">
{albumType && (
<div>
{new Date(releaseDate).getFullYear()} &bull;&nbsp;
<span className="capitalize">{albumType}</span>
</div>
)}

{album && (
<div className="flex max-w-[150px] justify-start">
<ItemArtists artists={artists} />
</div>
)}

{(album ?? artists) && <SpotifyLink href={href} />}
</div>
) : (
<SpotifyLink href={href} />
</div>
)}
</div>
</Card>
)
Expand Down
17 changes: 16 additions & 1 deletion app/components/items/list/items-list.skeleton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function ItemsListSkeleton({
}: ItemsListSkeleton.Props) {
return (
<div className="flex flex-col gap-8">
{view === View.CARD && (
{view === View.TOP && (
<>
<div className="mt-16 flex w-full flex-col items-center justify-center gap-4 self-center pt-4 md:flex-row md:items-start lg:mt-24">
<div className="flex h-full flex-col-reverse justify-center gap-4 md:w-2/3 md:flex-row">
Expand Down Expand Up @@ -87,6 +87,21 @@ function ItemsListSkeleton({
))}
</div>
)}

{view === View.CARD && (
<div className="flex flex-col md:flex-row gap-4">
{Array.from({ length: 10 })
.fill(0)
.map((_, index) => (
<ItemsListElementSkeleton
key={index}
withArtists={withArtists}
withPlayedAt={withPlayedAt}
withPlaysOrPlayTime={withProgress}
/>
))}
</div>
)}
</div>
)
}
Expand Down
2 changes: 1 addition & 1 deletion app/components/items/list/items-list.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export const Skeleton: ItemsListStory = {
}

export const SkeletonWithTop: ItemsListStory = {
render: () => <ItemsListSkeleton view={View.CARD} />,
render: () => <ItemsListSkeleton view={View.TOP} />,
}

export const SkeletonWithArtists: ItemsListStory = {
Expand Down
40 changes: 26 additions & 14 deletions app/components/items/list/items-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import type { HtmlHTMLAttributes } from 'react'

import { ItemTopCard } from '../cards'
import { ItemCard, ItemTopCard } from '../cards'
import { formatItems } from '../helpers'
import type { ItemPosition } from '../misc'

Expand Down Expand Up @@ -32,6 +32,7 @@ namespace ItemsList {
| TrackEntity[]
| RigtchStatsResponse<ArtistEntity | TrackEntity | AlbumEntity>
isTop?: boolean
isCard?: boolean
positionSize?: ItemPosition.Props['size']
positionClassName?: string
lastItemSeparator?: boolean
Expand All @@ -44,6 +45,7 @@ namespace ItemsList {
function ItemsList({
items,
isTop,
isCard,
positionSize,
className,
positionClassName,
Expand Down Expand Up @@ -90,22 +92,32 @@ function ItemsList({
</>
)}

<div className="flex flex-col">
<div
className={cn(
isCard
? 'flex w-full flex-wrap justify-center gap-4'
: 'flex flex-col'
)}
>
{sortedItems.slice(isTop ? 3 : 0).map((item, index, items) => (
<div key={index}>
{/* @ts-expect-error: conditional types are already handled */}
<ItemsListElement
{...item}
genresDisplayLength={genresDisplayLength}
positionSize={positionSize}
positionClassName={positionClassName}
className={cn(
isRounded && index === 0 && 'rounded-t-lg',
isRounded && index === items.length - 1 && 'rounded-bl-lg'
)}
/>
{isCard ? (
<ItemCard {...item} />
) : (
/* @ts-expect-error: conditional types are already handled */
<ItemsListElement
{...item}
genresDisplayLength={genresDisplayLength}
positionSize={positionSize}
positionClassName={positionClassName}
className={cn(
isRounded && index === 0 && 'rounded-t-lg',
isRounded && index === items.length - 1 && 'rounded-bl-lg'
)}
/>
)}

{items.length === index + 1 ? (
{isCard ? null : items.length === index + 1 ? (
lastItemSeparator ? (
<Separator />
) : null
Expand Down
6 changes: 3 additions & 3 deletions app/components/items/misc/item-artists.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
'use client'

import type { ArtistEntity } from '@app/api/types'
import { LinkButton } from '@app/components/common/buttons'
import { cn } from '@app/utils/cn'
import type { ArtistEntity } from '@app/api/types'

namespace ItemArtists {
export type Props = Readonly<
Expand All @@ -14,7 +14,7 @@ namespace ItemArtists {

function ItemArtists({ artists, className }: ItemArtists.Props) {
return (
<>
<span className="truncate">
{artists.map(({ name, id }, index) => (
<span key={name}>
<LinkButton
Expand All @@ -30,7 +30,7 @@ function ItemArtists({ artists, className }: ItemArtists.Props) {
{index !== artists.length - 1 && <span>, </span>}
</span>
))}
</>
</span>
)
}

Expand Down
13 changes: 9 additions & 4 deletions app/profile/components/common/selects/select-view.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client'

import { usePathname, useRouter, useSearchParams } from 'next/navigation'
import { LuLayers, LuList } from 'react-icons/lu'
import { LuLayers, LuList, LuStar } from 'react-icons/lu'

import type { ProfileSelectProps } from './props'

Expand All @@ -19,15 +19,20 @@ import { formatSearchParams } from '@app/utils/formatters'
export function SelectView({ initialValue }: ProfileSelectProps<View>) {
const viewOptions = [
{
icon: <LuLayers />,
value: View.CARD,
label: 'Card',
icon: <LuStar />,
value: View.TOP,
label: 'Top',
},
{
icon: <LuList />,
value: View.LIST,
label: 'List',
},
{
icon: <LuLayers />,
value: View.CARD,
label: 'Card',
},
]

const pathname = usePathname()
Expand Down
1 change: 1 addition & 0 deletions app/profile/enums/view.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export enum View {
LIST = 'list',
TOP = 'TOP',
CARD = 'card',
}
8 changes: 6 additions & 2 deletions app/profile/sections/items-section.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { NoDataAlert } from '../components/common'

import { DefaultSection } from '@app/sections'
import type {
AlbumEntity,
ArtistEntity,
Expand All @@ -9,6 +8,7 @@ import type {
} from '@app/api/types'
import { ItemsList } from '@app/components/items/list'
import { View } from '@app/profile/enums'
import { DefaultSection } from '@app/sections'

namespace ItemsSection {
export type Props = Readonly<
Expand All @@ -31,7 +31,11 @@ function ItemsSection({
return (
<DefaultSection {...props}>
{items.length > 0 && (
<ItemsList items={items} isTop={view === View.CARD} />
<ItemsList
items={items}
isTop={view === View.TOP}
isCard={view === View.CARD}
/>
)}

{items.length === 0 && <NoDataAlert />}
Expand Down
Loading

0 comments on commit a7c0450

Please sign in to comment.