forked from partypages/party-template
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.
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
.vscode
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
/node_modules
|
/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 {
|
.App {
|
||||||
text-align: center;
|
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 {
|
code {
|
||||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||||
monospace;
|
monospace;
|
||||||
}
|
}
|
@ -1,19 +1,16 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
import App from './App';
|
import { PartyContextProvider } from './PartyContext';
|
||||||
import reportWebVitals from './reportWebVitals';
|
import { PartyPage } from './PartyPage';
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(
|
const root = ReactDOM.createRoot(
|
||||||
document.getElementById('root') as HTMLElement
|
document.getElementById('root') as HTMLElement
|
||||||
);
|
);
|
||||||
root.render(
|
root.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<App />
|
<PartyContextProvider>
|
||||||
|
<PartyPage />
|
||||||
|
</PartyContextProvider>
|
||||||
</React.StrictMode>
|
</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