Added state and events context

This commit is contained in:
Pax1601
2024-04-02 15:18:10 +02:00
parent 42c7a36da7
commit 5d5c650162
7 changed files with 193 additions and 48 deletions

View File

@@ -1,28 +1,142 @@
import React from 'react'
import { useState } from 'react'
import './App.css'
import './app.css'
import { MapContainer, TileLayer } from 'react-leaflet'
import { Map } from './map/map'
import { Header } from './ui/header'
import { EventsProvider } from './eventscontext'
import { StateProvider } from './statecontext'
var map: Map;
const position = [51.505, -0.09]
function App() {
const [count, setCount] = useState(0)
return (
<div style={{ width: "100%", height: "100%" }}>
<MapContainer center={position} zoom={13} className='absolute w-full h-full top-0 left-0'>
<TileLayer
url="https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
/>
</MapContainer>
<Header></Header>
</div>
)
export type OlympusState = {
spawnMenuVisible: boolean,
unitControlMenuVisible: boolean,
measureMenuVisible: boolean,
drawingMenuVisible: boolean
}
export default App
export default class App extends React.Component<{}, OlympusState> {
constructor(props) {
super(props);
/* State initialization */
this.state = {
spawnMenuVisible: false,
unitControlMenuVisible: false,
measureMenuVisible: false,
drawingMenuVisible: false
}
/* Methods bindings */
this.showSpawnMenu = this.showSpawnMenu.bind(this);
this.toggleSpawnMenu = this.toggleSpawnMenu.bind(this);
this.showUnitControlMenu = this.showUnitControlMenu.bind(this);
this.toggleUnitControlMenu = this.toggleUnitControlMenu.bind(this);
this.showMeasureMenu = this.showMeasureMenu.bind(this);
this.toggleMeasureMenu = this.toggleMeasureMenu.bind(this);
this.showDrawingMenu = this.showDrawingMenu.bind(this);
this.toggleDrawingMenu = this.toggleDrawingMenu.bind(this);
}
showSpawnMenu(show: boolean) {
this.setState({
spawnMenuVisible: show,
unitControlMenuVisible: false,
measureMenuVisible: false,
drawingMenuVisible: false
});
}
toggleSpawnMenu() {
this.setState({
spawnMenuVisible: !this.state.spawnMenuVisible,
unitControlMenuVisible: false,
measureMenuVisible: false,
drawingMenuVisible: false
});
}
showUnitControlMenu(show: boolean) {
this.setState({
spawnMenuVisible: false,
unitControlMenuVisible: show,
measureMenuVisible: false,
drawingMenuVisible: false
});
}
toggleUnitControlMenu() {
this.setState({
spawnMenuVisible: false,
unitControlMenuVisible: !this.state.unitControlMenuVisible,
measureMenuVisible: false,
drawingMenuVisible: false
});
}
showMeasureMenu(show: boolean) {
this.setState({
spawnMenuVisible: false,
unitControlMenuVisible: false,
measureMenuVisible: show,
drawingMenuVisible: false
});
}
toggleMeasureMenu() {
this.setState({
spawnMenuVisible: false,
unitControlMenuVisible: false,
measureMenuVisible: !this.state.measureMenuVisible,
drawingMenuVisible: false
});
}
showDrawingMenu(show: boolean) {
this.setState({
spawnMenuVisible: false,
unitControlMenuVisible: false,
measureMenuVisible: false,
drawingMenuVisible: show
});
}
toggleDrawingMenu() {
this.setState({
spawnMenuVisible: false,
unitControlMenuVisible: false,
measureMenuVisible: false,
drawingMenuVisible: !this.state.drawingMenuVisible
});
}
render() {
return (
<div style={{ width: "100%", height: "100%" }}>
<StateProvider value={this.state}>
<EventsProvider value={
{
showSpawnMenu: this.showSpawnMenu,
toggleSpawnMenu: this.toggleSpawnMenu,
showUnitControlMenu: this.showUnitControlMenu,
toggleUnitControlMenu: this.toggleUnitControlMenu,
showMeasureMenu: this.showMeasureMenu,
toggleMeasureMenu: this.toggleMeasureMenu,
showDrawingMenu: this.showMeasureMenu,
toggleDrawingMenu: this.toggleDrawingMenu
}
}>
<MapContainer center={position} zoom={13} className='absolute w-full h-full top-0 left-0'>
<TileLayer
url="https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
/>
</MapContainer>
<Header ></Header>
</EventsProvider>
</StateProvider>
</div>
)
}
}

View File

@@ -0,0 +1,15 @@
import { createContext } from "react";
export const EventsContext = createContext({
showSpawnMenu: (e: boolean) => {},
toggleSpawnMenu: () => {},
showUnitControlMenu: (e: boolean) => {},
toggleUnitControlMenu: () => {},
showMeasureMenu: (e: boolean) => {},
toggleMeasureMenu: () => {},
showDrawingMenu: (e: boolean) => {},
toggleDrawingMenu: () => {}
})
export const EventsProvider = EventsContext.Provider;
export const EventsConsumer = EventsContext.Consumer;

View File

@@ -1,4 +1,4 @@
@import "./leaflet/leaflet.css";
@import "../node_modules/leaflet/dist/leaflet.css";
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;

View File

@@ -1,6 +1,6 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import App from './app.tsx'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')).render(

View File

@@ -0,0 +1,12 @@
import { createContext } from "react";
import { OlympusState } from "./App";
export const StateContext = createContext({
spawnMenuVisible: false,
unitControlMenuVisible: false,
measureMenuVisible: false,
drawingMenuVisible: false
} as OlympusState)
export const StateProvider = StateContext.Provider;
export const StateConsumer = StateContext.Consumer;

View File

@@ -2,28 +2,34 @@ import React from 'react'
import { StateButton } from './statebuttons';
import { faPlus, faGamepad, faRuler, faPencil } from '@fortawesome/free-solid-svg-icons';
import { library } from '@fortawesome/fontawesome-svg-core'
import { EventsConsumer, EventsContext } from '../eventscontext';
import { StateConsumer } from '../statecontext';
library.add(faPlus, faGamepad, faRuler, faPencil)
type HeaderProps = {
export class Header extends React.Component<{}, {}> {
constructor(props) {
super(props);
}
}
type HeaderState = {
}
export class Header extends React.Component<HeaderProps, HeaderState> {
render() {
return (
<div className='absolute top-0 left-0 h-16 w-full z-ui bg-background-steel flex flex-row items-center px-5'>
<div className="flex flex-row items-center gap-1">
<StateButton icon="fa-solid fa-plus"></StateButton>
<StateButton icon="fa-solid fa-gamepad"></StateButton>
<StateButton icon="fa-solid fa-ruler"></StateButton>
<StateButton icon="fa-solid fa-pencil"></StateButton>
</div>
</div>
);
}
render() {
return (
<StateConsumer>
{(appState) =>
<EventsConsumer>
{(events) =>
<div className='absolute top-0 left-0 h-16 w-full z-ui bg-background-steel flex flex-row items-center px-5'>
<div className="flex flex-row items-center gap-1">
<StateButton onClick={events.toggleSpawnMenu} active={appState.spawnMenuVisible} icon="fa-solid fa-plus"></StateButton>
<StateButton onClick={events.toggleUnitControlMenu} active={appState.unitControlMenuVisible} icon="fa-solid fa-gamepad"></StateButton>
<StateButton onClick={events.toggleMeasureMenu} active={appState.measureMenuVisible} icon="fa-solid fa-ruler"></StateButton>
<StateButton onClick={events.toggleDrawingMenu} active={appState.drawingMenuVisible} icon="fa-solid fa-pencil"></StateButton>
</div>
</div>
}
</EventsConsumer>
}
</StateConsumer>
);
}
}

View File

@@ -1,16 +1,14 @@
import React from 'react'
import React, { MouseEventHandler } from 'react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { IconProp } from '@fortawesome/fontawesome-svg-core'
type ButtonProperties = {
icon: string
}
type ButtonState = {
type ButtonProps = {
icon: string,
onClick: CallableFunction,
active: boolean
}
export class StateButton extends React.Component<ButtonProperties, ButtonState> {
export class StateButton extends React.Component<ButtonProps, {}> {
constructor(props) {
super(props);
this.state = {
@@ -20,10 +18,10 @@ export class StateButton extends React.Component<ButtonProperties, ButtonState>
render() {
var computedClassName = "";
computedClassName += this.state.active? 'bg-white text-background-steel': 'bg-transparent text-white border-white';
computedClassName += this.props.active? 'bg-white text-background-steel': 'bg-transparent text-white border-white';
return (
<FontAwesomeIcon icon={this.props.icon as IconProp} className={computedClassName + " rounded w-5 h-5 p-2 border-2"} onClick={() => this.setState({active: !this.state.active})}>
<FontAwesomeIcon icon={this.props.icon as IconProp} className={computedClassName + " rounded w-5 h-5 p-2 border-2"} onClick={this.props.onClick as MouseEventHandler}>
</FontAwesomeIcon>
);
}