Skip to content

Commit 5d3f0ec

Browse files
committed
Add badge indicator that loadout has active notes
1 parent e53bdb5 commit 5d3f0ec

5 files changed

Lines changed: 67 additions & 4 deletions

File tree

PLANS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Keep this checklist aligned with repository behavior. Check off work in the same
3131
- [x] Create, edit, duplicate, delete, and copy team loadouts; preview them from any non-button card area and keep the currently unused image-download action hidden.
3232
- [x] Offer detailed and compact monsterling stat-label share previews.
3333
- [x] Toggle Monsterlings between cropped stat-icon cards and full stat strips while keeping portraits aligned with visible equipment.
34-
- [x] Save loadout-specific notes from direct card and preview actions, with the loadout name shown in the notes dialog; keep the More dropdown deferred until it has additional actions.
34+
- [x] Save loadout-specific notes from direct card and preview actions, with the loadout name shown in the notes dialog and a notification dot on card and preview actions when meaningful notes are saved; keep the More dropdown deferred until it has additional actions.
3535
- [x] Record eight character build stats, pin up to five per character in canonical editor order (ATK, HP, Crit Rate, Crit DMG, DMG Boost Boss, Special Skill CD, Elemental Weakness, Element ATK), defaulting pins to ATK, Crit Rate, Crit DMG, Special Skill CD, and Element ATK, and show pinned values beside element, awakening, and skill levels in previews.
3636
- [x] Require three unique owned characters selected through searchable, filterable character cards.
3737
- [x] Assign three regular and one legendary owned monsterling per character through searchable, multi-tier-filterable cards, with regular-slot swapping and moving within a character.

src/components/loadouts/components/loadout-actions.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type LoadoutActionsProps = {
3232
onDownload?: () => void;
3333
onDelete?: () => void;
3434
onNotes?: () => void;
35+
hasNotes?: boolean;
3536
onCreateSnapshot?: () => void;
3637
onPreview?: () => void;
3738
activeImageAction?: LoadoutImageAction | null;
@@ -47,6 +48,7 @@ export const LoadoutActions = ({
4748
onCopy,
4849
onDelete,
4950
onNotes,
51+
hasNotes = false,
5052
onCreateSnapshot,
5153
onPreview,
5254
activeImageAction = null,
@@ -141,12 +143,27 @@ export const LoadoutActions = ({
141143
type="button"
142144
size="icon-sm"
143145
variant="outline"
146+
className="relative"
144147
disabled={busy}
145148
onClick={onNotes}
146-
aria-label={`Notes for ${loadoutName}`}
147-
title={`Notes for ${loadoutName}`}
149+
aria-label={
150+
hasNotes
151+
? `Notes saved for ${loadoutName}`
152+
: `Notes for ${loadoutName}`
153+
}
154+
title={
155+
hasNotes
156+
? `Notes saved for ${loadoutName}`
157+
: `Notes for ${loadoutName}`
158+
}
148159
>
149160
<FileTextIcon />
161+
{hasNotes && (
162+
<span
163+
aria-hidden="true"
164+
className="absolute -right-0.5 -top-0.5 size-2 rounded-full bg-red-600 ring-2 ring-background"
165+
/>
166+
)}
150167
</Button>
151168
)}
152169
{onCreateSnapshot && (

src/components/loadouts/components/loadout-card.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ export const LoadoutCard = ({
8383
onDownload={onDownload}
8484
onDelete={onDelete}
8585
onNotes={onNotes}
86+
hasNotes={Boolean(loadout.notes?.trim())}
8687
onCreateSnapshot={onCreateSnapshot}
8788
activeImageAction={activeImageAction}
8889
disabled={disabled}

src/components/loadouts/components/loadout-preview-dialog.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ export const LoadoutPreviewDialog = ({
164164
}
165165
onDelete={onDelete}
166166
onNotes={onNotes}
167+
hasNotes={target === "loadout" && Boolean(loadout.notes?.trim())}
167168
onCreateSnapshot={onCreateSnapshot}
168169
activeImageAction={imageActions.activeAction}
169170
itemType={target === "snapshot" ? "loadout snapshot" : undefined}

src/components/loadouts/components/loadouts-list-ui.test.tsx

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,51 @@ describe("LoadoutsList", () => {
493493
fireEvent.click(screen.getByRole("button", { name: "Save notes" }));
494494
expect(useAppStore.getState().loadouts.team.notes).toBe("Damage test");
495495
expect(event).toHaveBeenCalledWith("loadout_notes_save");
496-
expect(screen.getByRole("button", { name: "Notes for Team" })).toBeTruthy();
496+
const savedNotesButton = screen.getByRole("button", {
497+
name: "Notes saved for Team",
498+
});
499+
expect(savedNotesButton.title).toBe("Notes saved for Team");
500+
expect(
501+
savedNotesButton.querySelector('span[aria-hidden="true"]'),
502+
).toBeTruthy();
503+
504+
fireEvent.click(savedNotesButton);
505+
fireEvent.change(screen.getByRole("textbox", { name: "Loadout notes" }), {
506+
target: { value: " " },
507+
});
508+
fireEvent.click(screen.getByRole("button", { name: "Save notes" }));
509+
const clearedNotesButton = screen.getByRole("button", {
510+
name: "Notes for Team",
511+
});
512+
expect(
513+
clearedNotesButton.querySelector('span[aria-hidden="true"]'),
514+
).toBeNull();
515+
});
516+
517+
it("shows saved-note indicators on cards and previews only for meaningful notes", () => {
518+
useAppStore.setState({
519+
charactersOwned,
520+
monsterlingsOwned: {},
521+
loadouts: {
522+
team: { ...teamLoadout, notes: "Damage test" },
523+
blank: { ...teamLoadout, id: "blank", name: "Blank", notes: " " },
524+
},
525+
});
526+
render(<LoadoutsList />);
527+
528+
expect(
529+
screen.getByRole("button", { name: "Notes saved for Team" }),
530+
).toBeTruthy();
531+
expect(
532+
screen.getByRole("button", { name: "Notes for Blank" }),
533+
).toBeTruthy();
534+
535+
fireEvent.click(
536+
screen.getByRole("button", { name: "Preview Team loadout card" }),
537+
);
538+
expect(
539+
screen.getByRole("button", { name: "Notes saved for Team" }),
540+
).toBeTruthy();
497541
});
498542

499543
it("duplicates a loadout into the first available name", () => {

0 commit comments

Comments
 (0)