Support getMe and getParty Requests
This commit is contained in:
parent
25723bb24b
commit
9103f30a6a
1
.gitignore
vendored
1
.gitignore
vendored
@ -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
16691
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -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();
|
||||
});
|
26
src/App.tsx
26
src/App.tsx
@ -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
63
src/PartyContext.tsx
Normal 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" />;
|
||||
};
|
@ -1,3 +1,9 @@
|
||||
.loading {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
.App {
|
||||
text-align: center;
|
||||
}
|
27
src/PartyPage.tsx
Normal file
27
src/PartyPage.tsx
Normal 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>
|
||||
};
|
@ -10,4 +10,4 @@ body {
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
||||
}
|
@ -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
28
src/partyApi.ts
Normal 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;
|
||||
};
|
Loading…
Reference in New Issue
Block a user