add manual sorting to unit cards

This commit is contained in:
NilsUeter
2025-04-27 17:20:45 +02:00
parent 0578503235
commit 7949218076
3 changed files with 102 additions and 36 deletions
+89 -26
View File
@@ -60,14 +60,20 @@ export const Roster = ({
const Force = ({ force, onePerPage, colorUserChoice }) => {
const { units, factionRules, rules, catalog } = force;
const mergedRules = new Map([...factionRules, ...rules]);
// units with role "Character" are sorted to the top, then "Battleline", then "Other"
const sortedUnits = units.sort((a, b) => {
if (a.role === "Character" && b.role !== "Character") return -1;
if (a.role !== "Character" && b.role === "Character") return 1;
if (a.role === "Battleline" && b.role !== "Battleline") return -1;
if (a.role !== "Battleline" && b.role === "Battleline") return 1;
return a.name.localeCompare(b.name);
});
// State to manage the order of units
const [unitOrder, setUnitOrder] = useState([]);
useEffect(() => {
const sortedUnits = units.sort((a, b) => {
if (a.role === "Character" && b.role !== "Character") return -1;
if (a.role !== "Character" && b.role === "Character") return 1;
if (a.role === "Battleline" && b.role !== "Battleline") return -1;
if (a.role !== "Battleline" && b.role === "Battleline") return 1;
return a.name.localeCompare(b.name);
});
setUnitOrder(sortedUnits);
}, [units]);
return (
<div
@@ -75,30 +81,87 @@ const Force = ({ force, onePerPage, colorUserChoice }) => {
display: "contents",
}}
>
{sortedUnits.map((unit, index) => (
<Unit
key={unit.name + index}
index={index}
unit={unit}
catalog={catalog}
onePerPage={onePerPage}
forceRules={rules}
colorUserChoice={colorUserChoice}
/>
{unitOrder.map((unit, index) => (
<div key={unit.name + index} className="relative">
<div className="flex items-center justify-start gap-1 absolute text-[13px] -top-2.5 z-10 print-display-none">
<button
disabled={index === 0}
type="button"
className="py-0.5 px-1.5 pl-1"
onClick={() =>
// move unit up in the order
setUnitOrder((prevOrder) => {
const newOrder = [...prevOrder];
const unitToMove = newOrder.splice(index, 1)[0];
newOrder.splice(index - 1, 0, unitToMove);
return newOrder;
})
}
>
<svg
viewBox="0 0 24 24"
width={16}
height={16}
fill="#111113"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 4V20M12 4L8 8M12 4L16 8"
stroke="#000000"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
Up
</button>
<button
disabled={index === unitOrder.length - 1}
type="button"
className="py-0.5 px-1.5 pl-1"
onClick={() =>
// move unit down in the order
setUnitOrder((prevOrder) => {
const newOrder = [...prevOrder];
const unitToMove = newOrder.splice(index, 1)[0];
newOrder.splice(index + 1, 0, unitToMove);
return newOrder;
})
}
>
<svg
viewBox="0 0 24 24"
width={16}
height={16}
fill="#111113"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 4V20M12 20L8 16M12 20L16 16"
stroke="#000000"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
Down
</button>
</div>
<Unit
unit={unit}
catalog={catalog}
onePerPage={onePerPage}
forceRules={rules}
colorUserChoice={colorUserChoice}
/>
</div>
))}
<ForceRules rules={mergedRules} onePerPage={onePerPage} />
</div>
);
};
const Unit = ({
unit,
index,
catalog,
onePerPage,
forceRules,
colorUserChoice,
}) => {
const Unit = ({ unit, catalog, onePerPage, forceRules, colorUserChoice }) => {
const [hide, setHide] = useState(false);
const [hideModelCount, setHideModelCount] = useState(false);
const uploadRef = useRef();
+1 -1
View File
@@ -24,7 +24,7 @@ export const ShortSummaryTable = ({ force, primaryColor, name, points }) => {
const [hide, setHide] = useState(false);
const { units, factionRules, rules, catalog } = force;
const sortedUnits = units.sort((a, b) => {
const sortedUnits = units.slice().sort((a, b) => {
// sort by points cost desc first, then by name
if (a.cost.points < b.cost.points) return 1;
if (a.cost.points > b.cost.points) return -1;
+12 -9
View File
@@ -4,9 +4,8 @@
@layer base {
:root {
font-family:
"Noto Sans", sans-serif, Inter, system-ui, Avenir, Helvetica, Arial,
sans-serif;
font-family: "Noto Sans", sans-serif, Inter, system-ui, Avenir, Helvetica,
Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
font-size: 13px;
@@ -80,7 +79,7 @@
font-weight: 500;
font-family: inherit;
cursor: pointer;
transition: border-color 0.25s;
transition: border-color 0.15s;
}
button:hover,
.button:hover {
@@ -94,6 +93,13 @@
outline: 4px auto -webkit-focus-ring-color;
}
button:disabled,
.button[disabled] {
background-color: #f0f0f0;
color: #999;
border-color: #999;
}
.body {
display: flex;
flex-direction: column;
@@ -139,11 +145,8 @@
font-size: 1.5rem;
text-transform: uppercase;
cursor: pointer;
transition:
color 0.25s,
border 0.25s,
font-size 0.25s,
background-color 0.25s;
transition: color 0.15s, border 0.15s, font-size 0.15s, background-color
0.15s;
}
.rosterUpload:hover {