diff --git a/backend/pkg/db/events/events.go b/backend/pkg/db/events/events.go
index 0f4de3a..670bb5b 100644
--- a/backend/pkg/db/events/events.go
+++ b/backend/pkg/db/events/events.go
@@ -35,6 +35,11 @@ type EventWithAvailabilities struct {
Availabilities availabilities.AvailabilityMap `json:"availabilities"`
}
+type EventWithAssignmentsUserAvailability struct {
+ EventWithAssignments
+ Availability *int `json:"availability" db:"availabilityID"`
+}
+
type EventCreate struct {
Date string `db:"date" json:"date" validate:"required,datetime=2006-01-02T15:04:05.999999999Z"`
Description string `db:"description" json:"description"`
@@ -54,6 +59,19 @@ func (e EventData) WithAssignments() (EventWithAssignments, error) {
}
}
+func (e EventWithAssignments) WithUserAvailability(userName string) (EventWithAssignmentsUserAvailability, error) {
+ // get the availability of the user
+ event := EventWithAssignmentsUserAvailability{
+ EventWithAssignments: e,
+ }
+
+ if err := db.DB.Select(&event, "SELECT availabilityID FROM USER_AVAILABILITIES WHERE eventID = $1 AND userName = $2", e.EventID, userName); err != nil {
+ return EventWithAssignmentsUserAvailability{}, err
+ } else {
+ return event, nil
+ }
+}
+
func (e EventData) WithAvailabilities() (EventWithAvailabilities, error) {
// get the event with assignments
if event, err := e.WithAssignments(); err != nil {
@@ -217,6 +235,26 @@ func WithAvailabilities() ([]EventWithAvailabilities, error) {
}
}
+func WithUserAvailability(userName string) ([]EventWithAssignmentsUserAvailability, error) {
+ var events []EventWithAssignmentsUserAvailability
+
+ if err := db.DB.Select(&events, "SELECT EVENTS.eventID, EVENTS.description, EVENTS.date, USER_AVAILABILITIES.availabilityID FROM EVENTS LEFT JOIN USER_AVAILABILITIES ON EVENTS.eventID = USER_AVAILABILITIES.eventID AND USER_AVAILABILITIES.userName = $1", userName); err != nil {
+ return nil, err
+ } else {
+ // get the assignments for every event
+ for ii, event := range events {
+ if eventWithAssignments, err := event.EventWithAssignments.EventData.WithAssignments(); err != nil {
+ // remove the current event from the events
+ events = append(events[:ii], events[ii+1:]...)
+ } else {
+ events[ii].EventWithAssignments = eventWithAssignments
+ }
+ }
+
+ return events, nil
+ }
+}
+
func UserPending(userName string) ([]EventData, error) {
var result []EventData
diff --git a/backend/pkg/router/events.go b/backend/pkg/router/events.go
index 906259f..5d34692 100644
--- a/backend/pkg/router/events.go
+++ b/backend/pkg/router/events.go
@@ -90,6 +90,17 @@ func (a *Handler) getEventsAvailabilities() {
}
}
+func (a *Handler) getEventUserAssignmentAvailability() {
+ // retrieve the assignments
+ if events, err := events.WithUserAvailability(a.UserName); err != nil {
+ a.Status = fiber.StatusBadRequest
+
+ logger.Log().Msgf("getting events with tasks and user-availability failed: %v", err)
+ } else {
+ a.Data = events
+ }
+}
+
func (a *Handler) getEventsUserPending() {
if events, err := events.UserPending(a.UserName); err != nil {
a.Status = fiber.StatusInternalServerError
diff --git a/backend/pkg/router/router.go b/backend/pkg/router/router.go
index 6f15c33..e956044 100644
--- a/backend/pkg/router/router.go
+++ b/backend/pkg/router/router.go
@@ -83,6 +83,9 @@ func init() {
// all events with the availabilities of the individual users
"events/availabilities": (*Handler).getEventsAvailabilities,
+ // all events with the task-assignments and the availability of the current user
+ "events/user/assignmentAvailability": (*Handler).getEventUserAssignmentAvailability,
+
// events the user has to enter his availability for
"events/user/pending": (*Handler).getEventsUserPending,
diff --git a/client/src/Zustand.ts b/client/src/Zustand.ts
index f456442..31da8fd 100644
--- a/client/src/Zustand.ts
+++ b/client/src/Zustand.ts
@@ -10,10 +10,16 @@ export interface BaseEvent {
description: string;
}
+export type EventAvailability = BaseEvent & {
+ availability: number;
+};
+
export type EventData = BaseEvent & {
tasks: TaskAssignment[];
};
+export type EventDataWithAvailability = EventData & EventAvailability;
+
export interface TaskAssignment {
taskID: number;
taskName: string;
diff --git a/client/src/app/Overview.tsx b/client/src/app/Overview.tsx
index 9647a10..bb431ee 100644
--- a/client/src/app/Overview.tsx
+++ b/client/src/app/Overview.tsx
@@ -1,5 +1,5 @@
import MyEvents from "./MyEvents";
-import PengingEvents from "./PendingEvents";
+import PendingEvents from "./PendingEvents";
export default function Overview() {
return (
@@ -12,7 +12,7 @@ export default function Overview() {
Pending Events
-
+
);
diff --git a/client/src/app/PendingEvents.tsx b/client/src/app/PendingEvents.tsx
index 504b40d..1979146 100644
--- a/client/src/app/PendingEvents.tsx
+++ b/client/src/app/PendingEvents.tsx
@@ -1,17 +1,12 @@
"use client";
-import AvailabilityChip from "@/components/AvailabilityChip";
+import AvailabilitySelector from "@/components/Event/AvailabilitySelector";
import Event from "@/components/Event/Event";
-import { apiCall, getAvailabilities } from "@/lib";
-import { BaseEvent } from "@/Zustand";
-import { Select, SelectItem } from "@heroui/react";
+import { apiCall } from "@/lib";
+import { EventAvailability } from "@/Zustand";
import { useAsyncList } from "@react-stately/data";
-type EventAvailability = BaseEvent & {
- availability: number;
-};
-
-export default function PengingEvents() {
+export default function PendingEvents() {
// get the events the user hasn't yet inserted his availability for
const events = useAsyncList({
async load() {
@@ -32,56 +27,11 @@ export default function PengingEvents() {
},
});
- // the individual, selectable availabilities
- const availabilities = useAsyncList({
- async load() {
- return {
- items: (await getAvailabilities()).filter((a) => a.enabled),
- };
- },
- });
-
- async function setAvailability(eventID: number, availabilityID: number) {
- await apiCall(
- "PUT",
- "events/user/availability",
- { eventID },
- availabilityID,
- );
- }
-
return (
{events.items.map((e) => (
-
+
))}
diff --git a/client/src/app/events/page.tsx b/client/src/app/events/page.tsx
index f7685c4..69b5bab 100644
--- a/client/src/app/events/page.tsx
+++ b/client/src/app/events/page.tsx
@@ -3,23 +3,31 @@ import AddEvent from "@/components/Event/AddEvent";
import AssignmentTable from "@/components/Event/AssignmentTable";
import Event from "@/components/Event/Event";
import { apiCall } from "@/lib";
-import zustand, { EventData } from "@/Zustand";
+import zustand, { EventDataWithAvailability } from "@/Zustand";
import { Add } from "@carbon/icons-react";
-import { Button } from "@heroui/react";
+import { Button, Tab, Tabs } from "@heroui/react";
import { useAsyncList } from "@react-stately/data";
import { useState } from "react";
+import AvailabilitySelector from "@/components/Event/AvailabilitySelector";
export default function Events() {
const [showAddItemDialogue, setShowAddItemDialogue] = useState(false);
- const admin = zustand((state) => state.user?.admin);
+ const [filter, setFilter] = useState("");
- const events = useAsyncList({
+ const user = zustand((state) => state.user);
+
+ const events = useAsyncList({
async load() {
- const result = await apiCall("GET", "events/assignments");
+ const result = await apiCall(
+ "GET",
+ "events/user/assignmentAvailability",
+ );
if (result.ok) {
const data = await result.json();
+ console.debug(data);
+
return {
items: data,
};
@@ -31,20 +39,52 @@ export default function Events() {
},
});
+ function showEvent(event: EventDataWithAvailability): boolean {
+ switch (filter) {
+ case "assigned":
+ return event.tasks.some((t) => {
+ return t.userName === user?.userName;
+ });
+
+ case "pending":
+ return event.availability === null;
+
+ default:
+ return true;
+ }
+ }
+
return (
-
-
Upcoming Events
+
+
Upcoming Events
+
+
+
+
+
+
+
- {events.items.map((ee, ii) => (
-
+ {events.items.filter(showEvent).map((e) => (
+
))}
- {admin ? (
+ {user?.admin ? (
<>