From e762f1b3661216bfac4b79f0f27b56e3381244d4 Mon Sep 17 00:00:00 2001 From: Solareon <769465+solareon@users.noreply.github.com> Date: Wed, 26 Jun 2024 21:39:57 +0200 Subject: [PATCH] refactor: use stores correctly --- web/src/App.tsx | 98 +++++++++++++++++++++-- web/src/components/ConfirmationDialog.tsx | 6 +- web/src/components/DataHandler.tsx | 3 +- web/src/components/GroupDashboard.tsx | 97 ++++++++++++---------- web/src/components/GroupJob.tsx | 41 ++++++---- web/src/components/PlayerList.tsx | 33 +++++--- web/src/storage/GroupJobStepStore.ts | 10 --- web/src/storage/GroupStore.ts | 63 ++------------- web/src/storage/PlayerDataStore.ts | 6 +- 9 files changed, 209 insertions(+), 148 deletions(-) diff --git a/web/src/App.tsx b/web/src/App.tsx index a85f746..9459d2b 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -2,10 +2,14 @@ import React, { useEffect, useRef, useState } from "react"; import GroupDashboard from "./components/GroupDashboard"; import PlayerList from "./components/PlayerList"; import GroupJob from "./components/GroupJob"; -import DataHandler from './components/DataHandler'; +import DataHandler from "./components/DataHandler"; import { GroupJobStep } from "./types/GroupJobStep"; import { Group } from "./types/Group"; import { useNuiEvent } from "./hooks/useNuiEvent"; +import { fetchReactNui } from "./utils/fetchReactNui"; +import { useGroupJobStepStore } from "./storage/GroupJobStepStore"; +import { useGroupStore } from "./storage/GroupStore"; +import { usePlayerDataStore } from "./storage/PlayerDataStore"; import "./App.css"; const devMode = !window?.["invokeNative"]; @@ -22,7 +26,9 @@ const App = () => { onSettingsChange, } = window as any; const [currentPage, setCurrentPage] = useState("GroupDashboard"); - const [inGroup, setInGroup] = useState(false); + const { setGroupJobSteps } = useGroupJobStepStore(); + const { inGroup, setGroups } = useGroupStore(); + const { setPlayerData } = usePlayerDataStore(); useEffect(() => { if (devMode) { @@ -35,6 +41,80 @@ const App = () => { } }, [theme]); + useEffect(() => { + fetchReactNui("setPlayerData", {}, { + source: 1, + citizenId: 'ABCD1234', + name: 'Testicle', + }).then((data) => { + setPlayerData(data); + }); + + fetchReactNui("getGroupJobSteps", {}, [ + { id: 1, name: "Step 1", isDone: false }, + { id: 2, name: "Step 2", isDone: false }, + { id: 3, name: "Step 3", isDone: false }, + ]).then((data) => { + setGroupJobSteps(data); + }); + + fetchReactNui("refreshGroups", {}, [ + { + id: 1, + status: "open", + GName: "Larrys Group", + GPass: "password", + leader: 1, + members: [ + { name: "Larry", CID: "ABCD1234", Player: 1 }, + { name: "Barry", CID: "EFGH5678", Player: 2 }, + { name: "Harry", CID: "IJKL9101", Player: 3 }, + ], + stage: [], + ScriptCreated: false, + }, + { + id: 2, + status: "open", + GName: "Group 2", + GPass: "password", + leader: 2, + members: [{ name: "Larry", CID: "ABCD1234", Player: 3 }], + stage: [], + ScriptCreated: false, + }, + { + id: 3, + status: "open", + GName: "Group 3", + GPass: "password", + leader: 3, + members: [ + { name: "Larry", CID: "ABCD1234", Player: 2 }, + { name: "Barry", CID: "EFGH5678", Player: 3 }, + ], + stage: [], + ScriptCreated: false, + }, + { + id: 4, + status: "open", + GName: "Group 4", + GPass: "password", + leader: 4, + members: [{ name: "Larry", CID: "ABCD1234", Player: 4 }], + stage: [], + ScriptCreated: false, + }, + ]).then((data) => setGroups(data)); + }, []); + + useEffect(() => { + if (!inGroup) { + setCurrentPage("GroupDashboard"); + } + }, [inGroup]); + useNuiEvent("startJob", () => { setCurrentPage("GroupJob"); }); @@ -87,15 +167,19 @@ const App = () => { ref={appDiv} data-theme={theme} > - {!devMode && ()} + {!devMode && ( + + )}
Groups
{currentPage === "GroupDashboard" && ( - + )} {currentPage === "GroupJob" && ( - + )} diff --git a/web/src/components/ConfirmationDialog.tsx b/web/src/components/ConfirmationDialog.tsx index a717a7f..9af94ff 100644 --- a/web/src/components/ConfirmationDialog.tsx +++ b/web/src/components/ConfirmationDialog.tsx @@ -1,11 +1,11 @@ import React from 'react'; -const ConfirmationDialog = ({ onClose, onConfirm }) => { +const ConfirmationDialog = ({ onClose, onConfirm, confirmation}) => { return (

- Leave the group? + {confirmation.message}

{currentGroups?.length > 0 ? ( -

Create a group or join an existing group below

+

+ Create a group or join an existing group below +

) : (

Create a group to get started

)} @@ -130,7 +140,6 @@ const GroupDashboard = ({ setCurrentPage, setInGroup, inGroup}) => { let isMember = group.members.some( (member) => member.Player === playerData.source ); - if (isMember === true) {} return (
{
<> - {isMember && (renderIcons(isLeader, isMember, group))} + {isMember && renderIcons(isLeader, isMember, group)} {group.members.length} @@ -185,12 +194,16 @@ const GroupDashboard = ({ setCurrentPage, setInGroup, inGroup}) => { /> )} {showPlayerList && ( - setShowPlayerList(false)} currentGroup={currentGroup}/> + setShowPlayerList(false)} + currentGroup={currentGroup} + /> )} {isDialogOpen && ( setIsDialogOpen(false)} onConfirm={handleConfirm} + confirmation={confirmation} /> )}
diff --git a/web/src/components/GroupJob.tsx b/web/src/components/GroupJob.tsx index 98d43da..c05c620 100644 --- a/web/src/components/GroupJob.tsx +++ b/web/src/components/GroupJob.tsx @@ -13,26 +13,38 @@ interface GroupJobProps { initialSteps: GroupJobStep[]; } -const GroupJob: React.FC = ({ setCurrentPage, inGroup }) => { - const { groups } = useGroupStore(); +const GroupJob: React.FC = ({ setCurrentPage }) => { + const { currentGroups, currentGroup, setCurrentGroup, inGroup, setInGroup } = useGroupStore(); const { playerData } = usePlayerDataStore(); - const { groupJobSteps, getGroupJobSteps } = useGroupJobStepStore(); - const [steps, setSteps] = useState([]); + const { groupJobSteps } = useGroupJobStepStore(); const [isDialogOpen, setIsDialogOpen] = useState(false); + const [confirmation, setConfirmation] = useState({ message: null, type: null }); useEffect(() => { - getGroupJobSteps(); - }, []); - - useEffect(() => { - setSteps(groupJobSteps); - }, [groupJobSteps]); + setInGroup( + currentGroups && + currentGroups.length > 0 && + currentGroups.some((group) => + group.members.some((member) => member.Player === playerData.source) + ) + ); + setCurrentGroup( + currentGroups.find((group) => + group.members.some((member) => member.Player === playerData.source) + ) + ); + }, [currentGroups]); const handleConfirm = () => { - fetchReactNui('leaveGroup') + fetchReactNui("leaveGroup"); setIsDialogOpen(false); }; + const leaveGroup = () => { + setConfirmation({message: "Leave the group?", type: "leaveGroup"}) + setIsDialogOpen(true); + }; + return (
@@ -45,21 +57,21 @@ const GroupJob: React.FC = ({ setCurrentPage, inGroup }) => { Show Groups
- {steps.length > 0 ? ( + {groupJobSteps.length > 0 ? (

Here are the current group tasks

) : (

No tasks available

)}
- {steps.map((step) => ( + {groupJobSteps.map((step) => (
= ({ setCurrentPage, inGroup }) => { setIsDialogOpen(false)} onConfirm={handleConfirm} + confirmation={confirmation} /> )}
diff --git a/web/src/components/PlayerList.tsx b/web/src/components/PlayerList.tsx index de9a26b..e6a4a11 100644 --- a/web/src/components/PlayerList.tsx +++ b/web/src/components/PlayerList.tsx @@ -1,16 +1,22 @@ import React, { useContext } from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faUser, faTrash } from '@fortawesome/free-solid-svg-icons'; +import { faUser, faTrash, faCrown } from '@fortawesome/free-solid-svg-icons'; import { usePlayerDataStore } from '../storage/PlayerDataStore'; +import { useGroupStore } from '../storage/GroupStore'; -const PlayerList: React.FC = ({ onClose, currentGroup }) => { +const PlayerList: React.FC = ({ onClose }) => { const { playerData } = usePlayerDataStore(); + const { currentGroup } = useGroupStore(); const removeGroupMember = (member) => { console.log('Remove Member', member); }; - const isLeader = currentGroup.members.find(member => member.Player === playerData.source).isLeader; + const promoteGroupMember = (member) => { + console.log('Promote Member', member); + } + + const isLeader = currentGroup.members.find(member => member.Player === playerData.source) && true; return (
@@ -28,13 +34,20 @@ const PlayerList: React.FC = ({ onClose, currentGroup }) => { > <> - { (isLeader && member.Player !== playerData.source) && - removeGroupMember(member)} - /> - } + { (isLeader && member.Player !== playerData.source) && ( + <> + removeGroupMember(member)} + /> + promoteGroupMember(member)} + /> + + )} {member.name}
diff --git a/web/src/storage/GroupJobStepStore.ts b/web/src/storage/GroupJobStepStore.ts index e64f0f9..bc5b18f 100644 --- a/web/src/storage/GroupJobStepStore.ts +++ b/web/src/storage/GroupJobStepStore.ts @@ -1,22 +1,12 @@ import { create } from 'zustand'; import { GroupJobStep } from '../types/GroupJobStep'; -import { fetchReactNui } from '../utils/fetchReactNui'; interface GroupJobStepStore { groupJobSteps: GroupJobStep[]; - getGroupJobSteps: () => void; setGroupJobSteps: (groupJobSteps: GroupJobStep[]) => void; } export const useGroupJobStepStore = create((set) => ({ groupJobSteps: [], - getGroupJobSteps: async () => { - const groupJobSteps = await fetchReactNui('getGroupJobSteps', {}, [ - { id: 1, name: 'Step 1', isDone: false }, - { id: 2, name: 'Step 2', isDone: false }, - { id: 3, name: 'Step 3', isDone: false }, - ]); - set({ groupJobSteps }); - }, setGroupJobSteps: (data) => set({ groupJobSteps: data }), })); \ No newline at end of file diff --git a/web/src/storage/GroupStore.ts b/web/src/storage/GroupStore.ts index d6e8536..30a4e3d 100644 --- a/web/src/storage/GroupStore.ts +++ b/web/src/storage/GroupStore.ts @@ -1,69 +1,20 @@ import { create } from "zustand"; -import { fetchReactNui } from "../utils/fetchReactNui"; import { Group } from "../types/Group"; import { GroupJobStep } from "../types/GroupJobStep"; interface GroupStore { currentGroups: Group[]; + currentGroup: Group; inGroup: boolean; - refreshGroups: () => void; setGroups: (currentGroups: Group[]) => void; + setCurrentGroup: (currentGroup: Group) => void; + setInGroup: (inGroup: boolean) => void; } export const useGroupStore = create((set) => ({ currentGroups: [], - refreshGroups: async () => { - const currentGroups = await fetchReactNui("refreshGroups", {}, [ - { - id: 1, - status: "open", - GName: "Larrys Group", - GPass: "password", - leader: 1, - members: [ - { name: "Larry", CID: "ABCD1234", Player: 1 }, - { name: "Barry", CID: "EFGH5678", Player: 2 }, - { name: "Harry", CID: "IJKL9101", Player: 3 }, - ], - stage: [], - ScriptCreated: false, - }, - { - id: 2, - status: "open", - GName: "Group 2", - GPass: "password", - leader: 2, - members: [{ name: "Larry", CID: "ABCD1234", Player: 3 }], - stage: [], - ScriptCreated: false, - }, - { - id: 3, - status: "open", - GName: "Group 3", - GPass: "password", - leader: 3, - members: [ - { name: "Larry", CID: "ABCD1234", Player: 2 }, - { name: "Barry", CID: "EFGH5678", Player: 3 }, - ], - stage: [], - ScriptCreated: false, - }, - { - id: 4, - status: "open", - GName: "Group 4", - GPass: "password", - leader: 4, - members: [{ name: "Larry", CID: "ABCD1234", Player: 4 }], - stage: [], - ScriptCreated: false, - }, - ]); - set({ currentGroups }, true); - console.log("Fetched groups"); - }, - setGroups: (currentGroups) => set({ currentGroups }), + inGroup: false, + setGroups: (data) => set({ currentGroups: data }), + setCurrentGroup: (data) => set({ currentGroup: data }), + setInGroup: (data) => set({ inGroup: data }), })); \ No newline at end of file diff --git a/web/src/storage/PlayerDataStore.ts b/web/src/storage/PlayerDataStore.ts index 923f13c..79fb07d 100644 --- a/web/src/storage/PlayerDataStore.ts +++ b/web/src/storage/PlayerDataStore.ts @@ -11,10 +11,6 @@ interface PlayerDataStore { } export const usePlayerDataStore = create((set) => ({ - playerData: { - source: 1, - citizenId: 'ABCD1234', - name: 'Testicle', - }, + playerData: null, setPlayerData: (data) => set({ playerData: data }), }));