-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement event attendance MVP (#804)
Co-authored-by: Mats Jun <[email protected]> Co-authored-by: Jo Gramnæs Tjernshaugen <[email protected]>
- Loading branch information
1 parent
404fa3d
commit 8d86626
Showing
122 changed files
with
4,456 additions
and
1,331 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
179 changes: 82 additions & 97 deletions
179
apps/dashboard/src/app/(dashboard)/event/[id]/attendance-page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,114 +1,99 @@ | ||
import type { Attendee, User } from "@dotkomonline/types" | ||
import { Button } from "@dotkomonline/ui" | ||
import { Box, Checkbox, Title } from "@mantine/core" | ||
import { createColumnHelper, getCoreRowModel, useReactTable } from "@tanstack/react-table" | ||
import React, { useMemo, useState, type FC } from "react" | ||
import GenericSearch from "../../../../components/GenericSearch" | ||
import { GenericTable } from "../../../../components/GenericTable" | ||
import { useDeregisterForEventMutation } from "../../../../modules/event/mutations/use-deregister-for-event-mutation" | ||
import { useRegisterForEventMutation } from "../../../../modules/event/mutations/use-register-for-event-mutation" | ||
import { useUpdateEventAttendanceMutation } from "../../../../modules/event/mutations/use-update-event-attendance-mutation" | ||
import { useEventAttendanceGetQuery } from "../../../../modules/event/queries/use-event-attendance-get-query" | ||
import { useUserSearchQuery } from "../../../../modules/user/queries/use-user-search-query" | ||
import type { Attendance } from "@dotkomonline/types" | ||
import { Divider } from "@mantine/core" | ||
import { Box, Title } from "@mantine/core" | ||
import type { FC } from "react" | ||
import { useAttendanceForm } from "../../../../modules/attendance/components/attendance-page/AttendanceForm" | ||
import { InfoBox } from "../../../../modules/attendance/components/attendance-page/InfoBox" | ||
import { PoolBox } from "../../../../modules/attendance/components/attendance-page/PoolsBox" | ||
import { usePoolsForm } from "../../../../modules/attendance/components/attendance-page/PoolsForm" | ||
import { | ||
useAddAttendanceMutation, | ||
useUpdateAttendanceMutation, | ||
} from "../../../../modules/attendance/mutations/use-attendance-mutations" | ||
import { usePoolsGetQuery } from "../../../../modules/attendance/queries/use-get-queries" | ||
import { useEventDetailsContext } from "./provider" | ||
|
||
interface CustomCheckboxProps { | ||
userId: string | ||
attendanceId: string | ||
defaultChecked?: boolean | ||
} | ||
const CustomCheckbox = React.memo(({ attendanceId, userId, defaultChecked }: CustomCheckboxProps) => { | ||
const updateAttendance = useUpdateEventAttendanceMutation() | ||
export const AttendancePage: FC = () => { | ||
const { attendance } = useEventDetailsContext() | ||
const { event } = useEventDetailsContext() | ||
|
||
const toggleAttendance = (userId: string, attendanceId: string, currentCheckedState: boolean) => { | ||
updateAttendance.mutate({ userId, attendanceId, attended: currentCheckedState }) | ||
if (!attendance) { | ||
return <NoAttendanceFallback eventId={event.id} /> | ||
} | ||
return ( | ||
<Checkbox | ||
onChange={(event) => { | ||
toggleAttendance(userId, attendanceId, event.currentTarget.checked) | ||
}} | ||
defaultChecked={defaultChecked} | ||
/> | ||
) | ||
}) | ||
|
||
CustomCheckbox.displayName = "attendanceToggle" | ||
return <_AttendancePage attendance={attendance} /> | ||
} | ||
|
||
export const EventAttendancePage: FC = () => { | ||
const { event } = useEventDetailsContext() | ||
const { eventAttendance } = useEventAttendanceGetQuery(event.id) | ||
const [searchQuery, setSearchQuery] = useState("") | ||
const { users } = useUserSearchQuery(searchQuery) | ||
const registerForEvent = useRegisterForEventMutation() | ||
const deregisterForEvent = useDeregisterForEventMutation() | ||
const NoAttendanceFallback: FC<{ eventId: string }> = ({ eventId }) => { | ||
const mutation = useAddAttendanceMutation() | ||
const AttendanceForm = useAttendanceForm({ | ||
defaultValues: { | ||
registerStart: new Date(), | ||
registerEnd: new Date(), | ||
deregisterDeadline: new Date(), | ||
extras: null, | ||
}, | ||
label: "Opprett", | ||
onSubmit: (values) => { | ||
mutation.mutate({ eventId, obj: values }) | ||
}, | ||
}) | ||
|
||
const columnHelper = createColumnHelper<Attendee>() | ||
const columns = useMemo( | ||
() => [ | ||
columnHelper.accessor("userId", { | ||
header: () => "Bruker", | ||
}), | ||
columnHelper.accessor((attendee) => attendee, { | ||
id: "attended", | ||
header: () => "Møtt", | ||
cell: (info) => ( | ||
<CustomCheckbox | ||
userId={info.getValue().userId} | ||
attendanceId={info.getValue().attendanceId} | ||
defaultChecked={info.getValue().attended} | ||
/> | ||
), | ||
}), | ||
columnHelper.accessor((attendee) => attendee, { | ||
id: "deregsiter", | ||
header: () => "Meld av", | ||
cell: (info) => ( | ||
<Button | ||
onClick={() => | ||
deregisterForEvent.mutate({ attendanceId: info.getValue().attendanceId, userId: info.getValue().userId }) | ||
} | ||
> | ||
X | ||
</Button> | ||
), | ||
}), | ||
], | ||
[columnHelper, deregisterForEvent] | ||
return ( | ||
<Box> | ||
<Title order={5}>Lag påmelding</Title> | ||
<AttendanceForm /> | ||
</Box> | ||
) | ||
} | ||
|
||
const table = useReactTable({ | ||
data: useMemo(() => eventAttendance.flatMap((attendance) => attendance.attendees), [eventAttendance]), | ||
getCoreRowModel: getCoreRowModel(), | ||
columns, | ||
}) | ||
interface EventAttendanceProps { | ||
attendance: Attendance | ||
} | ||
const _AttendancePage: FC<EventAttendanceProps> = ({ attendance }) => { | ||
const { pools } = usePoolsGetQuery(attendance.id) | ||
|
||
const handleUserSearch = (query: string) => { | ||
setSearchQuery(query) | ||
} | ||
const updateAttendanceMut = useUpdateAttendanceMutation() | ||
|
||
const handleUserClick = (user: User) => { | ||
registerForEvent.mutate({ eventId: event.id, userId: user.id.toString() }) | ||
} | ||
const AttendanceForm = useAttendanceForm({ | ||
defaultValues: attendance, | ||
label: "Oppdater", | ||
onSubmit: (values) => { | ||
updateAttendanceMut.mutate({ | ||
id: attendance.id, | ||
attendance: { | ||
registerStart: values.registerStart, | ||
registerEnd: values.registerEnd, | ||
deregisterDeadline: values.deregisterDeadline, | ||
}, | ||
}) | ||
}, | ||
}) | ||
|
||
const PoolsForm = usePoolsForm({ | ||
attendanceId: attendance.id, | ||
pools, | ||
}) | ||
|
||
return ( | ||
<Box> | ||
<Title order={3}>Meld på</Title> | ||
<GenericSearch | ||
onSearch={handleUserSearch} | ||
onSubmit={handleUserClick} | ||
items={users} | ||
dataMapper={(item: User) => item.id.toString()} | ||
placeholder="Søk etter bruker..." | ||
/> | ||
{eventAttendance.map((attendance) => ( | ||
<Box key={attendance.id} mb="sm"> | ||
<Title order={4}> | ||
{attendance.id} {`(${attendance.attendees.length}/${attendance.limit})`} | ||
</Title> | ||
<GenericTable table={table} /> | ||
</Box> | ||
))} | ||
<Box> | ||
<Title mb={10} order={3}> | ||
Generelt | ||
</Title> | ||
<AttendanceForm /> | ||
</Box> | ||
<Divider my={32} /> | ||
<Box> | ||
<Title mb={10} order={3}> | ||
Reserverte plasser | ||
</Title> | ||
<InfoBox pools={pools || []} /> | ||
</Box> | ||
<Box> | ||
<PoolsForm /> | ||
<PoolBox pools={pools || []} attendanceId={attendance.id} /> | ||
</Box> | ||
</Box> | ||
) | ||
} |
51 changes: 51 additions & 0 deletions
51
apps/dashboard/src/app/(dashboard)/event/[id]/attendees-page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import type { Attendance } from "@dotkomonline/types" | ||
import { Box, Divider, Title } from "@mantine/core" | ||
import type { FC } from "react" | ||
import { UserSearch } from "../../../../components/molecules/UserSearch/UserSearch" | ||
import { openCreateManualUserAttendModal } from "../../../../modules/attendance/modals/manual-user-attend-modal" | ||
import { useEventAttendeesGetQuery } from "../../../../modules/attendance/queries/use-get-queries" | ||
import { AllAttendeesTable } from "../all-users-table" | ||
import { useEventDetailsContext } from "./provider" | ||
|
||
export const AttendeesPage: FC = () => { | ||
const { attendance } = useEventDetailsContext() | ||
|
||
if (!attendance) { | ||
return <div>Arrangementet har ikke påmelding</div> | ||
} | ||
|
||
return <Page attendance={attendance} /> | ||
} | ||
|
||
interface Props { | ||
attendance: Attendance | ||
} | ||
|
||
const Page: FC<Props> = ({ attendance }) => { | ||
const { attendees } = useEventAttendeesGetQuery(attendance.id) | ||
|
||
return ( | ||
<Box> | ||
<Box> | ||
<Title mb={10} order={3}> | ||
Meld på bruker | ||
</Title> | ||
<UserSearch | ||
onSubmit={(values) => { | ||
openCreateManualUserAttendModal({ | ||
attendanceId: attendance.id, | ||
userId: values.id, | ||
}) | ||
}} | ||
/> | ||
</Box> | ||
<Divider my={32} /> | ||
<Box> | ||
<Title mb={10} order={3}> | ||
Alle påmeldte | ||
</Title> | ||
<AllAttendeesTable users={attendees} attendanceId={attendance.id} /> | ||
</Box> | ||
</Box> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 52 additions & 16 deletions
68
apps/dashboard/src/app/(dashboard)/event/[id]/extras-page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
8d86626
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
invoicification – ./apps/invoicification
invoicification.vercel.app
invoicification-git-main-dotkom.vercel.app
invoicification-dotkom.vercel.app
faktura.online.ntnu.no