From c37578c4e5738cc3e2de7540ea25ae09a4c7e7ba Mon Sep 17 00:00:00 2001 From: calli Date: Tue, 14 Apr 2026 22:14:39 +0300 Subject: [PATCH] add drag for characters inside an account card. also minimize for easier reorder --- src/app/components/Account/AccountCard.tsx | 177 ++++++++++++++++++--- 1 file changed, 153 insertions(+), 24 deletions(-) diff --git a/src/app/components/Account/AccountCard.tsx b/src/app/components/Account/AccountCard.tsx index 2dec4d7..f612f34 100644 --- a/src/app/components/Account/AccountCard.tsx +++ b/src/app/components/Account/AccountCard.tsx @@ -7,6 +7,8 @@ import { useContext, useState, useEffect } from "react"; import { PlanRow } from "./PlanRow"; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp'; +import ChevronRightIcon from '@mui/icons-material/ChevronRight'; +import { DragDropContext, Droppable, Draggable, DropResult } from "@hello-pangea/dnd"; import { planetCalculations } from "@/planets"; import { EvePraisalResult } from "@/eve-praisal"; import { STORAGE_IDS, PI_SCHEMATICS, PI_PRODUCT_VOLUMES, STORAGE_CAPACITIES } from "@/const"; @@ -242,6 +244,69 @@ export const AccountCard = ({ characters, isCollapsed: propIsCollapsed }: { char const theme = useTheme(); const [localIsCollapsed, setLocalIsCollapsed] = useState(false); const { planMode, piPrices, alertMode, balanceThreshold, minExtractionRate } = useContext(SessionContext); + const accountName = characters.length > 0 ? (characters[0].account ?? "-") : "-"; + const [characterOrder, setCharacterOrder] = useState(() => { + try { + const saved = localStorage.getItem(`characterOrder-${accountName}`); + if (saved) { + const parsed: number[] = JSON.parse(saved); + const ids = characters.map(c => c.character.characterId); + const valid = parsed.filter(id => ids.includes(id)); + const newIds = ids.filter(id => !valid.includes(id)); + return [...valid, ...newIds]; + } + } catch {} + return characters.map(c => c.character.characterId); + }); + + useEffect(() => { + const ids = characters.map(c => c.character.characterId); + setCharacterOrder(prev => { + const valid = prev.filter(id => ids.includes(id)); + const newIds = ids.filter(id => !valid.includes(id)); + return [...valid, ...newIds]; + }); + }, [characters]); + + useEffect(() => { + if (characterOrder.length > 0) { + localStorage.setItem(`characterOrder-${accountName}`, JSON.stringify(characterOrder)); + } + }, [characterOrder, accountName]); + + const [collapsedCharacters, setCollapsedCharacters] = useState>(() => { + try { + const saved = localStorage.getItem(`collapsedCharacters-${accountName}`); + if (saved) return new Set(JSON.parse(saved)); + } catch {} + return new Set(); + }); + + const toggleCharacterCollapsed = (characterId: number) => { + setCollapsedCharacters(prev => { + const next = new Set(prev); + if (next.has(characterId)) next.delete(characterId); + else next.add(characterId); + localStorage.setItem(`collapsedCharacters-${accountName}`, JSON.stringify(Array.from(next))); + return next; + }); + }; + + const orderedCharacters = characterOrder + .map(id => characters.find(c => c.character.characterId === id)) + .filter((c): c is AccessToken => c !== undefined); + + const handleCharacterDragEnd = (result: DropResult) => { + if (!result.destination) return; + const items = Array.from(characterOrder); + const [moved] = items.splice(result.source.index, 1); + items.splice(result.destination.index, 0, moved); + setCharacterOrder(items); + }; + + const DragDropContextComponent = DragDropContext as any; + const DroppableComponent = Droppable as any; + const DraggableComponent = Draggable as any; const { monthlyEstimate, storageValue, planetCount, characterCount, runningExtractors, totalExtractors } = calculateAccountTotals(characters, piPrices); // Calculate planet details and alert states for each planet @@ -421,30 +486,94 @@ export const AccountCard = ({ characters, isCollapsed: propIsCollapsed }: { char {localIsCollapsed ? : } - {!localIsCollapsed && characters.map((c) => ( - - - {planMode ? ( - - ) : ( - { - const details = planetDetails[`${c.character.characterId}-${planet.planet_id}`]; - acc[planet.planet_id] = { - ...details, - visibility: getAlertVisibility(details.alertState) - }; - return acc; - }, {} as Record)} - /> - )} - - ))} + {!localIsCollapsed && ( + + + {(provided: any) => ( + + {orderedCharacters.map((c, index) => ( + + {(provided: any, snapshot: any) => ( + + + + ⠿ + + toggleCharacterCollapsed(c.character.characterId)} + sx={{ + p: 0.25, + color: theme.palette.text.disabled, + '&:hover': { color: theme.palette.text.secondary }, + transform: collapsedCharacters.has(c.character.characterId) ? 'rotate(0deg)' : 'rotate(90deg)', + transition: 'transform 0.2s ease-in-out', + }} + > + + + + + {!collapsedCharacters.has(c.character.characterId) && ( + planMode ? ( + + ) : ( + { + const details = planetDetails[`${c.character.characterId}-${planet.planet_id}`]; + acc[planet.planet_id] = { + ...details, + visibility: getAlertVisibility(details.alertState) + }; + return acc; + }, {} as Record)} + /> + ) + )} + + )} + + ))} + {provided.placeholder} + + )} + + + )} );