Skip to content

Commit

Permalink
feat: wip, save everything
Browse files Browse the repository at this point in the history
  • Loading branch information
shanedg committed May 21, 2024
1 parent 10dc8d1 commit e885b13
Show file tree
Hide file tree
Showing 12 changed files with 272 additions and 170 deletions.
177 changes: 27 additions & 150 deletions client/src/App/App.tsx
Original file line number Diff line number Diff line change
@@ -1,164 +1,27 @@
import React, { StrictMode, useEffect, useState } from 'react';
import { createBrowserRouter, RouterProvider, Link, useParams, Outlet } from 'react-router-dom';
import React, { StrictMode, Suspense } from 'react';
import { createBrowserRouter, RouterProvider } from 'react-router-dom';

import './App.css';
import { useGuildMemberData } from './use-guild-member-data';
import { Welcome } from '../components/Welcome';

type GuildUserData = ReturnType<typeof useGuildMemberData>;
import { Home } from './components/Home';
import { NewWorld } from './components/NewWorld';
import { useGuildMemberData } from './components/use-guild-member-data';
import { WorldDetail } from './components/WorldDetail';
import { Worlds } from './components/Worlds';

const getWelcomeMessage = (guildUser: GuildUserData) => {
const welcome = 'welcome to the trash compactor';
export type GuildUserData = ReturnType<typeof useGuildMemberData>;

if (guildUser?.user?.username) {
return `${welcome}, ${guildUser.user.username}`;
}

return `${welcome}, <unknown>`;
};

const DelayedLoadingMessage = () => {
const [showLoading, setShowLoading] = useState(false);

useEffect(() => {
// Showing a loading message right away contributes to worse perceived performance
const timeout = setTimeout(() => setShowLoading(true), 500);

return () => clearTimeout(timeout);
});

if (showLoading) {
return (<p>loading...</p>);
}

return null;
};

const Home = () => {
const guildUser = useGuildMemberData();

// FIXME: if not a guild member, user just sees 'loading...' forever
if (guildUser) {
return (
<>
<ul className="navigation-list">
<li>
<Link to="/new">new</Link>
</li>
<li>
<Link to="/worlds">worlds</Link>
</li>
</ul>
<Welcome message={getWelcomeMessage(guildUser)} />
</>
);
}

return (<DelayedLoadingMessage />);
};

const WorldsList = () => {
const fakeWorlds = [
{
id: 1,
label: 'world one',
version: '1.16.5',
createdAt: '2023/06/28',
lastOnline: '2023/06/28',
createdBy: '@shaned.gg'
},
{
id: 2,
label: 'world two',
version: '1.19.0',
createdAt: '2023/06/28',
lastOnline: '2023/06/28',
createdBy: '@shaned.gg'
},
{
id: 3,
label: 'world three',
version: '1.20.1',
createdAt: '2023/06/28',
lastOnline: '2023/06/28',
createdBy: '@shaned.gg'
},
];

return (
<>
<ul className="navigation-list">
<li>
<Link to="/">back</Link>
</li>
</ul>
<table>
<thead>
<tr>
<td>name</td>
<td>version</td>
<td>created</td>
<td>last online</td>
<td>created by</td>
</tr>
</thead>
<tbody>
{fakeWorlds.map(({ id, label, version, createdAt, createdBy, lastOnline }) => {
return (
<tr key={`${id}-${label}-${version}`}>
<td><Link to={`${id}`}>{label}</Link></td>
<td>{version}</td>
<td>{new Date(createdAt).toLocaleDateString()}</td>
<td>{new Date(lastOnline).toLocaleDateString()}</td>
<td>{createdBy}</td>
</tr>
);
})}
</tbody>
</table>
<Outlet />
</>
);
};

const WorldDetail = () => {
const { worldId } = useParams();
return (
<>
<h2>{worldId}</h2>
</>
);
};

const NewWorld = () => {
return (
<>
<ul className="navigation-list">
<li>
<Link to="/">back</Link>
</li>
</ul>
<form>
<label htmlFor="version">version</label>
<select name="version">
<option>1.20.1</option>
</select>
<label htmlFor="name">name</label>
<input name="name" />
<button>create</button>
</form>
</>
);
};
const ErrorComponent = () => (<>sploops!</>);

const router = createBrowserRouter([
{
path: '/',
element: <Home />,
errorElement: <ErrorComponent />,
},
{
path: '/worlds',
element: <WorldsList />,
element: <Worlds />,
children: [
{
path: ':worldId',
Expand All @@ -175,8 +38,22 @@ const router = createBrowserRouter([
export const App = () => {
return (
<StrictMode>
<h1>trshcmpctr</h1>
<RouterProvider router={router} />
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}>
<article>
<header>
<h1>trshcmpctr</h1>
</header>
<section>
<Suspense fallback={null}>
<RouterProvider router={router} />
</Suspense>
</section>
</article>
</div>
</StrictMode>
);
};
22 changes: 22 additions & 0 deletions client/src/App/components/DelayedLoadingMessage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React, { useEffect, useState } from 'react';

/**
* A component that
*/
export const DelayedLoadingMessage = () => {
const [showLoading, setShowLoading] = useState(false);
const loadingTimeout = 500;

useEffect(() => {
// Showing a loading message right away contributes to worse perceived performance
const timeout = setTimeout(() => setShowLoading(true), loadingTimeout);

return () => clearTimeout(timeout);
});

if (showLoading) {
return (<p>loading...</p>);
}

return null;
};
40 changes: 40 additions & 0 deletions client/src/App/components/Home.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';
import { Link } from 'react-router-dom';

import { DelayedLoadingMessage } from './DelayedLoadingMessage';
import { useGuildMemberData } from './use-guild-member-data';
import { Welcome } from './Welcome';
import { GuildUserData } from '../App';

const getWelcomeMessage = (guildUser: GuildUserData) => {
const welcome = 'welcome to the trash compactor';

if (guildUser?.user?.username) {
return `${welcome}, ${guildUser.user.username}`;
}

return `${welcome}, <unknown>`;
};

export const Home = () => {
const guildUser = useGuildMemberData();

// TODO: FIXME: if not a guild member, user just sees 'loading...' forever
if (guildUser) {
return (
<>
<ul className="navigation-list">
<li>
<Link to="/new">new</Link>
</li>
<li>
<Link to="/worlds">worlds</Link>
</li>
</ul>
<Welcome message={getWelcomeMessage(guildUser)} />
</>
);
}

return (<DelayedLoadingMessage />);
};
23 changes: 23 additions & 0 deletions client/src/App/components/NewWorld.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import { Link } from 'react-router-dom';

export const NewWorld = () => {
return (
<>
<ul className="navigation-list">
<li>
<Link to="/">back</Link>
</li>
</ul>
<form>
<label htmlFor="version">version</label>
<select name="version">
<option>1.20.1</option>
</select>
<label htmlFor="name">name</label>
<input name="name" />
<button>create</button>
</form>
</>
);
};
11 changes: 11 additions & 0 deletions client/src/App/components/WorldDetail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import { useParams } from 'react-router-dom';

export const WorldDetail = () => {
const { worldId } = useParams();
return (
<>
<h2>{worldId}</h2>
</>
);
};
55 changes: 55 additions & 0 deletions client/src/App/components/Worlds.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from 'react';
import { Link, Outlet } from 'react-router-dom';

import { useRequest } from '../hooks/use-request';

type World = {
id: number,
label: string,
version: string,
createdAt: string,
lastOnline: string,
createdBy: string,
};

type Worlds = World[];

export const Worlds = () => {
const useWrapped = useRequest<Worlds>('/api/v1/worlds');
const { data: fakeWorlds } = useWrapped();

return (
<>
<ul className="navigation-list">
<li>
<Link to="/">back</Link>
</li>
</ul>
<table>
<thead>
<tr>
<td>name</td>
<td>version</td>
<td>created</td>
<td>last online</td>
<td>created by</td>
</tr>
</thead>
<tbody>
{fakeWorlds && fakeWorlds.map(({ id, label, version, createdAt, createdBy, lastOnline }) => {
return (
<tr key={`${id}-${label}-${version}`}>
<td><Link to={`${id}`}>{label}</Link></td>
<td>{version}</td>
<td>{new Date(createdAt).toLocaleDateString()}</td>
<td>{new Date(lastOnline).toLocaleDateString()}</td>
<td>{createdBy}</td>
</tr>
);
})}
</tbody>
</table>
<Outlet />
</>
);
};
7 changes: 7 additions & 0 deletions client/src/App/components/use-guild-member-data.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// import { renderHook } from '@testing-library/react';

describe('useGuildMemberData', () => {
it('truths', () => {
expect(true).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// TODO: FIXME: test this hook

import axios from 'axios';
import { useEffect, useState } from 'react';

Expand Down Expand Up @@ -36,10 +38,7 @@ export const useGuildMemberData = () => {
})
.catch((cause: unknown) => {
isFetching = false;
throw new Error(
'Something went wrong fetching guild membership data',
{ cause }
);
throw new Error('Something went wrong fetching guild membership data', { cause });
});
}, []);

Expand Down
Loading

0 comments on commit e885b13

Please sign in to comment.