refactor: use slide confirmation for role changes
All checks were successful
Build & Deploy Costco Grocery List / build (push) Successful in 11s
Build & Deploy Costco Grocery List / verify-images (push) Successful in 1s
Build & Deploy Costco Grocery List / deploy (push) Successful in 5s
Build & Deploy Costco Grocery List / notify (push) Successful in 0s
All checks were successful
Build & Deploy Costco Grocery List / build (push) Successful in 11s
Build & Deploy Costco Grocery List / verify-images (push) Successful in 1s
Build & Deploy Costco Grocery List / deploy (push) Successful in 5s
Build & Deploy Costco Grocery List / notify (push) Successful in 0s
This commit is contained in:
parent
cfec916392
commit
5a2848ebcf
@ -69,6 +69,7 @@ export default function ManageHousehold() {
|
|||||||
const [singleUseMode, setSingleUseMode] = useState("UNLIMITED");
|
const [singleUseMode, setSingleUseMode] = useState("UNLIMITED");
|
||||||
const [pendingDecisionId, setPendingDecisionId] = useState(null);
|
const [pendingDecisionId, setPendingDecisionId] = useState(null);
|
||||||
const [isLeaveModalOpen, setIsLeaveModalOpen] = useState(false);
|
const [isLeaveModalOpen, setIsLeaveModalOpen] = useState(false);
|
||||||
|
const [pendingRoleChange, setPendingRoleChange] = useState(null);
|
||||||
|
|
||||||
const isManager = ["owner", "admin"].includes(activeHousehold?.role);
|
const isManager = ["owner", "admin"].includes(activeHousehold?.role);
|
||||||
const isOwner = activeHousehold?.role === "owner";
|
const isOwner = activeHousehold?.role === "owner";
|
||||||
@ -277,15 +278,10 @@ export default function ManageHousehold() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUpdateRole = async (memberId, nextRole, memberName) => {
|
const handleConfirmRoleChange = async () => {
|
||||||
if (!nextRole) return;
|
if (!pendingRoleChange) return;
|
||||||
|
|
||||||
if (
|
const { memberId, nextRole, memberName } = pendingRoleChange;
|
||||||
nextRole === "owner" &&
|
|
||||||
!window.confirm(`Make ${memberName} the household owner? You will become an admin.`)
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await updateMemberRole(activeHousehold.id, memberId, nextRole);
|
await updateMemberRole(activeHousehold.id, memberId, nextRole);
|
||||||
@ -298,12 +294,19 @@ export default function ManageHousehold() {
|
|||||||
} else {
|
} else {
|
||||||
toast.success("Updated member role", `Updated role for ${memberName} to ${nextRole}`);
|
toast.success("Updated member role", `Updated role for ${memberName} to ${nextRole}`);
|
||||||
}
|
}
|
||||||
|
setPendingRoleChange(null);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const message = getApiErrorMessage(error, "Failed to update member role");
|
const message = getApiErrorMessage(error, "Failed to update member role");
|
||||||
toast.error("Update member role failed", `Update member role failed: ${message}`);
|
toast.error("Update member role failed", `Update member role failed: ${message}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleUpdateRole = (memberId, nextRole, memberName) => {
|
||||||
|
if (!nextRole) return;
|
||||||
|
|
||||||
|
setPendingRoleChange({ memberId, nextRole, memberName });
|
||||||
|
};
|
||||||
|
|
||||||
const handleRemoveMember = async (memberId, username) => {
|
const handleRemoveMember = async (memberId, username) => {
|
||||||
if (!confirm(`Remove ${username} from this household?`)) return;
|
if (!confirm(`Remove ${username} from this household?`)) return;
|
||||||
|
|
||||||
@ -640,6 +643,27 @@ export default function ManageHousehold() {
|
|||||||
onClose={() => setIsLeaveModalOpen(false)}
|
onClose={() => setIsLeaveModalOpen(false)}
|
||||||
onConfirm={handleLeaveHousehold}
|
onConfirm={handleLeaveHousehold}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<ConfirmSlideModal
|
||||||
|
isOpen={Boolean(pendingRoleChange)}
|
||||||
|
title={
|
||||||
|
pendingRoleChange?.nextRole === "owner"
|
||||||
|
? `Transfer ownership to ${pendingRoleChange?.memberName || "this member"}?`
|
||||||
|
: `Change ${pendingRoleChange?.memberName || "this member"} to ${pendingRoleChange?.nextRole || "member"}?`
|
||||||
|
}
|
||||||
|
description={
|
||||||
|
pendingRoleChange?.nextRole === "owner"
|
||||||
|
? "Slide to confirm. They will become the household owner and you will become an admin."
|
||||||
|
: "Slide to confirm this household role change."
|
||||||
|
}
|
||||||
|
confirmLabel={
|
||||||
|
pendingRoleChange?.nextRole === "owner"
|
||||||
|
? "Transfer Ownership"
|
||||||
|
: `Make ${pendingRoleChange?.nextRole === "admin" ? "Admin" : "Member"}`
|
||||||
|
}
|
||||||
|
onClose={() => setPendingRoleChange(null)}
|
||||||
|
onConfirm={handleConfirmRoleChange}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,25 @@ async function mockConfig(page: import("@playwright/test").Page) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function confirmSlide(page: import("@playwright/test").Page) {
|
||||||
|
const confirmModal = page.locator(".confirm-slide-modal");
|
||||||
|
await expect(confirmModal).toBeVisible();
|
||||||
|
|
||||||
|
const slider = confirmModal.locator(".confirm-slide-handle");
|
||||||
|
const track = confirmModal.locator(".confirm-slide-track");
|
||||||
|
const sliderBox = await slider.boundingBox();
|
||||||
|
const trackBox = await track.boundingBox();
|
||||||
|
|
||||||
|
if (!sliderBox || !trackBox) {
|
||||||
|
throw new Error("Confirm slide control was not measurable");
|
||||||
|
}
|
||||||
|
|
||||||
|
await page.mouse.move(sliderBox.x + sliderBox.width / 2, sliderBox.y + sliderBox.height / 2);
|
||||||
|
await page.mouse.down();
|
||||||
|
await page.mouse.move(trackBox.x + trackBox.width - 4, sliderBox.y + sliderBox.height / 2, { steps: 8 });
|
||||||
|
await page.mouse.up();
|
||||||
|
}
|
||||||
|
|
||||||
test("join household modal accepts invite links but rejects legacy invite codes", async ({ page }) => {
|
test("join household modal accepts invite links but rejects legacy invite codes", async ({ page }) => {
|
||||||
await seedAuthStorage(page);
|
await seedAuthStorage(page);
|
||||||
await mockConfig(page);
|
await mockConfig(page);
|
||||||
@ -285,15 +304,13 @@ test("household owner can transfer ownership from household settings", async ({
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
page.on("dialog", async (dialog) => {
|
|
||||||
await dialog.accept();
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto("/manage?tab=household");
|
await page.goto("/manage?tab=household");
|
||||||
|
|
||||||
await expect(page.getByRole("button", { name: "Make Owner" })).toBeVisible();
|
await expect(page.getByRole("button", { name: "Make Owner" })).toBeVisible();
|
||||||
|
|
||||||
await page.getByRole("button", { name: "Make Owner" }).click();
|
await page.getByRole("button", { name: "Make Owner" }).click();
|
||||||
|
await expect(page.getByText("Transfer ownership to nico-admin?")).toBeVisible();
|
||||||
|
await confirmSlide(page);
|
||||||
|
|
||||||
await expect(page.locator(".action-toast.action-toast-success")).toContainText("Transferred household ownership");
|
await expect(page.locator(".action-toast.action-toast-success")).toContainText("Transferred household ownership");
|
||||||
await expect(page.locator(".action-toast.action-toast-success")).toContainText("nico-admin");
|
await expect(page.locator(".action-toast.action-toast-success")).toContainText("nico-admin");
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user