89 lines
2.3 KiB
TypeScript
89 lines
2.3 KiB
TypeScript
import { notFound } from 'next/navigation';
|
|
import { SharedContentDisplay } from '@/components/SharedContentDisplay';
|
|
import type { ResolveShareResponse } from '@/types/api-types';
|
|
import type { Metadata } from 'next';
|
|
|
|
interface PageProps {
|
|
params: Promise<{ token: string }>;
|
|
}
|
|
|
|
async function getShareData(token: string): Promise<ResolveShareResponse | null> {
|
|
try {
|
|
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000';
|
|
const res = await fetch(`${baseUrl}/api/share/${token}`, {
|
|
cache: 'no-store',
|
|
});
|
|
|
|
if (!res.ok) return null;
|
|
return res.json();
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
|
|
const { token } = await params;
|
|
const data = await getShareData(token);
|
|
|
|
if (!data) {
|
|
return { title: 'Content Not Found | Sonic Cloud' };
|
|
}
|
|
|
|
let title = '';
|
|
let description = '';
|
|
let image = '';
|
|
|
|
if (data.type === 'SONG') {
|
|
const song = data.content as any;
|
|
title = `${song.title} by ${song.artist.stage_name}`;
|
|
description = `Listen to ${song.title} on Sonic Cloud`;
|
|
image = song.coverArtUrl;
|
|
} else if (data.type === 'PLAYLIST') {
|
|
const playlist = data.content as any;
|
|
title = playlist.name;
|
|
description = `${playlist.songCount} songs curated by ${playlist.curator.name}`;
|
|
image = playlist.coverImageUrl;
|
|
} else {
|
|
const album = data.content as any;
|
|
title = `${album.title} by ${album.artist.stage_name}`;
|
|
description = album.description || `Album by ${album.artist.stage_name}`;
|
|
image = album.coverArtUrl;
|
|
}
|
|
|
|
return {
|
|
title: `${title} | Sonic Cloud`,
|
|
description,
|
|
openGraph: {
|
|
title,
|
|
description,
|
|
images: image ? [image] : [],
|
|
type: 'music.song',
|
|
},
|
|
twitter: {
|
|
card: 'summary_large_image',
|
|
title,
|
|
description,
|
|
images: image ? [image] : [],
|
|
},
|
|
};
|
|
}
|
|
|
|
export default async function SharePage({ params }: PageProps) {
|
|
const { token } = await params;
|
|
const data = await getShareData(token);
|
|
|
|
if (!data) {
|
|
notFound();
|
|
}
|
|
|
|
return (
|
|
<div className="min-h-screen bg-zinc-950 flex items-center justify-center p-6">
|
|
<SharedContentDisplay
|
|
type={data.type}
|
|
content={data.content}
|
|
token={token}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|