Skip to content

Commit

Permalink
👌 - fix: pr fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Xaohs committed Sep 27, 2024
1 parent 2898fad commit 47b5ca4
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 65 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Badge, field2Title } from "@maykin-ui/admin-ui";
import { Badge, Outline, field2Title } from "@maykin-ui/admin-ui";
import React from "react";

import { ProcessingStatus } from "../../lib/api/processingStatus";
Expand All @@ -11,24 +11,44 @@ import {

type ProcessingStatusBadgeProps = {
processingStatus: ProcessingStatus;
plannedDestructionDate: string | null;
plannedDestructionDate?: string | null;
};

export const ProcessingStatusBadge: React.FC<ProcessingStatusBadgeProps> = ({
processingStatus,
plannedDestructionDate,
}) => {
const getLevel = () => {
if (processingStatus === "new" && plannedDestructionDate) {
return "warning";
}
return PROCESSING_STATUS_LEVEL_MAPPING[processingStatus];
};

const getStatusIcon = () => {
if (processingStatus === "new" && plannedDestructionDate) {
return <Outline.ClockIcon />;
}
return PROCESSING_STATUS_ICON_MAPPING[processingStatus];
};

const getStatusText = () => {
if (processingStatus === "new" && plannedDestructionDate) {
return `Vernietigd ${timeAgo(plannedDestructionDate ?? "", { shortFormat: true })}`;
const isPlannedDestructionDateInPast =
new Date(plannedDestructionDate) < new Date();
if (isPlannedDestructionDateInPast) {
return `Wordt vernietigd`;
}
return `Wordt vernietigd ${timeAgo(plannedDestructionDate, { shortFormat: true })}`;
}
return field2Title(PROCESSING_STATUS_MAPPING[processingStatus], {
unHyphen: false,
});
};

return (
<Badge level={PROCESSING_STATUS_LEVEL_MAPPING[processingStatus]}>
{PROCESSING_STATUS_ICON_MAPPING[processingStatus]}
<Badge level={getLevel()}>
{getStatusIcon()}
{getStatusText()}
</Badge>
);
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/fixtures/destructionListItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ export const FIXTURE_DESTRUCTION_LIST_ITEM_DELETED: DestructionListItem = {
extraZaakData: null,
zaak: null,
processingStatus: "succeeded",
plannedDestructionDate: null,
plannedDestructionDate: "2026-01-01T00:00:00Z",
};
export const FIXTURE_DESTRUCTION_LIST_ITEM_FAILED: DestructionListItem = {
pk: 3,
status: "suggested",
extraZaakData: null,
zaak: zaakFactory(),
processingStatus: "failed",
plannedDestructionDate: null,
plannedDestructionDate: "2026-01-01T00:00:00Z",
};

export const destructionListItemFactory = createObjectFactory(
Expand Down
67 changes: 62 additions & 5 deletions frontend/src/lib/format/date.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ describe("timeAgo()", () => {
beforeEach(mockDate);
afterEach(unMockDate);

// Year tests (past and future)
test("timeAgo() handles year ", () => {
const yearAgo = new Date("2022-09-15:00:00");
expect(timeAgo(yearAgo)).toBe("1 jaar geleden");
Expand All @@ -27,8 +28,17 @@ describe("timeAgo()", () => {
const yearsAgo = new Date("2021-09-15:00:00");
expect(timeAgo(yearsAgo)).toBe("2 jaren geleden");
expect(timeAgo(yearsAgo, { shortFormat: true })).toBe("2j");

const yearAhead = new Date("2024-09-15:00:00");
expect(timeAgo(yearAhead)).toBe("over 1 jaar");
expect(timeAgo(yearAhead, { shortFormat: true })).toBe("over 1j");

const yearsAhead = new Date("2025-09-15:00:00");
expect(timeAgo(yearsAhead)).toBe("over 2 jaren");
expect(timeAgo(yearsAhead, { shortFormat: true })).toBe("over 2j");
});

// Month tests (past and future)
test("timeAgo() handles month ", () => {
const monthAgo = new Date("2023-08-15:00:00");
expect(timeAgo(monthAgo)).toBe("1 maand geleden");
Expand All @@ -37,8 +47,17 @@ describe("timeAgo()", () => {
const monthsAgo = new Date("2023-07-15:00:00");
expect(timeAgo(monthsAgo)).toBe("2 maanden geleden");
expect(timeAgo(monthsAgo, { shortFormat: true })).toBe("2ma");

const monthAhead = new Date("2023-10-15:00:00");
expect(timeAgo(monthAhead)).toBe("over 1 maand");
expect(timeAgo(monthAhead, { shortFormat: true })).toBe("over 1ma");

const monthsAhead = new Date("2023-11-15:00:00");
expect(timeAgo(monthsAhead)).toBe("over 2 maanden");
expect(timeAgo(monthsAhead, { shortFormat: true })).toBe("over 2ma");
});

// Day tests (past and future)
test("timeAgo() handles day ", () => {
const dayAgo = new Date("2023-09-14:00:00");
expect(timeAgo(dayAgo)).toBe("1 dag geleden");
Expand All @@ -47,8 +66,17 @@ describe("timeAgo()", () => {
const daysAgo = new Date("2023-09-13:00:00");
expect(timeAgo(daysAgo)).toBe("2 dagen geleden");
expect(timeAgo(daysAgo, { shortFormat: true })).toBe("2d");

const dayAhead = new Date("2023-09-16:00:00");
expect(timeAgo(dayAhead)).toBe("over 1 dag");
expect(timeAgo(dayAhead, { shortFormat: true })).toBe("over 1d");

const daysAhead = new Date("2023-09-17:00:00");
expect(timeAgo(daysAhead)).toBe("over 2 dagen");
expect(timeAgo(daysAhead, { shortFormat: true })).toBe("over 2d");
});

// Hour tests (past and future)
test("timeAgo() handles hour ", () => {
const hourAgo = new Date("2023-09-14:23:00");
expect(timeAgo(hourAgo)).toBe("1 uur geleden");
Expand All @@ -57,8 +85,17 @@ describe("timeAgo()", () => {
const hoursAgo = new Date("2023-09-14:22:00");
expect(timeAgo(hoursAgo)).toBe("2 uur geleden");
expect(timeAgo(hoursAgo, { shortFormat: true })).toBe("2u");

const hourAhead = new Date("2023-09-15:01:00");
expect(timeAgo(hourAhead)).toBe("over 1 uur");
expect(timeAgo(hourAhead, { shortFormat: true })).toBe("over 1u");

const hoursAhead = new Date("2023-09-15:02:00");
expect(timeAgo(hoursAhead)).toBe("over 2 uur");
expect(timeAgo(hoursAhead, { shortFormat: true })).toBe("over 2u");
});

// Minute tests (past and future)
test("timeAgo() handles minute ", () => {
const minuteAgo = new Date("2023-09-14:23:59");
expect(timeAgo(minuteAgo)).toBe("1 minuut geleden");
Expand All @@ -67,8 +104,17 @@ describe("timeAgo()", () => {
const minutesAgo = new Date("2023-09-14:23:58");
expect(timeAgo(minutesAgo)).toBe("2 minuten geleden");
expect(timeAgo(minutesAgo, { shortFormat: true })).toBe("2m");

const minuteAhead = new Date("2023-09-15:00:01");
expect(timeAgo(minuteAhead)).toBe("over 1 minuut");
expect(timeAgo(minuteAhead, { shortFormat: true })).toBe("over 1m");

const minutesAhead = new Date("2023-09-15:00:02");
expect(timeAgo(minutesAhead)).toBe("over 2 minuten");
expect(timeAgo(minutesAhead, { shortFormat: true })).toBe("over 2m");
});

// Less than a minute tests (past and future)
test("timeAgo() handles less than a minute ", () => {
const secondAgo = new Date("2023-09-14:23:59:59");
expect(timeAgo(secondAgo)).toBe("Nu");
Expand All @@ -77,14 +123,17 @@ describe("timeAgo()", () => {
const secondsAgo = new Date("2023-09-14:23:59:59");
expect(timeAgo(secondsAgo)).toBe("Nu");
expect(timeAgo(secondsAgo, { shortFormat: true })).toBe("0m");
});

test("timeAgo() interprets future data as now ", () => {
const yearFromNow = new Date("2024-09-15:00:00");
expect(timeAgo(yearFromNow)).toBe("Nu");
expect(timeAgo(yearFromNow, { shortFormat: true })).toBe("0m");
const secondAhead = new Date("2023-09-15:00:00:01");
expect(timeAgo(secondAhead)).toBe("zo meteen");
expect(timeAgo(secondAhead, { shortFormat: true })).toBe("0m");

const secondsAhead = new Date("2023-09-15:00:00:02");
expect(timeAgo(secondsAhead)).toBe("zo meteen");
expect(timeAgo(secondsAhead, { shortFormat: true })).toBe("0m");
});

// Combined scenarios (past and future)
test("timeAgo() handles combined scenario ", () => {
const yearAgo = new Date("2022-08-14:23:59:59");
expect(timeAgo(yearAgo)).toBe("1 jaar geleden");
Expand All @@ -93,6 +142,14 @@ describe("timeAgo()", () => {
const monthsAgo = new Date("2023-07-13:22:58:58");
expect(timeAgo(monthsAgo)).toBe("2 maanden geleden");
expect(timeAgo(monthsAgo, { shortFormat: true })).toBe("2ma");

const yearAhead = new Date("2025-08-14:23:59:59");
expect(timeAgo(yearAhead)).toBe("over 1 jaar");
expect(timeAgo(yearAhead, { shortFormat: true })).toBe("over 1j");

const monthsAhead = new Date("2023-11-13:22:58:58");
expect(timeAgo(monthsAhead)).toBe("over 1 maand");
expect(timeAgo(monthsAhead, { shortFormat: true })).toBe("over 1ma");
});
});

Expand Down
29 changes: 19 additions & 10 deletions frontend/src/lib/format/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ interface TimeAgoOptions {
/**
* Calculate how long ago or how long until a given date and return a human-readable string in Dutch.
* The date can be provided as a Date object or an ISO 8601 string.
* Note that this function does currently not show dates like "1 jaar 1 maand 1 dag geleden", but would rather show "1 jaar geleden"
* TODO: Consider using a specialized library.
*
* @param dateInput - The date to calculate the time difference from. It can be a Date object or an ISO 8601 string.
Expand All @@ -48,24 +49,28 @@ export function timeAgo(
let seconds = Math.floor((now.getTime() - date.getTime()) / 1000);
const { shortFormat = false } = options;

// Define the intervals in seconds for various time units
const intervals = [
{ label: "jaar", plural: "jaren", shortFormat: "j", seconds: 31536000 },
{ label: "maand", plural: "maanden", shortFormat: "mnd", seconds: 2592000 },
{ label: "maand", plural: "maanden", shortFormat: "ma", seconds: 2592000 },
{ label: "week", plural: "weken", shortFormat: "w", seconds: 604800 },
{ label: "dag", plural: "dagen", shortFormat: "d", seconds: 86400 },
{ label: "uur", plural: "uren", shortFormat: "u", seconds: 3600 },
{ label: "uur", plural: "uur", shortFormat: "u", seconds: 3600 },
{ label: "minuut", plural: "minuten", shortFormat: "m", seconds: 60 },
{ label: "seconde", plural: "seconden", shortFormat: "s", seconds: 1 },
];

let result = "";
let isFuture = false;

// If the time difference is positive, the date is in the past
// If the time difference is negative, the date is in the future
if (seconds < 0) {
isFuture = true;
seconds = Math.abs(seconds); // Work with positive time difference for calculation
seconds = Math.abs(seconds);
}

// Special case for "Nu" or "zo meteen"
if (seconds < 60) {
return shortFormat ? "0m" : isFuture ? "zo meteen" : "Nu";
}

// Iterate over the intervals to determine the appropriate time unit
Expand All @@ -79,19 +84,23 @@ export function timeAgo(
? interval.label
: interval.plural;

// Check if it's future or past
if (isFuture) {
result = `over ${intervalCount}${shortFormat ? "" : " "}${label}`;
} else {
result = `${intervalCount}${shortFormat ? "" : " "}${label}`;
// Special case to not include "geleden" for the short format
if (shortFormat) {
result = `${intervalCount}${shortFormat ? "" : " "}${label}`;
} else {
result = `${intervalCount}${shortFormat ? "" : " "}${label} geleden`;
}
}
break;
}
}

// Return the result or default to "just now" or "0m" for short format
return (
result.trim() || (shortFormat ? "0m" : isFuture ? "zo meteen" : "zojuist")
);
// Return the formatted time difference
return result.trim();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,10 @@ export const DeleteDestructionList: Story = {
delay: 10,
},
);
await waitFor(async () => await expect(submit).not.toBeDisabled());
await waitFor(async () => {
const isDisabled = submit.getAttribute("disabled");
expect(isDisabled).toBe("");
});
},
};

Expand Down Expand Up @@ -450,3 +453,61 @@ export const DeleteFailedDestructionList: Story = {
},
},
};

const FIXTURE_CANCEL_PLANNED_DESTRUCTION: DestructionListDetailContext = {
storageKey: "storybook-storage-key",

destructionList: destructionListFactory({
status: "ready_to_delete",
processingStatus: "new",
plannedDestructionDate: "2026-01-01T00:00:00Z",
}),
destructionListItems: paginatedDestructionListItemsFactory(),
logItems: auditLogFactory(),

zaakSelection: {},
selectableZaken: paginatedZakenFactory(),

archivists: usersFactory(),
reviewers: usersFactory(),
user: usersFactory()[0],

review: null,
reviewItems: null,

selectieLijstKlasseChoicesMap: null,
};

export const CancelPlannedDestruction: Story = {
parameters: {
reactRouterDecorator: {
route: {
loader: async () => FIXTURE_CANCEL_PLANNED_DESTRUCTION,
},
},
},
play: async (context) => {
const canvas = within(context.canvasElement);
const vernietigingStarten = await canvas.findByText<HTMLButtonElement>(
"Vernietigen starten",
);
expect(vernietigingStarten).toBeDisabled();
await clickButton({
...context,
parameters: {
...context.parameters,
name: "Vernietigen annuleren",
},
});
await userEvent.click(document.activeElement as HTMLInputElement, {
delay: 10,
});
userEvent.type(document.activeElement as HTMLInputElement, "Test Comment", {
delay: 10,
});
const submit = await canvas.findByText<HTMLButtonElement>(
"Vernietigen annuleren",
);
expect(submit).not.toBeDisabled();
},
};
Loading

0 comments on commit 47b5ca4

Please sign in to comment.