Use of Server Components for easier Data fetching + start use of v2 API
This commit is contained in:
parent
49ceda5575
commit
f23c9dc0f1
6 changed files with 195 additions and 5 deletions
12
app/page.tsx
12
app/page.tsx
|
@ -1,12 +1,14 @@
|
||||||
'use client';
|
|
||||||
import '@/app/globals.css';
|
import '@/app/globals.css';
|
||||||
|
import { Game, GameGroup } from '@/types/stellaris';
|
||||||
|
import { GameView } from '@/components/gui/game-view';
|
||||||
|
import { generateUrl } from '@/components/server/fetchers';
|
||||||
|
|
||||||
|
export default async function Home() {
|
||||||
|
const games = await fetch(generateUrl('/games')).then((res) => res.json())
|
||||||
|
|
||||||
export default function Home() {
|
|
||||||
return (
|
return (
|
||||||
<main>
|
<main>
|
||||||
<div>
|
<GameView games={games}/>
|
||||||
<p>Empire Overview goes here evenutally</p>
|
|
||||||
</div>
|
|
||||||
</main>
|
</main>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
85
components/gui/game-group-select.tsx
Normal file
85
components/gui/game-group-select.tsx
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
import { Game, GameGroup } from "@/types/stellaris";
|
||||||
|
import { Dropdown } from "@nextui-org/react";
|
||||||
|
import { Dispatch, Key, SetStateAction, Suspense } from "react";
|
||||||
|
import { fetchGameGroups } from "@/components/server/fetchers";
|
||||||
|
|
||||||
|
type SelectionType = "all" | Set<Key>;
|
||||||
|
|
||||||
|
export const GameGroupSelect = (
|
||||||
|
props: {
|
||||||
|
game: Game,
|
||||||
|
groups: [GameGroup[], Dispatch<SetStateAction<Array<GameGroup>>>],
|
||||||
|
currentGroups: [GameGroup[], Dispatch<SetStateAction<Array<GameGroup>>>]
|
||||||
|
}) => {
|
||||||
|
const currentGame = props.game;
|
||||||
|
const [gameGroups, setGameGroups] = props.groups;
|
||||||
|
const [currentGameGroups, setCurrentGameGroups] = props.currentGroups;
|
||||||
|
|
||||||
|
const changeSelection = (keys: SelectionType) => {
|
||||||
|
if (keys != "all") {
|
||||||
|
let newSelection: GameGroup[] = [];
|
||||||
|
keys.forEach(key => {
|
||||||
|
gameGroups.forEach(group => {
|
||||||
|
if (key == group.name) {
|
||||||
|
newSelection.push(group);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
setCurrentGameGroups(newSelection)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Suspense>
|
||||||
|
<DataHandler game={currentGame} groups={[gameGroups, setGameGroups]} currentGroups={[currentGameGroups, setCurrentGameGroups]} />
|
||||||
|
</Suspense>
|
||||||
|
<Dropdown>
|
||||||
|
<Dropdown.Button flat color="secondary" css={{ tt: "capitalize" }}>
|
||||||
|
{currentGameGroups.map(elem => elem.name).join(", ")}
|
||||||
|
</Dropdown.Button>
|
||||||
|
<Dropdown.Menu
|
||||||
|
aria-label="Multiple selection actions"
|
||||||
|
color="secondary"
|
||||||
|
disallowEmptySelection
|
||||||
|
selectionMode="multiple"
|
||||||
|
selectedKeys={currentGameGroups.map(elem => elem.name)}
|
||||||
|
onSelectionChange={changeSelection}
|
||||||
|
items={gameGroups}
|
||||||
|
>
|
||||||
|
{gameGroups.map((item) => (
|
||||||
|
<Dropdown.Item
|
||||||
|
key={item.name}
|
||||||
|
color="default"
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</Dropdown.Item>
|
||||||
|
))}
|
||||||
|
</Dropdown.Menu>
|
||||||
|
</Dropdown>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const DataHandler = async (
|
||||||
|
props: {
|
||||||
|
game: Game,
|
||||||
|
groups: [GameGroup[], Dispatch<SetStateAction<Array<GameGroup>>>],
|
||||||
|
currentGroups: [GameGroup[], Dispatch<SetStateAction<Array<GameGroup>>>]
|
||||||
|
}) => {
|
||||||
|
if (props) {
|
||||||
|
const currentGame = props.game;
|
||||||
|
const [gameGroups, setGameGroups] = props.groups;
|
||||||
|
const [currentGameGroups, setCurrentGameGroups] = props.currentGroups;
|
||||||
|
|
||||||
|
if (!gameGroups[0] || gameGroups[0].game_id != currentGame.id) {
|
||||||
|
setGameGroups(await fetchGameGroups(currentGame));
|
||||||
|
}
|
||||||
|
else if (!currentGameGroups[0] || currentGameGroups[0].game_id != gameGroups[0].game_id) {
|
||||||
|
setCurrentGameGroups(gameGroups);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return <></>
|
||||||
|
}
|
43
components/gui/game-select.tsx
Normal file
43
components/gui/game-select.tsx
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import { Game } from "@/types/stellaris";
|
||||||
|
import { Dropdown } from "@nextui-org/react";
|
||||||
|
import { Dispatch, Key, SetStateAction, useState } from "react";
|
||||||
|
|
||||||
|
type SelectionType = "all" | Set<Key>;
|
||||||
|
|
||||||
|
export const GameSelect = (props: { games: Game[], currentGame: Game | undefined, setCurrentGame: Dispatch<SetStateAction<Game>> }) => {
|
||||||
|
const changeSelection = (keys: SelectionType) => {
|
||||||
|
if (keys != "all") {
|
||||||
|
props.games.forEach(game => {
|
||||||
|
if (game.name == keys.keys().next().value) [
|
||||||
|
props.setCurrentGame(game)
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dropdown>
|
||||||
|
<Dropdown.Button flat color="secondary" css={{ tt: "capitalize" }}>
|
||||||
|
{props.currentGame ? props.currentGame.name : "-"}
|
||||||
|
</Dropdown.Button>
|
||||||
|
<Dropdown.Menu
|
||||||
|
aria-label="Single selection actions"
|
||||||
|
color="secondary"
|
||||||
|
disallowEmptySelection
|
||||||
|
selectionMode="single"
|
||||||
|
selectedKeys={[props.currentGame ? props.currentGame.name : "-"]}
|
||||||
|
onSelectionChange={changeSelection}
|
||||||
|
items={props.games}
|
||||||
|
>
|
||||||
|
{props.games.map((item) => (
|
||||||
|
<Dropdown.Item
|
||||||
|
key={item.name}
|
||||||
|
color="default"
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</Dropdown.Item>
|
||||||
|
))}
|
||||||
|
</Dropdown.Menu>
|
||||||
|
</Dropdown>
|
||||||
|
)
|
||||||
|
}
|
22
components/gui/game-view.tsx
Normal file
22
components/gui/game-view.tsx
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
'use client';
|
||||||
|
import { Game } from "@/types/stellaris";
|
||||||
|
import { GameSelect } from "./game-select";
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { GameGroupSelect } from "./game-group-select";
|
||||||
|
import { SSRProvider } from "react-bootstrap";
|
||||||
|
|
||||||
|
export const GameView = (props: { games: Game[] }) => {
|
||||||
|
const [currentGame, setCurrentGame] = useState(props.games[0]);
|
||||||
|
|
||||||
|
const [gameGroups, setGameGroups] = useState([{id: 0, name: "", game_id: 0}]);
|
||||||
|
const [currentGameGroups, setCurrentGameGroups] = useState(gameGroups);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<SSRProvider>
|
||||||
|
<GameSelect games={props.games} currentGame={currentGame} setCurrentGame={setCurrentGame} />
|
||||||
|
<GameGroupSelect game={currentGame} groups={[gameGroups, setGameGroups]} currentGroups={[currentGameGroups, setCurrentGameGroups]} />
|
||||||
|
</SSRProvider>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
27
components/server/fetchers.ts
Normal file
27
components/server/fetchers.ts
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { Game } from "@/types/stellaris"
|
||||||
|
|
||||||
|
type Parameter = {
|
||||||
|
key: string,
|
||||||
|
val: string | number
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseUrl = 'http://stellaris.neshweb.net/api/v2'
|
||||||
|
|
||||||
|
export const generateUrl = (url: string, params?: Parameter[]) => {
|
||||||
|
let query: string = baseUrl + url;
|
||||||
|
if (params && params.length > 0) {
|
||||||
|
query = query + '?';
|
||||||
|
params.forEach((param, idx) => {
|
||||||
|
query = query + param.key + '=' + param.val;
|
||||||
|
if (idx + 1 != params.length) {
|
||||||
|
query = query + '&';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fetchGameGroups = async (game: Game) => {
|
||||||
|
const gameGroups = await fetch(generateUrl('/game_groups', [{key: "game_id", val: game.id}])).then((res) => res.json())
|
||||||
|
return gameGroups
|
||||||
|
}
|
|
@ -64,3 +64,14 @@ export enum Species {
|
||||||
Toxoid = 11,
|
Toxoid = 11,
|
||||||
Machine = 12,
|
Machine = 12,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Game = {
|
||||||
|
id: number,
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type GameGroup = {
|
||||||
|
id: number,
|
||||||
|
game_id: number,
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
Reference in a new issue