feat(frontend): RemitDrawer component with CAS adjustments + parties + claim payments
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
|
||||
/**
|
||||
* Read the current `?remit=…` query param off `window.location.search`.
|
||||
* Returns `null` when the param is absent or empty.
|
||||
*
|
||||
* `URLSearchParams` is the standard, locale-free way to parse query
|
||||
* strings in the browser. Using it (rather than hand-rolled string
|
||||
* slicing) means we correctly handle multiple params and percent-encoded
|
||||
* characters in remit IDs without surprises.
|
||||
*
|
||||
* Param name is `?remit=` (not `?remittance=`) — chosen to mirror the
|
||||
* shorter `?claim=` convention used by `useDrawerUrlState` (one-word
|
||||
* token, alphabetical brevity, no collision with the existing
|
||||
* `MatchedRemitCard` which uses the path `/remittances?id={id}`).
|
||||
*/
|
||||
function readRemitId(): string | null {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const value = params.get("remit");
|
||||
return value === "" ? null : value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the URL we want to push/replace into history.
|
||||
*
|
||||
* - `remitId === null` → drop the `?remit=` param, preserving any
|
||||
* other params (e.g. `?page=2&remit=…` keeps `page=2`).
|
||||
* - `remitId !== null` → set the param to the new id, also preserving
|
||||
* any other params.
|
||||
*
|
||||
* We return `pathname + search + hash` (a relative URL) rather than the
|
||||
* full href — `history.pushState` accepts a relative URL and rewriting
|
||||
* only the relative form keeps the document's origin stable.
|
||||
*/
|
||||
function buildUrl(remitId: string | null): string {
|
||||
const url = new URL(window.location.href);
|
||||
if (remitId === null) {
|
||||
url.searchParams.delete("remit");
|
||||
} else {
|
||||
url.searchParams.set("remit", remitId);
|
||||
}
|
||||
return url.pathname + url.search + url.hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Per-remittance detail drawer URL state (RemitDrawer).
|
||||
*
|
||||
* Mirrors `useDrawerUrlState` (SP4) but for the remits drawer — reads
|
||||
* `?remit=` from the URL on mount and keeps the value in sync with
|
||||
* history as the drawer is opened, navigated (j/k), and closed.
|
||||
*
|
||||
* - `remitId`: the id parsed from the URL (or `null` when the param
|
||||
* is absent). React state so consumers re-render on changes.
|
||||
* - `open(id)`: pushes a NEW history entry with `?remit={id}` — so the
|
||||
* browser Back button returns to the previous page (e.g. the
|
||||
* remits list) and not just to the previously-open remit.
|
||||
* - `setRemitId(id)`: REPLACES the current history entry — used by the
|
||||
* j/k nav handler so j/k moves through the list without polluting
|
||||
* history with one entry per keystroke.
|
||||
* - `close()`: pushes a NEW entry that strips the param, so Back from
|
||||
* the closed drawer returns to whatever page the user was on before
|
||||
* opening the drawer.
|
||||
*
|
||||
* The hook subscribes to `popstate` so that browser Back/Forward
|
||||
* (which fire popstate rather than our own pushState) propagate into
|
||||
* the React state. Without this, hitting Back would change the URL but
|
||||
* leave the drawer open on the stale id.
|
||||
*/
|
||||
export function useRemitDrawerUrlState(): {
|
||||
remitId: string | null;
|
||||
open: (id: string) => void;
|
||||
close: () => void;
|
||||
setRemitId: (id: string) => void;
|
||||
} {
|
||||
const [remitId, setRemitIdState] = useState<string | null>(() => readRemitId());
|
||||
|
||||
const open = useCallback((id: string) => {
|
||||
window.history.pushState(null, "", buildUrl(id));
|
||||
setRemitIdState(id);
|
||||
}, []);
|
||||
|
||||
const setRemitId = useCallback((id: string) => {
|
||||
window.history.replaceState(null, "", buildUrl(id));
|
||||
setRemitIdState(id);
|
||||
}, []);
|
||||
|
||||
const close = useCallback(() => {
|
||||
window.history.pushState(null, "", buildUrl(null));
|
||||
setRemitIdState(null);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const onPopState = () => {
|
||||
setRemitIdState(readRemitId());
|
||||
};
|
||||
window.addEventListener("popstate", onPopState);
|
||||
return () => window.removeEventListener("popstate", onPopState);
|
||||
}, []);
|
||||
|
||||
return { remitId, open, close, setRemitId };
|
||||
}
|
||||
Reference in New Issue
Block a user