108 lines
2.6 KiB
TypeScript
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,
|
|
};
|
|
}
|