Compare commits

...
Sign in to create a new pull request.

4 commits

Author SHA1 Message Date
bf7ea1a9e6 Merge pull request 'fix: Remove the Approved From and Approved to search field' (#137) from claude/issue-136 into master
All checks were successful
Refresh staging / refresh (push) Successful in 7s
Reviewed-on: #137
2026-06-25 22:25:09 +00:00
90a831790d Merge pull request 'fix(automation): issue watcher must not open PRs without tests' (#138) from fix/watcher-test-gate into master
All checks were successful
Refresh staging / refresh (push) Successful in 7s
Reviewed-on: #138
2026-06-25 22:24:54 +00:00
efa9d90ddb test(history): cover removal of Approved From/To filters (#136)
All checks were successful
PR checks / checks (pull_request) Successful in 51s
PR checks / integration (pull_request) Successful in 32s
Adds a unit test for HistoryFilters asserting the Approved From / Approved
To date filters no longer render (the issue #136 change) while the remaining
filters (created-date range, cost centre, accounting code, status) stay.
Satisfies the test-presence policy that PR #137 was missing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 03:46:03 +05:30
Claude (auto-fix)
5218eb3717 feat(history): remove Approved From/To search fields
Some checks failed
PR checks / checks (pull_request) Failing after 3s
PR checks / integration (pull_request) Successful in 33s
Drop the two approval-date pickers from the PO History filter bar per
the manager's request — they were deemed unnecessary. Removes the
inputs, their useState hooks, and their entries in buildParams/clear/
hasFilters.

The approvedFrom/approvedTo URL params are left intact server-side
(page.tsx, lib/history-filter.ts, export route) so existing deep-links
from the dashboard "Approved This Month" card and the report drill-downs
keep pre-filtering History by approval date.

Fixes #136

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 03:23:08 +05:30
2 changed files with 38 additions and 16 deletions

View file

@ -36,8 +36,6 @@ export function HistoryFilters({ vessels, accounts, perPageOptions, defaultPerPa
const [dateFrom, setDateFrom] = useState(sp.get("dateFrom") ?? ""); const [dateFrom, setDateFrom] = useState(sp.get("dateFrom") ?? "");
const [dateTo, setDateTo] = useState(sp.get("dateTo") ?? ""); const [dateTo, setDateTo] = useState(sp.get("dateTo") ?? "");
const [approvedFrom, setApprovedFrom] = useState(sp.get("approvedFrom") ?? "");
const [approvedTo, setApprovedTo] = useState(sp.get("approvedTo") ?? "");
const [vesselId, setVesselId] = useState(sp.get("vesselId") ?? ""); const [vesselId, setVesselId] = useState(sp.get("vesselId") ?? "");
const [accountId, setAccountId] = useState(sp.get("accountId") ?? ""); const [accountId, setAccountId] = useState(sp.get("accountId") ?? "");
const [statuses, setStatuses] = useState<string[]>(sp.getAll("status")); const [statuses, setStatuses] = useState<string[]>(sp.getAll("status"));
@ -65,8 +63,6 @@ export function HistoryFilters({ vessels, accounts, perPageOptions, defaultPerPa
const params = new URLSearchParams(); const params = new URLSearchParams();
if (dateFrom) params.set("dateFrom", dateFrom); if (dateFrom) params.set("dateFrom", dateFrom);
if (dateTo) params.set("dateTo", dateTo); if (dateTo) params.set("dateTo", dateTo);
if (approvedFrom) params.set("approvedFrom", approvedFrom);
if (approvedTo) params.set("approvedTo", approvedTo);
if (vesselId) params.set("vesselId", vesselId); if (vesselId) params.set("vesselId", vesselId);
if (accountId) params.set("accountId", accountId); if (accountId) params.set("accountId", accountId);
for (const s of statuses) params.append("status", s); for (const s of statuses) params.append("status", s);
@ -83,14 +79,14 @@ export function HistoryFilters({ vessels, accounts, perPageOptions, defaultPerPa
} }
function clear() { function clear() {
setDateFrom(""); setDateTo(""); setApprovedFrom(""); setApprovedTo(""); setVesselId(""); setAccountId(""); setStatuses([]); setDateFrom(""); setDateTo(""); setVesselId(""); setAccountId(""); setStatuses([]);
const params = new URLSearchParams(); const params = new URLSearchParams();
if (perPage !== defaultPerPage) params.set("perPage", String(perPage)); if (perPage !== defaultPerPage) params.set("perPage", String(perPage));
const qs = params.toString(); const qs = params.toString();
router.push(qs ? `/history?${qs}` : "/history"); router.push(qs ? `/history?${qs}` : "/history");
} }
const hasFilters = dateFrom || dateTo || approvedFrom || approvedTo || vesselId || accountId || statuses.length > 0; const hasFilters = dateFrom || dateTo || vesselId || accountId || statuses.length > 0;
const statusLabel = const statusLabel =
statuses.length === 0 statuses.length === 0
@ -112,16 +108,6 @@ export function HistoryFilters({ vessels, accounts, perPageOptions, defaultPerPa
<input type="date" value={dateTo} onChange={(e) => setDateTo(e.target.value)} <input type="date" value={dateTo} onChange={(e) => setDateTo(e.target.value)}
className="w-full rounded-lg border border-neutral-300 px-3 py-2 text-sm focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20" /> className="w-full rounded-lg border border-neutral-300 px-3 py-2 text-sm focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20" />
</div> </div>
<div>
<label className="block text-xs font-medium text-neutral-600 mb-1">Approved From</label>
<input type="date" value={approvedFrom} onChange={(e) => setApprovedFrom(e.target.value)}
className="w-full rounded-lg border border-neutral-300 px-3 py-2 text-sm focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20" />
</div>
<div>
<label className="block text-xs font-medium text-neutral-600 mb-1">Approved To</label>
<input type="date" value={approvedTo} onChange={(e) => setApprovedTo(e.target.value)}
className="w-full rounded-lg border border-neutral-300 px-3 py-2 text-sm focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20" />
</div>
<div> <div>
<label className="block text-xs font-medium text-neutral-600 mb-1">Cost Centre</label> <label className="block text-xs font-medium text-neutral-600 mb-1">Cost Centre</label>
<select value={vesselId} onChange={(e) => setVesselId(e.target.value)} <select value={vesselId} onChange={(e) => setVesselId(e.target.value)}

View file

@ -0,0 +1,36 @@
import { describe, it, expect, vi } from "vitest";
import { render, screen } from "@testing-library/react";
// HistoryFilters reads the URL via next/navigation; mock both hooks it uses.
vi.mock("next/navigation", () => ({
useRouter: () => ({ push: vi.fn(), refresh: vi.fn() }),
useSearchParams: () => new URLSearchParams(""),
}));
import { HistoryFilters } from "@/app/(portal)/history/history-filters";
const props = {
vessels: [{ id: "v1", name: "Vessel One" }],
accounts: [],
perPageOptions: [25, 50, 100],
defaultPerPage: 25,
};
describe("HistoryFilters", () => {
// Regression guard for issue #136: the "Approved From" / "Approved To" date
// filters were removed from PO History. They must not reappear.
it("does not render the Approved From / Approved To filters", () => {
render(<HistoryFilters {...props} />);
expect(screen.queryByText("Approved From")).toBeNull();
expect(screen.queryByText("Approved To")).toBeNull();
});
it("still renders the remaining filters (created-date range, cost centre, accounting code, status)", () => {
render(<HistoryFilters {...props} />);
expect(screen.getByText("From")).toBeInTheDocument();
expect(screen.getByText("To")).toBeInTheDocument();
expect(screen.getByText("Cost Centre")).toBeInTheDocument();
expect(screen.getByText("Accounting Code")).toBeInTheDocument();
expect(screen.getByText("Status")).toBeInTheDocument();
});
});