Fixed the ability to add monsters while a fight is going.

This commit is contained in:
Robert Johnson 2025-05-26 21:17:42 -04:00
parent 40a798514d
commit 785af983da

View File

@ -1,8 +1,8 @@
import React, { useState, useEffect, useRef } from 'react';
import React, { useState, useEffect, useRef, useMemo } from 'react';
import { initializeApp } from 'firebase/app';
import { getAuth, signInAnonymously, onAuthStateChanged, signInWithCustomToken } from 'firebase/auth';
import { getFirestore, doc, setDoc, addDoc, getDoc, getDocs, collection, onSnapshot, updateDoc, deleteDoc, query, writeBatch } from 'firebase/firestore';
import { PlusCircle, Users, Swords, Shield, Trash2, Eye, Edit3, Save, XCircle, ChevronsUpDown, UserCheck, UserX, HeartCrack, HeartPulse, Zap, /* ImageIcon removed */ EyeOff, ExternalLink, AlertTriangle } from 'lucide-react'; // ImageIcon removed
import { getFirestore, doc, setDoc, getDoc, getDocs, collection, onSnapshot, updateDoc, deleteDoc, query, writeBatch } from 'firebase/firestore';
import { PlusCircle, Users, Swords, Trash2, Eye, Edit3, Save, XCircle, ChevronsUpDown, UserCheck, UserX, HeartCrack, HeartPulse, Zap, EyeOff, ExternalLink, AlertTriangle } from 'lucide-react'; // ImageIcon removed
// --- Firebase Configuration ---
const firebaseConfig = {
@ -92,6 +92,8 @@ function useFirestoreCollection(collectionPath, queryConstraints = []) {
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
const queryString = useMemo(() => JSON.stringify(queryConstraints), [queryConstraints]);
useEffect(() => {
if (!db || !collectionPath) {
setData([]);
@ -103,8 +105,7 @@ function useFirestoreCollection(collectionPath, queryConstraints = []) {
setIsLoading(true);
setError(null);
const constraints = Array.isArray(queryConstraints) ? queryConstraints : [];
const q = query(collection(db, collectionPath), ...constraints);
const q = query(collection(db, collectionPath), ...queryConstraints);
const unsubscribe = onSnapshot(q, (snapshot) => {
const items = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
@ -118,7 +119,8 @@ function useFirestoreCollection(collectionPath, queryConstraints = []) {
});
return () => unsubscribe();
}, [collectionPath, JSON.stringify(queryConstraints)]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [collectionPath, queryString]);
return { data, isLoading, error };
}
@ -218,6 +220,7 @@ function App() {
TTRPG Initiative Tracker
</h1>
<div className="flex items-center space-x-4">
{/* UID display removed */}
<button
onClick={openPlayerWindow}
className={`px-4 py-2 rounded-md text-sm font-medium transition-colors bg-teal-500 hover:bg-teal-600 text-white flex items-center`}
@ -233,7 +236,7 @@ function App() {
{!isAuthReady && !error && <p>Authenticating...</p>}
</main>
<footer className="bg-slate-900 p-4 text-center text-sm text-slate-400 mt-8">
TTRPG Initiative Tracker v0.1.24
TTRPG Initiative Tracker v0.1.25
</footer>
</div>
);
@ -372,9 +375,9 @@ function AdminView({ userId }) {
className={cardClasses}
style={cardStyle}
>
{/* Overlay for text readability if background image exists */}
<div className={`relative z-10 ${campaign.playerDisplayBackgroundUrl ? 'bg-black bg-opacity-60 p-3 rounded-md' : ''}`}>
<h3 className="text-xl font-semibold text-white">{campaign.name}</h3>
{/* ImageIcon removed from here */}
<button
onClick={(e) => {
e.stopPropagation();
@ -415,12 +418,9 @@ function AdminView({ userId }) {
);
}
// ... (CreateCampaignForm, CharacterManager, EncounterManager, CreateEncounterForm, ParticipantManager, EditParticipantModal, InitiativeControls, DisplayView, Modal, Icons remain the same as v0.1.23)
// For brevity, only the changed AdminView is shown in full. The rest of the components are identical to the previous version.
// The DisplayView, CharacterManager, EncounterManager, etc., and their sub-components
// (CreateEncounterForm, ParticipantManager, EditParticipantModal, InitiativeControls)
// are not changed from the previous version provided (v0.1.23).
// The Modal component and Icon components also remain unchanged.
// --- CreateCampaignForm, CharacterManager, EncounterManager, CreateEncounterForm, ParticipantManager, EditParticipantModal, InitiativeControls, DisplayView, Modal, Icons ---
// The rest of the components are identical to the previous version (v0.1.23) and are included below for completeness.
// The changes for ESLint warnings were primarily in the imports at the top of App.js and in the useFirestoreCollection hook.
function CreateCampaignForm({ onCreate, onCancel }) {
const [name, setName] = useState('');
@ -1060,7 +1060,6 @@ function InitiativeControls({ campaignId, encounter, encounterPath }) {
);
}
// DisplayView remains the same as v0.1.19 (before focused view)
function DisplayView() {
const { data: activeDisplayData, isLoading: isLoadingActiveDisplay, error: activeDisplayError } = useFirestoreDocument(getActiveDisplayDocPath());
@ -1154,9 +1153,25 @@ function DisplayView() {
let participantsToRender = [];
if (participants) {
if (isStarted && activeEncounterData.turnOrderIds?.length > 0 ) {
participantsToRender = activeEncounterData.turnOrderIds
.map(id => participants.find(p => p.id === id)).filter(p => p && p.isActive);
} else {
const inTurnOrderAndActive = activeEncounterData.turnOrderIds
.map(id => participants.find(p => p.id === id))
.filter(p => p && p.isActive);
const notInTurnOrderButActive = participants.filter(p =>
p.isActive &&
!activeEncounterData.turnOrderIds.includes(p.id)
).sort((a,b) => {
if(a.initiative === b.initiative) {
const indexA = participants.findIndex(originalP => originalP.id === a.id);
const indexB = participants.findIndex(originalP => originalP.id === b.id);
return indexA - indexB;
}
return b.initiative - a.initiative;
});
participantsToRender = [...inTurnOrderAndActive, ...notInTurnOrderButActive];
} else {
participantsToRender = [...participants].filter(p => p.isActive)
.sort((a, b) => {
if (a.initiative === b.initiative) {