Add extra invul save display, may have some missing cases
Add checkbox to hide model selection
This commit is contained in:
+206
-6
@@ -76,6 +76,7 @@ const Unit = ({
|
|||||||
colorUserChoice,
|
colorUserChoice,
|
||||||
}) => {
|
}) => {
|
||||||
const [hide, setHide] = useState(false);
|
const [hide, setHide] = useState(false);
|
||||||
|
const [hideModelCount, setHideModelCount] = useState(false);
|
||||||
const uploadRef = useRef();
|
const uploadRef = useRef();
|
||||||
let {
|
let {
|
||||||
name,
|
name,
|
||||||
@@ -179,6 +180,7 @@ const Unit = ({
|
|||||||
: "",
|
: "",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<div className="flex justify-end gap-3">
|
||||||
<label
|
<label
|
||||||
className="print-display-none"
|
className="print-display-none"
|
||||||
style={{
|
style={{
|
||||||
@@ -186,16 +188,34 @@ const Unit = ({
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "flex-end",
|
justifyContent: "flex-end",
|
||||||
gap: 4,
|
gap: 4,
|
||||||
|
userSelect: "none",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
onChange={(e) => setHideModelCount(e.target.checked)}
|
||||||
|
/>
|
||||||
|
<span className="print-display-none">Hide model selection</span>
|
||||||
|
</label>
|
||||||
|
<label
|
||||||
|
className="print-display-none"
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
gap: 4,
|
||||||
|
userSelect: "none",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<input type="checkbox" onChange={() => setHide(!hide)} />
|
<input type="checkbox" onChange={() => setHide(!hide)} />
|
||||||
<span className="print-display-none">Don't print this card.</span>
|
<span className="print-display-none">Don't print this card.</span>
|
||||||
</label>
|
</label>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
className="min-h-[15rem]"
|
className="min-h-[15rem]"
|
||||||
style={{
|
style={{
|
||||||
padding: "24px 0",
|
paddingTop: 24,
|
||||||
paddingBottom: 24,
|
paddingBottom: 4,
|
||||||
background:
|
background:
|
||||||
"linear-gradient(90deg, rgba(20,21,25,1) 0%, rgba(48,57,62,1) 45%, rgba(73,74,79,1) 100%)",
|
"linear-gradient(90deg, rgba(20,21,25,1) 0%, rgba(48,57,62,1) 45%, rgba(73,74,79,1) 100%)",
|
||||||
color: "#fff",
|
color: "#fff",
|
||||||
@@ -287,10 +307,11 @@ const Unit = ({
|
|||||||
modelList={modelList}
|
modelList={modelList}
|
||||||
index={index}
|
index={index}
|
||||||
showName={modelStats.length > 1}
|
showName={modelStats.length > 1}
|
||||||
|
abilities={abilities.Abilities}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
{modelStats?.[0] && (
|
{!hideModelCount && modelStats?.[0] && (
|
||||||
<div
|
<div
|
||||||
className={`mt-[17px] ${
|
className={`mt-[17px] ${
|
||||||
modelStats.length > 1 ? "" : "self-center"
|
modelStats.length > 1 ? "" : "self-center"
|
||||||
@@ -475,14 +496,117 @@ const Unit = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ModelStats = ({ modelStat, index, showName, modelList }) => {
|
const checkAbilitiesForInvul = (abilitiesMap, name) => {
|
||||||
|
const abilities = [...abilitiesMap.keys()];
|
||||||
|
for (let ability of abilities) {
|
||||||
|
if (ability.includes(":")) {
|
||||||
|
// if : then only match if the name is the same
|
||||||
|
if (
|
||||||
|
!name
|
||||||
|
.trim()
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(ability.split(":")[1].trim().toLowerCase())
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (abilitiesMap.get(ability)?.trim()?.toLowerCase()) {
|
||||||
|
case "2+":
|
||||||
|
if (ability?.toLowerCase().includes("invulnerable save")) return "2+";
|
||||||
|
break;
|
||||||
|
case "3+":
|
||||||
|
if (ability?.toLowerCase().includes("invulnerable save")) return "3+";
|
||||||
|
break;
|
||||||
|
case "4+":
|
||||||
|
if (ability?.toLowerCase().includes("invulnerable save")) return "4+";
|
||||||
|
break;
|
||||||
|
case "5+":
|
||||||
|
if (ability?.toLowerCase().includes("invulnerable save")) return "5+";
|
||||||
|
break;
|
||||||
|
case "6+":
|
||||||
|
if (ability?.toLowerCase().includes("invulnerable save")) return "6+";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "this model has a 2+ invulnerable save.":
|
||||||
|
return "2+";
|
||||||
|
case "this model has a 3+ invulnerable save.":
|
||||||
|
return "3+";
|
||||||
|
case "this model has a 4+ invulnerable save.":
|
||||||
|
return "4+";
|
||||||
|
case "this model has a 5+ invulnerable save.":
|
||||||
|
return "5+";
|
||||||
|
case "this model has a 6+ invulnerable save.":
|
||||||
|
return "6+";
|
||||||
|
|
||||||
|
case "models in this unit have a 2+ invulnerable save.":
|
||||||
|
return "2+";
|
||||||
|
case "models in this unit have a 3+ invulnerable save.":
|
||||||
|
return "3+";
|
||||||
|
case "models in this unit have a 4+ invulnerable save.":
|
||||||
|
return "4+";
|
||||||
|
case "models in this unit have a 5+ invulnerable save.":
|
||||||
|
return "5+";
|
||||||
|
case "models in this unit have a 6+ invulnerable save.":
|
||||||
|
return "6+";
|
||||||
|
|
||||||
|
case "models in this unit have a 2+ invulnerable save against ranged weapons.":
|
||||||
|
return "2+*";
|
||||||
|
case "models in this unit have a 3+ invulnerable save against ranged weapons.":
|
||||||
|
return "3+*";
|
||||||
|
case "models in this unit have a 4+ invulnerable save against ranged weapons.":
|
||||||
|
return "4+*";
|
||||||
|
case "models in this unit have a 5+ invulnerable save against ranged weapons.":
|
||||||
|
return "5+*";
|
||||||
|
case "models in this unit have a 6+ invulnerable save against ranged weapons.":
|
||||||
|
return "6+*";
|
||||||
|
|
||||||
|
case "while this model is leading a unit, models in that unit have a 2+ invulnerable save.":
|
||||||
|
return "2+*";
|
||||||
|
case "while this model is leading a unit, models in that unit have a 3+ invulnerable save.":
|
||||||
|
return "3+*";
|
||||||
|
case "while this model is leading a unit, models in that unit have a 4+ invulnerable save.":
|
||||||
|
return "4+*";
|
||||||
|
case "while this model is leading a unit, models in that unit have a 5+ invulnerable save.":
|
||||||
|
return "5+*";
|
||||||
|
case "while this model is leading a unit, models in that unit have a 6+ invulnerable save.":
|
||||||
|
return "6+*";
|
||||||
|
|
||||||
|
case "while this model is leading a unit, models in that unit have a 2+ invulnerable save against ranged attacks.":
|
||||||
|
return "2+*";
|
||||||
|
case "while this model is leading a unit, models in that unit have a 3+ invulnerable save against ranged attacks.":
|
||||||
|
return "3+*";
|
||||||
|
case "while this model is leading a unit, models in that unit have a 4+ invulnerable save against ranged attacks.":
|
||||||
|
return "4+*";
|
||||||
|
case "while this model is leading a unit, models in that unit have a 5+ invulnerable save against ranged attacks.":
|
||||||
|
return "5+*";
|
||||||
|
case "while this model is leading a unit, models in that unit have a 6+ invulnerable save against ranged attacks.":
|
||||||
|
return "6+*";
|
||||||
|
|
||||||
|
case "this model has a 2+ invulnerable save. you cannot re-roll invulnerable saving throws made for this model.":
|
||||||
|
return "2+*";
|
||||||
|
case "this model has a 3+ invulnerable save. you cannot re-roll invulnerable saving throws made for this model.":
|
||||||
|
return "3+*";
|
||||||
|
case "this model has a 4+ invulnerable save. you cannot re-roll invulnerable saving throws made for this model.":
|
||||||
|
return "4+*";
|
||||||
|
case "this model has a 5+ invulnerable save. you cannot re-roll invulnerable saving throws made for this model.":
|
||||||
|
return "5+*";
|
||||||
|
case "this model has a 6+ invulnerable save. you cannot re-roll invulnerable saving throws made for this model.":
|
||||||
|
return "6+*";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ModelStats = ({ modelStat, index, showName, abilities }) => {
|
||||||
let { move, toughness, save, wounds, leadership, name, oc, bs, ws, attacks } =
|
let { move, toughness, save, wounds, leadership, name, oc, bs, ws, attacks } =
|
||||||
modelStat;
|
modelStat;
|
||||||
if (!wounds) {
|
if (!wounds) {
|
||||||
wounds = "/";
|
wounds = "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hasInvul = checkAbilitiesForInvul(abilities, name);
|
||||||
return (
|
return (
|
||||||
|
<div className="flex flex-col">
|
||||||
<div style={{ display: "flex", gap: "1.2rem" }}>
|
<div style={{ display: "flex", gap: "1.2rem" }}>
|
||||||
<Characteristic title="M" characteristic={move} index={index} />
|
<Characteristic title="M" characteristic={move} index={index} />
|
||||||
<Characteristic title="T" characteristic={toughness} index={index} />
|
<Characteristic title="T" characteristic={toughness} index={index} />
|
||||||
@@ -495,6 +619,7 @@ const ModelStats = ({ modelStat, index, showName, modelList }) => {
|
|||||||
className="flex flex-wrap items-center gap-2"
|
className="flex flex-wrap items-center gap-2"
|
||||||
style={{
|
style={{
|
||||||
marginTop: index === 0 ? 16 : 0,
|
marginTop: index === 0 ? 16 : 0,
|
||||||
|
marginLeft: "-0.2rem",
|
||||||
textShadow: "0px 0px 5px rgb(0 0 0)",
|
textShadow: "0px 0px 5px rgb(0 0 0)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -502,6 +627,43 @@ const ModelStats = ({ modelStat, index, showName, modelList }) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<InvulRow hasInvul={hasInvul} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const InvulRow = ({ hasInvul }) => {
|
||||||
|
if (!hasInvul) return null;
|
||||||
|
|
||||||
|
const isSpecialInvul = hasInvul.includes("*");
|
||||||
|
const invulWithoutSpecial = hasInvul.replace("*", "");
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="relative flex gap-6 py-1.5 pb-1"
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="flex" style={{ gap: "1.2rem", left: 0, top: -16 }}>
|
||||||
|
<FancyBox className={"invisible"}></FancyBox>
|
||||||
|
<FancyBox className={"invisible"}></FancyBox>
|
||||||
|
<FancyShield>{invulWithoutSpecial}</FancyShield>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
className="font-semibold uppercase"
|
||||||
|
style={{
|
||||||
|
marginLeft: "-6rem",
|
||||||
|
paddingLeft: "6.4rem",
|
||||||
|
paddingRight: "1.2rem",
|
||||||
|
paddingTop: 2,
|
||||||
|
paddingBottom: 1,
|
||||||
|
backgroundColor: "var(--primary-color)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
INVULNERABLE SAVE{isSpecialInvul ? "*" : ""}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -672,15 +834,17 @@ const Characteristic = ({ title, characteristic, index }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const FancyBox = ({ children }) => {
|
const FancyBox = ({ children, className, style }) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
className={className}
|
||||||
style={{
|
style={{
|
||||||
color: "var(--primary-color)",
|
color: "var(--primary-color)",
|
||||||
padding: 2,
|
padding: 2,
|
||||||
background: "var(--primary-color)",
|
background: "var(--primary-color)",
|
||||||
clipPath:
|
clipPath:
|
||||||
"polygon(12% 0, 100% 0, 100% 20%, 100% 88%, 88% 100%, 20% 100%, 0 100%, 0 12%)",
|
"polygon(12% 0, 100% 0, 100% 20%, 100% 88%, 88% 100%, 20% 100%, 0 100%, 0 12%)",
|
||||||
|
...style,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@@ -693,7 +857,7 @@ const FancyBox = ({ children }) => {
|
|||||||
background: "#E8EDE7",
|
background: "#E8EDE7",
|
||||||
clipPath:
|
clipPath:
|
||||||
"polygon(10% 0, 100% 0, 100% 20%, 100% 90%, 90% 100%, 20% 100%, 0 100%, 0 10%)",
|
"polygon(10% 0, 100% 0, 100% 20%, 100% 90%, 90% 100%, 20% 100%, 0 100%, 0 10%)",
|
||||||
padding: 3,
|
padding: "3px 1px",
|
||||||
fontSize: "1.6em",
|
fontSize: "1.6em",
|
||||||
fontWeight: 800,
|
fontWeight: 800,
|
||||||
}}
|
}}
|
||||||
@@ -704,6 +868,42 @@ const FancyBox = ({ children }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const FancyShield = ({ children, className, style }) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={className}
|
||||||
|
style={{
|
||||||
|
color: "var(--primary-color)",
|
||||||
|
background: "var(--primary-color)",
|
||||||
|
clipPath:
|
||||||
|
"polygon(0% 0%, 100% 0%, 100% 41.42%, 99.13% 49.08%, 96.48% 58.58%, 90.13% 69.72%, 81.6% 79.45%, 72.02% 87.52%, 50% 100%, 28.68% 87.52%, 18.31% 79.45%, 9.46% 69.72%, 3.65% 58.58%, 1.13% 49.08%, 0% 41.42%)",
|
||||||
|
...style,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
margin: 2,
|
||||||
|
minWidth: "calc(3rem - 1px)",
|
||||||
|
minHeight: "3.6rem",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
background: "#E8EDE7",
|
||||||
|
clipPath:
|
||||||
|
"polygon(0% 0%, 100% 0%, 100% 41.42%, 99.13% 49.08%, 96.48% 58.58%, 90.13% 69.72%, 81.6% 79.45%, 72.02% 87.52%, 50% 100%, 28.68% 87.52%, 18.31% 79.45%, 9.46% 69.72%, 3.65% 58.58%, 1.13% 49.08%, 0% 41.42%)",
|
||||||
|
|
||||||
|
fontSize: "1.6em",
|
||||||
|
fontWeight: 800,
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ marginTop: -4 }}>{children}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const OtherAbilities = ({ abilities }) => {
|
const OtherAbilities = ({ abilities }) => {
|
||||||
let keys = [...Object.keys(abilities)?.filter((key) => key !== "Abilities")];
|
let keys = [...Object.keys(abilities)?.filter((key) => key !== "Abilities")];
|
||||||
return keys.map((key) => {
|
return keys.map((key) => {
|
||||||
|
|||||||
+8
-1
@@ -314,7 +314,14 @@ function App() {
|
|||||||
className="print-display-none max-w-[95vw]"
|
className="print-display-none max-w-[95vw]"
|
||||||
style={{ display: roster ? "flex" : "none", width: "100%", gap: 16 }}
|
style={{ display: roster ? "flex" : "none", width: "100%", gap: 16 }}
|
||||||
>
|
>
|
||||||
<label style={{ display: "flex", alignItems: "center", gap: 4 }}>
|
<label
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 4,
|
||||||
|
minHeight: 26,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
onChange={(e) => setOnePerPage(e.target.checked)}
|
onChange={(e) => setOnePerPage(e.target.checked)}
|
||||||
|
|||||||
Reference in New Issue
Block a user