37 lines
1.8 KiB
TypeScript
37 lines
1.8 KiB
TypeScript
import Image from "next/image";
|
|
import Link from "next/link";
|
|
import type { Locale } from "@/lib/i18n";
|
|
import { getMelodyPath } from "@/lib/melody-content";
|
|
import AudioPlayer from "@/components/public/audio-player";
|
|
|
|
type MelodyCardProps = {
|
|
locale: Locale;
|
|
melody: {
|
|
slug: string;
|
|
id: string;
|
|
titleAr: string;
|
|
titleEn: string;
|
|
descAr: string | null;
|
|
descEn: string | null;
|
|
audioFile: string;
|
|
coverImage: string | null;
|
|
isDownloadable: boolean;
|
|
category: { nameAr: string; nameEn: string };
|
|
};
|
|
};
|
|
|
|
export default function MelodyCard({ locale, melody }: MelodyCardProps) {
|
|
const title = locale === "ar" ? melody.titleAr : melody.titleEn;
|
|
const description = locale === "ar" ? melody.descAr : melody.descEn;
|
|
const category = locale === "ar" ? melody.category.nameAr : melody.category.nameEn;
|
|
return (
|
|
<article className="overflow-hidden rounded-2xl border border-border bg-card shadow-sm">
|
|
{melody.coverImage ? <Link href={getMelodyPath(locale, melody.slug)} className="relative block aspect-[16/9] bg-muted"><Image src={melody.coverImage} alt={title} fill unoptimized sizes="(max-width: 768px) 100vw, 50vw" className="object-cover" /></Link> : null}
|
|
<div className="space-y-4 p-5">
|
|
<div><p className="text-xs font-semibold uppercase tracking-[0.16em] text-brand-2">{category}</p><h2 className="mt-2 text-xl font-semibold"><Link href={getMelodyPath(locale, melody.slug)} className="hover:underline">{title}</Link></h2>{description ? <p className="mt-2 line-clamp-2 text-sm leading-6 text-muted-foreground">{description}</p> : null}</div>
|
|
<AudioPlayer src={melody.audioFile} title={title} locale={locale} downloadable={melody.isDownloadable} analytics={{ entityId: melody.id }} />
|
|
</div>
|
|
</article>
|
|
);
|
|
}
|