mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-06 15:55:02 +00:00
Merge pull request #1471 from Tria-plc/freight/fix/quick-fixes
fix: matrix
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import { POSITION_COOKIE } from "@/shared/utils/positionCookie";
|
||||
|
||||
const DEFAULT_PATH = "/";
|
||||
const SEVEN_DAYS_IN_SECONDS = 60 * 60 * 24 * 7;
|
||||
|
||||
@@ -32,6 +34,8 @@ export const clearSessionCookies = () => {
|
||||
AUTH_TOKEN_COOKIE,
|
||||
REFRESH_TOKEN_COOKIE,
|
||||
AUTH_USER_COOKIE,
|
||||
POSITION_COOKIE,
|
||||
// Pre-rename name, still cleared so a stale value cannot outlive logout.
|
||||
"current-position-id",
|
||||
"selected-position-id",
|
||||
].forEach(clearCookie);
|
||||
|
||||
@@ -174,6 +174,10 @@ export function DiffRow({
|
||||
from: string;
|
||||
to: string;
|
||||
}) {
|
||||
// No real "before" (field went from unset straight to a value, e.g. the
|
||||
// onboarding wizard's first save) — show the value alone rather than a
|
||||
// fake "— → value" that implies a prior state that never existed.
|
||||
const hadBefore = from !== "—";
|
||||
const changed = from !== to;
|
||||
return (
|
||||
<Stack gap={2}>
|
||||
@@ -181,24 +185,24 @@ export function DiffRow({
|
||||
{label}
|
||||
</Text>
|
||||
<Group gap={8} wrap="nowrap" align="center">
|
||||
<Text
|
||||
size="sm"
|
||||
c="dimmed"
|
||||
td={changed ? "line-through" : undefined}
|
||||
style={{ wordBreak: "break-word" }}
|
||||
>
|
||||
{from}
|
||||
</Text>
|
||||
{changed && (
|
||||
<>
|
||||
<Text size="sm" c="edr-muted">
|
||||
→
|
||||
</Text>
|
||||
<Text size="sm" fw={600} c="edr-text">
|
||||
{to}
|
||||
</Text>
|
||||
</>
|
||||
{hadBefore && (
|
||||
<Text
|
||||
size="sm"
|
||||
c="dimmed"
|
||||
td={changed ? "line-through" : undefined}
|
||||
style={{ wordBreak: "break-word" }}
|
||||
>
|
||||
{from}
|
||||
</Text>
|
||||
)}
|
||||
{hadBefore && changed && (
|
||||
<Text size="sm" c="edr-muted">
|
||||
→
|
||||
</Text>
|
||||
)}
|
||||
<Text size="sm" fw={changed ? 600 : undefined} c={changed ? "edr-text" : "dimmed"}>
|
||||
{to}
|
||||
</Text>
|
||||
</Group>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
@@ -22,6 +22,7 @@ import { type ReactNode } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import DocReviewAlertButton from "@/features/bookingWindows/DocReviewAlertButton";
|
||||
import { PositionSelect } from "@/record-management/components/positionSelection";
|
||||
import NotificationBellContainer from "@/features/notifications/NotificationBellContainer";
|
||||
|
||||
import type { PageMeta } from "./types";
|
||||
@@ -111,6 +112,10 @@ const FreightDashboardHeader = ({
|
||||
renders only during a review phase that still has undecided
|
||||
requests, so it never competes for space otherwise. */}
|
||||
<Group gap={10} wrap="nowrap" align="center">
|
||||
{/* Staff holding two posts switch desks here. Renders nothing for the
|
||||
single-position majority, so it costs the header no space. */}
|
||||
<PositionSelect />
|
||||
|
||||
<DocReviewAlertButton />
|
||||
|
||||
<Tooltip label="Language" withArrow openDelay={300}>
|
||||
|
||||
@@ -18,6 +18,10 @@ import {
|
||||
TooltipTrigger,
|
||||
} from "@/shared/common/ui/tooltip";
|
||||
import { PositionName } from "../dto/delegation/delegationDto";
|
||||
import {
|
||||
getPositionCookie,
|
||||
setPositionCookie,
|
||||
} from "@/shared/utils/positionCookie";
|
||||
interface BasePosition {
|
||||
id: string;
|
||||
employeePositionId: string;
|
||||
@@ -55,7 +59,7 @@ export const PositionSelect = () => {
|
||||
? unFilteredUserDetails.employee.flatMap((emp) => emp?.positions ?? [])
|
||||
: [];
|
||||
const selectablePositions = allPositions ?? [];
|
||||
const currentPositionCookie = Cookies.get("current-position-id");
|
||||
const currentPositionCookie = getPositionCookie();
|
||||
const delegatedPositionCookie = Cookies.get("delegatedPositionId");
|
||||
const activePositionId =
|
||||
selectedPositionId || currentPositionCookie || delegatedPositionCookie;
|
||||
@@ -85,15 +89,18 @@ export const PositionSelect = () => {
|
||||
// (useAuthUser already self-heals this cookie for the same reason.)
|
||||
if (
|
||||
currentPosition.employeePositionId &&
|
||||
Cookies.get("current-position-id") !== currentPosition.employeePositionId
|
||||
getPositionCookie() !== currentPosition.employeePositionId
|
||||
) {
|
||||
Cookies.set("current-position-id", currentPosition.employeePositionId);
|
||||
setPositionCookie(currentPosition.employeePositionId);
|
||||
}
|
||||
|
||||
applyDelegationCookie(currentPosition);
|
||||
}, [currentPosition, isLoading, selectedPositionId, setSelectedPositionId]);
|
||||
|
||||
if (isLoading || selectablePositions.length === 0) return null;
|
||||
// Below two desks there is nothing to switch between. This now sits in the
|
||||
// main freight header, so a one-option dropdown would show for every
|
||||
// single-desk staff member.
|
||||
if (isLoading || selectablePositions.length < 2) return null;
|
||||
|
||||
const handleChange = (value: string) => {
|
||||
const selected = selectablePositions.find((pos) => pos.id === value);
|
||||
@@ -102,7 +109,7 @@ export const PositionSelect = () => {
|
||||
// dropdown's own value is position.id, which the API does not match on.
|
||||
setSelectedPositionId(selected?.employeePositionId ?? value);
|
||||
if (selected?.employeePositionId) {
|
||||
Cookies.set("current-position-id", selected.employeePositionId);
|
||||
setPositionCookie(selected.employeePositionId);
|
||||
}
|
||||
applyDelegationCookie(selected);
|
||||
|
||||
|
||||
@@ -12,9 +12,11 @@ import {
|
||||
} from "@/record-management/dto/userRecords/teetersAndSignatureDto";
|
||||
import Cookies from "js-cookie";
|
||||
|
||||
import { getPositionCookie } from "@/shared/utils/positionCookie";
|
||||
|
||||
export const withHeaders = (passPosId: boolean = false) => {
|
||||
const unitId = Cookies.get("unit-id");
|
||||
const positionId = Cookies.get("current-position-id");
|
||||
const positionId = getPositionCookie();
|
||||
const projectId = Cookies.get("current-project-id");
|
||||
const delegatedPositionId = Cookies.get("delegatedPositionId");
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import Cookies from "js-cookie";
|
||||
|
||||
import { getPositionCookie } from "@/shared/utils/positionCookie";
|
||||
|
||||
export const withHeaders = () => {
|
||||
const tenantKey = Cookies.get("tenant-key");
|
||||
const unitId = Cookies.get("unit-id");
|
||||
const positionId = Cookies.get("current-position-id");
|
||||
const positionId = getPositionCookie();
|
||||
const projectId = Cookies.get("current-project-id");
|
||||
const delegatedPositionId = Cookies.get("delegatedPositionId");
|
||||
const headers: Record<string, string> = {};
|
||||
|
||||
@@ -30,6 +30,10 @@ import {
|
||||
persistRememberMePreference,
|
||||
setAuthCookies,
|
||||
} from "@/shared/utils/authPersistence";
|
||||
import {
|
||||
getPositionCookie,
|
||||
setPositionCookie,
|
||||
} from "@/shared/utils/positionCookie";
|
||||
import { clearComplaintVerification } from "@/complaints/utils/complaintVerificationStorage";
|
||||
|
||||
interface LoginPayload {
|
||||
@@ -46,7 +50,7 @@ export const useAuthUser = () => {
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
const delegatedPositionId = Cookies.get("delegatedPositionId");
|
||||
const currentPositionId = Cookies.get("current-position-id");
|
||||
const currentPositionId = getPositionCookie();
|
||||
|
||||
const {
|
||||
setUser,
|
||||
@@ -96,7 +100,7 @@ export const useAuthUser = () => {
|
||||
userDetails.employee?.[0]?.positions?.[0]?.employeePositionId;
|
||||
if (firstPositionId) {
|
||||
setSelectedPositionId(firstPositionId);
|
||||
Cookies.set("current-position-id", firstPositionId, cookieOptions);
|
||||
setPositionCookie(firstPositionId, cookieOptions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +145,7 @@ export const useAuthUser = () => {
|
||||
|
||||
if (fallbackId) {
|
||||
setSelectedPositionId(fallbackId);
|
||||
Cookies.set("current-position-id", fallbackId);
|
||||
setPositionCookie(fallbackId);
|
||||
}
|
||||
} else if (selectedPositionId) {
|
||||
// Self-heal stale cookies that were set to position.id instead of
|
||||
@@ -157,10 +161,7 @@ export const useAuthUser = () => {
|
||||
|
||||
if (matchingPosition?.employeePositionId) {
|
||||
setSelectedPositionId(matchingPosition.employeePositionId);
|
||||
Cookies.set(
|
||||
"current-position-id",
|
||||
matchingPosition.employeePositionId,
|
||||
);
|
||||
setPositionCookie(matchingPosition.employeePositionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
getAuthCookieOptions,
|
||||
setAuthCookies,
|
||||
} from "@/shared/utils/authPersistence";
|
||||
import { setPositionCookie } from "@/shared/utils/positionCookie";
|
||||
import type { VerifiedCitizen } from "@/complaints/types/complaint.types";
|
||||
|
||||
function unwrapApiData<T>(payload: T | { data?: T }): T {
|
||||
@@ -138,7 +139,7 @@ export async function persistFaydaRegistrationAuth(
|
||||
const firstPositionId =
|
||||
userDetails.employee?.[0]?.positions?.[0]?.employeePositionId;
|
||||
if (firstPositionId) {
|
||||
Cookies.set("current-position-id", firstPositionId, cookieOptions);
|
||||
setPositionCookie(firstPositionId, cookieOptions);
|
||||
}
|
||||
|
||||
return userDetails;
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import Cookies from "js-cookie";
|
||||
|
||||
type CookieOptions = NonNullable<Parameters<typeof Cookies.set>[2]>;
|
||||
|
||||
/**
|
||||
* Freight's own active-position cookie.
|
||||
*
|
||||
* Smart Office is a separate app on the same IAM and it also writes a cookie
|
||||
* named `current-position-id` — but it stores `position.id` where freight
|
||||
* stores `employeePositionId`. The two are not interchangeable, so on a shared
|
||||
* domain each app's login silently overwrote the other's desk selection and the
|
||||
* loser fell back to `positions[0]`. Freight keeps its own cookie name so both
|
||||
* can hold a selection at once.
|
||||
*/
|
||||
export const POSITION_COOKIE = "freight-current-position-id";
|
||||
|
||||
/**
|
||||
* The pre-rename, shared-with-Smart-Office name. Still read so a session that
|
||||
* is live across the deploy keeps its desk, and cleared on every write so the
|
||||
* colliding cookie does not linger.
|
||||
*/
|
||||
const LEGACY_POSITION_COOKIE = "current-position-id";
|
||||
|
||||
/** The active `employeePositionId`, or undefined when no desk is selected. */
|
||||
export const getPositionCookie = (): string | undefined =>
|
||||
Cookies.get(POSITION_COOKIE) ?? Cookies.get(LEGACY_POSITION_COOKIE);
|
||||
|
||||
export const setPositionCookie = (
|
||||
value: string,
|
||||
options?: CookieOptions,
|
||||
): void => {
|
||||
Cookies.set(POSITION_COOKIE, value, options);
|
||||
Cookies.remove(LEGACY_POSITION_COOKIE);
|
||||
};
|
||||
|
||||
export const clearPositionCookie = (): void => {
|
||||
Cookies.remove(POSITION_COOKIE);
|
||||
Cookies.remove(LEGACY_POSITION_COOKIE);
|
||||
};
|
||||
Reference in New Issue
Block a user