Skip to content

Commit 9bbcb86

Browse files
♻️ #187 - refactor: create separate files for loaders and actions
1 parent 9a0aba5 commit 9bbcb86

25 files changed

+618
-590
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { ActionFunctionArgs } from "@remix-run/router/utils";
2+
import { redirect } from "react-router-dom";
3+
4+
import { createDestructionList } from "../../../lib/api/destructionLists";
5+
import { clearZaakSelection } from "../../../lib/zaakSelection/zaakSelection";
6+
import { DESTRUCTION_LIST_CREATE_KEY } from "./DestructionListCreate";
7+
8+
/**
9+
* React Router action.
10+
* @param request
11+
*/
12+
export async function destructionListCreateAction({
13+
request,
14+
}: ActionFunctionArgs) {
15+
const formData = await request.formData();
16+
const name = formData.get("name") as string;
17+
const zaakUrls = formData.getAll("zaakUrls") as string[];
18+
const assigneeIds = formData.getAll("assigneeIds") as string[];
19+
20+
try {
21+
await createDestructionList(name, zaakUrls, assigneeIds);
22+
} catch (e: unknown) {
23+
return await (e as Response).json();
24+
}
25+
await clearZaakSelection(DESTRUCTION_LIST_CREATE_KEY);
26+
return redirect("/");
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { LoaderFunctionArgs } from "@remix-run/router/utils";
2+
3+
import { User } from "../../../lib/api/auth";
4+
import { listReviewers } from "../../../lib/api/reviewers";
5+
import { PaginatedZaken, listZaken } from "../../../lib/api/zaken";
6+
import {
7+
canStartDestructionListRequired,
8+
loginRequired,
9+
} from "../../../lib/auth/loaders";
10+
import { isZaakSelected } from "../../../lib/zaakSelection/zaakSelection";
11+
import { DESTRUCTION_LIST_CREATE_KEY } from "./DestructionListCreate";
12+
import "./DestructionListCreate.css";
13+
14+
/**
15+
* React Router loader.
16+
* @param request
17+
*/
18+
export const destructionListCreateLoader = loginRequired(
19+
canStartDestructionListRequired(async ({ request }: LoaderFunctionArgs) => {
20+
const searchParamsZakenEndpoint: Record<string, string> = {
21+
not_in_destruction_list: "true",
22+
};
23+
const searchParams = new URL(request.url).searchParams;
24+
Object.keys(searchParamsZakenEndpoint).forEach((key) =>
25+
searchParams.set(key, searchParamsZakenEndpoint[key]),
26+
);
27+
28+
// Get reviewers, zaken and zaaktypen.
29+
const promises = [listReviewers(), listZaken(searchParams)];
30+
const [reviewers, zaken] = (await Promise.all(promises)) as [
31+
User[],
32+
PaginatedZaken,
33+
];
34+
35+
// Get zaak selection.
36+
const isZaakSelectedPromises = zaken.results.map((zaak) =>
37+
isZaakSelected(DESTRUCTION_LIST_CREATE_KEY, zaak),
38+
);
39+
const isZaakSelectedResults = await Promise.all(isZaakSelectedPromises);
40+
const selectedZaken = zaken.results.filter(
41+
(_, index) => isZaakSelectedResults[index],
42+
);
43+
44+
return { reviewers, zaken, selectedZaken };
45+
}),
46+
);

frontend/src/pages/destructionlist/create/DestructionListCreate.tsx

+4-73
Original file line numberDiff line numberDiff line change
@@ -5,94 +5,25 @@ import {
55
Modal,
66
SerializedFormData,
77
} from "@maykin-ui/admin-ui";
8-
import {
9-
ActionFunctionArgs,
10-
LoaderFunctionArgs,
11-
} from "@remix-run/router/utils";
128
import { FormEvent, useState } from "react";
13-
import { redirect, useLoaderData, useSubmit } from "react-router-dom";
9+
import { useLoaderData, useSubmit } from "react-router-dom";
1410

1511
import { DestructionList } from "../../../components";
1612
import { User } from "../../../lib/api/auth";
17-
import { createDestructionList } from "../../../lib/api/destructionLists";
18-
import { listReviewers } from "../../../lib/api/reviewers";
19-
import { PaginatedZaken, listZaken } from "../../../lib/api/zaken";
20-
import {
21-
canStartDestructionListRequired,
22-
loginRequired,
23-
} from "../../../lib/auth/loaders";
24-
import {
25-
clearZaakSelection,
26-
getZaakSelection,
27-
isZaakSelected,
28-
} from "../../../lib/zaakSelection/zaakSelection";
13+
import { PaginatedZaken } from "../../../lib/api/zaken";
14+
import { getZaakSelection } from "../../../lib/zaakSelection/zaakSelection";
2915
import { Zaak } from "../../../types";
3016
import "./DestructionListCreate.css";
3117

3218
/** We need a key to store the zaak selection to, however we don't have a destruction list name yet. */
33-
const DESTRUCTION_LIST_CREATE_KEY = "destruction-list-create";
19+
export const DESTRUCTION_LIST_CREATE_KEY = "destruction-list-create";
3420

3521
export type DestructionListCreateContext = {
3622
reviewers: User[];
3723
zaken: PaginatedZaken;
3824
selectedZaken: Zaak[];
3925
};
4026

41-
/**
42-
* React Router loader.
43-
* @param request
44-
*/
45-
export const destructionListCreateLoader = loginRequired(
46-
canStartDestructionListRequired(async ({ request }: LoaderFunctionArgs) => {
47-
const searchParamsZakenEndpoint: Record<string, string> = {
48-
not_in_destruction_list: "true",
49-
};
50-
const searchParams = new URL(request.url).searchParams;
51-
Object.keys(searchParamsZakenEndpoint).forEach((key) =>
52-
searchParams.set(key, searchParamsZakenEndpoint[key]),
53-
);
54-
55-
// Get reviewers, zaken and zaaktypen.
56-
const promises = [listReviewers(), listZaken(searchParams)];
57-
const [reviewers, zaken] = (await Promise.all(promises)) as [
58-
User[],
59-
PaginatedZaken,
60-
];
61-
62-
// Get zaak selection.
63-
const isZaakSelectedPromises = zaken.results.map((zaak) =>
64-
isZaakSelected(DESTRUCTION_LIST_CREATE_KEY, zaak),
65-
);
66-
const isZaakSelectedResults = await Promise.all(isZaakSelectedPromises);
67-
const selectedZaken = zaken.results.filter(
68-
(_, index) => isZaakSelectedResults[index],
69-
);
70-
71-
return { reviewers, zaken, selectedZaken };
72-
}),
73-
);
74-
75-
/**
76-
* React Router action.
77-
* @param request
78-
*/
79-
export async function destructionListCreateAction({
80-
request,
81-
}: ActionFunctionArgs) {
82-
const formData = await request.formData();
83-
const name = formData.get("name") as string;
84-
const zaakUrls = formData.getAll("zaakUrls") as string[];
85-
const assigneeIds = formData.getAll("assigneeIds") as string[];
86-
87-
try {
88-
await createDestructionList(name, zaakUrls, assigneeIds);
89-
} catch (e: unknown) {
90-
return await (e as Response).json();
91-
}
92-
await clearZaakSelection(DESTRUCTION_LIST_CREATE_KEY);
93-
return redirect("/");
94-
}
95-
9627
/**
9728
* Destruction list creation page
9829
*/
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
export * from "./DestructionListCreate";
2+
export * from "./DestructionListCreate.action";
3+
export * from "./DestructionListCreate.loader";

frontend/src/pages/destructionlist/detail/Assignees.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { useActionData } from "react-router-dom";
1111
import { useSubmitAction } from "../../../hooks";
1212
import { DestructionListAssignee } from "../../../lib/api/destructionLists";
1313
import { formatUser } from "../utils";
14-
import { UpdateDestructionListAction } from "./DestructionListDetail";
14+
import { UpdateDestructionListAction } from "./DestructionListDetail.action";
1515
import { AssigneesEditableProps } from "./types";
1616

1717
export function AssigneesEditable({
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import { ActionFunctionArgs } from "@remix-run/router/utils";
2+
import { redirect } from "react-router-dom";
3+
4+
import { TypedAction } from "../../../hooks";
5+
import {
6+
DestructionListItemUpdate,
7+
updateDestructionList,
8+
} from "../../../lib/api/destructionLists";
9+
import {
10+
ReviewResponse,
11+
createReviewResponse,
12+
} from "../../../lib/api/reviewResponse";
13+
14+
export type UpdateDestructionListAction<T> = TypedAction<
15+
"PROCESS_REVIEW" | "UPDATE_ASSIGNEES" | "UPDATE_ZAKEN",
16+
T
17+
>;
18+
19+
/**
20+
* React Router action.
21+
*/
22+
export async function destructionListUpdateAction({
23+
request,
24+
params,
25+
}: ActionFunctionArgs) {
26+
const data = await request.clone().json();
27+
const action = data as UpdateDestructionListAction<unknown>;
28+
29+
switch (action.type) {
30+
case "PROCESS_REVIEW":
31+
return await destructionListProcessReviewAction({ request, params });
32+
case "UPDATE_ASSIGNEES":
33+
return await destructionListUpdateAssigneesAction({ request, params });
34+
case "UPDATE_ZAKEN":
35+
return await destructionListUpdateZakenAction({ request, params });
36+
default:
37+
throw new Error("INVALID ACTION TYPE SPECIFIED!");
38+
}
39+
}
40+
41+
/**
42+
* React Router action (user intents to adds/remove zaken to/from the destruction list).
43+
*/
44+
export async function destructionListProcessReviewAction({
45+
request,
46+
}: ActionFunctionArgs) {
47+
const data = await request.json();
48+
const reviewResponse: ReviewResponse = data.payload;
49+
50+
try {
51+
await createReviewResponse(reviewResponse);
52+
} catch (e: unknown) {
53+
if (e instanceof Response) {
54+
return await (e as Response).json();
55+
}
56+
throw e;
57+
}
58+
return redirect("/");
59+
}
60+
61+
/**
62+
* React Router action (user intents to reassign the destruction list).
63+
*/
64+
export async function destructionListUpdateAssigneesAction({
65+
request,
66+
params,
67+
}: ActionFunctionArgs) {
68+
const data: UpdateDestructionListAction<
69+
Record<string, string | Array<number | string>>
70+
> = await request.json();
71+
const { assigneeIds, comment } = data.payload;
72+
73+
const assignees = (assigneeIds as Array<number | string>)
74+
.filter((id) => id !== "") // Case in which a reviewer is removed
75+
.map((id, index) => ({
76+
user: Number(id),
77+
order: index,
78+
}));
79+
80+
try {
81+
await updateDestructionList(params.uuid as string, {
82+
assignees,
83+
comment: String(comment),
84+
});
85+
} catch (e: unknown) {
86+
if (e instanceof Response) {
87+
return await (e as Response).json();
88+
}
89+
throw e;
90+
}
91+
return redirect(`/destruction-lists/${params.uuid}/`);
92+
}
93+
94+
/**
95+
* React Router action (user intents to adds/remove zaken to/from the destruction list).
96+
*/
97+
export async function destructionListUpdateZakenAction({
98+
request,
99+
params,
100+
}: ActionFunctionArgs) {
101+
const data: UpdateDestructionListAction<Record<string, string[]>> =
102+
await request.json();
103+
const { zaakUrls } = data.payload;
104+
105+
const items = zaakUrls.map((zaakUrl) => ({
106+
zaak: zaakUrl,
107+
})) as DestructionListItemUpdate[];
108+
109+
try {
110+
await updateDestructionList(params.uuid as string, { items });
111+
} catch (e: unknown) {
112+
if (e instanceof Response) return await (e as Response).json();
113+
114+
throw e;
115+
}
116+
117+
return redirect(`/destruction-lists/${params.uuid}/`);
118+
}

frontend/src/pages/destructionlist/detail/DestructionListDetail.css

Whitespace-only changes.

0 commit comments

Comments
 (0)