From 353f51f2aef6f89155012df23443dd402286e06e Mon Sep 17 00:00:00 2001 From: z1glr Date: Fri, 7 Feb 2025 11:28:14 +0000 Subject: [PATCH] adjusted events view to only show the availability selector, when a user can do at least one task of the event --- backend/pkg/db/users/User.go | 8 ++++++++ backend/pkg/router/router.go | 1 + backend/pkg/router/user.go | 10 ++++++++++ client/src/Zustand.ts | 3 ++- client/src/app/events/page.tsx | 20 +++++++++++++++++--- client/src/app/layout.tsx | 4 ++-- client/src/components/Event/Event.tsx | 2 +- client/src/lib.ts | 25 ++++++++++++++++++++++++- 8 files changed, 65 insertions(+), 8 deletions(-) diff --git a/backend/pkg/db/users/User.go b/backend/pkg/db/users/User.go index a13ad73..a943a51 100644 --- a/backend/pkg/db/users/User.go +++ b/backend/pkg/db/users/User.go @@ -177,6 +177,14 @@ func (userName UserName) ChangePassword(password string) (string, error) { } } +func (userName UserName) GetTasks() ([]tasks.TaskID, error) { + var tasks []tasks.TaskID + + err := db.DB.Select(&tasks, "SELECT taskID FROM USER_TASKS WHERE userName = $1", userName) + + return tasks, err +} + func (userName UserName) SetTasks(tasks []tasks.TaskID) error { // remove all current possible tasks if _, err := db.DB.Exec("DELETE FROM USER_TASKS WHERE userName = $1", userName); err != nil { diff --git a/backend/pkg/router/router.go b/backend/pkg/router/router.go index 7d92570..5a519a3 100644 --- a/backend/pkg/router/router.go +++ b/backend/pkg/router/router.go @@ -99,6 +99,7 @@ func init() { "events/user/assigned": (*Handler).getEventsUserAssigned, "tasks": (*Handler).getTasks, // all available tasks "users": (*Handler).getUsers, // all users + "user/tasks": (*Handler).getUserTasks, // get all possible tasks for the user "availabilities": (*Handler).getAvailabilities, // all available availabilities }, "POST": { diff --git a/backend/pkg/router/user.go b/backend/pkg/router/user.go index afcea9f..b08fc88 100644 --- a/backend/pkg/router/user.go +++ b/backend/pkg/router/user.go @@ -20,6 +20,16 @@ func (a *Handler) getUsers() { } } +func (a *Handler) getUserTasks() { + if tasks, err := a.UserName.GetTasks(); err != nil { + a.Status = fiber.StatusInternalServerError + + logger.Error().Msgf("getting possible user-tasks failed: %v", err) + } else { + a.Data = tasks + } +} + func (a *Handler) postUser() { // check admin diff --git a/client/src/Zustand.ts b/client/src/Zustand.ts index 2aefe9e..99599bb 100644 --- a/client/src/Zustand.ts +++ b/client/src/Zustand.ts @@ -1,7 +1,7 @@ "use client"; import { create } from "zustand"; -import { Task } from "./lib"; +import { Task, TaskID } from "./lib"; import { Availability } from "./app/admin/(availabilities)/AvailabilityEditor"; export interface BaseEvent { @@ -41,6 +41,7 @@ export type UserAddModify = User & { interface Zustand { user: StateUser | null; + userTasks?: TaskID[]; tasks?: Task[]; availabilities?: Availability[]; users?: User[]; diff --git a/client/src/app/events/page.tsx b/client/src/app/events/page.tsx index 7ca630b..b236151 100644 --- a/client/src/app/events/page.tsx +++ b/client/src/app/events/page.tsx @@ -2,7 +2,7 @@ import AddEvent from "@/components/Event/AddEvent"; import AssignmentTable from "@/components/Event/AssignmentTable"; import Event from "@/components/Event/Event"; -import { apiCall } from "@/lib"; +import { apiCall, getUserTasks } from "@/lib"; import zustand, { EventDataWithAvailability } from "@/Zustand"; import { Add } from "@carbon/icons-react"; import { Button, Tab, Tabs } from "@heroui/react"; @@ -37,6 +37,14 @@ export default function Events() { }, }); + const userTasks = useAsyncList({ + async load() { + return { + items: await getUserTasks(), + }; + }, + }); + function showEvent(event: EventDataWithAvailability): boolean { switch (filter) { case "assigned": @@ -45,13 +53,17 @@ export default function Events() { }); case "pending": - return event.availability === null; + return event.availability === null && showAvailabilitySelector(event); default: return true; } } + function showAvailabilitySelector(event: EventDataWithAvailability): boolean { + return event.tasks.some((t) => userTasks.items.includes(t.taskID)); + } + return (

Upcoming Events

@@ -75,7 +87,9 @@ export default function Events() { tasks={e.tasks} className="mt-auto" /> - + {showAvailabilitySelector(e) ? ( + + ) : undefined} ))}
diff --git a/client/src/app/layout.tsx b/client/src/app/layout.tsx index f0c88f4..27db605 100644 --- a/client/src/app/layout.tsx +++ b/client/src/app/layout.tsx @@ -7,8 +7,8 @@ import Header from "./Header"; import Main from "./Main"; export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "Golunteer", + description: "Volunteeer coordination", }; export interface SiteLink { diff --git a/client/src/components/Event/Event.tsx b/client/src/components/Event/Event.tsx index 99edb9a..8afc869 100644 --- a/client/src/components/Event/Event.tsx +++ b/client/src/components/Event/Event.tsx @@ -43,7 +43,7 @@ export default function Event({ {Array.isArray(children) ? children[0] : children} - {Array.isArray(children) ? ( + {Array.isArray(children) && !!children[1] ? ( <> {children[1]} diff --git a/client/src/lib.ts b/client/src/lib.ts index f9cc501..3ae279f 100644 --- a/client/src/lib.ts +++ b/client/src/lib.ts @@ -144,8 +144,10 @@ export function validatePassword(password: string): string[] { return errors; } +export type TaskID = number; + export interface Task { - taskID: number | undefined; + taskID: TaskID | undefined; taskName: string; enabled: boolean; } @@ -219,3 +221,24 @@ export async function getUsers(): Promise { } } } + +export async function getUserTasks(): Promise { + // check wether it is cached in zustand + const state = zustand.getState(); + + if (!!state.userTasks) { + return state.userTasks; + } else { + const result = await apiCall("GET", "user/tasks"); + + if (result.ok) { + const userTasks = await result.json(); + + state.patch({ userTasks }); + + return userTasks; + } else { + return []; + } + } +}