Support getMe and getParty Requests

This commit is contained in:
Dominic Zimmer 2022-10-10 20:13:00 +02:00
parent 25723bb24b
commit 9103f30a6a
10 changed files with 178 additions and 16690 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
.vscode
# dependencies
/node_modules

16691
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +0,0 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});

View File

@ -1,26 +0,0 @@
import React from 'react';
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;

63
src/PartyContext.tsx Normal file
View File

@ -0,0 +1,63 @@
import React, { createContext, useEffect, useMemo, useState } from 'react';
import { getPartyStatusRequest, getSelfStatusRequest, parseURI } from './partyApi';
import './PartyPage.css';
export const PartyContext = createContext<PartyContextType>({
party: { definitely_coming: 0, maybe_coming: 0 },
self: { token: "", name: "", coming: "yes", grammatical_gender: "m" }
});
export type PartyContextType = {
party: PartyStatus,
self: SelfStatus,
}
export type PartyStatus = {
"definitely_coming": number,
"maybe_coming": number,
}
export type SelfStatus = {
token: string,
name: string,
coming: "yes" | "no" | "maybe",
"grammatical_gender": "m" | "f" | "d",
extra?: SelfStatusExtraData,
}
export type APIEndPoint = { partyName: string, token: string };
// Adapt this type to your desires
export type SelfStatusExtraData = {
};
export const PartyContextProvider: React.FC<{ children: React.ReactNode }> = (props) => {
const [partyContext, setPartyContext] = useState<PartyContextType>();
const apiEndpoint = useMemo<APIEndPoint>(() => {
// eslint-disable-next-line no-restricted-globals
const href = location.href;
const p = parseURI(href);
if (!p) return { partyName: "error", token: "" }
return p;
}, []);
const loadData = async () => {
if (partyContext !== undefined) return;
const selfStatus = await getSelfStatusRequest(apiEndpoint);
const partyStatus = await getPartyStatusRequest(apiEndpoint);
const ctx = { party: partyStatus, self: selfStatus };
setPartyContext(ctx);
};
useEffect(() => {
loadData();
}, [apiEndpoint]);
return partyContext ?
<PartyContext.Provider value={partyContext}>
{props.children}
</PartyContext.Provider>
: <div className="loading" />;
};

View File

@ -1,3 +1,9 @@
.loading {
height: 100vh;
width: 100vw;
background-color: black;
}
.App {
text-align: center;
}

27
src/PartyPage.tsx Normal file
View File

@ -0,0 +1,27 @@
import React, { useContext } from 'react';
import logo from './logo.svg';
import './PartyPage.css';
import { PartyContext } from './PartyContext';
export const PartyPage: React.FC = () => {
const partyContext = useContext(PartyContext);
return <div className="App" >
<header className="App-header" >
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code> src/PartyPage.tsx </code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
<span>Hello {partyContext.self.name}</span>
</header>
</div>
};

View File

@ -10,4 +10,4 @@ body {
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
}

View File

@ -1,19 +1,16 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { PartyContextProvider } from './PartyContext';
import { PartyPage } from './PartyPage';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
<App />
<PartyContextProvider>
<PartyPage />
</PartyContextProvider>
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
);

28
src/partyApi.ts Normal file
View File

@ -0,0 +1,28 @@
import { APIEndPoint, PartyStatus, SelfStatus } from "./PartyContext";
export const parseURI = (uri: string): APIEndPoint | undefined => {
const x = uri.match(/https?:\/\/(?<partyName>.+)\.party\.leafbla\.de\/(?<token>.+)/);
if (x === null || x.groups === undefined) return;
const partyName = x.groups["partyName"];
const token = x.groups["token"];
if (!partyName || !token) return;
return { partyName, token };
};
const apiUrl = (apiEndPoint : APIEndPoint): string => {
return `https://party.leafbla.de/api/${apiEndPoint.partyName}/${apiEndPoint.token}`;
};
export const getSelfStatusRequest = async (apiEndpoint: APIEndPoint): Promise<SelfStatus> => {
const result = await fetch(`${apiUrl(apiEndpoint)}/me`);
if (!result.ok) throw new Error("Error sending getSelfRequest");
const data = await result.json();
return data as SelfStatus;
};
export const getPartyStatusRequest = async (apiEndpoint: APIEndPoint): Promise<PartyStatus> => {
const result = await fetch(`${apiUrl(apiEndpoint)}/status`);
if (!result.ok) throw new Error("Error sending getSelfRequest");
const data = await result.json();
return data as PartyStatus;
};