Skip to content

Commit

Permalink
🚧 Start workin on destruction list create page
Browse files Browse the repository at this point in the history
  • Loading branch information
svenvandescheur committed May 14, 2024
1 parent 05d5c53 commit b114b63
Show file tree
Hide file tree
Showing 15 changed files with 6,780 additions and 72 deletions.
5 changes: 2 additions & 3 deletions frontend/bin/create_page.sh
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,17 @@ EOF
# Function to create the page file
function create_page_file() {
cat > "$2/$capitalized_page_name.tsx" <<EOF
import React from "react";
import "./$capitalized_page_name.css";
export type ${capitalized_page_name}Props = React.ComponentProps<"main"> & {
export type ${capitalized_page_name}PageProps = React.ComponentProps<"main"> & {
// Props here.
};
/**
* ${capitalized_page_name} page
*/
export function ${capitalized_page_name}Page({ children, ...props }: ${capitalized_page_name}Props) {
export function ${capitalized_page_name}Page({ children, ...props }: ${capitalized_page_name}PageProps) {
return (
<main className="${capitalized_page_name}Page" {...props}>
{children}
Expand Down
28 changes: 27 additions & 1 deletion frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,37 @@
import { NavigationContext, Outline } from "@maykin-ui/admin-ui";
import React from "react";
import { Outlet, useNavigate } from "react-router-dom";

import "./App.css";

export type AppProps = React.ComponentProps<"div">;

function App({ children }: AppProps) {
return <div className="App">{children}</div>;
const navigate = useNavigate();

return (
<div className="App">
<NavigationContext.Provider
value={{
primaryNavigationItems: [
{
children: <Outline.HomeIcon />,
title: "Home",
onClick: () => navigate("/"),
},
"spacer",
{
children: <Outline.ArrowRightOnRectangleIcon />,
title: "Uitloggen",
onClick: () => navigate("/logout"),
},
],
}}
>
<Outlet />
</NavigationContext.Provider>
</div>
);
}

export default App;
40 changes: 25 additions & 15 deletions frontend/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import "@maykin-ui/admin-ui/style";
import * as React from "react";
import * as ReactDOM from "react-dom/client";
import { RouterProvider, createBrowserRouter } from "react-router-dom";

import App from "./App";
import "./index.css";
import {
LandingPage,
DestructionListCreatePage,
LoginPage,
destructionListCreateLoader,
landingLoader,
loginAction,
logoutLoader,
Expand All @@ -15,24 +17,32 @@ import {
const router = createBrowserRouter([
{
path: "/",
element: <LandingPage />,
loader: landingLoader,
},
{
path: "/login",
element: <LoginPage />,
action: loginAction,
},
{
path: "/logout",
loader: logoutLoader,
element: <App />,
children: [
{
path: "/",
loader: landingLoader,
},
{
path: "/destruction-lists/create",
element: <DestructionListCreatePage />,
loader: destructionListCreateLoader,
},
{
path: "/login",
element: <LoginPage />,
action: loginAction,
},
{
path: "/logout",
loader: logoutLoader,
},
],
},
]);

ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<React.StrictMode>
<App>
<RouterProvider router={router} />
</App>
<RouterProvider router={router} />
</React.StrictMode>,
);
16 changes: 14 additions & 2 deletions frontend/src/lib/api/request.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
import { getCookie } from "../cookie/cookie";

/** Scheme for all API requests.. */
export const API_SCHEME = "http";

/** The host for the API server. */
export const API_HOST = "localhost";

/** The port for the API server. */
export const API_PORT = 8080;

/** The base path for all API requests. */
export const API_PATH = "/api/v1";

/** The base url for all API requests. */
export const BASE_URL = "http://localhost:8000/api/v1";
export const API_BASE_URL = `${API_SCHEME}://${API_HOST}:${API_PORT}${API_PATH}`;

/**
* Makes an actual fetch request to the API, should be used by all other API implementations.
Expand All @@ -17,7 +29,7 @@ export async function request(
headers?: Record<string, string>,
) {
const csrfToken = getCookie("csrftoken");
const url = BASE_URL + endpoint;
const url = API_BASE_URL + endpoint;
const abortController = new AbortController();

const response = await fetch(url, {
Expand Down
8 changes: 5 additions & 3 deletions frontend/src/lib/api/zaken.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Zaak } from "../../types";
import { request } from "./request";

export type Zaak = {
// TODO
export type PaginatedZaken = {
count: number;
results: Zaak[];
};

/**
Expand All @@ -10,6 +12,6 @@ export type Zaak = {
*/
export async function listZaken() {
const response = await request("GET", "/zaken/");
const promise: Promise<Zaak[]> = response.json();
const promise: Promise<PaginatedZaken[]> = response.json();
return promise;
}
3 changes: 3 additions & 0 deletions frontend/src/pages/destructionlist/DestructionListCreate.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.DestructionListCreatePage {
/* Rules here. */
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { Meta, StoryObj } from "@storybook/react";

import { DestructionListCreatePage } from "./DestructionListCreate";

const meta: Meta<typeof DestructionListCreatePage> = {
title: "Pages/DestructionList/DestructionListCreatePage",
component: DestructionListCreatePage,
};

export default meta;
type Story = StoryObj<typeof meta>;

export const destructionListCreatePage: Story = {
args: {
children: "The quick brown fox jumps over the lazy dog.",
},
};
92 changes: 92 additions & 0 deletions frontend/src/pages/destructionlist/DestructionListCreate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import {
AttributeData,
DataGridProps,
List,
TypedField,
} from "@maykin-ui/admin-ui";
import React from "react";
import { useLoaderData } from "react-router-dom";

import { loginRequired } from "../../lib/api/loginRequired";
import { PaginatedZaken, listZaken } from "../../lib/api/zaken";
import { Zaak } from "../../types";
import "./DestructionListCreate.css";

/**
* React Router loader.
* @param request
* TOOD: Requires destruction list lists endpoint.
*/
export const destructionListCreateLoader = loginRequired(listZaken);

export type DestructionListCreateProps = React.ComponentProps<"main"> & {
// Props here.
};

/**
* Destruction list creation page
*/
export function DestructionListCreatePage({
children,
...props
}: DestructionListCreateProps) {
const { count, results } = useLoaderData() as PaginatedZaken;
const objectList = transformZakenForPresentation(results);

console.log(results, objectList);

const fields: TypedField[] = [
{ name: "identificatie", type: "string" },
{ name: "zaaktype", type: "string" },
{ name: "omschrijving", type: "string" },
{ name: "looptijd", type: "string" },
{ name: "resultaattype", type: "string" },
{ name: "bewaartermijn", type: "string" },
{ name: "vcs", type: "string" },
{ name: "relaties", type: "boolean" },
];

return (
<List
count={count}
fields={fields}
objectList={objectList}
labelSelect={"Selecteer item"} // FIXME: optional
labelSelectAll={"Selecteer alle items"} // FIXME: optional
pageSize={10}
showPaginator={false} // TODO
selectable={false} // TODO
dataGridProps={
// FIXME: Required attrs, alias
{
boolProps: {
explicit: true,
labelFalse: "Nee", // FIXME: optinal
},
filterable: true,
} as DataGridProps
}
title="Vernietigingslijst starten"
/>
);
}

export function transformZakenForPresentation(zaken: Zaak[]) {
return zaken.map<AttributeData>((zaak) => {
const startDate = new Date(zaak.startdatum);
const endDate = zaak.einddatum ? new Date(zaak.einddatum) : new Date();
const dayDelta =
(endDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24);

return {
identificatie: zaak.identificatie || "",
zaaktype: zaak.zaaktype,
omschrijving: zaak.omschrijving || "",
looptijd: String(dayDelta),
resultaattype: "TODO",
bewaartermijn: "TODO",
vcs: "TODO",
relaties: Boolean(zaak?.relevanteAndereZaken?.length || 0),
};
});
}
1 change: 1 addition & 0 deletions frontend/src/pages/destructionlist/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./DestructionListCreate";
1 change: 1 addition & 0 deletions frontend/src/pages/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Auto-generated file. Do not modify manually.
export * from "./destructionlist";
export * from "./landing";
export * from "./login";
export * from "./logout";
23 changes: 0 additions & 23 deletions frontend/src/pages/landing/Landing.stories.tsx

This file was deleted.

25 changes: 3 additions & 22 deletions frontend/src/pages/landing/Landing.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,10 @@
import React from "react";
import { useLoaderData } from "react-router-dom";
import { redirect, useLoaderData } from "react-router-dom";

import { loginRequired } from "../../lib/api/loginRequired";
import { listReviewers } from "../../lib/api/reviewers";
import "./Landing.css";

/**
* React Router loader.
* @param request
* TOOD: Requires destruction list lists endpoint.
*/
export const landingLoader = loginRequired(listReviewers);

export type LandingProps = React.ComponentProps<"main"> & {
// Props here.
};

/**
* Landing page
*/
export function LandingPage({ children, ...props }: LandingProps) {
const items = useLoaderData();

return (
<main className="LandingPage" {...props}>
{JSON.stringify(items)}
</main>
);
}
export const landingLoader = () => redirect("/destruction-lists/create");
3 changes: 1 addition & 2 deletions frontend/src/pages/login/Login.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { Login } from "@maykin-ui/admin-ui";
import "@maykin-ui/admin-ui/style";
import { ActionFunctionArgs } from "@remix-run/router/utils";
import React from "react";
import { redirect, useActionData, useSubmit } from "react-router-dom";

import { login } from "../../lib/api/auth";
Expand Down Expand Up @@ -58,6 +56,7 @@ export function LoginPage({ children, ...props }: LoginProps) {

return (
<Login
slotPrimaryNavigation={<></>} // FIXME: Shoudl be easier to override
formProps={{
nonFieldErrors,
errors,
Expand Down
1 change: 0 additions & 1 deletion frontend/src/pages/logout/Logout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from "react";
import { redirect } from "react-router-dom";

import { logout } from "../../lib/api/auth";
Expand Down
Loading

0 comments on commit b114b63

Please sign in to comment.