Character drag reorder via players array

Character list items draggable (ChevronsUpDown handle). Drop reorders
players array on campaign doc (single updateDoc). Array order = display
order.
This commit is contained in:
david raistrick
2026-07-07 15:40:58 -04:00
parent 9dbbb88730
commit 907484fc7f
+28 -1
View File
@@ -682,6 +682,22 @@ function CharacterManager({ campaignId, campaignCharacters }) {
const [editingCharacter, setEditingCharacter] = useState(null);
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
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(() => {
try { return localStorage.getItem('ttrpg.charactersCollapsed') !== 'true'; }
catch { return true; }
@@ -841,7 +857,17 @@ function CharacterManager({ campaignId, campaignCharacters }) {
<ul className="space-y-2">
{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 ? (
<form
onSubmit={(e) => {
@@ -917,6 +943,7 @@ function CharacterManager({ campaignId, campaignCharacters }) {
</div>
</>
)}
</div>
</li>
))}
</ul>