diff --git a/app/components/items/cards/item-card.tsx b/app/components/items/cards/item-card.tsx
index 259f2081..b251356c 100644
--- a/app/components/items/cards/item-card.tsx
+++ b/app/components/items/cards/item-card.tsx
@@ -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 {
@@ -43,30 +44,38 @@ function ItemCard({
album,
}: ItemCard.Props) {
return (
-
+
-
+
-
- {albumType ? (
-
- {new Date(releaseDate).getFullYear()} •
- {albumType}
-
- ) : album ? (
-
- ) : (
-
- )}
+ {(album ?? albumType) ? (
+
+ {albumType && (
+
+ {new Date(releaseDate).getFullYear()} •
+ {albumType}
+
+ )}
+
+ {album && (
+
+
+
+ )}
+ {(album ?? artists) &&
}
+
+ ) : (
-
+ )}
)
diff --git a/app/components/items/list/items-list.skeleton.tsx b/app/components/items/list/items-list.skeleton.tsx
index c7d504b4..c108bee4 100644
--- a/app/components/items/list/items-list.skeleton.tsx
+++ b/app/components/items/list/items-list.skeleton.tsx
@@ -25,7 +25,7 @@ function ItemsListSkeleton({
}: ItemsListSkeleton.Props) {
return (
- {view === View.CARD && (
+ {view === View.TOP && (
<>
@@ -87,6 +87,21 @@ function ItemsListSkeleton({
))}
)}
+
+ {view === View.CARD && (
+
+ {Array.from({ length: 10 })
+ .fill(0)
+ .map((_, index) => (
+
+ ))}
+
+ )}
)
}
diff --git a/app/components/items/list/items-list.spec.tsx b/app/components/items/list/items-list.spec.tsx
index e1b76418..dcb3918d 100644
--- a/app/components/items/list/items-list.spec.tsx
+++ b/app/components/items/list/items-list.spec.tsx
@@ -73,6 +73,7 @@ describe('ItemsList', () => {
test('should match snapshot with playTime', () => {
const view = render(
({
...track,
playTime: 1000 * 60 * 60 * 2,
@@ -88,6 +89,7 @@ describe('ItemsList', () => {
const view = render(
({
...track,
playTime: 1000 * 60 * 60 * 2,
diff --git a/app/components/items/list/items-list.stories.tsx b/app/components/items/list/items-list.stories.tsx
index 37a6970e..db7a9d01 100644
--- a/app/components/items/list/items-list.stories.tsx
+++ b/app/components/items/list/items-list.stories.tsx
@@ -141,7 +141,7 @@ export const Skeleton: ItemsListStory = {
}
export const SkeletonWithTop: ItemsListStory = {
- render: () => ,
+ render: () => ,
}
export const SkeletonWithArtists: ItemsListStory = {
diff --git a/app/components/items/list/items-list.tsx b/app/components/items/list/items-list.tsx
index 72d64dc0..58f18c27 100644
--- a/app/components/items/list/items-list.tsx
+++ b/app/components/items/list/items-list.tsx
@@ -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'
@@ -32,6 +32,7 @@ namespace ItemsList {
| TrackEntity[]
| RigtchStatsResponse
isTop?: boolean
+ isCard?: boolean
positionSize?: ItemPosition.Props['size']
positionClassName?: string
lastItemSeparator?: boolean
@@ -44,6 +45,7 @@ namespace ItemsList {
function ItemsList({
items,
isTop,
+ isCard,
positionSize,
className,
positionClassName,
@@ -59,7 +61,7 @@ function ItemsList({
if (isTop) sortedItems.splice(0, 2, sortedItems[1], sortedItems[0])
return (
-
+
{isTop && (
<>
@@ -90,22 +92,32 @@ function ItemsList({
>
)}
-
+
{sortedItems.slice(isTop ? 3 : 0).map((item, index, items) => (
- {/* @ts-expect-error: conditional types are already handled */}
-
+ {isCard ? (
+
+ ) : (
+ /* @ts-expect-error: conditional types are already handled */
+
+ )}
- {items.length === index + 1 ? (
+ {isCard ? null : items.length === index + 1 ? (
lastItemSeparator ? (
) : null
diff --git a/app/components/items/misc/item-artists.tsx b/app/components/items/misc/item-artists.tsx
index 1a2e5934..863a80ab 100644
--- a/app/components/items/misc/item-artists.tsx
+++ b/app/components/items/misc/item-artists.tsx
@@ -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<
@@ -14,7 +14,7 @@ namespace ItemArtists {
function ItemArtists({ artists, className }: ItemArtists.Props) {
return (
- <>
+
{artists.map(({ name, id }, index) => (
, }
))}
- >
+
)
}
diff --git a/app/components/items/misc/relative-time.tsx b/app/components/items/misc/relative-time.tsx
index 70069310..22108752 100644
--- a/app/components/items/misc/relative-time.tsx
+++ b/app/components/items/misc/relative-time.tsx
@@ -18,7 +18,7 @@ function RelativeTime({ value, options, className }: RelativeTime.Props) {
className={cn('whitespace-nowrap text-primary-foreground/80', className)}
suppressHydrationWarning
>
- {DateTime.fromISO(value, options).toRelative()}
+ {DateTime.fromISO(value, options).setLocale('en').toRelative()}
)
}
diff --git a/app/profile/components/common/selects/select-view.tsx b/app/profile/components/common/selects/select-view.tsx
index a202eb23..0256d00d 100644
--- a/app/profile/components/common/selects/select-view.tsx
+++ b/app/profile/components/common/selects/select-view.tsx
@@ -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'
@@ -19,15 +19,20 @@ import { formatSearchParams } from '@app/utils/formatters'
export function SelectView({ initialValue }: ProfileSelectProps
) {
const viewOptions = [
{
- icon: ,
- value: View.CARD,
- label: 'Card',
+ icon: ,
+ value: View.TOP,
+ label: 'Top',
},
{
icon: ,
value: View.LIST,
label: 'List',
},
+ {
+ icon: ,
+ value: View.CARD,
+ label: 'Card',
+ },
]
const pathname = usePathname()
diff --git a/app/profile/enums/view.ts b/app/profile/enums/view.ts
index 26b6e304..dc2245ca 100644
--- a/app/profile/enums/view.ts
+++ b/app/profile/enums/view.ts
@@ -1,4 +1,5 @@
export enum View {
LIST = 'list',
+ TOP = 'TOP',
CARD = 'card',
}
diff --git a/app/profile/sections/items-section.tsx b/app/profile/sections/items-section.tsx
index a55d2ba4..df44ef41 100644
--- a/app/profile/sections/items-section.tsx
+++ b/app/profile/sections/items-section.tsx
@@ -1,6 +1,5 @@
import { NoDataAlert } from '../components/common'
-import { DefaultSection } from '@app/sections'
import type {
AlbumEntity,
ArtistEntity,
@@ -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<
@@ -31,7 +31,11 @@ function ItemsSection({
return (
{items.length > 0 && (
-
+
)}
{items.length === 0 && }
diff --git a/app/sections/default-section.tsx b/app/sections/default-section.tsx
index 3f4b3f6b..8a0342ed 100644
--- a/app/sections/default-section.tsx
+++ b/app/sections/default-section.tsx
@@ -19,7 +19,7 @@ function DefaultSection({
...props
}: DefaultSection.Props) {
return (
-
+
{title}
diff --git a/tailwind.config.ts b/tailwind.config.ts
index 24bbf4bf..6a3e5f1b 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -1,6 +1,6 @@
import { type Config } from 'tailwindcss'
-import plugin from 'tailwindcss/plugin'
import TailwindCSSAnimate from 'tailwindcss-animate'
+import plugin from 'tailwindcss/plugin'
export default {
darkMode: ['class'],
diff --git a/tests/snapshots/item-artists.spec.tsx.snap b/tests/snapshots/item-artists.spec.tsx.snap
index 77accd4d..de2bd607 100644
--- a/tests/snapshots/item-artists.spec.tsx.snap
+++ b/tests/snapshots/item-artists.spec.tsx.snap
@@ -5,6 +5,24 @@ exports[`ItemArtists > should match snapshot with artist entity 1`] = `
"asFragment": [Function],
"baseElement":
+ ,
+ "container":
-
+
should match snapshot as album 1`] = `
style="color: transparent; min-height: 200px; max-height: 200px; min-width: 200px; max-width: 200px; object-fit: cover;"
width="200"
/>
-