diff --git a/apps/cyberstorm-remix/app/p/dependants/Dependants.module.css b/apps/cyberstorm-remix/app/p/dependants/Dependants.module.css new file mode 100644 index 000000000..13efecaea --- /dev/null +++ b/apps/cyberstorm-remix/app/p/dependants/Dependants.module.css @@ -0,0 +1,50 @@ +.root { + display: flex; + flex-direction: row; + gap: var(--space--32); +} + +@media (max-width: 30rem) { + .root { + gap: var(--space--16); + } +} + +.backgroundImg { + --w: 56vw; + + position: absolute; + top: calc(-1 * (var(--header-height) + var(--content-padding-top-desktop))); + right: 0; + + z-index: -1; + width: var(--w); + height: calc(var(--w) * 0.45); + background-repeat: no-repeat; + background-position: 50%; + background-size: cover; + opacity: 0.3; + + /* stylelint-disable property-no-vendor-prefix */ + -webkit-mask-image: var(--gradients); + -webkit-mask-composite: source-in; + /* stylelint-enable property-no-vendor-prefix */ + mask-image: var(--gradients); + mask-composite: intersect; + + --gradients: + linear-gradient(90deg, transparent 0%, white 70%, transparent 100%), + linear-gradient(180deg, white 40%, transparent 95%); +} + +.header { + padding: 0.5rem 0 1.5rem; + color: var(--color-text--default); + font-weight: var(--font-weight-bold); + font-size: 1.75rem; + line-height: 120%; +} + +.header a { + color: var(--color-cyber-green--60); +} diff --git a/apps/cyberstorm-remix/app/p/dependants/Dependants.tsx b/apps/cyberstorm-remix/app/p/dependants/Dependants.tsx new file mode 100644 index 000000000..b2eb3cc1a --- /dev/null +++ b/apps/cyberstorm-remix/app/p/dependants/Dependants.tsx @@ -0,0 +1,206 @@ +import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node"; +import { useLoaderData } from "@remix-run/react"; +import { BreadCrumbs, CyberstormLink } from "@thunderstore/cyberstorm"; +import styles from "./Dependants.module.css"; +import rootStyles from "../../RootLayout.module.css"; +import { getDapper } from "cyberstorm/dapper/sessionUtils"; +import { PackageSearch } from "~/commonComponents/PackageSearch/PackageSearch"; +import { ApiError } from "@thunderstore/thunderstore-api"; + +export const meta: MetaFunction = ({ data }) => { + return [ + { title: data?.community.name }, + { name: "description", content: `Mods for ${data?.community.name}` }, + ]; +}; + +export async function loader({ request, params }: LoaderFunctionArgs) { + if (params.communityId && params.namespaceId && params.packageId) { + try { + const dapper = await getDapper(); + const searchParams = new URL(request.url).searchParams; + const order = searchParams.get("order"); + const page = searchParams.get("page"); + const search = searchParams.get("search"); + const includedCategories = searchParams.get("includedCategories"); + const excludedCategories = searchParams.get("excludedCategories"); + const section = searchParams.get("section"); + const nsfw = searchParams.get("nsfw"); + const deprecated = searchParams.get("deprecated"); + const created_recent = searchParams.get("created_recent"); + const updated_recent = searchParams.get("updated_recent"); + const created_after = searchParams.get("created_after"); + const created_before = searchParams.get("created_before"); + const updated_after = searchParams.get("updated_after"); + const updated_before = searchParams.get("updated_before"); + return { + community: await dapper.getCommunity(params.communityId), + filters: await dapper.getCommunityFilters(params.communityId), + listing: await dapper.getPackageListingDetails( + params.communityId, + params.namespaceId, + params.packageId + ), + listings: await dapper.getPackageListings( + { + kind: "package-dependants", + communityId: params.communityId, + namespaceId: params.namespaceId, + packageName: params.packageId, + }, + order ?? "", + page === null ? undefined : Number(page), + search ?? "", + includedCategories?.split(",") ?? undefined, + excludedCategories?.split(",") ?? undefined, + section ?? "", + nsfw === "true" ? true : false, + deprecated === "true" ? true : false, + created_recent ?? "", + updated_recent ?? "", + created_after ?? "", + created_before ?? "", + updated_after ?? "", + updated_before ?? "" + ), + }; + } catch (error) { + if (error instanceof ApiError) { + throw new Response("Package not found", { status: 404 }); + } else { + // REMIX TODO: Add sentry + throw error; + } + } + } + throw new Response("Package not found", { status: 404 }); +} + +export async function clientLoader({ request, params }: LoaderFunctionArgs) { + if (params.communityId && params.namespaceId && params.packageId) { + try { + const dapper = await getDapper(true); + const searchParams = new URL(request.url).searchParams; + const order = searchParams.get("order"); + const page = searchParams.get("page"); + const search = searchParams.get("search"); + const includedCategories = searchParams.get("includedCategories"); + const excludedCategories = searchParams.get("excludedCategories"); + const section = searchParams.get("section"); + const nsfw = searchParams.get("nsfw"); + const deprecated = searchParams.get("deprecated"); + const created_recent = searchParams.get("created_recent"); + const updated_recent = searchParams.get("updated_recent"); + const created_after = searchParams.get("created_after"); + const created_before = searchParams.get("created_before"); + const updated_after = searchParams.get("updated_after"); + const updated_before = searchParams.get("updated_before"); + return { + community: await dapper.getCommunity(params.communityId), + filters: await dapper.getCommunityFilters(params.communityId), + listing: await dapper.getPackageListingDetails( + params.communityId, + params.namespaceId, + params.packageId + ), + listings: await dapper.getPackageListings( + { + kind: "package-dependants", + communityId: params.communityId, + namespaceId: params.namespaceId, + packageName: params.packageId, + }, + order ?? "", + page === null ? undefined : Number(page), + search ?? "", + includedCategories?.split(",") ?? undefined, + excludedCategories?.split(",") ?? undefined, + section ?? "", + nsfw === "true" ? true : false, + deprecated === "true" ? true : false, + created_recent ?? "", + updated_recent ?? "", + created_after ?? "", + created_before ?? "", + updated_after ?? "", + updated_before ?? "" + ), + }; + } catch (error) { + if (error instanceof ApiError) { + throw new Response("Community not found", { status: 404 }); + } else { + // REMIX TODO: Add sentry + throw error; + } + } + } + throw new Response("Community not found", { status: 404 }); +} + +export default function Community() { + const { community, filters, listing, listings } = useLoaderData< + typeof loader | typeof clientLoader + >(); + + return ( + <> + {community.background_image_url ? ( +
+ ) : null} + + Communities + + {community.name} + + + {listing.namespace} + + + {listing.name} + + Dependants + +
+
+
+ Mods that depend on{" "} + + {listing.name} + + {" by "} + + {listing.namespace} + +
+
+
+
+ +
+ + ); +} diff --git a/apps/cyberstorm-remix/vite.config.ts b/apps/cyberstorm-remix/vite.config.ts index 231e1cc35..029aafd5c 100644 --- a/apps/cyberstorm-remix/vite.config.ts +++ b/apps/cyberstorm-remix/vite.config.ts @@ -36,6 +36,10 @@ export default defineConfig({ route("versions", "p/tabs/Versions/Versions.tsx"); } ); + route( + "/c/:communityId/p/:namespaceId/:packageId/dependants", + "p/dependants/Dependants.tsx" + ); }); }, }),