Skip to content

Commit

Permalink
Add ability to change representing crew
Browse files Browse the repository at this point in the history
  • Loading branch information
NotNite committed Nov 28, 2023
1 parent 5ea696b commit 9f197c3
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 15 deletions.
38 changes: 38 additions & 0 deletions src/api/crew.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,3 +272,41 @@ export async function nukeItFromOrbit(
if (!req.ok) return req;
return { ok: true, value: null };
}

export async function getRepresentingCrew(): Promise<string | null> {
const token = useAuthStore.getState().key;
if (token == null) return null;

const req = await tryFetch(
`${import.meta.env.VITE_SLOP_CREW_SERVER}api/crew/represent`,
{
headers: {
Authorization: token
}
}
);

console.log(req);
if (!req.ok) return null;
if (req.value.status === 204) return null;
return await req.value.text();
}

export async function setRepresentingCrew(
crew: string | null
): Promise<boolean> {
const token = useAuthStore.getState().key;
if (token == null) return false;

let url = `${import.meta.env.VITE_SLOP_CREW_SERVER}api/crew/represent`;
if (crew != null) url += `?id=${crew}`;

const req = await tryFetch(url, {
method: "POST",
headers: {
Authorization: token
}
});

return req.ok;
}
4 changes: 3 additions & 1 deletion src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import CrewSettings from "./routes/crews/CrewSettings.tsx";
import {
crewsLoader,
crewLoader,
crewSettingsLoader
crewSettingsLoader,
settingsLoader
} from "./routes/loaders.ts";

const router = createBrowserRouter([
Expand All @@ -45,6 +46,7 @@ const router = createBrowserRouter([
},
{
path: "settings",
loader: settingsLoader,
element: <Settings />
},

Expand Down
87 changes: 76 additions & 11 deletions src/routes/Settings.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
import { useAuthStore } from "../stores";
import { useNavigate } from "react-router-dom";
import HiddenCode from "../components/HiddenCode";
import { settingsLoader } from "./loaders";
import { Await, useLoaderData } from "react-router-typesafe";
import { SimpleCrewResponse } from "../api/types";
import React from "react";
import { setRepresentingCrew } from "../api/crew";

export default function Settings() {
const key = useAuthStore((state) => state.key);

const navigate = useNavigate();
if (key == null) {
navigate("/link");
return <></>;
}

function CrewInner({
authKey,
crews,
representingCrew
}: {
authKey: string;
crews: SimpleCrewResponse[];
representingCrew: string | null;
}) {
return (
<>
<h1>Settings</h1>

<section>
<section className="smolPadding">
<h2>Authentication key</h2>

<p>
Expand All @@ -24,8 +29,68 @@ export default function Settings() {
will never ask for your auth token.
</p>

<HiddenCode code={key} />
<HiddenCode code={authKey} />
</section>

<section className="smolPadding">
<h2>Representing crew</h2>

<p>
Pick a crew to represent in game. Their tag will appear above your
nameplate.
</p>

<select
defaultValue={representingCrew ?? ""}
onChange={async (e) => {
console.log(e.target.value);
let crewId: string | null = e.target.value;
if (crewId == "") crewId = null;
await setRepresentingCrew(crewId);
}}
>
<option value="">Run solo</option>

{crews.map((crew) => (
<option key={crew.id} value={crew.id}>
{crew.name}
</option>
))}
</select>
</section>
</>
);
}

export default function Settings() {
const key = useAuthStore((state) => state.key);
const navigate = useNavigate();
const data = useLoaderData<typeof settingsLoader>();
const dataPromise = Promise.all([data.crews, data.representingCrew]);

if (key == null) {
navigate("/link");
return <></>;
}

return (
<React.Suspense
fallback={<span aria-busy="true">Loading your settings...</span>}
>
<Await
resolve={dataPromise}
errorElement={<span>Failed to load settings.</span>}
>
{([crews, representingCrew]) => {
return (
<CrewInner
authKey={key}
crews={crews}
representingCrew={representingCrew}
/>
);
}}
</Await>
</React.Suspense>
);
}
23 changes: 20 additions & 3 deletions src/routes/loaders.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { defer } from "react-router-typesafe";
import { getCrew, getCrews, getInvites } from "../api/crew";
import {
getCrew,
getCrews,
getInvites,
getRepresentingCrew
} from "../api/crew";
import { CrewResponse, SimpleCrewResponse } from "../api/types";
import { Params } from "react-router-dom";

Expand All @@ -25,16 +30,28 @@ export async function crewLoader({ params }: { params: Params<"id"> }) {
});
}

export type CrewSettingsData = {
export type CrewSettingsLoaderData = {
crew: Promise<CrewResponse | null>;
invites: Promise<string[]>;
};

export async function crewSettingsLoader({ params }: { params: Params<"id"> }) {
if (params.id == null) throw new Response("Not Found", { status: 404 });

return defer<CrewSettingsData>({
return defer<CrewSettingsLoaderData>({
crew: getCrew(params.id),
invites: getInvites(params.id)
});
}

export type SettingsLoaderData = {
crews: Promise<SimpleCrewResponse[]>;
representingCrew: Promise<string | null>;
};

export async function settingsLoader() {
return defer<SettingsLoaderData>({
crews: getCrews().then((res) => res ?? []),
representingCrew: getRepresentingCrew()
});
}

0 comments on commit 9f197c3

Please sign in to comment.