fix(work-orders): align sidebar and advanced filters with AAP (#185)
Some checks are pending
Frontend checks / Build and test (push) Waiting to run
Frontend checks / governance (push) Waiting to run
Frontend checks / Visual regression (push) Waiting to run
Deploy dev content / Deploy shoc-frontend-new-dev through Terraform (push) Waiting to run

* fix(work-orders): align sidebar and advanced filters with AAP

* test(vendors): scope Site locator exactly

* fix(work-orders): keep sidebar scope unchanged

* test(work-orders): refresh SH-220 filter baseline

---------

Co-authored-by: Codex Review Integration <codex-review@local.invalid>
This commit is contained in:
Arthur Bassi 2026-09-15 14:05:18 -03:00 • committed by GitHub
parent d88a2e7854
commit da86297fb4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 87 additions and 21 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 144 KiB

View file

@ -13,11 +13,7 @@ import {
import { AdvDocPill, AdvStatusPill } from "./adv-filter-pill";
import { AdvDateRangeSection } from "./adv-date-range-section";
import { AdvMultiSelect } from "./adv-multi-select";
import {
AdvAvetaSection,
AdvFlagInternalUpliftSections,
AdvIndicatorsSection,
} from "./adv-parity-filter-sections";
import { AdvFlagInternalUpliftSections, AdvIndicatorsSection } from "./adv-parity-filter-sections";
import { AdvSection } from "./adv-section";
import { AdvSeverityList } from "./adv-severity-list";
import { AdvTypeGrid } from "./adv-type-grid";
@ -131,8 +127,6 @@ export function AdvancedSearchFilterSections({
<AdvIndicatorsSection draft={draft} setDraft={setDraft} />
<AdvAvetaSection draft={draft} setDraft={setDraft} />
<AdvSection icon={Flame} label="Service" count={draft.pmTypes.size}>
<AdvMultiSelect
options={pmTypes.map((pmType) => ({ value: pmType, label: pmType }))}

View file

@ -125,6 +125,12 @@ export function AdvIndicatorsSection({ draft, setDraft }: DraftProps) {
);
}
const FILTER_TOGGLE_CHECKBOX_SX = {
padding: 0,
color: "var(--color-border-hover)",
"&.Mui-checked": { color: "var(--color-primary)" },
} as const;
export function AdvAvetaSection({ draft, setDraft }: DraftProps) {
return (
<AdvSection icon={ShieldCheck} label="Aveta Compliance" count={draft.avetaOnly ? 1 : 0}>
@ -133,11 +139,7 @@ export function AdvAvetaSection({ draft, setDraft }: DraftProps) {
size="small"
checked={draft.avetaOnly}
onChange={() => setDraft((prev) => ({ ...prev, avetaOnly: !prev.avetaOnly }))}
sx={{
padding: 0,
color: "var(--color-border-hover)",
"&.Mui-checked": { color: "var(--warning)" },
}}
sx={FILTER_TOGGLE_CHECKBOX_SX}
/>
<span className="text-sm text-muted-foreground">Aveta required only</span>
</label>
@ -195,6 +197,8 @@ export function AdvFlagInternalUpliftSections({
</button>
</AdvSection>
<AdvAvetaSection draft={draft} setDraft={setDraft} />
<AdvSection icon={DollarSign} label="Uplift" count={draft.hasUplift ? 1 : 0}>
<label className="flex cursor-pointer items-center gap-1.5 select-none">
<Checkbox
@ -207,11 +211,7 @@ export function AdvFlagInternalUpliftSections({
upliftStatuses: prev.hasUplift ? new Set() : prev.upliftStatuses,
}))
}
sx={{
padding: 0,
color: "var(--color-border-hover)",
"&.Mui-checked": { color: "var(--color-primary)" },
}}
sx={FILTER_TOGGLE_CHECKBOX_SX}
/>
<span className="text-sm text-muted-foreground">Has uplift</span>
</label>

View file

@ -55,11 +55,17 @@ export function useAdvancedSearchDraft({
};
const handleClearAll = () => {
if (activeCount === 0) {
return;
}
setDraft(cloneAdvancedFilters(EMPTY_ADVANCED_FILTERS));
onClearAll();
};
const handleApply = () => {
if (activeCount === 0) {
return;
}
onApply(cloneAdvancedFilters(draft));
onOpenChange(false);
};

View file

@ -64,7 +64,12 @@ export function WorkOrdersAdvancedSearchSheet({
/>
<div className="flex shrink-0 items-center gap-2 border-t border-border px-4 py-3">
<Button variant="ghost" className="text-xs" onClick={handleClearAll}>
<Button
variant="ghost"
className="text-xs"
disabled={activeCount === 0}
onClick={handleClearAll}
>
Clear all
</Button>
<div className="flex flex-1 justify-center">
@ -74,7 +79,7 @@ export function WorkOrdersAdvancedSearchSheet({
</span>
)}
</div>
<Button className="px-5 text-xs" onClick={handleApply}>
<Button className="px-5 text-xs" disabled={activeCount === 0} onClick={handleApply}>
Apply filters
</Button>
</div>

View file

@ -33,7 +33,9 @@ export function CollapsibleSection({
>
<div className="flex items-center gap-2">
{Icon != null && <Icon size={16} className="text-primary" />}
<span className="text-sm font-semibold text-foreground">{label}</span>
<span className="text-[length:var(--text-base)] font-semibold text-foreground">
{label}
</span>
</div>
<div className="flex items-center gap-2">
<CountBadge count={count} />

View file

@ -152,6 +152,8 @@ describe("WorkOrders Advanced Search page wiring (SH-121)", () => {
expect(within(sheet).getByText("HVAC")).toBeInTheDocument();
expect(within(sheet).getByText("Vendor Co")).toBeInTheDocument();
fireEvent.click(within(sheet).getByRole("button", { name: /Aveta Compliance/i }));
fireEvent.click(within(sheet).getByRole("checkbox", { name: /Aveta required only/i }));
fireEvent.click(within(sheet).getByRole("button", { name: /apply filters/i }));
expect(applyAdvancedFilters).toHaveBeenCalled();
expect(setAdvOpen).toHaveBeenCalledWith(false);
@ -341,6 +343,45 @@ describe("WorkOrders Advanced Search page wiring (SH-121)", () => {
expect(screen.getByRole("button", { name: /work order types, all types/i })).toBeEnabled();
});
it("places Aveta Compliance immediately above Uplift", () => {
const view = renderWithProviders(<WorkOrdersListPage />, {
route: "/workorders",
withAuth: false,
});
fireEvent.click(screen.getByRole("button", { name: "Advanced Filters" }));
advOpen = true;
view.rerender(<WorkOrdersListPage />);
const sheet = screen.getByRole("dialog", { name: "Advanced Filters" });
const aveta = within(sheet).getByRole("button", { name: /Aveta Compliance/i });
const uplift = within(sheet).getByRole("button", { name: /^Uplift/i });
expect(aveta.closest(".border-b")?.nextElementSibling).toBe(uplift.closest(".border-b"));
});
it("keeps Clear all and Apply filters disabled until a filter is selected", () => {
const view = renderWithProviders(<WorkOrdersListPage />, {
route: "/workorders",
withAuth: false,
});
fireEvent.click(screen.getByRole("button", { name: "Advanced Filters" }));
advOpen = true;
view.rerender(<WorkOrdersListPage />);
const sheet = screen.getByRole("dialog", { name: "Advanced Filters" });
const clearAll = within(sheet).getByRole("button", { name: /clear all/i });
const apply = within(sheet).getByRole("button", { name: /apply filters/i });
expect(clearAll).toBeDisabled();
expect(apply).toBeDisabled();
fireEvent.click(within(sheet).getByRole("button", { name: /Aveta Compliance/i }));
fireEvent.click(within(sheet).getByRole("checkbox", { name: /Aveta required only/i }));
expect(clearAll).toBeEnabled();
expect(apply).toBeEnabled();
});
it("applies Aveta required only through Advanced Filters", () => {
const view = renderWithProviders(<WorkOrdersListPage />, {
route: "/workorders",

View file

@ -211,7 +211,9 @@ describe("WorkOrdersListHeader slice affordances", () => {
);
expect(screen.getByRole("button", { name: /new wo/i })).toBeInTheDocument();
expect(screen.getByLabelText("Advanced Filters")).toBeInTheDocument();
const filters = screen.getByRole("button", { name: "Advanced Filters" });
expect(filters).toBeInTheDocument();
expect(filters).toHaveTextContent("Filters");
});
});

View file

@ -0,0 +1,16 @@
import { screen } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import { CollapsibleSection } from "@/components/ui/collapsible-section";
import { renderWithProviders } from "@/test/test-utils";
describe("CollapsibleSection", () => {
it("renders the section title at the 14px body size token", () => {
renderWithProviders(<CollapsibleSection label="Aveta Compliance">child</CollapsibleSection>, {
withAuth: false,
});
const title = screen.getByRole("button", { name: /Aveta Compliance/i }).querySelector("span");
expect(title).toHaveClass("text-[length:var(--text-base)]");
});
});