reset
This commit is contained in:
parent
9dd0c78850
commit
49fffc20a3
19 changed files with 2551 additions and 12482 deletions
|
@ -1,29 +0,0 @@
|
||||||
import { Link } from "@remix-run/react";
|
|
||||||
import { styled } from "styletron-react";
|
|
||||||
|
|
||||||
export const CardBase = styled("div", {
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
padding: "1rem",
|
|
||||||
backgroundColor: "#000",
|
|
||||||
border: "2px solid #fff",
|
|
||||||
borderRadius: "0.5rem",
|
|
||||||
margin: "1rem",
|
|
||||||
});
|
|
||||||
|
|
||||||
export const CardHeader = styled(Link, {
|
|
||||||
display: "flex",
|
|
||||||
flex: 1,
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
backgroundColor: "#ccc",
|
|
||||||
borderRadius: "0.5rem",
|
|
||||||
fontSize: "1.25rem",
|
|
||||||
color: "#000",
|
|
||||||
textDecoration: "none",
|
|
||||||
padding: "0.5rem",
|
|
||||||
cursor: "pointer",
|
|
||||||
":hover": {
|
|
||||||
backgroundColor: "#fff",
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,55 +0,0 @@
|
||||||
import { styled } from "styletron-react";
|
|
||||||
|
|
||||||
const BarRoot = styled("div", {
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center",
|
|
||||||
overflow: "hidden",
|
|
||||||
borderRadius: "0.5rem",
|
|
||||||
border: "1px solid #888",
|
|
||||||
});
|
|
||||||
|
|
||||||
const Bar = styled(
|
|
||||||
"div",
|
|
||||||
({
|
|
||||||
color,
|
|
||||||
size,
|
|
||||||
borders = false,
|
|
||||||
}: {
|
|
||||||
color: string;
|
|
||||||
size: number;
|
|
||||||
borders?: boolean;
|
|
||||||
}) => ({
|
|
||||||
backgroundColor: color,
|
|
||||||
flex: size,
|
|
||||||
padding: "0 0.35rem",
|
|
||||||
textAlign: "center",
|
|
||||||
textShadow: "0 0 0.25rem #000",
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
export const FactionBar = ({
|
|
||||||
nc,
|
|
||||||
tr,
|
|
||||||
vs,
|
|
||||||
showNumbers = true,
|
|
||||||
}: {
|
|
||||||
showNumbers?: boolean;
|
|
||||||
nc: number;
|
|
||||||
tr: number;
|
|
||||||
vs: number;
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<BarRoot>
|
|
||||||
<Bar size={nc} color="#22f" title="New Conglomerate">
|
|
||||||
{nc.toLocaleString()}
|
|
||||||
</Bar>
|
|
||||||
<Bar size={tr} color="#f11" title="Terran Republic">
|
|
||||||
{tr.toLocaleString()}
|
|
||||||
</Bar>
|
|
||||||
<Bar size={vs} color="#a0d" title="Vanu Sovreignty">
|
|
||||||
{vs.toLocaleString()}
|
|
||||||
</Bar>
|
|
||||||
</BarRoot>
|
|
||||||
);
|
|
||||||
};
|
|
|
@ -1,22 +0,0 @@
|
||||||
import { HiChevronRight } from "react-icons/hi2";
|
|
||||||
import { World } from "~/utils/saerro";
|
|
||||||
import { CardBase, CardHeader } from "./Card";
|
|
||||||
import { FactionBar } from "./FactionBar";
|
|
||||||
|
|
||||||
export const WorldCard = ({ world }: { world: World }) => {
|
|
||||||
return (
|
|
||||||
<CardBase>
|
|
||||||
<CardHeader to={`/worlds/${world.id}`}>
|
|
||||||
<div>{world.name}</div>
|
|
||||||
<HiChevronRight />
|
|
||||||
</CardHeader>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div>Population: {world.population.total.toLocaleString()}</div>
|
|
||||||
<div>
|
|
||||||
<FactionBar {...world.population} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardBase>
|
|
||||||
);
|
|
||||||
};
|
|
|
@ -1,22 +1,18 @@
|
||||||
|
/**
|
||||||
|
* By default, Remix will handle hydrating your app on the client for you.
|
||||||
|
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
|
||||||
|
* For more information, see https://remix.run/file-conventions/entry.client
|
||||||
|
*/
|
||||||
|
|
||||||
import { RemixBrowser } from "@remix-run/react";
|
import { RemixBrowser } from "@remix-run/react";
|
||||||
import { startTransition, StrictMode } from "react";
|
import { startTransition, StrictMode } from "react";
|
||||||
import { hydrateRoot } from "react-dom/client";
|
import { hydrateRoot } from "react-dom/client";
|
||||||
|
|
||||||
function hydrate() {
|
startTransition(() => {
|
||||||
startTransition(() => {
|
hydrateRoot(
|
||||||
hydrateRoot(
|
document,
|
||||||
document,
|
<StrictMode>
|
||||||
<StrictMode>
|
<RemixBrowser />
|
||||||
<RemixBrowser />
|
</StrictMode>
|
||||||
</StrictMode>
|
);
|
||||||
);
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof requestIdleCallback === "function") {
|
|
||||||
requestIdleCallback(hydrate);
|
|
||||||
} else {
|
|
||||||
// Safari doesn't support requestIdleCallback
|
|
||||||
// https://caniuse.com/requestidlecallback
|
|
||||||
setTimeout(hydrate, 1);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,26 +1,38 @@
|
||||||
import type { EntryContext } from "@remix-run/node";
|
/**
|
||||||
import { renderToString } from "react-dom/server";
|
* By default, Remix will handle generating the HTTP Response for you.
|
||||||
|
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
|
||||||
|
* For more information, see https://remix.run/file-conventions/entry.server
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { EntryContext } from "@remix-run/cloudflare";
|
||||||
import { RemixServer } from "@remix-run/react";
|
import { RemixServer } from "@remix-run/react";
|
||||||
|
import isbot from "isbot";
|
||||||
|
import { renderToReadableStream } from "react-dom/server";
|
||||||
|
|
||||||
import { collectStyles } from "./styletron";
|
export default async function handleRequest(
|
||||||
|
|
||||||
export default function handleRequest(
|
|
||||||
request: Request,
|
request: Request,
|
||||||
responseStatusCode: number,
|
responseStatusCode: number,
|
||||||
responseHeaders: Headers,
|
responseHeaders: Headers,
|
||||||
remixContext: EntryContext
|
remixContext: EntryContext
|
||||||
) {
|
) {
|
||||||
let markup = renderToString(
|
const body = await renderToReadableStream(
|
||||||
<RemixServer context={remixContext} url={request.url} />
|
<RemixServer context={remixContext} url={request.url} />,
|
||||||
|
{
|
||||||
|
signal: request.signal,
|
||||||
|
onError(error: unknown) {
|
||||||
|
console.error(error);
|
||||||
|
responseStatusCode = 500;
|
||||||
|
},
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Add server-rendered styles
|
if (isbot(request.headers.get("user-agent"))) {
|
||||||
markup = markup.replace("__STYLES__", collectStyles());
|
await body.allReady;
|
||||||
|
}
|
||||||
|
|
||||||
responseHeaders.set("Content-Type", "text/html");
|
responseHeaders.set("Content-Type", "text/html");
|
||||||
|
return new Response(body, {
|
||||||
return new Response("<!DOCTYPE html>" + markup, {
|
|
||||||
status: responseStatusCode,
|
|
||||||
headers: responseHeaders,
|
headers: responseHeaders,
|
||||||
|
status: responseStatusCode,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
import { styled } from "styletron-react";
|
|
||||||
|
|
||||||
export const Body = styled("body", {
|
|
||||||
backgroundImage:
|
|
||||||
"radial-gradient(ellipse at bottom right, #1b2735 0%,#090a0f 100%)",
|
|
||||||
backgroundSize: "cover",
|
|
||||||
backgroundAttachment: "fixed",
|
|
||||||
color: "#fff",
|
|
||||||
lineHeight: 1.6,
|
|
||||||
fontFamily: "'IBM Plex Mono', monospace",
|
|
||||||
});
|
|
35
app/root.tsx
35
app/root.tsx
|
@ -1,5 +1,5 @@
|
||||||
import type { LinksFunction, MetaFunction } from "@remix-run/node";
|
import type { LinksFunction } from "@remix-run/cloudflare";
|
||||||
import { Provider as StyletronProvider } from "styletron-react";
|
import { cssBundleHref } from "@remix-run/css-bundle";
|
||||||
import {
|
import {
|
||||||
Links,
|
Links,
|
||||||
LiveReload,
|
LiveReload,
|
||||||
|
@ -9,38 +9,25 @@ import {
|
||||||
ScrollRestoration,
|
ScrollRestoration,
|
||||||
} from "@remix-run/react";
|
} from "@remix-run/react";
|
||||||
|
|
||||||
import { styletron } from "./styletron";
|
|
||||||
import { Body } from "./globalStyles";
|
|
||||||
|
|
||||||
export const meta: MetaFunction = () => ({
|
|
||||||
charset: "utf-8",
|
|
||||||
title: "New Remix App",
|
|
||||||
viewport: "width=device-width,initial-scale=1",
|
|
||||||
});
|
|
||||||
|
|
||||||
export const links: LinksFunction = () => [
|
export const links: LinksFunction = () => [
|
||||||
{
|
...(cssBundleHref ? [{ rel: "stylesheet", href: cssBundleHref }] : []),
|
||||||
rel: "stylesheet",
|
|
||||||
href: "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@300;400;700&display=swap",
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
<meta charSet="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
<Meta />
|
<Meta />
|
||||||
<Links />
|
<Links />
|
||||||
{typeof document === "undefined" ? "__STYLES__" : null}
|
|
||||||
</head>
|
</head>
|
||||||
<StyletronProvider value={styletron}>
|
<body>
|
||||||
<Body>
|
<Outlet />
|
||||||
<Outlet />
|
<ScrollRestoration />
|
||||||
<ScrollRestoration />
|
<Scripts />
|
||||||
<Scripts />
|
<LiveReload />
|
||||||
<LiveReload />
|
</body>
|
||||||
</Body>
|
|
||||||
</StyletronProvider>
|
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
38
app/routes/_index.tsx
Normal file
38
app/routes/_index.tsx
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import type { V2_MetaFunction } from "@remix-run/cloudflare";
|
||||||
|
|
||||||
|
export const meta: V2_MetaFunction = () => {
|
||||||
|
return [{ title: "New Remix App" }];
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Index() {
|
||||||
|
return (
|
||||||
|
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}>
|
||||||
|
<h1>Welcome to Remix</h1>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
href="https://remix.run/tutorials/blog"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
15m Quickstart Blog Tutorial
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
href="https://remix.run/tutorials/jokes"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
Deep Dive Jokes App Tutorial
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a target="_blank" href="https://remix.run/docs" rel="noreferrer">
|
||||||
|
Remix Docs
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,112 +0,0 @@
|
||||||
import { CardBase, CardHeader } from "~/components/Card";
|
|
||||||
import { HiChevronRight } from "react-icons/hi2";
|
|
||||||
import type { IndexResponse, World } from "~/utils/saerro";
|
|
||||||
import { indexQuery } from "~/utils/saerro";
|
|
||||||
import { useLoaderData } from "@remix-run/react";
|
|
||||||
import { json } from "@remix-run/cloudflare";
|
|
||||||
import { FactionBar } from "~/components/FactionBar";
|
|
||||||
import { WorldCard } from "~/components/IndexWorldCard";
|
|
||||||
import { styled } from "styletron-react";
|
|
||||||
import React, { ReactNode } from "react";
|
|
||||||
|
|
||||||
export const loader = async () => {
|
|
||||||
return json(await indexQuery());
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function Index() {
|
|
||||||
const { allWorlds } = useLoaderData<typeof loader>();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Header />
|
|
||||||
<div>
|
|
||||||
{allWorlds.map((world) => (
|
|
||||||
<WorldCard world={world} key={world.id} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const HeaderBase = styled("div", {
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "row",
|
|
||||||
borderColor: "#fff",
|
|
||||||
backgroundColor: "#fff",
|
|
||||||
color: "#fff",
|
|
||||||
borderLeftWidth: "0.5rem",
|
|
||||||
borderTopWidth: "0.5rem",
|
|
||||||
borderRightWidth: "0",
|
|
||||||
borderBottomWidth: "0.5rem",
|
|
||||||
borderStyle: "solid",
|
|
||||||
borderTopLeftRadius: "0.5rem",
|
|
||||||
position: "relative",
|
|
||||||
});
|
|
||||||
|
|
||||||
const Header = () => (
|
|
||||||
<HeaderBase>
|
|
||||||
<QuoteUnquoteLogo>
|
|
||||||
<b>PS2.LIVE</b>
|
|
||||||
<br />
|
|
||||||
Realtime tools for PlanetSide 2
|
|
||||||
</QuoteUnquoteLogo>
|
|
||||||
<TheList>
|
|
||||||
<ListLink href="https://saerro.ps2.live" color="gold">
|
|
||||||
Saerro Live Pop API
|
|
||||||
</ListLink>
|
|
||||||
<ListLink href="https://try.ps2.live" color="#3333ff">
|
|
||||||
Census API Playground
|
|
||||||
</ListLink>
|
|
||||||
<ListLink href="https://agg.ps2.live/population" color="limegreen">
|
|
||||||
Population API
|
|
||||||
</ListLink>
|
|
||||||
<ListLink href="https://agg.ps2.live/continents" color="#44aadd">
|
|
||||||
Continents API
|
|
||||||
</ListLink>
|
|
||||||
<ListLink href="https://discord.ps2.live" color="#aa77dd">
|
|
||||||
Discord Character Link
|
|
||||||
</ListLink>
|
|
||||||
<ListLink href="https://metagame.ps2.live" color="#ff3333">
|
|
||||||
Metagame Webhooks
|
|
||||||
</ListLink>
|
|
||||||
</TheList>
|
|
||||||
</HeaderBase>
|
|
||||||
);
|
|
||||||
|
|
||||||
const QuoteUnquoteLogo = styled("div", {
|
|
||||||
width: "8rem",
|
|
||||||
backgroundColor: "#fff",
|
|
||||||
color: "#000",
|
|
||||||
textAlign: "right",
|
|
||||||
padding: "0.5rem",
|
|
||||||
borderRight: "0.5rem solid #fff",
|
|
||||||
});
|
|
||||||
|
|
||||||
const TheList = styled("div", {
|
|
||||||
backgroundColor: "#000",
|
|
||||||
borderRadius: "0.5rem",
|
|
||||||
position: "relative",
|
|
||||||
left: "-0.5rem",
|
|
||||||
display: "flex",
|
|
||||||
flexWrap: "wrap",
|
|
||||||
padding: "0.5rem",
|
|
||||||
gap: "0.5rem",
|
|
||||||
flexDirection: "column",
|
|
||||||
maxHeight: "8rem",
|
|
||||||
alignContent: "flex-start",
|
|
||||||
justifyContent: "center",
|
|
||||||
flex: 1,
|
|
||||||
});
|
|
||||||
|
|
||||||
const ListLink = styled("a", ({ color }: { color: string }) => ({
|
|
||||||
display: "block",
|
|
||||||
padding: "0.5rem",
|
|
||||||
color,
|
|
||||||
textDecoration: "none",
|
|
||||||
borderRadius: "0.4rem",
|
|
||||||
transition: "all 0.2s ease-in-out",
|
|
||||||
":hover": {
|
|
||||||
backgroundColor: color,
|
|
||||||
color: "#000",
|
|
||||||
},
|
|
||||||
}));
|
|
71
app/routes/worlds.$id.tsx
Normal file
71
app/routes/worlds.$id.tsx
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
import type { LoaderArgs } from "@remix-run/cloudflare";
|
||||||
|
import { json } from "@remix-run/cloudflare";
|
||||||
|
import { useLoaderData } from "@remix-run/react";
|
||||||
|
import {
|
||||||
|
WorldResponse,
|
||||||
|
Zone,
|
||||||
|
allClasses,
|
||||||
|
allVehicles,
|
||||||
|
worldQuery,
|
||||||
|
} from "~/utils/saerro";
|
||||||
|
import { pascalCaseToTitleCase, toTitleCase } from "~/utils/strings";
|
||||||
|
|
||||||
|
export const loader = async ({ params }: LoaderArgs) => {
|
||||||
|
return json(await worldQuery(params.id as string));
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Index() {
|
||||||
|
const { world } = useLoaderData<WorldResponse>();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.6" }}>
|
||||||
|
<h1>{world.name}</h1>
|
||||||
|
<h2>Total Population</h2>
|
||||||
|
<p>
|
||||||
|
{world.population.total} players ({world.population.vs} VS,{" "}
|
||||||
|
{world.population.nc} NC, {world.population.tr} TR)
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<h2>Continents</h2>
|
||||||
|
{world.zones.all.map((zone) => (
|
||||||
|
<ZoneInfo zone={zone} key={zone.id} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ZoneInfo = ({ zone }: { zone: Zone }) => {
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
<h3>{zone.name}</h3>
|
||||||
|
<p>
|
||||||
|
{zone.population.total} players ({zone.population.vs} VS,{" "}
|
||||||
|
{zone.population.nc} NC, {zone.population.tr} TR)
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<ul>
|
||||||
|
{allClasses.map((cls, idx) => (
|
||||||
|
<li key={idx}>
|
||||||
|
<b>{pascalCaseToTitleCase(cls)}</b>: {zone.classes?.[cls].total}{" "}
|
||||||
|
total, {zone.classes?.[cls].vs} VS, {zone.classes?.[cls].nc} NC,{" "}
|
||||||
|
{zone.classes?.[cls].tr} TR
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{zone.vehicles?.total} vehicles...
|
||||||
|
<ul>
|
||||||
|
{allVehicles.map((vehicle, idx) => (
|
||||||
|
<li key={idx}>
|
||||||
|
<b>{toTitleCase(vehicle)}</b>: {zone.vehicles?.[vehicle].total}{" "}
|
||||||
|
total, {zone.vehicles?.[vehicle].vs} VS,{" "}
|
||||||
|
{zone.vehicles?.[vehicle].nc} NC, {zone.vehicles?.[vehicle].tr} TR
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1,33 +0,0 @@
|
||||||
import { Client, Server } from "styletron-engine-atomic"; // or "styletron-engine-monolithic"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Styletron engine to use on the current runtime.
|
|
||||||
*/
|
|
||||||
export const styletron =
|
|
||||||
typeof document === "undefined"
|
|
||||||
? new Server()
|
|
||||||
: new Client({
|
|
||||||
hydrate: getHydrateClass(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export function isStyletronClient(engine: typeof styletron): engine is Client {
|
|
||||||
return styletron instanceof Client;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isStyletronServer(engine: typeof styletron): engine is Server {
|
|
||||||
return styletron instanceof Server;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function collectStyles(): string {
|
|
||||||
if (!isStyletronServer(styletron)) {
|
|
||||||
throw new Error("Can only collect styles during server-side rendering.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return styletron.getStylesheetsHtml();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getHydrateClass(): HTMLCollectionOf<HTMLStyleElement> {
|
|
||||||
return document.getElementsByClassName(
|
|
||||||
"_styletron_hydrate_"
|
|
||||||
) as HTMLCollectionOf<HTMLStyleElement>;
|
|
||||||
}
|
|
|
@ -21,6 +21,10 @@ export type Zone = {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
population: Population;
|
population: Population;
|
||||||
|
vehicles?: Record<(typeof allVehicles)[number], Population> & {
|
||||||
|
total: number;
|
||||||
|
};
|
||||||
|
classes?: Record<(typeof allClasses)[number], Population>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type World = {
|
export type World = {
|
||||||
|
@ -88,3 +92,79 @@ export const indexQuery = async (): Promise<IndexResponse> => {
|
||||||
|
|
||||||
return indexData;
|
return indexData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type WorldResponse = {
|
||||||
|
world: World;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const allVehicles = [
|
||||||
|
"flash",
|
||||||
|
"sunderer",
|
||||||
|
"lightning",
|
||||||
|
"scythe",
|
||||||
|
"vanguard",
|
||||||
|
"prowler",
|
||||||
|
"reaver",
|
||||||
|
"mosquito",
|
||||||
|
"galaxy",
|
||||||
|
"valkyrie",
|
||||||
|
"liberator",
|
||||||
|
"ant",
|
||||||
|
"harasser",
|
||||||
|
"dervish",
|
||||||
|
"chimera",
|
||||||
|
"javelin",
|
||||||
|
"corsair",
|
||||||
|
"magrider",
|
||||||
|
];
|
||||||
|
|
||||||
|
export const allClasses = [
|
||||||
|
"infiltrator",
|
||||||
|
"lightAssault",
|
||||||
|
"combatMedic",
|
||||||
|
"engineer",
|
||||||
|
"heavyAssault",
|
||||||
|
"max",
|
||||||
|
];
|
||||||
|
|
||||||
|
export const worldQuery = async (worldID: string): Promise<WorldResponse> => {
|
||||||
|
const query = `query {
|
||||||
|
world(by: {id: ${Number(worldID)}}) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
population {
|
||||||
|
total
|
||||||
|
nc
|
||||||
|
tr
|
||||||
|
vs
|
||||||
|
}
|
||||||
|
zones {
|
||||||
|
all {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
classes {
|
||||||
|
${allClasses.map((cls) => `${cls} { total nc tr vs }`).join(" ")}
|
||||||
|
}
|
||||||
|
vehicles {
|
||||||
|
total
|
||||||
|
${allVehicles
|
||||||
|
.map((vehicle) => `${vehicle} { total nc tr vs }`)
|
||||||
|
.join(" ")}
|
||||||
|
}
|
||||||
|
population {
|
||||||
|
total
|
||||||
|
nc
|
||||||
|
tr
|
||||||
|
vs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
|
||||||
|
console.log(query);
|
||||||
|
|
||||||
|
const worldData: WorldResponse = await saerroFetch(query);
|
||||||
|
|
||||||
|
return worldData;
|
||||||
|
};
|
||||||
|
|
9
app/utils/strings.ts
Normal file
9
app/utils/strings.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
export const toTitleCase = (str: string) => {
|
||||||
|
return str.replace(/\w\S*/g, (txt) => {
|
||||||
|
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const pascalCaseToTitleCase = (str: string) => {
|
||||||
|
return toTitleCase(str.replace(/([A-Z])/g, " $1"));
|
||||||
|
};
|
14405
package-lock.json
generated
14405
package-lock.json
generated
File diff suppressed because it is too large
Load diff
36
package.json
36
package.json
|
@ -5,36 +5,34 @@
|
||||||
"build": "remix build",
|
"build": "remix build",
|
||||||
"dev:remix": "remix watch",
|
"dev:remix": "remix watch",
|
||||||
"dev:wrangler": "cross-env NODE_ENV=development npm run wrangler",
|
"dev:wrangler": "cross-env NODE_ENV=development npm run wrangler",
|
||||||
"dev": "remix build && run-p \"dev:*\"",
|
"dev": "npm-run-all build --parallel \"dev:*\"",
|
||||||
"start": "cross-env NODE_ENV=production npm run wrangler",
|
"start": "cross-env NODE_ENV=production npm run wrangler",
|
||||||
"typecheck": "tsc",
|
"typecheck": "tsc",
|
||||||
"wrangler": "wrangler pages dev ./public"
|
"wrangler": "wrangler pages dev ./public",
|
||||||
|
"pages:deploy": "npm run build && wrangler pages publish ./public"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@remix-run/cloudflare": "^1.12.0",
|
"@remix-run/cloudflare": "^1.16.0",
|
||||||
"@remix-run/cloudflare-pages": "^1.12.0",
|
"@remix-run/cloudflare-pages": "^1.16.0",
|
||||||
"@remix-run/react": "^1.12.0",
|
"@remix-run/css-bundle": "^1.16.0",
|
||||||
|
"@remix-run/react": "^1.16.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
|
"isbot": "^3.6.8",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@cloudflare/workers-types": "^3.18.0",
|
"@cloudflare/workers-types": "^3.19.0",
|
||||||
"@remix-run/dev": "^1.12.0",
|
"@remix-run/dev": "^1.16.0",
|
||||||
"@remix-run/eslint-config": "^1.12.0",
|
"@remix-run/eslint-config": "^1.16.0",
|
||||||
"@remix-run/node": "^1.12.0",
|
"@types/react": "^18.0.35",
|
||||||
"@types/react": "^18.0.25",
|
"@types/react-dom": "^18.0.11",
|
||||||
"@types/react-dom": "^18.0.8",
|
"eslint": "^8.38.0",
|
||||||
"eslint": "^8.27.0",
|
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"prettier": "^2.8.3",
|
"typescript": "^5.0.4",
|
||||||
"react-icons": "^4.7.1",
|
"wrangler": "^2.15.1"
|
||||||
"styletron-engine-atomic": "^1.5.0",
|
|
||||||
"styletron-react": "^6.1.0",
|
|
||||||
"typescript": "^4.8.4",
|
|
||||||
"wrangler": "^2.2.1"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.13"
|
"node": ">=16.13"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,2 +1,2 @@
|
||||||
/build/*
|
/build/*
|
||||||
Cache-Control: public, max-age=31536000, s-maxage=31536000
|
Cache-Control: public, max-age=31536000, immutable
|
||||||
|
|
|
@ -1,11 +1,22 @@
|
||||||
/** @type {import('@remix-run/dev').AppConfig} */
|
/** @type {import('@remix-run/dev').AppConfig} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
serverBuildTarget: "cloudflare-pages",
|
|
||||||
server: "./server.js",
|
|
||||||
devServerBroadcastDelay: 1000,
|
devServerBroadcastDelay: 1000,
|
||||||
ignoredRouteFiles: ["**/.*"],
|
ignoredRouteFiles: ["**/.*"],
|
||||||
|
server: "./server.ts",
|
||||||
|
serverBuildPath: "functions/[[path]].js",
|
||||||
|
serverConditions: ["worker"],
|
||||||
|
serverDependenciesToBundle: "all",
|
||||||
|
serverMainFields: ["browser", "module", "main"],
|
||||||
|
serverMinify: true,
|
||||||
|
serverModuleFormat: "esm",
|
||||||
|
serverPlatform: "neutral",
|
||||||
// appDirectory: "app",
|
// appDirectory: "app",
|
||||||
// assetsBuildDirectory: "public/build",
|
// assetsBuildDirectory: "public/build",
|
||||||
// serverBuildPath: "functions/[[path]].js",
|
|
||||||
// publicPath: "/build/",
|
// publicPath: "/build/",
|
||||||
|
future: {
|
||||||
|
v2_errorBoundary: true,
|
||||||
|
v2_meta: true,
|
||||||
|
v2_normalizeFormMethod: true,
|
||||||
|
v2_routeConvention: true,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
import { createPagesFunctionHandler } from "@remix-run/cloudflare-pages";
|
import { createPagesFunctionHandler } from "@remix-run/cloudflare-pages";
|
||||||
import * as build from "@remix-run/dev/server-build";
|
import * as build from "@remix-run/dev/server-build";
|
||||||
|
|
||||||
const handleRequest = createPagesFunctionHandler({
|
export const onRequest = createPagesFunctionHandler({
|
||||||
build,
|
build,
|
||||||
mode: process.env.NODE_ENV,
|
|
||||||
getLoadContext: (context) => context.env,
|
getLoadContext: (context) => context.env,
|
||||||
|
mode: process.env.NODE_ENV,
|
||||||
});
|
});
|
||||||
|
|
||||||
export function onRequest(context) {
|
|
||||||
return handleRequest(context);
|
|
||||||
}
|
|
2
wrangler.toml
Normal file
2
wrangler.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
compatibility_date = "2022-04-05"
|
||||||
|
compatibility_flags = ["streams_enable_constructors"]
|
Loading…
Add table
Reference in a new issue