From 1465a556023f2e7ab325e9fba7a7b4ef5068f420 Mon Sep 17 00:00:00 2001 From: mudabbir-ahmad Date: Thu, 9 Apr 2026 14:04:55 +0100 Subject: [PATCH] Refactor UI components: update styles for consistency, changed colour scheme, dont like all the white light colours. --- src/components/UI/Card.js | 4 +- src/components/gameplay/CacheCardItem.js | 84 +++-- src/components/gameplay/ClaimTimerView.js | 13 +- src/components/layout/BottomNavbar.js | 14 +- src/components/layout/Screen.js | 4 +- src/components/layout/TopNavbar.js | 4 +- .../screens/DepartmentSettingsScreen.js | 92 +++-- src/components/screens/GameSettingsScreen.js | 160 +++++---- src/components/screens/LeaderboardScreen.js | 45 ++- src/components/screens/LoginScreen.js | 30 +- src/components/screens/MapScreen.js | 232 ++++++------- src/components/screens/PlayersScreen.js | 34 +- src/components/screens/RegisterScreen.js | 323 +++++++++--------- src/components/screens/TeamScreen.js | 124 +++---- 14 files changed, 556 insertions(+), 607 deletions(-) diff --git a/src/components/UI/Card.js b/src/components/UI/Card.js index 22d6d3f..e248505 100644 --- a/src/components/UI/Card.js +++ b/src/components/UI/Card.js @@ -13,12 +13,12 @@ const Card = ({children, style}) => { const styles = StyleSheet.create({ card: { - backgroundColor: '#ffffff', + backgroundColor: '#313244', borderRadius: 8, padding: 12, marginBottom: 8, borderWidth: 1, - borderColor: '#e5e7eb', + borderColor: '#45475a', }, }); diff --git a/src/components/gameplay/CacheCardItem.js b/src/components/gameplay/CacheCardItem.js index 520d7c3..546d93a 100644 --- a/src/components/gameplay/CacheCardItem.js +++ b/src/components/gameplay/CacheCardItem.js @@ -3,33 +3,27 @@ import Card from '../UI/Card'; import {Button} from '../UI/Button'; const CacheCardItem = ({cache, isAdmin, isClaimed, isSelected, onEdit, onDelete, onSelect, disabled, departmentName}) => { -// Initialisation ------------- + // Display name fallback for cache without a name + const displayName = cache.name || cache.clue || 'Unnamed Cache'; - const displayName = cache.name || cache.clue || 'Unnamed Cache'; - -// State ---------------------- -// Handlers ------------------- -// View ----------------------- - - return ( - - - - {displayName} - {isAdmin && departmentName ? ( - Department: {departmentName} - ) : null} - {cache.name ? ( - {cache.clue} - ) : null} - - {/* Players see team-specific claim status; admins see no status */} - {!isAdmin && !disabled && ( - - {isClaimed ? 'Claimed' : 'Available'} - - )} - + return ( + + + + {displayName} + {isAdmin && departmentName ? ( + Department: {departmentName} + ) : null} + {cache.name ? ( + {cache.clue} + ) : null} + + {!isAdmin && !disabled && ( + + {isClaimed ? 'Claimed' : 'Available'} + + )} + {isAdmin ? ( <> @@ -89,55 +83,55 @@ const styles = StyleSheet.create({ alignItems: 'center', marginBottom: 8, }, - clue: {fontSize: 13, color: '#6b7280', marginTop: 2}, - departmentText: {fontSize: 13, color: '#2563eb', marginTop: 2, fontWeight: '600'}, + clue: {fontSize: 13, color: '#6c7086', marginTop: 2}, + departmentText: {fontSize: 13, color: '#89b4fa', marginTop: 2, fontWeight: '600'}, nameWrap: {flex: 1, marginRight: 8}, - name: {fontSize: 15, fontWeight: '600', color: '#1f2937'}, - claimedText: {color: '#9ca3af'}, + name: {fontSize: 15, fontWeight: '600', color: '#cdd6f4'}, + claimedText: {color: '#6c7086'}, status: {fontSize: 13, fontWeight: '600'}, actions: {flexDirection: 'row', gap: 8}, editBtn: { - backgroundColor: '#2563eb', - borderColor: '#2563eb', + backgroundColor: '#89b4fa', + borderColor: '#89b4fa', minHeight: 36, paddingHorizontal: 14, flex: 1, }, deleteBtn: { - backgroundColor: '#dc2626', - borderColor: '#dc2626', + backgroundColor: '#f38ba8', + borderColor: '#f38ba8', minHeight: 36, paddingHorizontal: 14, flex: 1, }, selectBtn: { - backgroundColor: '#16a34a', - borderColor: '#16a34a', + backgroundColor: '#a6e3a1', + borderColor: '#a6e3a1', minHeight: 36, paddingHorizontal: 14, flex: 1, }, selectedBtn: { - backgroundColor: '#6b7280', - borderColor: '#6b7280', + backgroundColor: '#6c7086', + borderColor: '#6c7086', minHeight: 36, paddingHorizontal: 14, flex: 1, }, claimedBtn: { - backgroundColor: '#d1d5db', - borderColor: '#d1d5db', + backgroundColor: '#45475a', + borderColor: '#45475a', minHeight: 36, paddingHorizontal: 14, flex: 1, }, - claimedBtnLabel: {color: '#6b7280', fontWeight: '600', fontSize: 13}, - selectedBtnLabel: {color: '#ffffff', fontWeight: '600', fontSize: 13}, - selectedCard: {borderColor: '#2563eb', borderWidth: 2}, + claimedBtnLabel: {color: '#6c7086', fontWeight: '600', fontSize: 13}, + selectedBtnLabel: {color: '#cdd6f4', fontWeight: '600', fontSize: 13}, + selectedCard: {borderColor: '#89b4fa', borderWidth: 2}, claimedCard: {opacity: 0.5}, disabledCard: {opacity: 0.45}, - disabledText: {color: '#9ca3af'}, - btnLabel: {color: '#ffffff', fontWeight: '600', fontSize: 13}, + disabledText: {color: '#6c7086'}, + btnLabel: {color: '#cdd6f4', fontWeight: '600', fontSize: 13}, }); export default CacheCardItem; diff --git a/src/components/gameplay/ClaimTimerView.js b/src/components/gameplay/ClaimTimerView.js index 6c97e29..45b8c0f 100644 --- a/src/components/gameplay/ClaimTimerView.js +++ b/src/components/gameplay/ClaimTimerView.js @@ -3,15 +3,11 @@ import {StyleSheet, Text, View} from 'react-native'; import {CACHE_CLAIM_TIMER} from '../../utils/geoMath'; const ClaimTimerView = ({ cache, onClaimSuccess, isClaiming, showClaimedPopup }) => { -// Initialisation ------------- -// State ---------------------- - const [timeLeft, setTimeLeft] = useState(CACHE_CLAIM_TIMER); // Use a ref for the callback so it does not appear in the dependency array const onClaimRef = useRef(onClaimSuccess); onClaimRef.current = onClaimSuccess; -// Handlers ------------------- useEffect(() => { let timer; @@ -25,7 +21,6 @@ const ClaimTimerView = ({ cache, onClaimSuccess, isClaiming, showClaimedPopup }) return () => clearTimeout(timer); }, [isClaiming, timeLeft, cache]); -// View ----------------------- // Show "Cache Claimed!" popup after a successful claim if (showClaimedPopup) { @@ -50,27 +45,27 @@ const ClaimTimerView = ({ cache, onClaimSuccess, isClaiming, showClaimedPopup }) const styles = StyleSheet.create({ overlay: { alignSelf: 'center', - backgroundColor: 'rgba(0,0,0,0.75)', + backgroundColor: 'rgba(0, 0, 0, 0.75)', paddingHorizontal: 16, paddingVertical: 12, borderRadius: 10, marginTop: 8, }, text: { - color: '#ffffff', + color: '#cdd6f4', fontSize: 16, fontWeight: '700', }, claimedOverlay: { alignSelf: 'center', - backgroundColor: '#16a34a', + backgroundColor: '#a6e3a1', paddingHorizontal: 20, paddingVertical: 14, borderRadius: 10, marginTop: 8, }, claimedText: { - color: '#ffffff', + color: '#1e1e2e', fontSize: 18, fontWeight: '700', }, diff --git a/src/components/layout/BottomNavbar.js b/src/components/layout/BottomNavbar.js index 4090cb6..b7b7238 100644 --- a/src/components/layout/BottomNavbar.js +++ b/src/components/layout/BottomNavbar.js @@ -90,8 +90,8 @@ const styles = StyleSheet.create({ container: { minHeight: 64, borderTopWidth: 1, - borderTopColor: '#555555', - backgroundColor: '#4a4a4a', + borderTopColor: '#45475a', + backgroundColor: '#313244', flexDirection: 'row', alignItems: 'center', justifyContent: 'space-around', @@ -107,22 +107,22 @@ const styles = StyleSheet.create({ marginHorizontal: 4, }, tabActive: { - backgroundColor: '#5c5c5c', + backgroundColor: '#45475a', }, tabLeave: { - backgroundColor: 'rgba(220,38,38,0.15)', + backgroundColor: 'rgba(243, 139, 168, 0.15)', }, tabText: { - color: '#d1d5db', + color: '#bac2de', fontSize: 12, fontWeight: '600', textAlign: 'center', }, tabTextActive: { - color: '#ffffff', + color: '#cdd6f4', }, tabTextLeave: { - color: '#fca5a5', + color: '#f38ba8', }, }); diff --git a/src/components/layout/Screen.js b/src/components/layout/Screen.js index a73bdf7..988a25a 100644 --- a/src/components/layout/Screen.js +++ b/src/components/layout/Screen.js @@ -44,13 +44,13 @@ const Screen = ({ children, style, showBack = false }) => { const styles = StyleSheet.create({ screen: { flex: 1, - backgroundColor: "#fff", + backgroundColor: '#1e1e2e', }, content: { flex: 1, padding: 15, zIndex: 1, - overflow: "hidden", + overflow: 'hidden', }, }); diff --git a/src/components/layout/TopNavbar.js b/src/components/layout/TopNavbar.js index d39a291..b7bdd91 100644 --- a/src/components/layout/TopNavbar.js +++ b/src/components/layout/TopNavbar.js @@ -47,12 +47,12 @@ const styles = StyleSheet.create({ container: { minHeight: 56, borderBottomWidth: 1, - borderBottomColor: '#333333', + borderBottomColor: '#45475a', flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 12, - backgroundColor: '#000000', + backgroundColor: '#313244', zIndex: 10, }, leftSlot: { diff --git a/src/components/screens/DepartmentSettingsScreen.js b/src/components/screens/DepartmentSettingsScreen.js index 08f15a5..009a0f3 100644 --- a/src/components/screens/DepartmentSettingsScreen.js +++ b/src/components/screens/DepartmentSettingsScreen.js @@ -5,39 +5,35 @@ import {Button, ButtonTray} from '../UI/Button'; import useGameHook from '../../hooks/useGameHook'; const DepartmentSettingsScreen = ({route, navigation}) => { -// Initialisation ------------ + const {SGid, Gid} = route.params; + const {getSubgroup, updateSubgroup, getCaches, resetGame} = useGameHook(); - const {SGid, Gid} = route.params; - const {getSubgroup, updateSubgroup, getCaches, resetGame} = useGameHook(); - -// State ---------------------- - - const [loading, setLoading] = useState(true); - const [saving, setSaving] = useState(false); - const [deptName, setDeptName] = useState(''); - const [joinCode, setJoinCode] = useState(''); - const [teamsEnabled, setTeamsEnabled] = useState(false); - const [cacheTriggerMeters, setCacheTriggerMeters] = useState('20'); - const [cacheCount, setCacheCount] = useState(0); + const [loading, setLoading] = useState(true); + const [saving, setSaving] = useState(false); + const [deptName, setDeptName] = useState(''); + const [joinCode, setJoinCode] = useState(''); + const [teamsEnabled, setTeamsEnabled] = useState(false); + const [cacheTriggerMeters, setCacheTriggerMeters] = useState('20'); + const [cacheCount, setCacheCount] = useState(0); // Handlers ------------------- - useEffect(() => { - const load = async () => { - const sg = await getSubgroup(SGid); - if (sg) { - setDeptName(sg.SubGroupName || ''); - setJoinCode(sg.JoinCode || ''); - setTeamsEnabled(Boolean(sg.TeamsEnabled)); - setCacheTriggerMeters(String(sg.CacheTriggerMeters || 20)); - } - // Load cache count for this department - const caches = await getCaches(Gid, SGid); - setCacheCount((caches || []).length); - setLoading(false); - }; - load(); - }, []); + useEffect(() => { + const load = async () => { + const sg = await getSubgroup(SGid); + if (sg) { + setDeptName(sg.SubGroupName || ''); + setJoinCode(sg.JoinCode || ''); + setTeamsEnabled(Boolean(sg.TeamsEnabled)); + setCacheTriggerMeters(String(sg.CacheTriggerMeters || 20)); + } + // Load cache count for this department + const caches = await getCaches(Gid, SGid); + setCacheCount((caches || []).length); + setLoading(false); + }; + load(); + }, []); const handleSave = async () => { setSaving(true); @@ -167,17 +163,17 @@ const DepartmentSettingsScreen = ({route, navigation}) => { const styles = StyleSheet.create({ center: {justifyContent: 'center', alignItems: 'center'}, formContainer: {paddingBottom: 20}, - sectionTitle: {fontSize: 20, fontWeight: '700', color: '#1f2937', marginBottom: 16}, - label: {fontSize: 14, fontWeight: '600', color: '#374151', marginBottom: 6, marginTop: 14}, + sectionTitle: {fontSize: 20, fontWeight: '700', color: '#cdd6f4', marginBottom: 16}, + label: {fontSize: 14, fontWeight: '600', color: '#bac2de', marginBottom: 6, marginTop: 14}, input: { borderWidth: 1, - borderColor: '#d1d5db', + borderColor: '#45475a', borderRadius: 8, paddingHorizontal: 12, paddingVertical: 10, fontSize: 16, - color: '#1f2937', - backgroundColor: '#ffffff', + color: '#cdd6f4', + backgroundColor: '#313244', }, codeSection: { flexDirection: 'row', @@ -186,11 +182,11 @@ const styles = StyleSheet.create({ marginTop: 16, paddingVertical: 12, paddingHorizontal: 12, - backgroundColor: '#f3f4f6', + backgroundColor: '#313244', borderRadius: 8, }, - codeLabel: {fontSize: 14, fontWeight: '600', color: '#374151'}, - codeValue: {fontSize: 16, fontWeight: '700', color: '#2563eb', letterSpacing: 2}, + codeLabel: {fontSize: 14, fontWeight: '600', color: '#bac2de'}, + codeValue: {fontSize: 16, fontWeight: '700', color: '#89b4fa', letterSpacing: 2}, toggleRow: { flexDirection: 'row', justifyContent: 'space-between', @@ -198,9 +194,9 @@ const styles = StyleSheet.create({ marginTop: 16, paddingVertical: 10, borderBottomWidth: 1, - borderBottomColor: '#e5e7eb', + borderBottomColor: '#45475a', }, - toggleLabel: {fontSize: 14, fontWeight: '600', color: '#374151'}, + toggleLabel: {fontSize: 14, fontWeight: '600', color: '#bac2de'}, infoRow: { flexDirection: 'row', justifyContent: 'space-between', @@ -208,20 +204,20 @@ const styles = StyleSheet.create({ marginTop: 16, paddingVertical: 12, paddingHorizontal: 12, - backgroundColor: '#f3f4f6', + backgroundColor: '#313244', borderRadius: 8, }, - infoLabel: {fontSize: 14, fontWeight: '600', color: '#374151'}, - infoValue: {fontSize: 16, fontWeight: '700', color: '#1f2937'}, + infoLabel: {fontSize: 14, fontWeight: '600', color: '#bac2de'}, + infoValue: {fontSize: 16, fontWeight: '700', color: '#cdd6f4'}, saveWrap: {marginTop: 24}, - saveButton: {backgroundColor: '#16a34a', borderColor: '#16a34a'}, - saveLabel: {color: '#ffffff', fontWeight: '600'}, + saveButton: {backgroundColor: '#a6e3a1', borderColor: '#a6e3a1'}, + saveLabel: {color: '#1e1e2e', fontWeight: '600'}, mapWrap: {marginTop: 16}, - mapButton: {backgroundColor: '#2563eb', borderColor: '#2563eb'}, - mapLabel: {color: '#ffffff', fontWeight: '600'}, + mapButton: {backgroundColor: '#89b4fa', borderColor: '#89b4fa'}, + mapLabel: {color: '#1e1e2e', fontWeight: '600'}, resetWrap: {marginTop: 30}, - resetButton: {backgroundColor: '#dc2626', borderColor: '#dc2626'}, - resetLabel: {color: '#ffffff', fontWeight: '600'}, + resetButton: {backgroundColor: '#f38ba8', borderColor: '#f38ba8'}, + resetLabel: {color: '#1e1e2e', fontWeight: '600'}, }); export default DepartmentSettingsScreen; diff --git a/src/components/screens/GameSettingsScreen.js b/src/components/screens/GameSettingsScreen.js index addd150..3a22e6e 100644 --- a/src/components/screens/GameSettingsScreen.js +++ b/src/components/screens/GameSettingsScreen.js @@ -8,63 +8,58 @@ import useGameHook from '../../hooks/useGameHook'; import {getSession, setSessionTeamsEnabled} from '../../hooks/SessionStore'; const GameSettingsScreen = ({navigation}) => { -// Initialisation ------------ + const session = getSession(); + const {getLobby, updateGroup, getSubgroups, createSubgroup, deleteSubgroup, resetGame, getAdminWaitlist, approveAdmin, rejectAdmin, getUser, disbandTeams} = useGameHook(); + const gameApiRef = useRef({ + getLobby, + getSubgroups, + getAdminWaitlist, + getUser, + }); + gameApiRef.current = { + getLobby, + getSubgroups, + getAdminWaitlist, + getUser, + }; + const isMountedRef = useRef(true); + const isRefreshingRef = useRef(false); + const hasHydratedRef = useRef(false); - const session = getSession(); - const {getLobby, updateGroup, getSubgroups, createSubgroup, deleteSubgroup, resetGame, getAdminWaitlist, approveAdmin, rejectAdmin, getUser, disbandTeams} = useGameHook(); - const gameApiRef = useRef({ - getLobby, - getSubgroups, - getAdminWaitlist, - getUser, - }); - gameApiRef.current = { - getLobby, - getSubgroups, - getAdminWaitlist, - getUser, - }; - const isMountedRef = useRef(true); - const isRefreshingRef = useRef(false); - const hasHydratedRef = useRef(false); - -// State ---------------------- - - const [loading, setLoading] = useState(true); - const [saving, setSaving] = useState(false); - const [groupName, setGroupName] = useState(''); - const [businessName, setBusinessName] = useState(''); - const [teamsEnabled, setTeamsEnabled] = useState(session.teamsEnabled); - const [serverTeamsEnabled, setServerTeamsEnabled] = useState(session.teamsEnabled); - const [cacheTriggerMeters, setCacheTriggerMeters] = useState('20'); - const [adminJoinCode, setAdminJoinCode] = useState(''); - const [orgJoinCode, setOrgJoinCode] = useState(''); - const [memberJoinCode, setMemberJoinCode] = useState(''); - const [waitlist, setWaitlist] = useState([]); - const [waitlistNames, setWaitlistNames] = useState({}); - const [isBusinessGroup, setIsBusinessGroup] = useState(Boolean(session.isBusiness)); - // Business subgroup management - const [subgroupList, setSubgroupList] = useState([]); - const [newDeptName, setNewDeptName] = useState(''); + const [loading, setLoading] = useState(true); + const [saving, setSaving] = useState(false); + const [groupName, setGroupName] = useState(''); + const [businessName, setBusinessName] = useState(''); + const [teamsEnabled, setTeamsEnabled] = useState(session.teamsEnabled); + const [serverTeamsEnabled, setServerTeamsEnabled] = useState(session.teamsEnabled); + const [cacheTriggerMeters, setCacheTriggerMeters] = useState('20'); + const [adminJoinCode, setAdminJoinCode] = useState(''); + const [orgJoinCode, setOrgJoinCode] = useState(''); + const [memberJoinCode, setMemberJoinCode] = useState(''); + const [waitlist, setWaitlist] = useState([]); + const [waitlistNames, setWaitlistNames] = useState({}); + const [isBusinessGroup, setIsBusinessGroup] = useState(Boolean(session.isBusiness)); + const [subgroupList, setSubgroupList] = useState([]); + const [newDeptName, setNewDeptName] = useState(''); // Handlers ------------------- - useEffect(() => () => { - isMountedRef.current = false; - }, []); + useEffect(() => () => { + isMountedRef.current = false; + }, []); - const refreshSettings = useCallback(async ({showLoader = false} = {}) => { - const activeSession = getSession(); - if (!activeSession.currentGid) { - if (isMountedRef.current) setLoading(false); - return; - } + const refreshSettings = useCallback(async ({showLoader = false} = {}) => { + const activeSession = getSession(); + if (!activeSession.currentGid) { + if (isMountedRef.current) setLoading(false); + return; + } - // Guard against re-entrant focus refresh calls. - if (isRefreshingRef.current) return; - isRefreshingRef.current = true; + // Guard against re-entrant focus refresh calls. + if (isRefreshingRef.current) return; + isRefreshingRef.current = true; - if (showLoader && isMountedRef.current) setLoading(true); + if (showLoader && isMountedRef.current) setLoading(true); try { const [group, sgs, waitlistRows] = await Promise.all([ @@ -78,7 +73,7 @@ const GameSettingsScreen = ({navigation}) => { if (group) { setGroupName(group.GroupName || ''); setBusinessName(group.BusinessOrSchoolName || ''); - // Organisation mode is based on organisation profile data, not generic org join code presence. + // Organisation mode setIsBusinessGroup(Boolean(group.BusinessOrSchoolName)); const serverTeams = Boolean(group.TeamsEnabled); @@ -487,18 +482,18 @@ const GameSettingsScreen = ({navigation}) => { const styles = StyleSheet.create({ center: {justifyContent: 'center', alignItems: 'center'}, formContainer: {paddingBottom: 20}, - sectionTitle: {fontSize: 20, fontWeight: '700', color: '#1f2937', marginBottom: 16}, - label: {fontSize: 14, fontWeight: '600', color: '#374151', marginBottom: 6, marginTop: 14}, - body: {color: '#4b5563', fontSize: 15}, + sectionTitle: {fontSize: 20, fontWeight: '700', color: '#cdd6f4', marginBottom: 16}, + label: {fontSize: 14, fontWeight: '600', color: '#bac2de', marginBottom: 6, marginTop: 14}, + body: {color: '#bac2de', fontSize: 15}, input: { borderWidth: 1, - borderColor: '#d1d5db', + borderColor: '#45475a', borderRadius: 8, paddingHorizontal: 12, paddingVertical: 10, fontSize: 16, - color: '#1f2937', - backgroundColor: '#ffffff', + color: '#cdd6f4', + backgroundColor: '#313244', }, toggleRow: { flexDirection: 'row', @@ -507,9 +502,9 @@ const styles = StyleSheet.create({ marginTop: 16, paddingVertical: 10, borderBottomWidth: 1, - borderBottomColor: '#e5e7eb', + borderBottomColor: '#45475a', }, - toggleLabel: {fontSize: 14, fontWeight: '600', color: '#374151'}, + toggleLabel: {fontSize: 14, fontWeight: '600', color: '#bac2de'}, codeSection: { flexDirection: 'row', justifyContent: 'space-between', @@ -517,47 +512,44 @@ const styles = StyleSheet.create({ marginTop: 16, paddingVertical: 12, paddingHorizontal: 12, - backgroundColor: '#f3f4f6', + backgroundColor: '#313244', borderRadius: 8, }, - codeLabel: {fontSize: 14, fontWeight: '600', color: '#374151'}, - codeValue: {fontSize: 16, fontWeight: '700', color: '#2563eb', letterSpacing: 2}, + codeLabel: {fontSize: 14, fontWeight: '600', color: '#bac2de'}, + codeValue: {fontSize: 16, fontWeight: '700', color: '#89b4fa', letterSpacing: 2}, saveWrap: {marginTop: 24}, - saveButton: {backgroundColor: '#16a34a', borderColor: '#16a34a'}, - saveLabel: {color: '#ffffff', fontWeight: '600'}, - // Department / subgroup styles + saveButton: {backgroundColor: '#a6e3a1', borderColor: '#a6e3a1'}, + saveLabel: {color: '#1e1e2e', fontWeight: '600'}, deptSection: {marginTop: 30}, - deptIndexLabel: {fontSize: 14, fontWeight: '700', color: '#374151', marginBottom: 8}, + deptIndexLabel: {fontSize: 14, fontWeight: '700', color: '#bac2de', marginBottom: 8}, deptCardRow: {flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8}, deptCardInfo: {flex: 1, paddingRight: 10}, deptCardActions: {flexDirection: 'row', gap: 6, flex: 0}, - deptInfoLabel: {fontSize: 12, fontWeight: '600', color: '#6b7280', marginBottom: 2}, - deptName: {fontSize: 15, fontWeight: '700', color: '#1f2937'}, - deptCode: {fontSize: 13, fontWeight: '600', color: '#2563eb', marginTop: 2, letterSpacing: 1}, - deptDeleteButton: {backgroundColor: '#dc2626', borderColor: '#dc2626', minHeight: 36, flex: 0, paddingHorizontal: 10}, - deptOpenButton: {backgroundColor: '#2563eb', borderColor: '#2563eb', minHeight: 36, flex: 0, paddingHorizontal: 10}, - deptBtnLabel: {color: '#ffffff', fontWeight: '600', fontSize: 13}, + deptInfoLabel: {fontSize: 12, fontWeight: '600', color: '#6c7086', marginBottom: 2}, + deptName: {fontSize: 15, fontWeight: '700', color: '#cdd6f4'}, + deptCode: {fontSize: 13, fontWeight: '600', color: '#89b4fa', marginTop: 2, letterSpacing: 1}, + deptDeleteButton: {backgroundColor: '#f38ba8', borderColor: '#f38ba8', minHeight: 36, flex: 0, paddingHorizontal: 10}, + deptOpenButton: {backgroundColor: '#89b4fa', borderColor: '#89b4fa', minHeight: 36, flex: 0, paddingHorizontal: 10}, + deptBtnLabel: {color: '#1e1e2e', fontWeight: '600', fontSize: 13}, createDeptRow: {flexDirection: 'row', gap: 10, marginTop: 12, alignItems: 'center'}, - createDeptButton: {backgroundColor: '#16a34a', borderColor: '#16a34a', flex: 0, paddingHorizontal: 16}, - createDeptLabel: {color: '#ffffff', fontWeight: '600'}, - emptyText: {color: '#9ca3af', textAlign: 'center', marginTop: 10, fontSize: 14}, - // Admin waitlist styles + createDeptButton: {backgroundColor: '#a6e3a1', borderColor: '#a6e3a1', flex: 0, paddingHorizontal: 16}, + createDeptLabel: {color: '#1e1e2e', fontWeight: '600'}, + emptyText: {color: '#6c7086', textAlign: 'center', marginTop: 10, fontSize: 14}, waitlistSection: {marginTop: 30}, waitlistRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', }, - waitlistName: {fontSize: 15, fontWeight: '600', color: '#1f2937', flex: 1}, + waitlistName: {fontSize: 15, fontWeight: '600', color: '#cdd6f4', flex: 1}, waitlistActions: {flexDirection: 'row', gap: 6}, - approveButton: {backgroundColor: '#16a34a', borderColor: '#16a34a', minHeight: 36, flex: 0, paddingHorizontal: 10}, - approveBtnLabel: {color: '#ffffff', fontWeight: '600', fontSize: 13}, - rejectButton: {backgroundColor: '#dc2626', borderColor: '#dc2626', minHeight: 36, flex: 0, paddingHorizontal: 10}, - rejectBtnLabel: {color: '#ffffff', fontWeight: '600', fontSize: 13}, - // Reset game styles + approveButton: {backgroundColor: '#a6e3a1', borderColor: '#a6e3a1', minHeight: 36, flex: 0, paddingHorizontal: 10}, + approveBtnLabel: {color: '#1e1e2e', fontWeight: '600', fontSize: 13}, + rejectButton: {backgroundColor: '#f38ba8', borderColor: '#f38ba8', minHeight: 36, flex: 0, paddingHorizontal: 10}, + rejectBtnLabel: {color: '#1e1e2e', fontWeight: '600', fontSize: 13}, resetSection: {marginTop: 30}, - resetButton: {backgroundColor: '#dc2626', borderColor: '#dc2626'}, - resetLabel: {color: '#ffffff', fontWeight: '600'}, + resetButton: {backgroundColor: '#f38ba8', borderColor: '#f38ba8'}, + resetLabel: {color: '#1e1e2e', fontWeight: '600'}, }); export default GameSettingsScreen; diff --git a/src/components/screens/LeaderboardScreen.js b/src/components/screens/LeaderboardScreen.js index c30b5fa..b347587 100644 --- a/src/components/screens/LeaderboardScreen.js +++ b/src/components/screens/LeaderboardScreen.js @@ -411,13 +411,13 @@ const LeaderboardScreen = ({navigation, route}) => { const styles = StyleSheet.create({ center: {justifyContent: 'center', alignItems: 'center'}, container: {padding: 0}, - body: {color: '#4b5563', fontSize: 15}, - departmentTitle: {fontSize: 20, fontWeight: '700', color: '#1f2937', paddingHorizontal: 15, paddingTop: 15, marginBottom: 6}, - openLabel: {fontSize: 13, fontWeight: '700', color: '#2563eb'}, + body: {color: '#bac2de', fontSize: 15}, + departmentTitle: {fontSize: 20, fontWeight: '700', color: '#cdd6f4', paddingHorizontal: 15, paddingTop: 15, marginBottom: 6}, + openLabel: {fontSize: 13, fontWeight: '700', color: '#89b4fa'}, tabRow: { flexDirection: 'row', borderBottomWidth: 1, - borderBottomColor: '#e5e7eb', + borderBottomColor: '#45475a', }, tabButton: { flex: 1, @@ -426,47 +426,44 @@ const styles = StyleSheet.create({ }, tabButtonActive: { borderBottomWidth: 2, - borderBottomColor: '#2563eb', + borderBottomColor: '#89b4fa', }, - tabLabel: {fontSize: 15, fontWeight: '600', color: '#6b7280'}, - tabLabelActive: {color: '#2563eb'}, + tabLabel: {fontSize: 15, fontWeight: '600', color: '#6c7086'}, + tabLabelActive: {color: '#89b4fa'}, listSection: {flex: 1, paddingHorizontal: 15, paddingTop: 10}, rankRow: { flexDirection: 'row', alignItems: 'center', gap: 10, }, - rank: {fontSize: 16, fontWeight: '700', color: '#374151', width: 32}, - rankName: {flex: 1, fontSize: 15, fontWeight: '600', color: '#1f2937'}, - score: {fontSize: 14, fontWeight: '600', color: '#16a34a'}, + rank: {fontSize: 16, fontWeight: '700', color: '#bac2de', width: 32}, + rankName: {flex: 1, fontSize: 15, fontWeight: '600', color: '#cdd6f4'}, + score: {fontSize: 14, fontWeight: '600', color: '#a6e3a1'}, subRow: { flexDirection: 'row', alignItems: 'center', paddingLeft: 42, paddingVertical: 6, borderTopWidth: 1, - borderTopColor: '#f3f4f6', + borderTopColor: '#45475a', }, - subName: {fontSize: 13, color: '#4b5563'}, - subScore: {fontSize: 13, fontWeight: '600', color: '#16a34a', marginRight: 8}, - emptyText: {color: '#9ca3af', textAlign: 'center', marginTop: 30, fontSize: 14}, - // Admin delete team button + subName: {fontSize: 13, color: '#bac2de'}, + subScore: {fontSize: 13, fontWeight: '600', color: '#a6e3a1', marginRight: 8}, + emptyText: {color: '#6c7086', textAlign: 'center', marginTop: 30, fontSize: 14}, deleteTeamWrap: {marginTop: 8, paddingLeft: 42, flexDirection: 'row', gap: 8}, - resetTeamButton: {backgroundColor: '#f59e0b', borderColor: '#f59e0b', minHeight: 36, flex: 1}, - deleteTeamButton: {backgroundColor: '#dc2626', borderColor: '#dc2626', minHeight: 36, flex: 1}, - deleteTeamLabel: {color: '#ffffff', fontWeight: '600', fontSize: 13}, - // Admin reset mini button (inline) + resetTeamButton: {backgroundColor: '#f4a460', borderColor: '#f4a460', minHeight: 36, flex: 1}, + deleteTeamButton: {backgroundColor: '#f38ba8', borderColor: '#f38ba8', minHeight: 36, flex: 1}, + deleteTeamLabel: {color: '#1e1e2e', fontWeight: '600', fontSize: 13}, resetMiniButton: { - backgroundColor: '#f59e0b', + backgroundColor: '#f4a460', borderRadius: 6, paddingHorizontal: 10, paddingVertical: 4, marginLeft: 6, }, - resetMiniLabel: {color: '#ffffff', fontWeight: '600', fontSize: 12}, - // Current user self-highlight (light green card / sub-row) - selfCard: {backgroundColor: '#dcfce7', borderColor: '#86efac'}, - selfSubRow: {backgroundColor: '#dcfce7'}, + resetMiniLabel: {color: '#1e1e2e', fontWeight: '600', fontSize: 12}, + selfCard: {backgroundColor: 'rgba(166, 227, 161, 0.15)', borderColor: '#a6e3a1'}, + selfSubRow: {backgroundColor: 'rgba(166, 227, 161, 0.15)'}, }); export default LeaderboardScreen; diff --git a/src/components/screens/LoginScreen.js b/src/components/screens/LoginScreen.js index 497b3d8..7d30de9 100644 --- a/src/components/screens/LoginScreen.js +++ b/src/components/screens/LoginScreen.js @@ -5,16 +5,9 @@ import Screen from '../layout/Screen'; import {Button, ButtonTray} from '../UI/Button'; const LoginScreen = ({ navigation }) => { -// Initialisation ------------- - const { email, password, error, isLoading, setEmail, setPassword, login } = useAuthHook(); - -// State ---------------------- - const [submitting, setSubmitting] = useState(false); -// Handlers ------------------- - const handleLogin = async () => { setSubmitting(true); const user = await login(); @@ -29,8 +22,6 @@ const LoginScreen = ({ navigation }) => { navigation.reset({ index: 0, routes: [{ name: 'Game' }] }); }; -// View ----------------------- - return ( @@ -39,7 +30,7 @@ const LoginScreen = ({ navigation }) => { { { -// Initialisation ------------ + const session = getSession(); + const {getCaches, claimCache, upsertCache, deleteCache, joinPrivateGame, createPrivateGame, getLobby, getUser, getSubgroups, getGroupByOrgCode} = useGameHook(); - const session = getSession(); - const {getCaches, claimCache, upsertCache, deleteCache, joinPrivateGame, createPrivateGame, getLobby, getUser, getSubgroups, getGroupByOrgCode} = useGameHook(); + // Stable ref to prevent infinite re-render loops + const getCachesRef = useRef(getCaches); + getCachesRef.current = getCaches; + const lastAppliedRouteDepartmentRef = useRef(null); - // Stable ref to prevent infinite re-render loops - const getCachesRef = useRef(getCaches); - getCachesRef.current = getCaches; - const lastAppliedRouteDepartmentRef = useRef(null); + const [inGame, setInGame] = useState(Boolean(session.currentGid)); + const [isAdmin, setIsAdmin] = useState(session.isAcceptedAdmin); + const [userLocation, setUserLocation] = useState(null); + const [heading, setHeading] = useState(null); + const [playerLoading, setPlayerLoading] = useState(true); + const [cacheRecords, setCacheRecords] = useState([]); + const [error, setError] = useState(''); + const [gameCode, setGameCode] = useState(''); + const [groupInfo, setGroupInfo] = useState(null); + const [selectedCacheId, setSelectedCacheIdState] = useState(session.selectedCacheId); + const [claimedPopupVisible, setClaimedPopupVisible] = useState(false); + const [subgroups, setSubgroups] = useState([]); -// State ---------------------- + // Business join flow state + const [joinStep, setJoinStep] = useState(null); + const [orgCode, setOrgCode] = useState(''); + const [deptCode, setDeptCode] = useState(''); + const [matchedGroup, setMatchedGroup] = useState(null); + const [joinError, setJoinError] = useState(''); - const [inGame, setInGame] = useState(Boolean(session.currentGid)); - const [isAdmin, setIsAdmin] = useState(session.isAcceptedAdmin); - const [userLocation, setUserLocation] = useState(null); - const [heading, setHeading] = useState(null); - const [playerLoading, setPlayerLoading] = useState(true); - const [cacheRecords, setCacheRecords] = useState([]); - const [error, setError] = useState(''); - const [gameCode, setGameCode] = useState(''); - const [groupInfo, setGroupInfo] = useState(null); - const [selectedCacheId, setSelectedCacheIdState] = useState(session.selectedCacheId); - const [claimedPopupVisible, setClaimedPopupVisible] = useState(false); - const [subgroups, setSubgroups] = useState([]); + // Admin cache creation / editing state + const [isCreating, setIsCreating] = useState(false); + const [editingCacheId, setEditingCacheId] = useState(null); + const [newCoord, setNewCoord] = useState(null); + const [newName, setNewName] = useState(''); + const [newClue, setNewClue] = useState(''); + const [selectedCacheSubgroupId, setSelectedCacheSubgroupId] = useState(null); + const [departmentDropdownOpen, setDepartmentDropdownOpen] = useState(false); - // Business join flow state - const [joinStep, setJoinStep] = useState(null); // null | 'deptCode' - const [orgCode, setOrgCode] = useState(''); - const [deptCode, setDeptCode] = useState(''); - const [matchedGroup, setMatchedGroup] = useState(null); - const [joinError, setJoinError] = useState(''); + const claimDistance = groupInfo?.CacheTriggerMeters || 20; + const isPlayer = inGame && !isAdmin; + const requiresTeam = Boolean(isPlayer && groupInfo?.TeamsEnabled && !session.currentTid); + const EMPTY_CACHES = useMemo(() => [], []); - // Admin cache creation / editing state - const [isCreating, setIsCreating] = useState(false); - const [editingCacheId, setEditingCacheId] = useState(null); - const [newCoord, setNewCoord] = useState(null); - const [newName, setNewName] = useState(''); - const [newClue, setNewClue] = useState(''); - const [selectedCacheSubgroupId, setSelectedCacheSubgroupId] = useState(null); - const [departmentDropdownOpen, setDepartmentDropdownOpen] = useState(false); - - const claimDistance = groupInfo?.CacheTriggerMeters || 20; - const isPlayer = inGame && !isAdmin; - const requiresTeam = Boolean(isPlayer && groupInfo?.TeamsEnabled && !session.currentTid); - const EMPTY_CACHES = useMemo(() => [], []); - - // Caches not yet claimed by the current user's team (or user if no team) - const activeCachesForPlayer = useMemo(() => { - if (!isPlayer) return EMPTY_CACHES; - return cacheRecords.filter((cache) => { - const claims = cache.Claims || []; - if (session.currentTid) { - return !claims.some((c) => c.Tid === session.currentTid); - } - return !claims.some((c) => c.Uid === session.currentUid); - }); - }, [cacheRecords, isPlayer, session.currentTid, session.currentUid, EMPTY_CACHES]); + // Caches not yet claimed by the current user's team (or user if no team) + const activeCachesForPlayer = useMemo(() => { + if (!isPlayer) return EMPTY_CACHES; + return cacheRecords.filter((cache) => { + const claims = cache.Claims || []; + if (session.currentTid) { + return !claims.some((c) => c.Tid === session.currentTid); + } + return !claims.some((c) => c.Uid === session.currentUid); + }); + }, [cacheRecords, isPlayer, session.currentTid, session.currentUid, EMPTY_CACHES]); const {visibleCaches, isClaiming, setIsClaiming} = usePlayerGame( (isPlayer && !requiresTeam) ? userLocation : null, @@ -83,31 +79,29 @@ const MapScreen = ({navigation, route}) => { selectedCacheId, ); - const mapRegion = userLocation - ? {...userLocation, latitudeDelta: 0.01, longitudeDelta: 0.01} - : DEFAULT_REGION; + const mapRegion = userLocation + ? {...userLocation, latitudeDelta: 0.01, longitudeDelta: 0.01} + : DEFAULT_REGION; -// Handlers ------------------- + useEffect(() => { + if (!session.currentGid) return; + getLobby(session.currentGid).then(setGroupInfo); + getSubgroups(session.currentGid).then(setSubgroups); + }, [inGame]); - useEffect(() => { - if (!session.currentGid) return; - getLobby(session.currentGid).then(setGroupInfo); - getSubgroups(session.currentGid).then(setSubgroups); - }, [inGame]); - - // Default member subgroup SGid for cache creation (first non-admin subgroup) - const departments = useMemo( - () => subgroups.filter((sg) => !sg.IsAdminGroup), - [subgroups], - ); - const defaultMemberSGid = departments[0]?.SGid || null; - const departmentNamesById = useMemo(() => { - const map = {}; - for (const subgroup of departments) { - map[String(subgroup.SGid)] = subgroup.SubGroupName || `Department ${subgroup.SGid}`; - } - return map; - }, [departments]); + // Default member subgroup SGid for cache creation (first non-admin subgroup) + const departments = useMemo( + () => subgroups.filter((sg) => !sg.IsAdminGroup), + [subgroups], + ); + const defaultMemberSGid = departments[0]?.SGid || null; + const departmentNamesById = useMemo(() => { + const map = {}; + for (const subgroup of departments) { + map[String(subgroup.SGid)] = subgroup.SubGroupName || `Department ${subgroup.SGid}`; + } + return map; + }, [departments]); useEffect(() => { if (!isAdmin || departments.length === 0) return; @@ -378,6 +372,8 @@ const MapScreen = ({navigation, route}) => { return claims.some((c) => c.Uid === session.currentUid); }; + const showAdminDepartmentLabel = Boolean(isAdmin && groupInfo?.BusinessOrSchoolName); + // View ----------------------- // Not in a game — Business flow @@ -668,7 +664,7 @@ const MapScreen = ({navigation, route}) => { key={cache.id} cache={cache} isAdmin={true} - departmentName={departmentNamesById[String(cache.subgroupId)] || 'Unassigned'} + departmentName={showAdminDepartmentLabel ? (departmentNamesById[String(cache.subgroupId)] || 'Unassigned') : null} onEdit={handleEditCache} onDelete={handleDeleteCache} /> @@ -755,33 +751,32 @@ const styles = StyleSheet.create({ center: {justifyContent: 'center', alignItems: 'center'}, containerMap: {padding: 0}, mapContainer: {height: 200}, - error: {color: '#dc2626', fontSize: 15}, - loadingText: {color: '#6b7280', fontSize: 14, marginTop: 10}, + error: {color: '#f38ba8', fontSize: 15}, + loadingText: {color: '#6c7086', fontSize: 14, marginTop: 10}, inputRow: {flexDirection: 'row', gap: 10, marginBottom: 15, width: '100%', paddingHorizontal: 20}, fullRow: {width: '100%', paddingHorizontal: 20}, codeInput: { flex: 1, borderWidth: 1, - borderColor: '#d1d5db', + borderColor: '#45475a', borderRadius: 8, paddingHorizontal: 12, paddingVertical: 10, fontSize: 16, - color: '#1f2937', - backgroundColor: '#ffffff', + color: '#cdd6f4', + backgroundColor: '#313244', }, - joinButton: {backgroundColor: '#2563eb', borderColor: '#2563eb', flex: 0, paddingHorizontal: 20}, - joinLabel: {color: '#ffffff', fontWeight: '600'}, - createButton: {backgroundColor: '#16a34a', borderColor: '#16a34a'}, - createLabel: {color: '#ffffff', fontWeight: '600'}, - // Business join flow styles - bizTitle: {fontSize: 22, fontWeight: '700', color: '#1f2937', marginBottom: 6, textAlign: 'center'}, - bizSubtitle: {fontSize: 14, color: '#6b7280', textAlign: 'center', marginBottom: 20, paddingHorizontal: 20}, - joinError: {color: '#dc2626', textAlign: 'center', marginTop: 8, marginBottom: 4, fontSize: 14, paddingHorizontal: 20}, - backButton: {backgroundColor: '#6b7280', borderColor: '#6b7280'}, - backLabel: {color: '#ffffff', fontWeight: '600'}, + joinButton: {backgroundColor: '#89b4fa', borderColor: '#89b4fa', flex: 0, paddingHorizontal: 20}, + joinLabel: {color: '#1e1e2e', fontWeight: '600'}, + createButton: {backgroundColor: '#a6e3a1', borderColor: '#a6e3a1'}, + createLabel: {color: '#1e1e2e', fontWeight: '600'}, + bizTitle: {fontSize: 22, fontWeight: '700', color: '#cdd6f4', marginBottom: 6, textAlign: 'center'}, + bizSubtitle: {fontSize: 14, color: '#bac2de', textAlign: 'center', marginBottom: 20, paddingHorizontal: 20}, + joinError: {color: '#f38ba8', textAlign: 'center', marginTop: 8, marginBottom: 4, fontSize: 14, paddingHorizontal: 20}, + backButton: {backgroundColor: '#6c7086', borderColor: '#6c7086'}, + backLabel: {color: '#cdd6f4', fontWeight: '600'}, warning: { - color: '#dc2626', + color: '#f38ba8', fontWeight: 'bold', textAlign: 'center', paddingVertical: 8, @@ -791,7 +786,7 @@ const styles = StyleSheet.create({ position: 'absolute', top: 10, left: 10, - backgroundColor: 'rgba(0,0,0,0.6)', + backgroundColor: 'rgba(0, 0, 0, 0.6)', borderRadius: 6, width: 36, height: 36, @@ -799,38 +794,36 @@ const styles = StyleSheet.create({ justifyContent: 'center', zIndex: 10, }, - expandIcon: {color: '#ffffff', fontSize: 18, fontWeight: '700'}, - // Admin create button + scrollable cache list + expandIcon: {color: '#cdd6f4', fontSize: 18, fontWeight: '700'}, createCacheWrap: { paddingHorizontal: 12, paddingVertical: 10, - backgroundColor: '#ffffff', + backgroundColor: '#313244', borderBottomWidth: 1, - borderBottomColor: '#e5e7eb', + borderBottomColor: '#45475a', }, - createCacheButton: {backgroundColor: '#2563eb', borderColor: '#2563eb', flex: 0}, - createCacheLabel: {color: '#ffffff', fontWeight: '600'}, - cacheListWrap: {flex: 1, backgroundColor: '#f3f4f6'}, + createCacheButton: {backgroundColor: '#89b4fa', borderColor: '#89b4fa', flex: 0}, + createCacheLabel: {color: '#1e1e2e', fontWeight: '600'}, + cacheListWrap: {flex: 1, backgroundColor: '#1e1e2e'}, cacheListContent: {paddingHorizontal: 12, paddingTop: 10, paddingBottom: 12}, - // Cache editor form formSection: {flex: 1, paddingHorizontal: 12, paddingVertical: 10}, formInput: { borderWidth: 1, - borderColor: '#d1d5db', + borderColor: '#45475a', borderRadius: 8, paddingHorizontal: 12, paddingVertical: 10, fontSize: 16, - color: '#1f2937', - backgroundColor: '#ffffff', + color: '#cdd6f4', + backgroundColor: '#313244', marginBottom: 10, }, - departmentLabel: {fontSize: 13, fontWeight: '600', color: '#374151', marginBottom: 6}, + departmentLabel: {fontSize: 13, fontWeight: '600', color: '#bac2de', marginBottom: 6}, departmentSelector: { borderWidth: 1, - borderColor: '#d1d5db', + borderColor: '#45475a', borderRadius: 8, - backgroundColor: '#ffffff', + backgroundColor: '#313244', paddingHorizontal: 12, paddingVertical: 10, flexDirection: 'row', @@ -838,28 +831,27 @@ const styles = StyleSheet.create({ alignItems: 'center', marginBottom: 8, }, - departmentSelectorText: {color: '#1f2937', fontSize: 15, fontWeight: '500'}, - departmentSelectorChevron: {color: '#6b7280', fontSize: 12, fontWeight: '700'}, + departmentSelectorText: {color: '#cdd6f4', fontSize: 15, fontWeight: '500'}, + departmentSelectorChevron: {color: '#6c7086', fontSize: 12, fontWeight: '700'}, departmentMenu: { borderWidth: 1, - borderColor: '#e5e7eb', + borderColor: '#45475a', borderRadius: 8, - backgroundColor: '#ffffff', + backgroundColor: '#313244', marginBottom: 10, overflow: 'hidden', }, - departmentOption: {paddingHorizontal: 12, paddingVertical: 10, borderBottomWidth: 1, borderBottomColor: '#f3f4f6'}, - departmentOptionText: {color: '#374151', fontSize: 14}, + departmentOption: {paddingHorizontal: 12, paddingVertical: 10, borderBottomWidth: 1, borderBottomColor: '#45475a'}, + departmentOptionText: {color: '#cdd6f4', fontSize: 14}, coordRow: {flexDirection: 'row', gap: 10}, coordField: {flex: 1}, - coordLabel: {fontSize: 12, fontWeight: '600', color: '#6b7280', marginBottom: 4}, - saveButton: {backgroundColor: '#16a34a', borderColor: '#16a34a'}, - saveLabel: {color: '#ffffff', fontWeight: '600'}, - cancelButton: {backgroundColor: '#6b7280', borderColor: '#6b7280'}, - cancelLabel: {color: '#ffffff', fontWeight: '600'}, - // Player cache section - cacheSection: {flex: 1, backgroundColor: '#f3f4f6', paddingHorizontal: 12, paddingTop: 10}, - emptyText: {color: '#9ca3af', textAlign: 'center', marginTop: 20, fontSize: 14}, + coordLabel: {fontSize: 12, fontWeight: '600', color: '#6c7086', marginBottom: 4}, + saveButton: {backgroundColor: '#a6e3a1', borderColor: '#a6e3a1'}, + saveLabel: {color: '#1e1e2e', fontWeight: '600'}, + cancelButton: {backgroundColor: '#6c7086', borderColor: '#6c7086'}, + cancelLabel: {color: '#cdd6f4', fontWeight: '600'}, + cacheSection: {flex: 1, backgroundColor: '#1e1e2e', paddingHorizontal: 12, paddingTop: 10}, + emptyText: {color: '#6c7086', textAlign: 'center', marginTop: 20, fontSize: 14}, mapWrap: {flex: 1}, }); diff --git a/src/components/screens/PlayersScreen.js b/src/components/screens/PlayersScreen.js index b6e0a9a..d5ebd65 100644 --- a/src/components/screens/PlayersScreen.js +++ b/src/components/screens/PlayersScreen.js @@ -287,40 +287,38 @@ const PlayersScreen = ({navigation, route}) => { const styles = StyleSheet.create({ center: {justifyContent: 'center', alignItems: 'center', flex: 1}, container: {padding: 0}, - body: {color: '#4b5563', fontSize: 15}, + body: {color: '#bac2de', fontSize: 15}, sectionTitle: { fontSize: 20, fontWeight: '700', - color: '#1f2937', + color: '#cdd6f4', marginBottom: 12, paddingHorizontal: 15, paddingTop: 15, }, - openLabel: {fontSize: 13, fontWeight: '700', color: '#2563eb'}, + openLabel: {fontSize: 13, fontWeight: '700', color: '#89b4fa'}, listSection: {flex: 1, paddingHorizontal: 15}, - emptyText: {color: '#9ca3af', textAlign: 'center', marginTop: 30, fontSize: 14}, + emptyText: {color: '#6c7086', textAlign: 'center', marginTop: 30, fontSize: 14}, playerRow: { flexDirection: 'row', alignItems: 'center', gap: 8, marginBottom: 8, }, - playerName: {fontSize: 15, fontWeight: '600', color: '#1f2937', flex: 1}, + playerName: {fontSize: 15, fontWeight: '600', color: '#cdd6f4', flex: 1}, playerMeta: {flexDirection: 'row', alignItems: 'center', gap: 6}, - leaderBadge: {fontSize: 11, color: '#2563eb', fontWeight: '700'}, - teamCodeBadge: {fontSize: 12, fontWeight: '700', color: '#16a34a', letterSpacing: 1}, - adminBadge: {fontSize: 12, fontWeight: '700', color: '#dc2626'}, - waitlistBadge: {fontSize: 11, fontWeight: '600', color: '#f59e0b'}, + leaderBadge: {fontSize: 11, color: '#89b4fa', fontWeight: '700'}, + teamCodeBadge: {fontSize: 12, fontWeight: '700', color: '#a6e3a1', letterSpacing: 1}, + adminBadge: {fontSize: 12, fontWeight: '700', color: '#f38ba8'}, + waitlistBadge: {fontSize: 11, fontWeight: '600', color: '#f4a460'}, actionRow: {flexDirection: 'row', gap: 8}, - resetButton: {backgroundColor: '#f59e0b', borderColor: '#f59e0b', minHeight: 36, flex: 1, paddingHorizontal: 10}, - removeButton: {backgroundColor: '#dc2626', borderColor: '#dc2626', minHeight: 36, flex: 1, paddingHorizontal: 10}, - actionLabel: {color: '#ffffff', fontWeight: '600', fontSize: 13}, - departmentName: {fontSize: 14, color: '#6b7280', fontStyle: 'italic'}, - // Waitlisted admin card tint — light red so they read as pending, not regular players - waitlistCard: {backgroundColor: '#FFD1DC', borderColor: '#fca5a5'}, - // Approve / deny buttons for waitlisted admins - approveButton: {backgroundColor: '#16a34a', borderColor: '#16a34a', minHeight: 36, flex: 1, paddingHorizontal: 10}, - denyButton: {backgroundColor: '#dc2626', borderColor: '#dc2626', minHeight: 36, flex: 1, paddingHorizontal: 10}, + resetButton: {backgroundColor: '#f4a460', borderColor: '#f4a460', minHeight: 36, flex: 1, paddingHorizontal: 10}, + removeButton: {backgroundColor: '#f38ba8', borderColor: '#f38ba8', minHeight: 36, flex: 1, paddingHorizontal: 10}, + actionLabel: {color: '#1e1e2e', fontWeight: '600', fontSize: 13}, + departmentName: {fontSize: 14, color: '#6c7086', fontStyle: 'italic'}, + waitlistCard: {backgroundColor: 'rgba(243, 139, 168, 0.15)', borderColor: '#f38ba8'}, + approveButton: {backgroundColor: '#a6e3a1', borderColor: '#a6e3a1', minHeight: 36, flex: 1, paddingHorizontal: 10}, + denyButton: {backgroundColor: '#f38ba8', borderColor: '#f38ba8', minHeight: 36, flex: 1, paddingHorizontal: 10}, }); export default PlayersScreen; diff --git a/src/components/screens/RegisterScreen.js b/src/components/screens/RegisterScreen.js index 9c6774f..c3a6a2f 100644 --- a/src/components/screens/RegisterScreen.js +++ b/src/components/screens/RegisterScreen.js @@ -5,182 +5,175 @@ import Screen from '../layout/Screen'; import {Button, ButtonTray} from '../UI/Button'; const RegisterScreen = ({navigation}) => { -// Initialisation ------------ + const { + username, email, password, confirmPassword, accountType, + error, isLoading, + setUsername, setEmail, setPassword, setConfirmPassword, setAccountType, + register, + } = useAuthHook(); - const { - username, email, password, confirmPassword, accountType, - error, isLoading, - setUsername, setEmail, setPassword, setConfirmPassword, setAccountType, - register, - } = useAuthHook(); + const [submitting, setSubmitting] = useState(false); -// State ---------------------- + const handleRegister = async () => { + setSubmitting(true); + const user = await register(); + setSubmitting(false); + if (!user) return; + if (user.IsAcceptedAdmin) { + navigation.reset({index: 0, routes: [{name: 'Admin'}]}); + return; + } + navigation.reset({index: 0, routes: [{name: 'Game'}]}); + }; - const [submitting, setSubmitting] = useState(false); + return ( + + + Create Account -// Handlers ------------------- + + + + - const handleRegister = async () => { - setSubmitting(true); - const user = await register(); - setSubmitting(false); - if (!user) return; - if (user.IsAcceptedAdmin) { - navigation.reset({index: 0, routes: [{name: 'Admin'}]}); - return; - } - navigation.reset({index: 0, routes: [{name: 'Game'}]}); - }; + + setAccountType('Individual')} + disabled={isLoading} + > + + Individual + + + setAccountType('Business/School')} + disabled={isLoading} + > + + Business + + + -// View ----------------------- + {error ? {error} : null} - return ( - - - Create Account + +