Add create game and manage game pages, update navigation and session handling for individual and business users

This commit is contained in:
bobbert committed 2026-03-17 23:33:30 +00:00
1 parent 1bd640f8d5
commit 6e5fe2b8b8
21 files changed
+831 -137

No files matched your search

@@ -1,11 +1,21 @@
import { useState } from 'react';
import { createPrivateGame, joinAsAdmin } from '../API/API';
import { getSession, setSessionGroup } from '../Model/SessionStore';
import {useState} from 'react';
import {createPrivateGame, getCreatedPrivateGame, joinAsAdmin} from '../API/API';
import {getSession, setSessionMembership} from '../Model/SessionStore';
const useManagePrivateSubtaskViewModel = () => {
const [businessOrSchoolName, setBusinessOrSchoolName] = useState('');
const [error, setError] = useState('');
const isBusinessUser = Boolean(getSession().currentIsBusiness);
const findExistingPrivateGame = async () => {
const { currentUid } = getSession();
if (!currentUid) {
return null;
}
return getCreatedPrivateGame(currentUid);
};
const createNewPrivateGame = async () => {
setError('');
const { currentUid } = getSession();
@@ -14,9 +24,15 @@ const useManagePrivateSubtaskViewModel = () => {
userId: currentUid,
groupName: businessOrSchoolName.trim() || 'New Private Game',
businessOrSchoolName: businessOrSchoolName.trim() || 'Unnamed Business',
isBusiness: true,
isBusiness: isBusinessUser,
});
setSessionGroup(group.Gid, 0);
if (isBusinessUser) {
setSessionMembership({ gid: group.Gid, sgid: 0, isAcceptedAdmin: true });
} else {
setSessionMembership({ gid: group.Gid, sgid: 1, isAcceptedAdmin: false });
}
return group;
} catch (e) {
setError(e.message);
@@ -24,6 +40,26 @@ const useManagePrivateSubtaskViewModel = () => {
}
};
const resolveIndividualPrivateRoute = async () => {
setError('');
try {
const existingGroup = await findExistingPrivateGame();
if (existingGroup) {
setSessionMembership({ gid: existingGroup.Gid, sgid: 1, isAcceptedAdmin: false });
return '(routes)/manage-game';
}
const created = await createNewPrivateGame();
if (!created) {
return null;
}
return '(routes)/create-game';
} catch (e) {
setError(e.message);
return null;
}
};
const joinAdminForPrivate = async () => {
setError('');
const { currentUid } = getSession();
@@ -34,7 +70,10 @@ const useManagePrivateSubtaskViewModel = () => {
});
const gid = response?.Gid ?? null;
if (gid !== null) {
setSessionGroup(gid, 0);
setSessionMembership({ gid, sgid: 0, isAcceptedAdmin: !response.queued });
}
if (response?.queued) {
setError('Admin access request submitted. You will see admin tools after approval.');
}
return response;
} catch (e) {
@@ -46,8 +85,10 @@ const useManagePrivateSubtaskViewModel = () => {
return {
businessOrSchoolName,
error,
isBusinessUser,
setBusinessOrSchoolName,
createNewPrivateGame,
resolveIndividualPrivateRoute,
joinAdminForPrivate,
};
};
+20 -4
View File
@@ -1,22 +1,35 @@
import { useCallback, useEffect, useState } from 'react';
import { createSubgroup, getSubgroups, updateSubgroupCache } from '../API/API';
import { getSession } from '../Model/SessionStore';
import {useCallback, useEffect, useMemo, useState} from 'react';
import {createSubgroup, getVisibleSubgroups, updateSubgroupCache} from '../API/API';
import {getSession} from '../Model/SessionStore';
const useSubgroupAdminViewModel = () => {
const [subgroups, setSubgroups] = useState([]);
const [subgroupName, setSubgroupName] = useState('');
const [cacheTriggerMeters, setCacheTriggerMeters] = useState('20');
const [error, setError] = useState('');
const [searchQuery, setSearchQuery] = useState('');
const { currentGid } = getSession();
const loadSubgroups = useCallback(async () => {
if (!currentGid) {
return;
}
const rows = await getSubgroups(currentGid);
const rows = await getVisibleSubgroups(currentGid);
setSubgroups(rows);
}, [currentGid]);
const filteredSubgroups = useMemo(() => {
if (!searchQuery.trim()) {
return subgroups;
}
const q = searchQuery.trim().toLowerCase();
return subgroups.filter((sg) => {
const nameMatch = sg.SubGroupName.toLowerCase().includes(q);
const idMatch = String(sg.SGid) === q;
return nameMatch || idMatch;
});
}, [subgroups, searchQuery]);
useEffect(() => {
loadSubgroups();
}, [loadSubgroups]);
@@ -52,9 +65,12 @@ const useSubgroupAdminViewModel = () => {
return {
subgroups,
filteredSubgroups,
searchQuery,
subgroupName,
cacheTriggerMeters,
error,
setSearchQuery,
setSubgroupName,
setCacheTriggerMeters,
addSubgroup,