Skip to content

Commit

Permalink
Some improvements to Tables and OverviewPage (#990)
Browse files Browse the repository at this point in the history
  • Loading branch information
Lionqueen94 authored Feb 13, 2025
1 parent c2ce075 commit 126ba15
Show file tree
Hide file tree
Showing 20 changed files with 201 additions and 80 deletions.
10 changes: 5 additions & 5 deletions frontend/app/component/election/status/ElectionStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,18 +159,18 @@ function getTableHeaderForCategory(category: StatusCategory): React.ReactNode {
function CategoryHeader({ children }: { children?: React.ReactNode[] }) {
return (
<Table.Header key={category} className="bg-gray">
<Table.Column key={`${category}-number`}>{t("number")}</Table.Column>
<Table.Column key={`${category}-name`}>{t("polling_station.title.singular")}</Table.Column>
<Table.HeaderCell key={`${category}-number`}>{t("number")}</Table.HeaderCell>
<Table.HeaderCell key={`${category}-name`}>{t("polling_station.title.singular")}</Table.HeaderCell>
{children}
</Table.Header>
);
}

const finishedAtColumn = <Table.Column key={`${category}-time`}>{t("finished_at")}</Table.Column>;
const finishedAtColumn = <Table.HeaderCell key={`${category}-time`}>{t("finished_at")}</Table.HeaderCell>;
const progressColumn = (
<Table.Column key={`${category}-progress`} className="w-13">
<Table.HeaderCell key={`${category}-progress`} className="w-13">
{t("progress")}
</Table.Column>
</Table.HeaderCell>
);

switch (category) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,40 @@ describe("Test PollingStationChoiceForm", () => {
expect(screen.getByText("Geen stembureaus gevonden")).toBeVisible();
});

test("All data entries of polling stations are finished, polling station list shows message", async () => {
overrideOnce("get", "/api/elections/1", 200, electionDetailsMockResponse);
overrideOnce("get", "/api/elections/1/status", 200, {
statuses: [
{
polling_station_id: 1,
status: "definitive",
},
{
polling_station_id: 2,
status: "definitive",
},
{
polling_station_id: 3,
status: "definitive",
},
{
polling_station_id: 4,
status: "entries_different",
},
],
} satisfies ElectionStatusResponse);

const user = userEvent.setup();
renderPollingStationChoicePage();

const openPollingStationList = await screen.findByTestId("openPollingStationList");
await user.click(openPollingStationList);
expect(screen.getByText("Kies het stembureau")).toBeVisible();

// Check if the error message is visible
expect(screen.getByText("Alle stembureaus zijn twee keer ingevoerd")).toBeVisible();
});

test("Second data entry has correct link", async () => {
overrideOnce("get", "/api/elections/1", 200, electionDetailsMockResponse);
overrideOnce("get", "/api/elections/1/status", 200, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ export function PollingStationChoiceForm({ anotherEntry }: PollingStationChoiceF
status: status.status,
}));

const pollingStationsForDataEntry = pollingStations.filter((pollingStation: PollingStation) => {
const status = electionStatus.statuses.find((status) => status.polling_station_id === pollingStation.id)?.status;
return status !== "definitive" && status !== "entries_different";
});

return (
<form
onSubmit={(e) => {
Expand Down Expand Up @@ -145,12 +150,16 @@ export function PollingStationChoiceForm({ anotherEntry }: PollingStationChoiceF
</span>
</summary>
<h2 className={cls.formTitle}>{t("polling_station_choice.choose_polling_station")}</h2>
{pollingStations.length === 0 ? (
{!pollingStations.length ? (
<Alert type="error" variant="small">
<p>{t("polling_station_choice.no_polling_stations_found")}</p>
</Alert>
) : !pollingStationsForDataEntry.length ? (
<Alert type="notify" variant="small">
<p>{t("polling_station_choice.all_polling_stations_filled_in_twice")}</p>
</Alert>
) : (
<PollingStationsList pollingStations={pollingStations} />
<PollingStationsList pollingStations={pollingStationsForDataEntry} />
)}
</details>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,14 @@ export function PollingStationsList({ pollingStations }: PollingStationsListProp
return (
<Table id="polling_station_list">
<Table.Header>
<Table.Column>{t("number")}</Table.Column>
<Table.Column>{t("polling_station.title.singular")}</Table.Column>
<Table.HeaderCell>{t("number")}</Table.HeaderCell>
<Table.HeaderCell>{t("polling_station.title.singular")}</Table.HeaderCell>
</Table.Header>
<Table.Body>
{pollingStations.map((pollingStation: PollingStation) => {
const status = electionStatus.statuses.find(
(status) => status.polling_station_id === pollingStation.id,
)?.status;
if (status === "definitive" || status === "entries_different") {
return null;
}

return (
<Table.LinkRow
Expand Down
3 changes: 3 additions & 0 deletions frontend/app/module/election/page/ElectionReportPage.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Footer } from "app/component/footer/Footer";

import { useElection, useElectionStatus } from "@kiesraad/api";
import { t, tx } from "@kiesraad/i18n";
import { Button, FormLayout, PageTitle } from "@kiesraad/ui";
Expand Down Expand Up @@ -82,6 +84,7 @@ export function ElectionReportPage() {
</FormLayout.Controls>
</article>
</main>
<Footer />
</>
);
}
49 changes: 49 additions & 0 deletions frontend/app/module/election/page/OverviewPage.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { screen } from "@testing-library/react";
import { beforeEach, describe, expect, test } from "vitest";

import { ElectionListProvider, ElectionListResponse } from "@kiesraad/api";
import { ElectionListRequestHandler } from "@kiesraad/api-mocks";
import { overrideOnce, render, server } from "@kiesraad/test";

import { OverviewPage } from "./OverviewPage";

describe("OverviewPage", () => {
beforeEach(() => {
server.use(ElectionListRequestHandler);
});

test("Show elections", async () => {
render(
<ElectionListProvider>
<OverviewPage />
</ElectionListProvider>,
);

const table = await screen.findByRole("table");
expect(table).toBeVisible();
expect(table).toHaveTableContent([
["Verkiezing", "Gebied", "Status"],
["Gemeenteraadsverkiezingen 2026", "Heemdamseburg", "Steminvoer bezig"],
]);
});

test("Show no elections message", async () => {
overrideOnce("get", "/api/elections", 200, {
elections: [],
} satisfies ElectionListResponse);

render(
<ElectionListProvider>
<OverviewPage />
</ElectionListProvider>,
);

expect(await screen.findByText(/Abacus is nog niet klaar voor gebruik/)).toBeVisible();
expect(
await screen.findByText(
/Je kan als invoerder nog niks doen. Wacht tot de coördinator het systeem openstelt voor het invoeren van telresultaten./,
),
).toBeVisible();
expect(screen.queryByRole("table")).toBeNull();
});
});
58 changes: 35 additions & 23 deletions frontend/app/module/election/page/OverviewPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,29 +45,41 @@ export function OverviewPage() {
)}
<main>
<article>
<Table id="overview">
<Table.Header>
<Table.Column>{t("election.title.singular")}</Table.Column>
<Table.Column>
{!isAdminOrCoordinator ? t("election.location") : t("election.level_polling_station")}
</Table.Column>
<Table.Column>{t("election_status.label")}</Table.Column>
</Table.Header>
<Table.Body className="fs-md">
{electionList.map((election) => (
<Table.LinkRow key={election.id} to={electionLink(election)}>
<Table.Cell className="fs-body">{election.name}</Table.Cell>
<Table.Cell>{!isAdminOrCoordinator ? election.location : ""}</Table.Cell>
<Table.Cell>
<ElectionStatusWithIcon
status={election.status}
userRole={isAdminOrCoordinator ? "coordinator" : "typist"}
/>
</Table.Cell>
</Table.LinkRow>
))}
</Table.Body>
</Table>
{!electionList.length ? (
!isAdminOrCoordinator ? (
<>
<h2 className="mb-lg">{t("election.not_ready_for_use")}</h2>
<p className="md form-paragraph">{t("election.please_wait_for_coordinator")}</p>
</>
) : (
<h2>{t("election.no_elections_added")}</h2>
// TODO: To be expanded in issue #888
)
) : (
<Table id="overview">
<Table.Header>
<Table.HeaderCell>{t("election.title.singular")}</Table.HeaderCell>
<Table.HeaderCell>
{!isAdminOrCoordinator ? t("election.location") : t("election.level_polling_station")}
</Table.HeaderCell>
<Table.HeaderCell>{t("election_status.label")}</Table.HeaderCell>
</Table.Header>
<Table.Body className="fs-md">
{electionList.map((election) => (
<Table.LinkRow key={election.id} to={electionLink(election)}>
<Table.Cell className="fs-body">{election.name}</Table.Cell>
<Table.Cell>{!isAdminOrCoordinator ? election.location : ""}</Table.Cell>
<Table.Cell>
<ElectionStatusWithIcon
status={election.status}
userRole={isAdminOrCoordinator ? "coordinator" : "typist"}
/>
</Table.Cell>
</Table.LinkRow>
))}
</Table.Body>
</Table>
)}
</article>
</main>
<Footer />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ export function PollingStationListPage() {

<Table id="polling_stations">
<Table.Header>
<Table.Column>{t("number")}</Table.Column>
<Table.Column>{t("name")}</Table.Column>
<Table.Column>{t("type")}</Table.Column>
<Table.HeaderCell>{t("number")}</Table.HeaderCell>
<Table.HeaderCell>{t("name")}</Table.HeaderCell>
<Table.HeaderCell>{t("type")}</Table.HeaderCell>
</Table.Header>
<Table.Body className="fs-md">
{data.polling_stations.map((station) => (
Expand Down
8 changes: 4 additions & 4 deletions frontend/app/module/users/UserListPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ export function UserListPage() {

<Table id="users">
<Table.Header>
<Table.Column>{t("users.username")}</Table.Column>
<Table.Column>{t("role")}</Table.Column>
<Table.Column>{t("users.fullname")}</Table.Column>
<Table.Column>{t("users.last_activity")}</Table.Column>
<Table.HeaderCell>{t("users.username")}</Table.HeaderCell>
<Table.HeaderCell>{t("role")}</Table.HeaderCell>
<Table.HeaderCell>{t("users.fullname")}</Table.HeaderCell>
<Table.HeaderCell>{t("users.last_activity")}</Table.HeaderCell>
</Table.Header>
<Table.Body className="fs-md">
{users.map((user) => (
Expand Down
2 changes: 0 additions & 2 deletions frontend/lib/api/election/ElectionListProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ export function ElectionListProvider({ children }: ElectionListProviderProps) {
return (
<RequestStateHandler
requestState={requestState}
notFoundMessage="error.elections_not_found"
isFoundCheck={(data) => data.elections.length > 0}
renderOnSuccess={(data) => (
<ElectionListProviderContext.Provider value={{ electionList: data.elections }}>
{children}
Expand Down
3 changes: 3 additions & 0 deletions frontend/lib/i18n/locales/nl/election.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
},
"level_polling_station": "Niveau stembureau",
"location": "Gebied",
"no_elections_added": "Nog geen verkiezingen ingesteld",
"not_ready_for_use": "Abacus is nog niet klaar voor gebruik",
"please_wait_for_coordinator": "Je kan als invoerder nog niks doen. Wacht tot de coördinator het systeem openstelt voor het invoeren van telresultaten.",
"status": "Status",
"start_when_count_list_received": "Zodra je een tellijst van een stembureau hebt gekregen kan je beginnen met invoeren."
}
19 changes: 10 additions & 9 deletions frontend/lib/i18n/locales/nl/polling_station_choice.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
{
"all_polling_stations_filled_in_twice": "Alle stembureaus zijn twee keer ingevoerd",
"choose_polling_station": "Kies het stembureau",
"enter_a_valid_number_to_start": "Voer een geldig nummer van een stembureau in om te beginnen",
"polling_station_entry_not_possible": "Het stembureau dat je geselecteerd hebt kan niet meer ingevoerd worden",
"has_already_been_filled_twice": "Stembureau {nr} <strong>({name})</strong> is al twee keer ingevoerd",
"unfinished_input_title": "Je hebt nog een openstaande invoer",
"unfinished_input_content": "Je bent begonnen met het invoeren van onderstaande stembureaus, maar hebt deze nog niet helemaal afgerond:",
"insert_title": "Welk stembureau ga je invoeren?",
"insert_another": "Verder met een volgend stembureau?",
"insert_number": "Voer het nummer in:",
"insert_title": "Welk stembureau ga je invoeren?",
"name_correct_warning": "Klopt de naam van het stembureau met de naam op je papieren proces-verbaal?\nDan kan je beginnen. Klopt de naam niet? Overleg met de coördinator.",
"unknown_number": "Weet je het nummer niet?",
"view_list": "Bekijk de lijst met alle stembureaus",
"choose_polling_station": "Kies het stembureau",
"no_polling_station_found_with_number": "Geen stembureau gevonden met nummer {nr}",
"no_polling_stations_found": "Geen stembureaus gevonden",
"insert_number": "Voer het nummer in:",
"polling_station_entry_not_possible": "Het stembureau dat je geselecteerd hebt kan niet meer ingevoerd worden",
"searching": "aan het zoeken",
"no_polling_station_found_with_number": "Geen stembureau gevonden met nummer {nr}"
"unfinished_input_title": "Je hebt nog een openstaande invoer",
"unfinished_input_content": "Je bent begonnen met het invoeren van onderstaande stembureaus, maar hebt deze nog niet helemaal afgerond:",
"unknown_number": "Weet je het nummer niet?",
"view_list": "Bekijk de lijst met alle stembureaus"
}
1 change: 1 addition & 0 deletions frontend/lib/icon/generated.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ export const IconChevronRight = (props: React.SVGAttributes<SVGElement>) => (
version="1.1"
viewBox="0 0 20 20"
role="img"
fill="#475467"
>
<path d="M7.5,15.8c-.2,0-.4,0-.6-.2-.3-.3-.3-.9,0-1.2l4.4-4.4-4.4-4.4c-.3-.3-.3-.9,0-1.2.3-.3.9-.3,1.2,0l5,5c.3.3.3.9,0,1.2l-5,5c-.2.2-.4.2-.6.2Z" />
</svg>
Expand Down
2 changes: 1 addition & 1 deletion frontend/lib/icon/svg/chevronRight.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions frontend/lib/ui/Alert/Alert.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
}

&.error {
border-color: var(--color-error-darkest);
border-color: var(--color-error-darker);
background-color: var(--color-error-bg);
> button:focus,
> button:focus-visible {
Expand All @@ -56,7 +56,7 @@
background: var(--color-error-hover);
}
svg {
fill: var(--color-error-darkest);
fill: var(--color-error-darker);
}
}
&.warning {
Expand Down Expand Up @@ -115,7 +115,7 @@
padding: 0;
}
p {
color: var(--color-error-darkest);
color: var(--base-black);
font-size: var(--font-size-md);
}
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/lib/ui/ProgressList/ProgressList.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@
&:global(.error) {
aside {
svg {
fill: var(--color-error-darkest);
fill: var(--color-error-darker);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/lib/ui/StatusList/StatusList.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@

&:global(.error) {
svg {
fill: var(--color-error-darkest);
fill: var(--color-error-darker);
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion frontend/lib/ui/Table/Table.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@
background: var(--color-hover);
}

/* Cell with the chevron icon */
td:last-of-type {
padding-right: 2.75rem;
padding-right: 4.5rem;
background-image: url("../../icon/svg/chevronRight.svg");
background-size: 1.25rem;
background-position: center right 1.5rem;
Expand Down
Loading

0 comments on commit 126ba15

Please sign in to comment.