started working on the backend

This commit is contained in:
z1glr
2025-01-07 16:37:37 +00:00
parent 03b2b0e206
commit c3bc06fe82
34 changed files with 1437 additions and 54 deletions

View File

@@ -1,8 +1,18 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
output: "export"
/* config options here */
// output: "export",
rewrites: async () => ({
beforeFiles: [],
afterFiles: [],
fallback: [
{
source: "/api/:path*",
destination: "http://golunteer-frontend:8080/api/:path*",
},
],
}),
};
export default nextConfig;

View File

@@ -15,10 +15,12 @@
"@nextui-org/checkbox": "^2.3.8",
"@nextui-org/date-picker": "^2.3.9",
"@nextui-org/divider": "^2.2.5",
"@nextui-org/form": "^2.1.8",
"@nextui-org/input": "^2.4.8",
"@nextui-org/modal": "^2.2.7",
"@nextui-org/radio": "^2.3.8",
"@nextui-org/select": "^2.4.9",
"@nextui-org/switch": "^2.2.8",
"@nextui-org/system": "^2.4.6",
"@nextui-org/table": "^2.2.8",
"@nextui-org/theme": "^2.4.5",
@@ -1498,6 +1500,30 @@
"react-dom": ">=18 || >=19.0.0-rc.0"
}
},
"node_modules/@nextui-org/switch": {
"version": "2.2.8",
"resolved": "https://registry.npmjs.org/@nextui-org/switch/-/switch-2.2.8.tgz",
"integrity": "sha512-wk9qQSOfUEtmdWR1omKjmEYzgMjJhVizvfW6Z0rKOiMUuSud2d4xYnUmZhU22cv2WtoPV//kBjXkYD/E/t6rdg==",
"license": "MIT",
"dependencies": {
"@nextui-org/react-utils": "2.1.3",
"@nextui-org/shared-utils": "2.1.2",
"@nextui-org/use-safe-layout-effect": "2.1.1",
"@react-aria/focus": "3.19.0",
"@react-aria/interactions": "3.22.5",
"@react-aria/switch": "3.6.10",
"@react-aria/utils": "3.26.0",
"@react-aria/visually-hidden": "3.8.18",
"@react-stately/toggle": "3.8.0",
"@react-types/shared": "3.26.0"
},
"peerDependencies": {
"@nextui-org/system": ">=2.4.0",
"@nextui-org/theme": ">=2.4.3",
"react": ">=18 || >=19.0.0-rc.0",
"react-dom": ">=18 || >=19.0.0-rc.0"
}
},
"node_modules/@nextui-org/system": {
"version": "2.4.6",
"resolved": "https://registry.npmjs.org/@nextui-org/system/-/system-2.4.6.tgz",
@@ -2179,6 +2205,22 @@
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
}
},
"node_modules/@react-aria/switch": {
"version": "3.6.10",
"resolved": "https://registry.npmjs.org/@react-aria/switch/-/switch-3.6.10.tgz",
"integrity": "sha512-FtaI9WaEP1tAmra1sYlAkYXg9x75P5UtgY8pSbe9+1WRyWbuE1QZT+RNCTi3IU4fZ7iJQmXH6+VaMyzPlSUagw==",
"license": "Apache-2.0",
"dependencies": {
"@react-aria/toggle": "^3.10.10",
"@react-stately/toggle": "^3.8.0",
"@react-types/shared": "^3.26.0",
"@react-types/switch": "^3.5.7",
"@swc/helpers": "^0.5.0"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
}
},
"node_modules/@react-aria/table": {
"version": "3.16.0",
"resolved": "https://registry.npmjs.org/@react-aria/table/-/table-3.16.0.tgz",
@@ -2759,6 +2801,18 @@
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
}
},
"node_modules/@react-types/switch": {
"version": "3.5.7",
"resolved": "https://registry.npmjs.org/@react-types/switch/-/switch-3.5.7.tgz",
"integrity": "sha512-1IKiq510rPTHumEZuhxuazuXBa2Cuxz6wBIlwf3NCVmgWEvU+uk1ETG0sH2yymjwCqhtJDKXi+qi9HSgPEDwAg==",
"license": "Apache-2.0",
"dependencies": {
"@react-types/shared": "^3.26.0"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
}
},
"node_modules/@react-types/table": {
"version": "3.10.3",
"resolved": "https://registry.npmjs.org/@react-types/table/-/table-3.10.3.tgz",

View File

@@ -16,10 +16,12 @@
"@nextui-org/checkbox": "^2.3.8",
"@nextui-org/date-picker": "^2.3.9",
"@nextui-org/divider": "^2.2.5",
"@nextui-org/form": "^2.1.8",
"@nextui-org/input": "^2.4.8",
"@nextui-org/modal": "^2.2.7",
"@nextui-org/radio": "^2.3.8",
"@nextui-org/select": "^2.4.9",
"@nextui-org/switch": "^2.2.8",
"@nextui-org/system": "^2.4.6",
"@nextui-org/table": "^2.2.8",
"@nextui-org/theme": "^2.4.5",

View File

@@ -7,10 +7,25 @@ import AddEvent from "../components/Event/AddEvent";
import zustand from "../Zustand";
import { Button } from "@nextui-org/button";
import AssignmentTable from "@/components/Event/AssignmentTable";
import { useAsyncList } from "@react-stately/data";
import { apiCall } from "@/lib";
export default function EventVolunteer() {
const [showAddItemDialogue, setShowAddItemDialogue] = useState(false);
// fetch the events from the server
useAsyncList({
load: async () => {
const data = await apiCall("GET", "events");
console.debug(await data.json());
return {
items: [],
};
},
});
return (
<div className="relative flex-1 p-4">
<h2 className="mb-4 text-center text-4xl">Overview</h2>

View File

@@ -40,8 +40,4 @@
h6 {
@apply font-headline text-highlight;
}
input {
@apply border-2 border-accent-1 bg-transparent;
}
}

View File

@@ -1,5 +1,54 @@
import EventVolunteer from "./Overview";
"use client";
import { Input } from "@nextui-org/input";
import { useState } from "react";
import { ViewFilled, ViewOffFilled } from "@carbon/icons-react";
import { Switch } from "@nextui-org/switch";
import { Button } from "@nextui-org/button";
import { Form } from "@nextui-org/form";
export default function Home() {
return <EventVolunteer />;
const [visibility, setVisibility] = useState(false);
// return <EventVolunteer />;
return (
<div>
<h2 className="mb-4 text-center text-4xl">Login</h2>
<Form
validationBehavior="native"
className="flex flex-col items-center gap-2"
onSubmit={(e) => e.preventDefault()}
>
<Input
isRequired
type="user"
label="Name"
name="username"
variant="bordered"
className="max-w-xs"
/>
<Input
isRequired
label="Password"
name="password"
autoComplete="current-password"
endContent={
<Switch
className="my-auto"
startContent={<ViewFilled />}
endContent={<ViewOffFilled />}
onValueChange={setVisibility}
isSelected={visibility}
/>
}
type={visibility ? "text" : "password"}
variant="bordered"
className="max-w-xs"
/>
<Button className="w-full max-w-xs" color="primary" type="submit">
Login
</Button>
</Form>
</div>
);
}

56
client/src/lib.ts Normal file
View File

@@ -0,0 +1,56 @@
type QueryParams = Record<string, string | { toString(): string }>;
export type APICallResult<T extends object> = Response & { json: () => Promise<T> };
export async function apiCall<K extends object>(
method: "GET",
api: string,
params?: QueryParams
): Promise<APICallResult<K>>;
export async function apiCall<K extends object>(
method: "POST" | "PATCH",
api: string,
params?: QueryParams,
body?: object
): Promise<APICallResult<K>>;
export async function apiCall<K extends object>(
method: "DELETE",
api: string,
params?: QueryParams,
body?: object
): Promise<APICallResult<K>>;
export async function apiCall<K extends object>(
method: "GET" | "POST" | "PATCH" | "DELETE",
api: string,
params?: QueryParams,
body?: object
): Promise<APICallResult<K>> {
let url = window.origin + "/api/" + api;
if (params) {
const urlsearchparams = new URLSearchParams(
Object.fromEntries(
Object.entries(params).map(([key, value]): [string, string] => {
if (typeof value !== "string") {
return [key, value.toString()];
} else {
return [key, value];
}
})
)
);
url += "?" + urlsearchparams.toString();
}
const response = await fetch(url, {
headers: {
"Content-Type": "application/json; charset=UTF-8"
},
credentials: "include",
method,
body: body !== undefined ? JSON.stringify(body) : undefined
});
return response;
}

View File

@@ -24,16 +24,16 @@ export default {
foreground: {
DEFAULT: FOREGROUND,
"50": FOREGROUND,
"100": "#fce8ff",
"200": "#fad0fe",
"300": "#f8abfc",
"400": "#f579f9",
"500": "#eb46ef",
"600": "#d226d3",
"700": "#af1cad",
"800": "#8f198c",
"900": "#751a70",
"950": "#4e044a",
"100": FOREGROUND,
"200": FOREGROUND,
"300": FOREGROUND,
"400": FOREGROUND,
"500": FOREGROUND,
"600": "#fce8ff",
"700": "#fad0fe",
"800": "#f8abfc",
"900": "#f579f9",
"950": "#eb46ef",
},
"accent-1": ACCENT1,
"accent-2": ACCENT2,