Skip to content

Commit

Permalink
feat(character card): Added bond tracks, experience, and legacy track…
Browse files Browse the repository at this point in the history
…s to the character cards on the GM screen
  • Loading branch information
scottbenton committed Nov 25, 2023
1 parent 9d81545 commit f934eb4
Show file tree
Hide file tree
Showing 9 changed files with 182 additions and 50 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

### New Features

- Added a way to override feature flags from query parameters - this will allow me to send out beta links
- Added a new beta tests dialog in the user settings menu - this will allow me to test changes before fully releasing them

### Changes

Expand All @@ -15,6 +15,7 @@
- Added a test mobile view for moves and oracles
- Redesigned stats and tracks sections on mobile
- Redesigned moves and oracles to make each section collapsible
- Added bond tracks, experience, and legacy tracks to the character cards on the GM screen

### Accessibility

Expand Down
2 changes: 2 additions & 0 deletions src/components/features/ProgressTrack/ProgressTrack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@ export function ProgressTrack(props: ProgressTracksProps) {
}
borderTop={1}
borderBottom={1}
borderLeft={onValueChange ? 0 : 1}
borderRight={onValueChange ? 0 : 1}
borderColor={(theme) => theme.palette.divider}
role={"meter"}
aria-labelledby={labelId}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export function MovesSection() {
isEmpty,
} = useFilterMoves();

console.debug(isEmpty);
const openDialog = useStore((store) => store.appState.openDialog);

return (
Expand Down
1 change: 0 additions & 1 deletion src/hooks/featureFlags/useSyncFeatureFlags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ export function useSyncFeatureFlags() {
const localStorageResults: { [group: string]: boolean } = JSON.parse(
localStorage.getItem("forcedGroups") ?? "{}"
);
console.debug("UPDATING STATE TO:", localStorageResults);
updateBetaTests(localStorageResults);
}, [updateBetaTests]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import { InitiativeStatusChip } from "components/features/characters/InitiativeS
import { PortraitAvatar } from "components/features/characters/PortraitAvatar/PortraitAvatar";
import { Stat } from "types/stats.enum";
import { useStore } from "stores/store";
import { useGameSystemValue } from "hooks/useGameSystemValue";
import { GAME_SYSTEMS } from "types/GameSystems.type";
import { IronswornTracks } from "./IronswornTracks";
import { LegacyTracks } from "./LegacyTracks";

export interface CharacterCardProps {
uid: string;
Expand All @@ -25,6 +29,17 @@ export interface CharacterCardProps {
export function CharacterCard(props: CharacterCardProps) {
const { uid, characterId, character } = props;

const trackLabel = useGameSystemValue<string>({
[GAME_SYSTEMS.IRONSWORN]: "XP and Bonds",
[GAME_SYSTEMS.STARFORGED]: "Legacy Tracks",
});
const TrackComponent = useGameSystemValue<
(props: { characterId: string }) => JSX.Element
>({
[GAME_SYSTEMS.IRONSWORN]: IronswornTracks,
[GAME_SYSTEMS.STARFORGED]: LegacyTracks,
});

const storedAssets = useStore(
(store) =>
store.campaigns.currentCampaign.characters.characterAssets[characterId]
Expand Down Expand Up @@ -173,6 +188,14 @@ export function CharacterCard(props: CharacterCardProps) {
</Stack>
</AccordionDetails>
</Accordion>
<Accordion>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
{trackLabel}
</AccordionSummary>
<AccordionDetails>
<TrackComponent characterId={characterId} />
</AccordionDetails>
</Accordion>

{/* <Accordion>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import SpentIcon from "@mui/icons-material/RadioButtonChecked";
import EarnedIcon from "@mui/icons-material/HighlightOff";
import EmptyIcon from "@mui/icons-material/RadioButtonUnchecked";
import { useStore } from "stores/store";
import { Box, Typography } from "@mui/material";
import { ProgressTrack } from "components/features/ProgressTrack";

const totalExp = 30;
export interface IronswornTracksProps {
characterId: string;
}

export function IronswornTracks(props: IronswornTracksProps) {
const { characterId } = props;
const xp = useStore(
(store) =>
store.campaigns.currentCampaign.characters.characterMap[characterId]
.experience
);
const spentExp = xp?.spent ?? 0;
const earnedExp = xp?.earned ?? 0;

const bondValue = useStore(
(store) =>
store.campaigns.currentCampaign.characters.characterMap[characterId]
.bonds ?? 0
);

return (
<Box>
<Typography fontFamily={(theme) => theme.fontFamilyTitle}>
Experience
</Typography>
<Box display={"flex"} flexWrap={"wrap"}>
<Box mr={2}>
{new Array(spentExp).fill(undefined).map((key, index) => (
<SpentIcon key={index} color={"action"} fontSize={"small"} />
))}
{new Array(earnedExp - spentExp).fill(undefined).map((key, index) => (
<EarnedIcon key={index} color={"action"} fontSize={"small"} />
))}
{new Array(totalExp - earnedExp).fill(undefined).map((key, index) => (
<EmptyIcon key={index} color={"action"} fontSize={"small"} />
))}
</Box>
</Box>
<Typography fontFamily={(theme) => theme.fontFamilyTitle} sx={{ mt: 2 }}>
Bonds
</Typography>
<ProgressTrack value={bondValue} max={40} />
</Box>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Stack } from "@mui/material";
import { LegacyTrack } from "pages/Character/CharacterSheetPage/Tabs/TracksSection/LegacyTrack";
import { useStore } from "stores/store";

export interface LegacyTracksProps {
characterId: string;
}

export function LegacyTracks(props: LegacyTracksProps) {
const { characterId } = props;

const legacyTracks = useStore(
(store) =>
store.campaigns.currentCampaign.characters.characterMap[characterId]
.legacyTracks ?? {}
);

return (
<Stack spacing={2} px={2} sx={{ overflowX: "auto" }}>
<LegacyTrack
label={"Quests"}
value={legacyTracks.quests?.value ?? 0}
checkedExperience={legacyTracks.quests?.spentExperience ?? {}}
isLegacy={legacyTracks.quests?.isLegacy ?? false}
/>
<LegacyTrack
label={"Bonds"}
value={legacyTracks.bonds?.value ?? 0}
checkedExperience={legacyTracks.bonds?.spentExperience ?? {}}
isLegacy={legacyTracks.bonds?.isLegacy ?? false}
/>
<LegacyTrack
label={"Discoveries"}
value={legacyTracks.discoveries?.value ?? 0}
checkedExperience={legacyTracks.discoveries?.spentExperience ?? {}}
isLegacy={legacyTracks.discoveries?.isLegacy ?? false}
/>
</Stack>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./CharacterCard";
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ export interface LegacyTrackProps {
label: string;
value: number;
checkedExperience: { [key: number]: boolean };
onValueChange: (value: number) => void;
onExperienceChecked: (index: number, checked: boolean) => void;
onValueChange?: (value: number) => void;
onExperienceChecked?: (index: number, checked: boolean) => void;
isLegacy: boolean;
onIsLegacyChecked: (checked: boolean) => void;
onIsLegacyChecked?: (checked: boolean) => void;
}

export function LegacyTrack(props: LegacyTrackProps) {
Expand Down Expand Up @@ -73,7 +73,10 @@ export function LegacyTrack(props: LegacyTrackProps) {
control={
<Checkbox
checked={isLegacy}
onChange={(evt, value) => onIsLegacyChecked(value)}
disabled={!onIsLegacyChecked}
onChange={(evt, value) =>
onIsLegacyChecked && onIsLegacyChecked(value)
}
/>
}
label={"10"}
Expand All @@ -87,34 +90,41 @@ export function LegacyTrack(props: LegacyTrackProps) {
: theme.palette.grey[300]
}
>
<ButtonBase
onClick={() => onValueChange(value > 0 ? value - 1 : 0)}
sx={(theme) => ({
height: isMobile ? 34 : 48,
backgroundColor:
theme.palette.darkGrey[
theme.palette.mode === "light" ? "main" : "light"
],
color: theme.palette.darkGrey.contrastText,
px: 0.5,
"&:hover": {
backgroundColor: theme.palette.darkGrey.dark,
},
borderTopLeftRadius: `${theme.shape.borderRadius}px`,
borderBottomLeftRadius: `${theme.shape.borderRadius}px`,
})}
>
<MinusIcon />
</ButtonBase>
{checks.map((value, index) => (
{onValueChange && (
<ButtonBase
onClick={() => onValueChange(value > 0 ? value - 1 : 0)}
sx={(theme) => ({
height: isMobile ? 34 : 48,
backgroundColor:
theme.palette.darkGrey[
theme.palette.mode === "light" ? "main" : "light"
],
color: theme.palette.darkGrey.contrastText,
px: 0.5,
"&:hover": {
backgroundColor: theme.palette.darkGrey.dark,
},
borderTopLeftRadius: `${theme.shape.borderRadius}px`,
borderBottomLeftRadius: `${theme.shape.borderRadius}px`,
})}
>
<MinusIcon />
</ButtonBase>
)}
{checks.map((value, index, arr) => (
<Box key={index}>
<Box
sx={(theme) => ({
borderStyle: "solid",
borderColor: theme.palette.divider,
borderLeftColor:
index !== 0 ? theme.palette.divider : "transparent",
borderRightColor: "transparent",
index !== 0 || !onValueChange
? theme.palette.divider
: "transparent",
borderRightColor:
index === arr.length - 1 && !onValueChange
? theme.palette.divider
: "transparent",
borderWidth: 1,
width: isMobile ? 34 : 48,
height: isMobile ? 34 : 48,
Expand All @@ -139,9 +149,10 @@ export function LegacyTrack(props: LegacyTrackProps) {
sx={{ p: 0 }}
icon={<UncheckedIcon fontSize={"inherit"} />}
checkedIcon={<CheckedIcon fontSize={"inherit"} />}
disabled={value !== 4}
disabled={value !== 4 || !onExperienceChecked}
checked={checkedExperience[index * 2] ?? false}
onChange={(evt, checked) =>
onExperienceChecked &&
onExperienceChecked(index * 2, checked)
}
/>
Expand All @@ -150,35 +161,38 @@ export function LegacyTrack(props: LegacyTrackProps) {
sx={{ p: 0 }}
icon={<UncheckedIcon fontSize={"inherit"} />}
checkedIcon={<CheckedIcon fontSize={"inherit"} />}
disabled={value !== 4}
disabled={value !== 4 || !onExperienceChecked}
checked={checkedExperience[index * 2 + 1] ?? false}
onChange={(evt, checked) =>
onExperienceChecked &&
onExperienceChecked(index * 2 + 1, checked)
}
/>
)}
</Box>
</Box>
))}
<ButtonBase
onClick={() => onValueChange(value < 40 ? value + 1 : 40)}
sx={(theme) => ({
height: isMobile ? 34 : 48,
backgroundColor:
theme.palette.darkGrey[
theme.palette.mode === "light" ? "main" : "light"
],
color: theme.palette.darkGrey.contrastText,
px: 0.5,
"&:hover": {
backgroundColor: theme.palette.darkGrey.dark,
},
borderTopRightRadius: `${theme.shape.borderRadius}px`,
borderBottomRightRadius: `${theme.shape.borderRadius}px`,
})}
>
<PlusIcon />
</ButtonBase>
{onValueChange && (
<ButtonBase
onClick={() => onValueChange(value < 40 ? value + 1 : 40)}
sx={(theme) => ({
height: isMobile ? 34 : 48,
backgroundColor:
theme.palette.darkGrey[
theme.palette.mode === "light" ? "main" : "light"
],
color: theme.palette.darkGrey.contrastText,
px: 0.5,
"&:hover": {
backgroundColor: theme.palette.darkGrey.dark,
},
borderTopRightRadius: `${theme.shape.borderRadius}px`,
borderBottomRightRadius: `${theme.shape.borderRadius}px`,
})}
>
<PlusIcon />
</ButtonBase>
)}
</Box>
</Box>
</Box>
Expand Down

0 comments on commit f934eb4

Please sign in to comment.