kemono2/client/src/pages/shares.tsx
2024-11-26 00:11:49 +01:00

108 lines
2.6 KiB
TypeScript

import { LoaderFunctionArgs, useLoaderData } from "react-router-dom";
import { createProfilesSharesPageURL } from "#lib/urls";
import { parseOffset } from "#lib/pagination";
import { fetchProfileShares } from "#api/shares";
import { PageSkeleton } from "#components/pages";
import { Paginator } from "#components/pagination";
import { CardList, ShareCard } from "#components/cards";
import { validatePaysite } from "#entities/paysites";
import { IShare } from "#entities/files";
interface IProps {
service: string;
profileID: string;
offset?: number;
count: number;
shares: IShare[];
}
export function ProfileSharesPage() {
const { service, profileID, count, offset, shares } =
useLoaderData() as IProps;
const title = "Filehaus";
const heading = "Filehaus";
return (
<PageSkeleton name="all-dms" title={title} heading={heading}>
<div id="paginator-top" className="paginator">
<Paginator
count={count}
offset={offset}
constructURL={(offset) =>
String(createProfilesSharesPageURL(service, profileID, offset))
}
/>
</div>
<CardList layout={"phone"}>
{!count ? (
<div className="no-results">
<h2 className="site-section__subheading">
Nobody here but us chickens!
</h2>
<p className="subtitle">There are no uploads.</p>
</div>
) : (
shares.map((share) => <ShareCard key={share.id} share={share} />)
)}
</CardList>
<div className="paginator" id="paginator-bottom">
<Paginator
count={count}
offset={offset}
constructURL={(offset) =>
String(createProfilesSharesPageURL(service, profileID, offset))
}
/>
</div>
</PageSkeleton>
);
}
export async function loader({
params,
request,
}: LoaderFunctionArgs): Promise<IProps> {
const searchParams = new URL(request.url).searchParams;
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.");
}
}
let offset: number | undefined = undefined;
{
const inputOffset = searchParams.get("o")?.trim();
if (inputOffset) {
offset = parseOffset(inputOffset);
}
}
const { results, props } = await fetchProfileShares(
service,
profileID,
offset
);
const { share_count } = props;
return {
service,
profileID,
shares: results,
count: share_count,
offset,
};
}