Server heavy refactoring 4 (not functionnal)

This commit is contained in:
Sebastien Riviere
2026-03-12 23:17:21 +01:00
parent e1b6c0e0c5
commit 1389dce132
95 changed files with 5320 additions and 27986 deletions

View File

@@ -2,60 +2,53 @@ import { useEffect, useState } from "react";
import "leaflet/dist/leaflet.css";
import { CustomMapContainer, MapEventListener } from "@/components/map";
import { NumberInput } from "@/components/input";
import useAdmin from "@/hook/useAdmin";
import useMapCircleDraw from "@/hook/useCircleDraw";
import useLocalVariable from "@/hook/useLocalVariable";
import { defaultZoneSettings } from "@/util/configurations";
import { ZoneTypes } from "@/util/types";
import { defaultZoneSettings } from "@/config/configurations";
import { ZoneTypes } from "@/config/types";
import { CircleZone } from "@/components/layer";
import { useAdmin } from "@/context/adminContext";
import { emitSettings } from "@/services/socket/emitters";
const EditMode = {
MIN: 0,
MAX: 1
}
};
function Drawings({ minZone, setMinZone, maxZone, setMaxZone, editMode }) {
const { drawingCircle: drawingMaxCircle, handleLeftClick: maxLeftClick, handleRightClick: maxRightClick, handleMouseMove: maxHover } = useMapCircleDraw(maxZone, setMaxZone);
const { drawingCircle: drawingMinCircle, handleLeftClick: minLeftClick, handleRightClick: minRightClick, handleMouseMove: minHover } = useMapCircleDraw(minZone, setMinZone);
function MaxCircleZone() {
return (
drawingMaxCircle
? <CircleZone circle={drawingMaxCircle} color="blue" />
: <CircleZone circle={maxZone} color="blue" />
);
}
function MinCircleZone() {
return (
drawingMinCircle
? <CircleZone circle={drawingMinCircle} color="red" />
: <CircleZone circle={minZone} color="red" />
);
}
return (<>
<MapEventListener
onLeftClick={editMode == EditMode.MAX ? maxLeftClick : minLeftClick}
onRightClick={editMode == EditMode.MAX ? maxRightClick : minRightClick}
onMouseMove={editMode == EditMode.MAX ? maxHover : minHover}
/>
<MaxCircleZone/>
<MinCircleZone/>
{
drawingMaxCircle
? <CircleZone circle={drawingMaxCircle} color="blue" />
: <CircleZone circle={maxZone} color="blue" />
}
{
drawingMinCircle
? <CircleZone circle={drawingMinCircle} color="red" />
: <CircleZone circle={minZone} color="red" />
}
</>);
}
export default function CircleZoneSelector({ display }) {
const {settings, updateSettings} = useAdmin();
const [localZoneSettings, setLocalZoneSettings, applyLocalZoneSettings] = useLocalVariable(settings.playingZones, (e) => updateSettings({playingZones: e}));
const [localOutOfZoneDelay, setLocalOutOfZoneDelay, applyLocalOutOfZoneDelay] = useLocalVariable(settings.outOfZoneDelay, (e) => updateSettings({outOfZoneDelay: e}));
const { settings } = useAdmin();
const [localZoneSettings, setLocalZoneSettings, applyLocalZoneSettings] = useLocalVariable(settings.playingZones, (e) => emitSettings({...settings, playingZones: e}));
const [localOutOfZoneDelay, setLocalOutOfZoneDelay, applyLocalOutOfZoneDelay] = useLocalVariable(settings.outOfZoneDelay, (e) => emitSettings({...settings, outOfZoneDelay: e}));
const [editMode, setEditMode] = useState(EditMode.MAX);
useEffect(() => {
if (!localZoneSettings || localZoneSettings.type != ZoneTypes.CIRCLE) {
setLocalZoneSettings(defaultZoneSettings.circle);
}
}, [localZoneSettings]);
}, [localZoneSettings, setLocalZoneSettings]);
function setMinZone(minZone) {
setLocalZoneSettings({...localZoneSettings, min: minZone});
@@ -96,7 +89,7 @@ export default function CircleZoneSelector({ display }) {
<NumberInput id="reduction-number" value={localZoneSettings.reductionCount ?? ""} onChange={updateReductionCount} />
</div>
<div className="w-full flex flex-row gap-2 items-center justify-between">
<p>Durée d'une zone</p>
<p>{"Durée d'une zone"}</p>
<NumberInput id="duration" value={localZoneSettings.duration ?? ""} onChange={updateDuration} />
</div>
<div className="w-full flex flex-row gap-2 items-center justify-between">

View File

@@ -1,8 +0,0 @@
import { Section } from "@/components/section";
export default function Messages() {
return (
<Section title="Messages" innerClassName="w-full h-full flex flex-col gap-3 items-center">
</Section>
);
}

View File

@@ -1,9 +1,9 @@
import { useEffect, useState } from "react";
import { List } from "@/components/list";
import { CustomMapContainer, MapEventListener } from "@/components/map";
import useAdmin from '@/hook/useAdmin';
import useMultipleCircleDraw from "@/hook/useMultipleCircleDraw";
import { CircleZone, Tag } from "@/components/layer";
import { useAdmin } from "@/context/adminContext";
function Drawings({ placementZones, addZone, removeZone, handleRightClick }) {
const { handleLeftClick, handleRightClick: handleRightClickDrawing } = useMultipleCircleDraw(placementZones, addZone, removeZone, 30);
@@ -24,10 +24,12 @@ function Drawings({ placementZones, addZone, removeZone, handleRightClick }) {
}
export default function PlacementZoneSelector({ display }) {
const { teams, getTeam, placementTeam } = useAdmin();
const { teams, getTeam } = useAdmin();
const [selectedTeamId, setSelectedTeamId] = useState(null);
const [placementZones, setPlacementZones] = useState([]);
// TODO replace old function placementTeam
useEffect(() => {
setPlacementZones(teams.filter(team => team.startingArea).map(team => ({id: team.id, name: team.name, center: team.startingArea.center, radius: team.startingArea.radius})));
}, [teams]);

View File

@@ -1,7 +1,5 @@
import dynamic from "next/dynamic";
import { ZoneTypes } from "@/util/types";
import useLocalVariable from "@/hook/useLocalVariable";
import useAdmin from "@/hook/useAdmin";
import { ZoneTypes } from "@/config/types";
// Imported at runtime and not at compile time
const CircleZoneSelector = dynamic(() => import('./circleZoneSelector'), { ssr: false });
@@ -19,13 +17,12 @@ function ZoneTypeButton({title, onClick, isSelected}) {
}
export default function PlayingZoneSelector({ display }) {
return (
<div className={display ? 'w-full h-full gap-3 flex flex-col' : "hidden"}>
<div className="w-full flex flex-row gap-3 items-center">
<p className="text-l">Type de zone :</p>
<ZoneTypeButton title="Cercles" onClick={() => setLocalZoneType(ZoneTypes.CIRCLE)} isSelected={ZoneTypes.POLYGON == ZoneTypes.CIRCLE} />
<ZoneTypeButton title="Polygones" onClick={() => setLocalZoneType(ZoneTypes.POLYGON)} isSelected={ZoneTypes.POLYGON == ZoneTypes.POLYGON} />
<ZoneTypeButton title="Cercles" onClick={() => { /*setLocalZoneType(ZoneTypes.CIRCLE)*/ }} isSelected={ZoneTypes.POLYGON == ZoneTypes.CIRCLE} />
<ZoneTypeButton title="Polygones" onClick={() => { /*setLocalZoneType(ZoneTypes.POLYGON)*/ }} isSelected={ZoneTypes.POLYGON == ZoneTypes.POLYGON} />
</div>
<div className="w-full flex-1">
<CircleZoneSelector display={ZoneTypes.POLYGON == ZoneTypes.CIRCLE} />

View File

@@ -1,26 +1,24 @@
import { useEffect, useState } from "react";
import { useEffect, useMemo } from "react";
import { Polyline } from "react-leaflet";
import "leaflet/dist/leaflet.css";
import { ReorderList } from "@/components/list";
import { CustomMapContainer, MapEventListener } from "@/components/map";
import { NumberInput } from "@/components/input";
import { Node, PolygonZone, Label } from "@/components/layer";
import useAdmin from "@/hook/useAdmin";
import useMapPolygonDraw from "@/hook/usePolygonDraw";
import useLocalVariable from "@/hook/useLocalVariable";
import { defaultZoneSettings } from "@/util/configurations";
import { ZoneTypes } from "@/util/types";
import { defaultZoneSettings } from "@/config/configurations";
import { ZoneTypes } from "@/config/types";
import { emitSettings } from "@/services/socket/emitters";
import { useAdmin } from "@/context/adminContext";
function Drawings({ localZoneSettings, addZone, removeZone }) {
const [polygons, setPolygons] = useState([]);
const { currentPolygon, highlightNodes, handleLeftClick, handleRightClick, handleMouseMove } = useMapPolygonDraw(polygons, addZone, removeZone);
useEffect(() => {
if (localZoneSettings.type == ZoneTypes.POLYGON) {
setPolygons(localZoneSettings.polygons.map(zone => zone.polygon));
}
const polygons = useMemo(() => {
return localZoneSettings.type == ZoneTypes.POLYGON ? localZoneSettings.polygons.map(zone => zone.polygon) : [];
}, [localZoneSettings]);
const { currentPolygon, highlightNodes, handleLeftClick, handleRightClick, handleMouseMove } = useMapPolygonDraw(polygons, addZone, removeZone);
function getLabelPosition(polygon) {
const sum = polygon.reduce(
(acc, coord) => ({
@@ -38,7 +36,7 @@ function Drawings({ localZoneSettings, addZone, removeZone }) {
return (<>
<MapEventListener onLeftClick={handleLeftClick} onRightClick={handleRightClick} onMouseMove={handleMouseMove} />
{localZoneSettings.polygons.map(zone =>
<PolygonZone key={zone.id} polygon={zone.polygon} color="black" opacity='0.5' >
<PolygonZone key={zone.id} polygon={zone.polygon} color="black" >
<Label position={getLabelPosition(zone.polygon)} label={zone.id} color="white" />
</PolygonZone>
)}
@@ -54,15 +52,15 @@ function Drawings({ localZoneSettings, addZone, removeZone }) {
export default function PolygonZoneSelector({ display }) {
const defaultDuration = 10;
const {settings, updateSettings} = useAdmin();
const [localZoneSettings, setLocalZoneSettings, applyLocalZoneSettings] = useLocalVariable(settings.zones, (e) => updateSettings({zone: e}));
const [localOutOfZoneDelay, setLocalOutOfZoneDelay, applyLocalOutOfZoneDelay] = useLocalVariable(settings.outOfZoneDelay, (e) => updateSettings({outOfZoneDelay: e}));
const { settings } = useAdmin();
const [localZoneSettings, setLocalZoneSettings, applyLocalZoneSettings] = useLocalVariable(settings.zones, (e) => emitSettings({...settings, zone: e}));
const [localOutOfZoneDelay, setLocalOutOfZoneDelay, applyLocalOutOfZoneDelay] = useLocalVariable(settings.outOfZoneDelay, (e) => emitSettings({...settings, outOfZoneDelay: e}));
useEffect(() => {
if (!localZoneSettings || localZoneSettings.type != ZoneTypes.POLYGON) {
setLocalZoneSettings(defaultZoneSettings.polygon);
}
}, [localZoneSettings]);
}, [localZoneSettings, setLocalZoneSettings]);
function getNewPolygonName() {
const existingIds = new Set(localZoneSettings.polygons.map(zone => zone.id));

View File

@@ -1,35 +1,36 @@
import { useState } from "react";
import Image from "next/image";
import { ReorderList } from '@/components/list';
import useAdmin from '@/hook/useAdmin';
import useLocalVariable from "@/hook/useLocalVariable";
import { NumberInput } from "@/components/input";
import { Section } from "@/components/section";
import { useAdmin } from "@/context/adminContext";
import { emitAddTeam, emitEliminateTeam, emitRemoveTeam, emitReorderTeam, emitReviveTeam, emitSettings } from "@/services/socket/emitters";
function TeamManagerItem({ team }) {
const { captureTeam, removeTeam } = useAdmin();
return (
<div className='w-full flex flex-row items-center justify-between p-2 gap-3 bg-white'>
<p className='text-xl font-bold'>{team.name}</p>
<div className='flex flex-row items-center justify-between gap-3'>
<p className='text-xl font-bold'>{String(team.id).padStart(6, '0').replace(/(\d{3})(\d{3})/, "$1 $2")}</p>
<img src={`/icons/heart/${team.captured ? "grey" : "pink"}.png`} className="w-8 h-8 cursor-pointer" onClick={() => captureTeam(team.id)} />
<img src="/icons/trash.png" className="w-8 h-8 cursor-pointer" onClick={() => removeTeam(team.id)} />
<Image src={`/icons/heart/${team.captured ? "grey" : "pink"}.png`} alt="heart" className="w-8 h-8 cursor-pointer" onClick={() => team.captured ? emitReviveTeam(team.id) : emitEliminateTeam(team.id)} />
<Image src="/icons/trash.png" alt="trash" className="w-8 h-8 cursor-pointer" onClick={() => emitRemoveTeam(team.id)} />
</div>
</div>
);
}
export default function TeamManager() {
const { teams, addTeam, reorderTeams, settings, updateSettings } = useAdmin();
const { teams, settings } = useAdmin();
const [teamName, setTeamName] = useState('');
const [localSendPositionDelay, setLocalSendPositionDelay, applyLocalSendPositionDelay] = useLocalVariable(settings.scanDelay, (e) => updateSettings({scanDelay: e}));
const [localSendPositionDelay, setLocalSendPositionDelay, applyLocalSendPositionDelay] = useLocalVariable(settings.scanDelay, (e) => emitSettings({...settings, scanDelay: e}));
function handleTeamSubmit(e) {
e.preventDefault();
if (teamName !== "") {
addTeam(teamName);
setTeamName("")
emitAddTeam(teamName);
setTeamName("");
}
}
@@ -37,14 +38,14 @@ export default function TeamManager() {
<Section title="Équipes" outerClassName="flex-1 min-h-0" innerClassName="flex flex-col items-center gap-3">
<form className='w-full flex flex-row gap-3' onSubmit={handleTeamSubmit}>
<div className='w-full'>
<input name="teamName" label='Team name' value={teamName} onChange={(e) => setTeamName(e.target.value)} type="text" className="w-full h-full p-4 ring-1 ring-inset ring-gray-300" />
<input name="teamName" value={teamName} onChange={(e) => setTeamName(e.target.value)} type="text" className="w-full h-full p-4 ring-1 ring-inset ring-gray-300" />
</div>
<div className='w-1/5'>
<button type="submit" className="w-full h-full bg-custom-light-blue hover:bg-blue-500 transition text-3xl font-bold">+</button>
</div>
</form>
<div className="w-full flex-1 min-h-0 ">
<ReorderList droppableId="team-manager" array={teams} setArray={(teams) => reorderTeams(teams.map(team => team.id))}>
<ReorderList droppableId="team-manager" array={teams} setArray={(teams) => emitReorderTeam(teams.map(team => team.id))}>
{(team) => (
<TeamManagerItem team={team}/>
)}