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 { 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 (
|
||||
<main>
|
||||
<div>
|
||||
<p>Empire Overview goes here evenutally</p>
|
||||
</div>
|
||||
<GameView games={games}/>
|
||||
</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,
|
||||
Machine = 12,
|
||||
}
|
||||
|
||||
export type Game = {
|
||||
id: number,
|
||||
name: string
|
||||
}
|
||||
|
||||
export type GameGroup = {
|
||||
id: number,
|
||||
game_id: number,
|
||||
name: string
|
||||
}
|
||||
|
|
Reference in a new issue