From 22f9d65484e76c1c55b369c42e63e33237aa72ed Mon Sep 17 00:00:00 2001 From: Felix Thape Date: Sun, 23 Feb 2025 12:26:24 +0100 Subject: [PATCH] feat: add team page --- customer/api/dataclasses/user_seat.ts | 19 +++- customer/api/mutations/user_seat_mutations.ts | 77 +++++++++++++ customer/components/layout/Page.tsx | 3 +- customer/pages/team/index.tsx | 101 ++++++++++++++++++ 4 files changed, 198 insertions(+), 2 deletions(-) create mode 100644 customer/api/mutations/user_seat_mutations.ts create mode 100644 customer/pages/team/index.tsx diff --git a/customer/api/dataclasses/user_seat.ts b/customer/api/dataclasses/user_seat.ts index df72e84d3..2cddc8e56 100644 --- a/customer/api/dataclasses/user_seat.ts +++ b/customer/api/dataclasses/user_seat.ts @@ -1,7 +1,24 @@ +import type { Translation } from '@helpwave/common/hooks/useTranslation' + +export const userRoles = ['admin' , 'user'] as const + /** * Defines the possible roles a user can have. */ -export type UserRole = 'admin' | 'user'; +export type UserRole = typeof userRoles[number] + +export type UserRoleTranslation = Record + +export const defaultUserRoleTranslation: Translation = { + en: { + user: 'User', + admin: 'Admin' + }, + de: { + user: 'Nutzer', + admin: 'Admin' + } +} /** * Represents a user seat in the system. diff --git a/customer/api/mutations/user_seat_mutations.ts b/customer/api/mutations/user_seat_mutations.ts new file mode 100644 index 000000000..dd19e4652 --- /dev/null +++ b/customer/api/mutations/user_seat_mutations.ts @@ -0,0 +1,77 @@ +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' +import { QueryKeys } from '@/api/mutations/query_keys' +import type { UserSeat } from '@/api/dataclasses/user_seat' + +// TODO delete later +const userSeatData: UserSeat[] = [ + { + customerUUID: 'customer', + email: 'test1@helpwave.de', + firstName: 'Max', + lastName: 'Mustermann', + role: 'admin', + enabled: true + }, + { + customerUUID: 'customer', + email: 'test2@helpwave.de', + firstName: 'Mary', + lastName: 'Jane', + role: 'admin', + enabled: true + }, + { + customerUUID: 'customer', + email: 'test3@helpwave.de', + firstName: 'Maxine', + lastName: 'Mustermann', + role: 'user', + enabled: true + }, + { + customerUUID: 'customer', + email: 'test4@helpwave.de', + firstName: 'John', + lastName: 'Doe', + role: 'user', + enabled: false + }, + { + customerUUID: 'customer', + email: 'test5@helpwave.de', + firstName: 'Peter', + lastName: 'Parker', + role: 'user', + enabled: false + }, +] + +export const useUserSeatsQuery = () => { + return useQuery({ + queryKey: [QueryKeys.userSeat, 'all'], + queryFn: async () => { + // TODO do request here with auth data + return userSeatData + }, + }) +} + +export const useUserSeatUpdateMutation = () => { + const queryClient = useQueryClient() + return useMutation({ + mutationFn: async (userSeat: UserSeat) => { + // TODO do request here + + const index = userSeatData.findIndex(e => e.customerUUID === userSeat.customerUUID && e.email === userSeat.email) + if (index === -1) { + throw 'User Seat not found' + } + userSeatData[index] = userSeat + + return userSeat + }, + onSuccess: () => { + queryClient.refetchQueries([QueryKeys.customer]).catch(reason => console.error(reason)) + } + }) +} diff --git a/customer/components/layout/Page.tsx b/customer/components/layout/Page.tsx index 9563a035e..d7e6db9db 100644 --- a/customer/components/layout/Page.tsx +++ b/customer/components/layout/Page.tsx @@ -10,7 +10,7 @@ import Link from 'next/link' import { Helpwave } from '@helpwave/common/icons/Helpwave' import type { Languages } from '@helpwave/common/hooks/useLanguage' import { useTranslation } from '@helpwave/common/hooks/useTranslation' -import { GaugeIcon, Menu, Package, Receipt, Settings } from 'lucide-react' +import { GaugeIcon, Menu, Package, Receipt, Settings, UsersIcon } from 'lucide-react' import Head from 'next/head' import { MobileNavigationOverlay } from '@/components/layout/MobileNavigationOverlay' @@ -34,6 +34,7 @@ export type PageProps = PropsWithChildren<{ const navItems: NavItem[] = [ { name: { en: 'Dashboard', de: 'dashboard' }, url: '/', icon: () }, + { name: { en: 'Team', de: 'Team' }, url: '/team', icon: () }, { name: { en: 'Products', de: 'Produkte' }, url: '/products', icon: () }, { name: { en: 'Invoices', de: 'Rechnungen' }, url: '/invoices', icon: () }, { name: { en: 'Settings', de: 'Einstellungen' }, url: '/settings', icon: () }, diff --git a/customer/pages/team/index.tsx b/customer/pages/team/index.tsx new file mode 100644 index 000000000..54f3f7856 --- /dev/null +++ b/customer/pages/team/index.tsx @@ -0,0 +1,101 @@ +import type { NextPage } from 'next' +import type { Languages } from '@helpwave/common/hooks/useLanguage' +import { useTranslation, type PropsForTranslation } from '@helpwave/common/hooks/useTranslation' +import { Page } from '@/components/layout/Page' +import titleWrapper from '@/utils/titleWrapper' +import { Section } from '@/components/layout/Section' +import { LoadingAndErrorComponent } from '@helpwave/common/components/LoadingAndErrorComponent' +import { tw } from '@twind/core' +import type { UserRole, UserRoleTranslation, UserSeat } from '@/api/dataclasses/user_seat' +import { userRoles } from '@/api/dataclasses/user_seat' +import { defaultUserRoleTranslation } from '@/api/dataclasses/user_seat' +import { useUserSeatsQuery, useUserSeatUpdateMutation } from '@/api/mutations/user_seat_mutations' +import { Table } from '@helpwave/common/components/Table' +import { Select } from '@helpwave/common/components/user-input/Select' +import { Checkbox } from '@helpwave/common/components/user-input/Checkbox' + +type TeamTranslation = { + team: string, + teamDescription: string, + role : string, + enabled: string, +} & UserRoleTranslation + +const defaultTeamTranslations: Record = { + en: { + ...defaultUserRoleTranslation.en, + team: 'Team', + teamDescription: 'Here you can change and add members to your team.', + role: 'Role', + enabled: 'Enabled', + }, + de: { + ...defaultUserRoleTranslation.de, + team: 'Team', + teamDescription: 'Hier kannst du Mitglieder deines Teams verwalten.', + role: 'Rolle', + enabled: 'Aktiv', + } +} + +type TeamServerSideProps = { + jsonFeed: unknown, +} + +const Team: NextPage> = ({ overwriteTranslation }) => { + const translation = useTranslation(defaultTeamTranslations, overwriteTranslation) + const { data, isError, isLoading } = useUserSeatsQuery() + const userSeatUpdate = useUserSeatUpdateMutation() + + const idMapping = (value: UserSeat): string => value.customerUUID + value.email + + // TODO do input validation + return ( + +
+ + {!!data && ( +
+ {translation.teamDescription} + {translation.user}), + ({translation.role}), + ({translation.enabled}) + ]} + rowMappingToCells={dataObject => [ + ( +
+ {`${dataObject.firstName} ${dataObject.lastName}`} + {dataObject.email} +
+ ), + ( + + key={idMapping(dataObject) + '-role'} + value={dataObject.role} + options={userRoles.map(role => ({ value: role, label: translation[role] }))} + onChange={role => userSeatUpdate.mutate({ ...dataObject, role })} + /> + ), + ( + userSeatUpdate.mutate({ ...dataObject, enabled })} + /> + ) + ]} + /> + + )} + + + + ) +} + +export default Team