Updated look of site.

This commit is contained in:
2026-04-25 18:37:55 -04:00
parent 895fa06227
commit 3be9b0a921
5 changed files with 55 additions and 52 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 658 KiB

+3
View File
@@ -10,6 +10,9 @@
/> />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cinzel:wght@400;600;700;900&family=EB+Garamond:ital,wght@0,400;0,500;0,600;1,400&display=swap" rel="stylesheet">
<title>TTRPG Initiative Tracker</title> <title>TTRPG Initiative Tracker</title>
</head> </head>
<body> <body>
+45 -45
View File
@@ -227,7 +227,7 @@ function Modal({ onClose, title, children }) {
<div className="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center p-4 z-50"> <div className="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center p-4 z-50">
<div className="bg-slate-800 p-6 rounded-lg shadow-xl w-full max-w-md"> <div className="bg-slate-800 p-6 rounded-lg shadow-xl w-full max-w-md">
<div className="flex justify-between items-center mb-4"> <div className="flex justify-between items-center mb-4">
<h2 className="text-xl font-semibold text-sky-300">{title}</h2> <h2 className="text-xl font-semibold text-amber-300 font-cinzel tracking-wide">{title}</h2>
<button onClick={onClose} className="text-slate-400 hover:text-slate-200"> <button onClick={onClose} className="text-slate-400 hover:text-slate-200">
<XCircle size={24} /> <XCircle size={24} />
</button> </button>
@@ -271,7 +271,7 @@ function ConfirmationModal({ isOpen, onClose, onConfirm, title, message }) {
function LoadingSpinner({ message = "Loading..." }) { function LoadingSpinner({ message = "Loading..." }) {
return ( return (
<div className="min-h-screen bg-slate-900 text-white flex flex-col items-center justify-center p-4"> <div className="min-h-screen bg-slate-900 text-white flex flex-col items-center justify-center p-4">
<div className="animate-spin rounded-full h-16 w-16 border-t-4 border-blue-500 border-solid"></div> <div className="animate-spin rounded-full h-16 w-16 border-t-4 border-amber-500 border-solid"></div>
<p className="mt-4 text-xl">{message}</p> <p className="mt-4 text-xl">{message}</p>
</div> </div>
); );
@@ -314,7 +314,7 @@ function CreateCampaignForm({ onCreate, onCancel }) {
id="campaignName" id="campaignName"
value={name} value={name}
onChange={(e) => setName(e.target.value)} onChange={(e) => setName(e.target.value)}
className="mt-1 block w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-sky-500 focus:border-sky-500 sm:text-sm text-white" className="mt-1 block w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-amber-600 focus:border-amber-600 sm:text-sm text-white"
required required
/> />
</div> </div>
@@ -328,7 +328,7 @@ function CreateCampaignForm({ onCreate, onCancel }) {
value={backgroundUrl} value={backgroundUrl}
onChange={(e) => setBackgroundUrl(e.target.value)} onChange={(e) => setBackgroundUrl(e.target.value)}
placeholder="https://example.com/image.jpg" placeholder="https://example.com/image.jpg"
className="mt-1 block w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-sky-500 focus:border-sky-500 sm:text-sm text-white" className="mt-1 block w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-amber-600 focus:border-amber-600 sm:text-sm text-white"
/> />
</div> </div>
<div className="flex justify-end space-x-3"> <div className="flex justify-end space-x-3">
@@ -371,7 +371,7 @@ function CreateEncounterForm({ onCreate, onCancel }) {
id="encounterName" id="encounterName"
value={name} value={name}
onChange={(e) => setName(e.target.value)} onChange={(e) => setName(e.target.value)}
className="mt-1 block w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-sky-500 focus:border-sky-500 sm:text-sm text-white" className="mt-1 block w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-amber-600 focus:border-amber-600 sm:text-sm text-white"
required required
/> />
</div> </div>
@@ -421,7 +421,7 @@ function EditParticipantModal({ participant, onClose, onSave }) {
type="text" type="text"
value={name} value={name}
onChange={(e) => setName(e.target.value)} onChange={(e) => setName(e.target.value)}
className="mt-1 block w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-sky-500 focus:border-sky-500 sm:text-sm text-white" className="mt-1 block w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-amber-600 focus:border-amber-600 sm:text-sm text-white"
/> />
</div> </div>
<div> <div>
@@ -430,7 +430,7 @@ function EditParticipantModal({ participant, onClose, onSave }) {
type="number" type="number"
value={initiative} value={initiative}
onChange={(e) => setInitiative(e.target.value)} onChange={(e) => setInitiative(e.target.value)}
className="mt-1 block w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-sky-500 focus:border-sky-500 sm:text-sm text-white" className="mt-1 block w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-amber-600 focus:border-amber-600 sm:text-sm text-white"
/> />
</div> </div>
<div className="flex gap-4"> <div className="flex gap-4">
@@ -440,7 +440,7 @@ function EditParticipantModal({ participant, onClose, onSave }) {
type="number" type="number"
value={currentHp} value={currentHp}
onChange={(e) => setCurrentHp(e.target.value)} onChange={(e) => setCurrentHp(e.target.value)}
className="mt-1 block w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-sky-500 focus:border-sky-500 sm:text-sm text-white" className="mt-1 block w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-amber-600 focus:border-amber-600 sm:text-sm text-white"
/> />
</div> </div>
<div className="flex-1"> <div className="flex-1">
@@ -449,7 +449,7 @@ function EditParticipantModal({ participant, onClose, onSave }) {
type="number" type="number"
value={maxHp} value={maxHp}
onChange={(e) => setMaxHp(e.target.value)} onChange={(e) => setMaxHp(e.target.value)}
className="mt-1 block w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-sky-500 focus:border-sky-500 sm:text-sm text-white" className="mt-1 block w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-amber-600 focus:border-amber-600 sm:text-sm text-white"
/> />
</div> </div>
</div> </div>
@@ -477,7 +477,7 @@ function EditParticipantModal({ participant, onClose, onSave }) {
</button> </button>
<button <button
type="submit" type="submit"
className="px-4 py-2 text-sm font-medium text-white bg-sky-500 hover:bg-sky-600 rounded-md transition-colors" className="px-4 py-2 text-sm font-medium text-white bg-amber-700 hover:bg-amber-800 rounded-md transition-colors"
> >
<Save size={18} className="mr-1 inline-block" /> Save <Save size={18} className="mr-1 inline-block" /> Save
</button> </button>
@@ -592,7 +592,7 @@ function CharacterManager({ campaignId, campaignCharacters }) {
<> <>
<div className="p-4 bg-slate-800 rounded-lg shadow"> <div className="p-4 bg-slate-800 rounded-lg shadow">
<div className="flex justify-between items-center mb-3"> <div className="flex justify-between items-center mb-3">
<h3 className="text-xl font-semibold text-sky-300 flex items-center"> <h3 className="text-xl font-semibold text-amber-300 font-cinzel tracking-wide flex items-center">
<Users size={24} className="mr-2" /> Campaign Characters <Users size={24} className="mr-2" /> Campaign Characters
</h3> </h3>
<button <button
@@ -617,7 +617,7 @@ function CharacterManager({ campaignId, campaignCharacters }) {
value={characterName} value={characterName}
onChange={(e) => setCharacterName(e.target.value)} onChange={(e) => setCharacterName(e.target.value)}
placeholder="Character name" placeholder="Character name"
className="w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-sky-500 focus:border-sky-500 sm:text-sm text-white" className="w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-amber-600 focus:border-amber-600 sm:text-sm text-white"
/> />
</div> </div>
<div className="w-full sm:w-auto"> <div className="w-full sm:w-auto">
@@ -629,7 +629,7 @@ function CharacterManager({ campaignId, campaignCharacters }) {
id="defaultMaxHp" id="defaultMaxHp"
value={defaultMaxHp} value={defaultMaxHp}
onChange={(e) => setDefaultMaxHp(e.target.value)} onChange={(e) => setDefaultMaxHp(e.target.value)}
className="w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-sky-500 focus:border-sky-500 sm:text-sm text-white" className="w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-amber-600 focus:border-amber-600 sm:text-sm text-white"
/> />
</div> </div>
<div className="w-full sm:w-auto"> <div className="w-full sm:w-auto">
@@ -641,12 +641,12 @@ function CharacterManager({ campaignId, campaignCharacters }) {
id="defaultInitMod" id="defaultInitMod"
value={defaultInitMod} value={defaultInitMod}
onChange={(e) => setDefaultInitMod(e.target.value)} onChange={(e) => setDefaultInitMod(e.target.value)}
className="w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-sky-500 focus:border-sky-500 sm:text-sm text-white" className="w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-amber-600 focus:border-amber-600 sm:text-sm text-white"
/> />
</div> </div>
<button <button
type="submit" type="submit"
className="sm:col-span-3 sm:w-auto sm:justify-self-end px-4 py-2 text-sm font-medium text-white bg-sky-500 hover:bg-sky-600 rounded-md transition-colors flex items-center justify-center" className="sm:col-span-3 sm:w-auto sm:justify-self-end px-4 py-2 text-sm font-medium text-white bg-amber-700 hover:bg-amber-800 rounded-md transition-colors flex items-center justify-center"
> >
<PlusCircle size={18} className="mr-1" /> Add Character <PlusCircle size={18} className="mr-1" /> Add Character
</button> </button>
@@ -1120,7 +1120,7 @@ function ParticipantManager({ encounter, encounterPath, campaignCharacters }) {
<> <>
<div className="p-3 bg-slate-800 rounded-md mt-4"> <div className="p-3 bg-slate-800 rounded-md mt-4">
<div className="flex justify-between items-center mb-3"> <div className="flex justify-between items-center mb-3">
<h4 className="text-lg font-medium text-sky-200">Add Participants</h4> <h4 className="text-lg font-medium text-amber-200 font-cinzel tracking-wide">Add Participants</h4>
<button <button
onClick={handleAddAllCampaignCharacters} onClick={handleAddAllCampaignCharacters}
className="px-3 py-1.5 text-xs font-medium text-white bg-indigo-600 hover:bg-indigo-700 rounded-md transition-colors flex items-center" className="px-3 py-1.5 text-xs font-medium text-white bg-indigo-600 hover:bg-indigo-700 rounded-md transition-colors flex items-center"
@@ -1179,7 +1179,7 @@ function ParticipantManager({ encounter, encounterPath, campaignCharacters }) {
value={participantName} value={participantName}
onChange={(e) => setParticipantName(e.target.value)} onChange={(e) => setParticipantName(e.target.value)}
placeholder="e.g., Dire Wolf" placeholder="e.g., Dire Wolf"
className="mt-1 w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-sky-500 focus:border-sky-500 sm:text-sm text-white" className="mt-1 w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-amber-600 focus:border-amber-600 sm:text-sm text-white"
/> />
</div> </div>
<div className="md:col-span-2"> <div className="md:col-span-2">
@@ -1191,7 +1191,7 @@ function ParticipantManager({ encounter, encounterPath, campaignCharacters }) {
id="monsterInitMod" id="monsterInitMod"
value={monsterInitMod} value={monsterInitMod}
onChange={(e) => setMonsterInitMod(e.target.value)} onChange={(e) => setMonsterInitMod(e.target.value)}
className="mt-1 w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-sky-500 focus:border-sky-500 sm:text-sm text-white" className="mt-1 w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-amber-600 focus:border-amber-600 sm:text-sm text-white"
/> />
</div> </div>
<div className="md:col-span-2"> <div className="md:col-span-2">
@@ -1203,7 +1203,7 @@ function ParticipantManager({ encounter, encounterPath, campaignCharacters }) {
id="monsterMaxHp" id="monsterMaxHp"
value={maxHp} value={maxHp}
onChange={(e) => setMaxHp(e.target.value)} onChange={(e) => setMaxHp(e.target.value)}
className="mt-1 w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-sky-500 focus:border-sky-500 sm:text-sm text-white" className="mt-1 w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-amber-600 focus:border-amber-600 sm:text-sm text-white"
/> />
</div> </div>
<div className="md:col-span-2 flex items-center pt-5"> <div className="md:col-span-2 flex items-center pt-5">
@@ -1242,7 +1242,7 @@ function ParticipantManager({ encounter, encounterPath, campaignCharacters }) {
type="number" type="number"
value={maxHp} value={maxHp}
onChange={(e) => setMaxHp(e.target.value)} onChange={(e) => setMaxHp(e.target.value)}
className="mt-1 w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-sky-500 focus:border-sky-500 sm:text-sm text-white" className="mt-1 w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md shadow-sm focus:outline-none focus:ring-amber-600 focus:border-amber-600 sm:text-sm text-white"
/> />
</div> </div>
</> </>
@@ -1275,7 +1275,7 @@ function ParticipantManager({ encounter, encounterPath, campaignCharacters }) {
const isDraggable = (!encounter.isStarted || encounter.isPaused) && tiedInitiatives.includes(Number(p.initiative)); const isDraggable = (!encounter.isStarted || encounter.isPaused) && tiedInitiatives.includes(Number(p.initiative));
const participantDisplayType = p.type === 'monster' ? (p.isNpc ? 'NPC' : 'Monster') : 'Character'; const participantDisplayType = p.type === 'monster' ? (p.isNpc ? 'NPC' : 'Monster') : 'Character';
let bgColor = p.type === 'character' ? 'bg-sky-800' : (p.isNpc ? 'bg-slate-600' : 'bg-[#8e351c]'); let bgColor = p.type === 'character' ? 'bg-blue-950' : (p.isNpc ? 'bg-slate-600' : 'bg-[#8e351c]');
if (isCurrentTurn && !encounter.isPaused) bgColor = 'bg-green-600'; if (isCurrentTurn && !encounter.isPaused) bgColor = 'bg-green-600';
const isDead = p.currentHp === 0; const isDead = p.currentHp === 0;
@@ -1340,7 +1340,7 @@ function ParticipantManager({ encounter, encounterPath, campaignCharacters }) {
placeholder="HP" placeholder="HP"
value={hpChangeValues[p.id] || ''} value={hpChangeValues[p.id] || ''}
onChange={(e) => setHpChangeValues(prev => ({ ...prev, [p.id]: e.target.value }))} onChange={(e) => setHpChangeValues(prev => ({ ...prev, [p.id]: e.target.value }))}
className="w-16 p-1 text-sm bg-slate-600 border border-slate-500 rounded-md text-white focus:ring-sky-500 focus:border-sky-500" className="w-16 p-1 text-sm bg-slate-600 border border-slate-500 rounded-md text-white focus:ring-amber-600 focus:border-amber-600"
aria-label={`HP change for ${p.name}`} aria-label={`HP change for ${p.name}`}
/> />
{!isDead && ( {!isDead && (
@@ -1541,7 +1541,7 @@ function InitiativeControls({ campaignId, encounter, encounterPath }) {
return ( return (
<> <>
<div className="lg:sticky lg:top-4 p-4 bg-slate-800 rounded-md shadow-lg"> <div className="lg:sticky lg:top-4 p-4 bg-slate-800 rounded-md shadow-lg">
<h4 className="text-lg font-medium text-sky-200 mb-4 text-center">Combat Controls</h4> <h4 className="text-lg font-medium text-amber-200 mb-4 text-center font-cinzel tracking-wide">Combat Controls</h4>
<div className="flex flex-col gap-3"> <div className="flex flex-col gap-3">
{!encounter.isStarted ? ( {!encounter.isStarted ? (
<button <button
@@ -1576,7 +1576,7 @@ function InitiativeControls({ campaignId, encounter, encounterPath }) {
{/* Round Counter */} {/* Round Counter */}
<div className="mt-2 pt-3 border-t border-slate-600"> <div className="mt-2 pt-3 border-t border-slate-600">
<p className="text-center text-lg font-semibold text-sky-300">Round: {encounter.round}</p> <p className="text-center text-lg font-semibold text-amber-300 font-cinzel">Round: {encounter.round}</p>
{encounter.isPaused && ( {encounter.isPaused && (
<p className="text-center text-sm text-yellow-400 font-semibold mt-1">(Paused)</p> <p className="text-center text-sm text-yellow-400 font-semibold mt-1">(Paused)</p>
)} )}
@@ -1737,7 +1737,7 @@ function EncounterManager({ campaignId, initialActiveEncounterId, campaignCharac
<> <>
<div className="mt-6 p-4 bg-slate-800 rounded-lg shadow"> <div className="mt-6 p-4 bg-slate-800 rounded-lg shadow">
<div className="flex justify-between items-center mb-3"> <div className="flex justify-between items-center mb-3">
<h3 className="text-xl font-semibold text-sky-300 flex items-center"> <h3 className="text-xl font-semibold text-amber-300 font-cinzel tracking-wide flex items-center">
<Swords size={24} className="mr-2" /> Encounters <Swords size={24} className="mr-2" /> Encounters
</h3> </h3>
<button <button
@@ -1761,7 +1761,7 @@ function EncounterManager({ campaignId, initialActiveEncounterId, campaignCharac
return ( return (
<div <div
key={encounter.id} key={encounter.id}
className={`p-3 rounded-md shadow transition-all ${selectedEncounterId === encounter.id ? 'bg-sky-600 ring-2 ring-sky-400' : 'bg-slate-700 hover:bg-slate-650'} ${isLive ? 'ring-2 ring-green-500 shadow-md shadow-green-500/30' : ''}`} className={`p-3 rounded-md shadow transition-all ${selectedEncounterId === encounter.id ? 'bg-amber-900 ring-2 ring-amber-500' : 'bg-slate-700 hover:bg-slate-600'} ${isLive ? 'ring-2 ring-green-500 shadow-md shadow-green-500/30' : ''}`}
> >
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<div onClick={() => setSelectedEncounterId(encounter.id)} className="cursor-pointer flex-grow"> <div onClick={() => setSelectedEncounterId(encounter.id)} className="cursor-pointer flex-grow">
@@ -1778,7 +1778,7 @@ function EncounterManager({ campaignId, initialActiveEncounterId, campaignCharac
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<button <button
onClick={() => handleTogglePlayerDisplay(encounter.id)} onClick={() => handleTogglePlayerDisplay(encounter.id)}
className={`p-1 rounded transition-colors ${isLive ? 'bg-red-500 hover:bg-red-600 text-white' : 'text-teal-400 hover:text-teal-300 bg-slate-600 hover:bg-slate-500'}`} className={`p-1 rounded transition-colors ${isLive ? 'bg-red-500 hover:bg-red-600 text-white' : 'text-amber-400 hover:text-amber-300 bg-slate-600 hover:bg-slate-500'}`}
title={isLive ? "Deactivate for Player Display" : "Activate for Player Display"} title={isLive ? "Deactivate for Player Display" : "Activate for Player Display"}
> >
{isLive ? <EyeOff size={18} /> : <Eye size={18} />} {isLive ? <EyeOff size={18} /> : <Eye size={18} />}
@@ -1810,8 +1810,8 @@ function EncounterManager({ campaignId, initialActiveEncounterId, campaignCharac
)} )}
{selectedEncounter && ( {selectedEncounter && (
<div className="mt-6 p-4 bg-slate-750 rounded-lg shadow-inner"> <div className="mt-6 p-4 bg-slate-800 rounded-lg shadow-inner">
<h3 className="text-xl font-semibold text-amber-300 mb-3"> <h3 className="text-xl font-semibold text-amber-300 mb-3 font-cinzel tracking-wide">
Managing Encounter: {selectedEncounter.name} Managing Encounter: {selectedEncounter.name}
</h3> </h3>
<div className="flex flex-col lg:flex-row gap-4"> <div className="flex flex-col lg:flex-row gap-4">
@@ -1991,7 +1991,7 @@ function AdminView({ userId }) {
<div className="space-y-6"> <div className="space-y-6">
<div> <div>
<div className="flex justify-between items-center mb-4"> <div className="flex justify-between items-center mb-4">
<h2 className="text-2xl font-semibold text-sky-300">Campaigns</h2> <h2 className="text-2xl font-semibold text-amber-300 font-cinzel tracking-wide">Campaigns</h2>
<button <button
onClick={() => setShowCreateModal(true)} onClick={() => setShowCreateModal(true)}
className="bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded-lg flex items-center transition-colors" className="bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded-lg flex items-center transition-colors"
@@ -2010,7 +2010,7 @@ function AdminView({ userId }) {
? { backgroundImage: `url(${campaign.playerDisplayBackgroundUrl})` } ? { backgroundImage: `url(${campaign.playerDisplayBackgroundUrl})` }
: {}; : {};
const cardClasses = `h-40 flex flex-col justify-between rounded-lg shadow-md cursor-pointer transition-all relative overflow-hidden bg-cover bg-center ${selectedCampaignId === campaign.id ? 'ring-4 ring-sky-400' : ''} ${!campaign.playerDisplayBackgroundUrl ? 'bg-slate-700 hover:bg-slate-600' : 'hover:shadow-xl'}`; const cardClasses = `h-40 flex flex-col justify-between rounded-lg shadow-md cursor-pointer transition-all relative overflow-hidden bg-cover bg-center ${selectedCampaignId === campaign.id ? 'ring-4 ring-amber-500' : ''} ${!campaign.playerDisplayBackgroundUrl ? 'bg-slate-700 hover:bg-slate-600' : 'hover:shadow-xl'}`;
return ( return (
<div <div
@@ -2059,8 +2059,8 @@ function AdminView({ userId }) {
)} )}
{selectedCampaign && ( {selectedCampaign && (
<div className="mt-6 p-6 bg-slate-750 rounded-lg shadow-xl"> <div className="mt-6 p-6 bg-slate-800 rounded-lg shadow-xl">
<h2 className="text-2xl font-semibold text-amber-300 mb-4"> <h2 className="text-2xl font-semibold text-amber-300 mb-4 font-cinzel tracking-wide">
Managing: {selectedCampaign.name} Managing: {selectedCampaign.name}
</h2> </h2>
<CharacterManager <CharacterManager
@@ -2200,7 +2200,7 @@ function DisplayView() {
return ( return (
<div className="min-h-screen bg-black text-slate-400 flex flex-col items-center justify-center p-4 text-center"> <div className="min-h-screen bg-black text-slate-400 flex flex-col items-center justify-center p-4 text-center">
<EyeOff size={64} className="mb-4 text-slate-500" /> <EyeOff size={64} className="mb-4 text-slate-500" />
<h2 className="text-3xl font-semibold">Game Session Paused</h2> <h2 className="text-3xl font-semibold font-cinzel tracking-wide">Game Session Paused</h2>
<p className="text-xl mt-2">The Dungeon Master has not activated an encounter for display.</p> <p className="text-xl mt-2">The Dungeon Master has not activated an encounter for display.</p>
</div> </div>
); );
@@ -2230,9 +2230,9 @@ function DisplayView() {
style={displayStyles} style={displayStyles}
> >
<div className={campaignBackgroundUrl ? 'bg-slate-900 bg-opacity-75 p-4 md:p-6 rounded-lg' : ''}> <div className={campaignBackgroundUrl ? 'bg-slate-900 bg-opacity-75 p-4 md:p-6 rounded-lg' : ''}>
<h2 className="text-4xl md:text-5xl font-bold text-center text-amber-400 mb-2">{name}</h2> <h2 className="text-4xl md:text-5xl font-bold text-center text-amber-400 mb-2 font-cinzel tracking-wide">{name}</h2>
{isStarted && <p className="text-2xl text-center text-sky-300 mb-1">Round: {round}</p>} {isStarted && <p className="text-2xl text-center text-amber-300 mb-1 font-cinzel">Round: {round}</p>}
{isStarted && isPaused && ( {isStarted && isPaused && (
<p className="text-xl text-center text-yellow-400 mb-4 font-semibold">(Combat Paused)</p> <p className="text-xl text-center text-yellow-400 mb-4 font-semibold">(Combat Paused)</p>
@@ -2256,7 +2256,7 @@ function DisplayView() {
const isDying = p.isDying || false; const isDying = p.isDying || false;
let participantBgColor = p.type === 'monster' let participantBgColor = p.type === 'monster'
? (p.isNpc ? 'bg-slate-700' : 'bg-[#8e351c]') ? (p.isNpc ? 'bg-slate-700' : 'bg-[#8e351c]')
: 'bg-sky-700'; : 'bg-blue-950';
const isCurrentTurn = p.id === currentTurnParticipantId && isStarted && !isPaused; const isCurrentTurn = p.id === currentTurnParticipantId && isStarted && !isPaused;
@@ -2274,7 +2274,7 @@ function DisplayView() {
> >
<div className="flex justify-between items-center mb-2"> <div className="flex justify-between items-center mb-2">
<h3 <h3
className={`text-2xl md:text-3xl font-bold ${isCurrentTurn ? 'text-white' : (p.type === 'character' ? 'text-sky-100' : (p.isNpc ? 'text-slate-100' : 'text-white'))}`} className={`text-2xl md:text-3xl font-bold font-cinzel ${isCurrentTurn ? 'text-white' : (p.type === 'character' ? 'text-amber-100' : (p.isNpc ? 'text-slate-100' : 'text-white'))}`}
> >
{isDead && <span className="mr-2">☠️</span>} {isDead && <span className="mr-2">☠️</span>}
{p.name} {p.name}
@@ -2333,7 +2333,7 @@ function App() {
useEffect(() => { useEffect(() => {
const queryParams = new URLSearchParams(window.location.search); const queryParams = new URLSearchParams(window.location.search);
if (queryParams.get('playerView') === 'true') { if (queryParams.get('playerView') === 'true' || window.location.pathname === '/display') {
setIsPlayerViewOnlyMode(true); setIsPlayerViewOnlyMode(true);
} }
@@ -2387,13 +2387,13 @@ function App() {
} }
const openPlayerWindow = () => { const openPlayerWindow = () => {
const playerViewUrl = window.location.origin + window.location.pathname + '?playerView=true'; const playerViewUrl = window.location.origin + '/display';
window.open(playerViewUrl, '_blank', 'noopener,noreferrer,width=1024,height=768'); window.open(playerViewUrl, '_blank', 'noopener,noreferrer,width=1024,height=768');
}; };
if (isPlayerViewOnlyMode) { if (isPlayerViewOnlyMode) {
return ( return (
<div className="min-h-screen bg-slate-800 text-slate-100 font-sans"> <div className="min-h-screen bg-slate-900 text-slate-100 font-garamond">
{isAuthReady && <DisplayView />} {isAuthReady && <DisplayView />}
{!isAuthReady && !error && <p>Authenticating for Player Display...</p>} {!isAuthReady && !error && <p>Authenticating for Player Display...</p>}
</div> </div>
@@ -2401,13 +2401,13 @@ function App() {
} }
return ( return (
<div className="min-h-screen bg-slate-800 text-slate-100 font-sans"> <div className="min-h-screen bg-slate-900 text-slate-100 font-garamond">
<header className="bg-slate-900 p-4 shadow-lg"> <header className="bg-slate-900 p-4 shadow-lg border-b border-amber-900">
<div className="container mx-auto flex justify-between items-center"> <div className="container mx-auto flex justify-between items-center">
<h1 className="text-3xl font-bold text-sky-400">TTRPG Initiative Tracker</h1> <h1 className="text-3xl font-bold text-amber-400 font-cinzel tracking-wide">TTRPG Initiative Tracker</h1>
<button <button
onClick={openPlayerWindow} 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" className="px-4 py-2 rounded-md text-sm font-medium transition-colors bg-amber-700 hover:bg-amber-800 text-white flex items-center"
> >
<ExternalLink size={16} className="mr-2" /> Open Player Window <ExternalLink size={16} className="mr-2" /> Open Player Window
</button> </button>
+1 -6
View File
@@ -7,14 +7,9 @@
body { body {
margin: 0; margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', font-family: 'EB Garamond', Georgia, 'Times New Roman', serif;
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
/* background-color: #1A202C; /* Tailwind Slate 900 */
/* color: #E2E8F0; /* Tailwind Slate 200 */
/* These will likely be overridden by the App component's Tailwind classes */
} }
code { code {
+6 -1
View File
@@ -6,7 +6,12 @@ module.exports = {
"./public/index.html" "./public/index.html"
], ],
theme: { theme: {
extend: {}, extend: {
fontFamily: {
cinzel: ['Cinzel', 'serif'],
garamond: ['"EB Garamond"', 'Georgia', 'serif'],
},
},
}, },
plugins: [], plugins: [],
} }