Generic (non-5e) ruleset mode + UI polish + combat switch fix #7
+28
-1
@@ -682,6 +682,22 @@ function CharacterManager({ campaignId, campaignCharacters }) {
|
|||||||
const [editingCharacter, setEditingCharacter] = useState(null);
|
const [editingCharacter, setEditingCharacter] = useState(null);
|
||||||
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
|
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
|
||||||
const [itemToDelete, setItemToDelete] = useState(null);
|
const [itemToDelete, setItemToDelete] = useState(null);
|
||||||
|
const [draggedCharId, setDraggedCharId] = useState(null);
|
||||||
|
|
||||||
|
const handleCharDragStart = (e, id) => { setDraggedCharId(id); e.dataTransfer.effectAllowed = 'move'; };
|
||||||
|
const handleCharDragOver = (e) => { e.preventDefault(); e.dataTransfer.dropEffect = 'move'; };
|
||||||
|
const handleCharDrop = async (e, targetId) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (!campaignId || !draggedCharId || draggedCharId === targetId) { setDraggedCharId(null); return; }
|
||||||
|
const reordered = [...campaignCharacters];
|
||||||
|
const fromIdx = reordered.findIndex(c => c.id === draggedCharId);
|
||||||
|
const toIdx = reordered.findIndex(c => c.id === targetId);
|
||||||
|
if (fromIdx === -1 || toIdx === -1) { setDraggedCharId(null); return; }
|
||||||
|
const [moved] = reordered.splice(fromIdx, 1);
|
||||||
|
reordered.splice(toIdx, 0, moved);
|
||||||
|
try { await storage.updateDoc(getPath.campaign(campaignId), { players: reordered }); } catch (err) {}
|
||||||
|
setDraggedCharId(null);
|
||||||
|
};
|
||||||
const [isOpen, setIsOpen] = useState(() => {
|
const [isOpen, setIsOpen] = useState(() => {
|
||||||
try { return localStorage.getItem('ttrpg.charactersCollapsed') !== 'true'; }
|
try { return localStorage.getItem('ttrpg.charactersCollapsed') !== 'true'; }
|
||||||
catch { return true; }
|
catch { return true; }
|
||||||
@@ -841,7 +857,17 @@ function CharacterManager({ campaignId, campaignCharacters }) {
|
|||||||
|
|
||||||
<ul className="space-y-2">
|
<ul className="space-y-2">
|
||||||
{campaignCharacters.map(character => (
|
{campaignCharacters.map(character => (
|
||||||
<li key={character.id} className="flex justify-between items-center p-3 bg-stone-800 rounded-md">
|
<li
|
||||||
|
key={character.id}
|
||||||
|
draggable
|
||||||
|
onDragStart={(e) => handleCharDragStart(e, character.id)}
|
||||||
|
onDragOver={handleCharDragOver}
|
||||||
|
onDrop={(e) => handleCharDrop(e, character.id)}
|
||||||
|
onDragEnd={() => setDraggedCharId(null)}
|
||||||
|
className={`flex justify-between items-center p-3 bg-stone-800 rounded-md cursor-grab ${draggedCharId === character.id ? 'opacity-50 ring-2 ring-yellow-400' : ''}`}
|
||||||
|
>
|
||||||
|
<div className="flex items-center flex-grow">
|
||||||
|
<ChevronsUpDown size={16} className="text-stone-400 flex-shrink-0 mr-2" title="Drag to reorder" />
|
||||||
{editingCharacter && editingCharacter.id === character.id ? (
|
{editingCharacter && editingCharacter.id === character.id ? (
|
||||||
<form
|
<form
|
||||||
onSubmit={(e) => {
|
onSubmit={(e) => {
|
||||||
@@ -917,6 +943,7 @@ function CharacterManager({ campaignId, campaignCharacters }) {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
Reference in New Issue
Block a user