kemono2/client/src/pages/profile/dms.tsx
2025-04-11 00:54:15 +02:00

102 lines
2.9 KiB
TypeScript

import { LoaderFunctionArgs, useLoaderData } from "react-router";
import { Helmet } from "@dr.pogodin/react-helmet";
import { ICONS_PREPEND, KEMONO_SITE, SITE_NAME } from "#env/env-vars";
import { fetchProfileDMs } from "#api/dms";
import { PageSkeleton } from "#components/pages";
import { CardList, DMCard } from "#components/cards";
import { ProfileHeader, Tabs, IArtist } from "#entities/profiles";
import { paysites, validatePaysite } from "#entities/paysites";
import { IApprovedDM } from "#entities/dms";
interface IProps {
profile: IArtist;
service: string;
dmCount: number;
dms: IApprovedDM[];
}
export function ProfileDMsPage() {
const { profile, service, dmCount, dms } = useLoaderData() as IProps;
const paysite = paysites[service];
const title = `DMs of "${profile.name}" (${profile.id}) from ${paysite.title}`;
const heading = "DMs";
return (
<PageSkeleton name="user" title={title} heading={heading}>
<Helmet>
<meta name="id" content={profile.id} />
<meta name="service" content={service} />
<meta name="artist_name" content={profile.name} />
{/* <link rel="canonical" href="{{ g.canonical_url }}" /> */}
<meta property="og:title" content={title} />
<meta property="og:type" content="website" />
<meta property="og:site_name" content={SITE_NAME} />
<meta
property="og:image"
content={`${ICONS_PREPEND ?? KEMONO_SITE}}/icons/${service}/${
profile.id
}`}
/>
{/* <meta property="og:url" content="{{ g.canonical_url }}" /> */}
</Helmet>
<ProfileHeader
service={service}
profileID={profile.id}
profileName={profile.name}
/>
<div className="paginator" id="paginator-top">
<Tabs
currentPage="dms"
service={service}
artistID={profile.id}
dmCount={dmCount}
/>
</div>
<CardList layout="phone">
{dmCount === 0 ? (
<div className="no-results">
<h2 className="site-section__subheading">
Nobody here but us chickens!
</h2>
<p className="subtitle">There are no DMs for your query.</p>
</div>
) : (
dms.map((dm) => <DMCard key={dm.hash} dm={dm} />)
)}
</CardList>
</PageSkeleton>
);
}
export async function loader({ params }: LoaderFunctionArgs): Promise<IProps> {
const service = params.service?.trim();
{
if (!service) {
throw new Error("Service name is required.");
}
validatePaysite(service);
}
const profileID = params.creator_id?.trim();
{
if (!profileID) {
throw new Error("Artist ID is required.");
}
}
const { props } = await fetchProfileDMs(service, profileID);
const { artist, dm_count, dms } = props;
return {
profile: artist,
service,
dmCount: dm_count,
dms,
};
}