From 2907652468ec7695742e789a95222d8799f3f24e Mon Sep 17 00:00:00 2001 From: DasProffi <67233923+DasProffi@users.noreply.github.com> Date: Wed, 2 Jul 2025 10:03:51 +0200 Subject: [PATCH 1/4] chore: update tasks to hightide version 0.1.8 --- api-services/authentication/useAuth.tsx | 6 +-- api-services/mutations/tasks/bed_mutations.ts | 2 +- customer/api/auth/authService.ts | 4 +- customer/hooks/useAuth.tsx | 2 +- customer/pages/auth/callback.tsx | 2 +- pnpm-lock.yaml | 13 +++-- scripts/generate_boilerplate.js | 10 ++-- tasks/components/UserMenu.tsx | 37 ++++---------- tasks/components/cards/TaskCard.tsx | 2 +- .../layout/property/PropertyEntry.tsx | 48 ++++++++++--------- tasks/components/selects/AssigneeSelect.tsx | 18 ++++--- tasks/package.json | 2 +- tasks/pages/index.tsx | 2 - 13 files changed, 68 insertions(+), 80 deletions(-) diff --git a/api-services/authentication/useAuth.tsx b/api-services/authentication/useAuth.tsx index 37d6f5db7..61a53a481 100644 --- a/api-services/authentication/useAuth.tsx +++ b/api-services/authentication/useAuth.tsx @@ -112,10 +112,10 @@ export const ProvideAuth = ({ children }: PropsWithChildren) => { if (!user) throw new Error('Invalid fake token') try { OrganizationService.getForUser().then(organizations => { - console.log(`Found ${organizations.length} organizations for fake token user`) + console.debug(`Found ${organizations.length} organizations for fake token user`) if (organizations.length > 0) { const organization = organizations[0]! - console.log(`Using ${organization.longName} for user.`, organization) + console.debug(`Using ${organization.longName} for user.`, organization) setUser(() => ({ ...user, organization: { @@ -126,7 +126,7 @@ export const ProvideAuth = ({ children }: PropsWithChildren) => { setToken(config.fakeToken) didInit.current = true } else { - console.log('Creating a new organization') + console.debug('Creating a new organization') OrganizationService.create({ id: '', email: 'test@helpwave.de', diff --git a/api-services/mutations/tasks/bed_mutations.ts b/api-services/mutations/tasks/bed_mutations.ts index 490795a9d..678022bac 100644 --- a/api-services/mutations/tasks/bed_mutations.ts +++ b/api-services/mutations/tasks/bed_mutations.ts @@ -43,7 +43,7 @@ export const useBedCreateMutation = () => { const res = await APIServices.bed.createBed(req, getAuthenticatedGrpcMetadata()) if (!res.toObject()) { - console.log('error in BedCreate') + console.error('error in BedCreate') } return { id: res.getId(), name: bed.name } diff --git a/customer/api/auth/authService.ts b/customer/api/auth/authService.ts index 76ccceb86..8d4b5b043 100644 --- a/customer/api/auth/authService.ts +++ b/customer/api/auth/authService.ts @@ -50,11 +50,11 @@ export const restoreSession = async (): Promise => { // If access token is expired, refresh it if (user.expired) { try { - console.log('Access token expired, refreshing...') + console.debug('Access token expired, refreshing...') const refreshedUser = await renewToken() return refreshedUser ?? undefined } catch (error) { - console.error('Silent token renewal failed', error) + console.debug('Silent token renewal failed', error) return } } diff --git a/customer/hooks/useAuth.tsx b/customer/hooks/useAuth.tsx index 688294be7..0906e650f 100644 --- a/customer/hooks/useAuth.tsx +++ b/customer/hooks/useAuth.tsx @@ -32,7 +32,7 @@ export const AuthProvider = ({ children }: PropsWithChildren) => { isLoading: false, }) onTokenExpiringCallback(async () => { - console.log('Token expiring, refreshing...') + console.debug('Token expiring, refreshing...') const identity = await renewToken() setAuthState({ identity: identity ?? undefined, diff --git a/customer/pages/auth/callback.tsx b/customer/pages/auth/callback.tsx index d0b0bfd90..dc9020aa5 100644 --- a/customer/pages/auth/callback.tsx +++ b/customer/pages/auth/callback.tsx @@ -45,7 +45,7 @@ const AuthCallback: NextPage { // Check if the URL contains OIDC callback params if (searchParams.get('code') && searchParams.get('state')) { - console.log('Processing OIDC callback...') + console.debug('Processing OIDC callback...') try { await handleCallback() const redirect = searchParams.get('redirect_uri') diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 53d9b0caf..37097b559 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -179,8 +179,8 @@ importers: specifier: workspace:* version: link:../api-services '@helpwave/hightide': - specifier: ^0.1.7-alpha.1 - version: 0.1.7-alpha.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17) + specifier: 0.1.8 + version: 0.1.8(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17) '@radix-ui/react-checkbox': specifier: 1.1.3 version: 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -372,8 +372,8 @@ packages: '@helpwave/hightide@0.0.17': resolution: {integrity: sha512-FTktcuyJ9/Vh3odP6r+LLFWHdqV+dHSxzJTOQrY9FZ4ikHSbhmAOfrszi4CZG69/K5KjGkv9WMuvmn+cK+YkQw==} - '@helpwave/hightide@0.1.7-alpha.1': - resolution: {integrity: sha512-HmoJjRNm4+V2JNt/tvpwxtFvzKaH2PWYqvFO2Kj9rgyOgyYludWqAVOnkSMHm/37qY/cnmZHLxpA0FKd1R6gIw==} + '@helpwave/hightide@0.1.8': + resolution: {integrity: sha512-yohlJe3iZ9nZnX6kI62ahLYWGDkLIBGKLY2r6FzAz6y8sgjRrGjGDvfg5gLWTWH5v/sh1OUmr2wbiTeZUF9cYQ==} '@helpwave/proto-ts@0.64.0-89e2023.0': resolution: {integrity: sha512-EqHsZDOttnCBqcAZ0WiRO32rGMICwvGUxvhSltU0KahFsbIx8o5DZ3l9N8GdB3c/66qe5tabTvVKbUzxf66Yjw==} @@ -2721,9 +2721,8 @@ snapshots: - babel-plugin-react-compiler - sass - '@helpwave/hightide@0.1.7-alpha.1(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)': + '@helpwave/hightide@0.1.8(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)': dependencies: - '@headlessui/react': 1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-checkbox': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@tailwindcss/cli': 4.1.10 clsx: 2.1.1 @@ -2735,7 +2734,7 @@ snapshots: react-dom: 18.3.1(react@18.3.1) simplebar-core: 1.3.0 simplebar-react: 3.3.0(react@18.3.1) - tailwindcss: 4.1.7 + tailwindcss: 4.1.10 tinycolor2: 1.6.0 zod: 3.24.1 transitivePeerDependencies: diff --git a/scripts/generate_boilerplate.js b/scripts/generate_boilerplate.js index 3aac32b0c..3d5141ba2 100644 --- a/scripts/generate_boilerplate.js +++ b/scripts/generate_boilerplate.js @@ -34,9 +34,9 @@ const options = program.opts() const args = program.args if(options.debug){ - console.log('options', options) - console.log('args', args) - console.log('execute location', process.env.INIT_CWD) + console.debug('options', options) + console.debug('args', args) + console.debug('execute location', process.env.INIT_CWD) } @@ -83,7 +83,7 @@ if (fs.existsSync(filePath) && !options.force) { console.error('Error creating directory:', err) process.exit(1) } else { - console.log(`Directory ${dir} created successfully.`) + console.debug(`Directory ${dir} created successfully.`) } }) } @@ -91,7 +91,7 @@ if (fs.existsSync(filePath) && !options.force) { if (err) { console.error('Error writing to file:', err) } else { - console.log(`File ${fileName} created successfully.`) + console.info(`File ${fileName} created successfully.`) } }) } diff --git a/tasks/components/UserMenu.tsx b/tasks/components/UserMenu.tsx index e9875bed0..7318e2576 100644 --- a/tasks/components/UserMenu.tsx +++ b/tasks/components/UserMenu.tsx @@ -1,5 +1,4 @@ import { useState } from 'react' -import Link from 'next/link' import { useRouter } from 'next/router' import type { Translation } from '@helpwave/hightide' import { @@ -91,45 +90,29 @@ export const UserMenu = ({ )}> - {translation.profile} - setLanguageModalOpen(true)} - > + router.push(settingsURL, '_blank')}> + {translation.profile} + + setLanguageModalOpen(true)}> {translation.language} - setThemeModalOpen(true)} - > + setThemeModalOpen(true)}> {translation.theme} - router.push('/templates')} - > + router.push('/templates')}> {translation.taskTemplates} - router.push('/properties')} - > + router.push('/properties')}> {translation.properties} - router.push('/organizations')} - > + router.push('/organizations')}> {translation.organizations} - router.push('/invitations')} - > + router.push('/invitations')}> {translation.invitations} signOut()} > {translation.signOut} diff --git a/tasks/components/cards/TaskCard.tsx b/tasks/components/cards/TaskCard.tsx index 94de3eed0..422afa532 100644 --- a/tasks/components/cards/TaskCard.tsx +++ b/tasks/components/cards/TaskCard.tsx @@ -50,7 +50,7 @@ export const TaskCard = ({ 'border-primary': isSelected, })} > -
+
{!task.isPublicVisible &&
} {task.name} diff --git a/tasks/components/layout/property/PropertyEntry.tsx b/tasks/components/layout/property/PropertyEntry.tsx index b16279d8d..7d8fd369b 100644 --- a/tasks/components/layout/property/PropertyEntry.tsx +++ b/tasks/components/layout/property/PropertyEntry.tsx @@ -1,17 +1,19 @@ -import { TextProperty } from '@helpwave/hightide' -import { NumberProperty } from '@helpwave/hightide' -import { DateProperty } from '@helpwave/hightide' -import { CheckboxProperty } from '@helpwave/hightide' -import { SingleSelectProperty } from '@helpwave/hightide' -import { MultiSelectProperty } from '@helpwave/hightide' -import { LoadingAndErrorComponent } from '@helpwave/hightide' +import { + CheckboxProperty, + DateProperty, + LoadingAndErrorComponent, + MultiSelectProperty, + NumberProperty, + SingleSelectProperty, + TextProperty +} from '@helpwave/hightide' import type { Property } from '@helpwave/api-services/types/properties/property' import type { AttachedProperty, AttachPropertySelectValue } from '@helpwave/api-services/types/properties/attached_property' -import { usePropertyQuery } from '@helpwave/api-services/mutations/properties/property_mutations' import { emptyPropertyValue } from '@helpwave/api-services/types/properties/attached_property' +import { usePropertyQuery } from '@helpwave/api-services/mutations/properties/property_mutations' type PropertyEntryDisplayProps = { property: Property, @@ -26,13 +28,13 @@ type PropertyEntryDisplayProps = { * A component for displaying a PropertyEntry */ export const PropertyEntryDisplay = ({ - property, - attachedProperty, - onChange, - onEditComplete, - onRemove, - readOnly = false -}: PropertyEntryDisplayProps) => { + property, + attachedProperty, + onChange, + onEditComplete, + onRemove, + readOnly = false + }: PropertyEntryDisplayProps) => { const commonProps = { name: property.name, readOnly, @@ -139,9 +141,9 @@ export const PropertyEntryDisplay = ({ options={property.selectData!.options .map(option => ({ value: option, - label: option.name + label: option.name, + searchTags: [option.name] }))} - searchMapping={option => [option.value.name]} selectedDisplayOverwrite={attachedProperty.value.singleSelectValue?.name} /> ) @@ -167,9 +169,11 @@ export const PropertyEntryDisplay = ({ .map(option => ({ value: option, label: option.name, - selected: !!attachedProperty.value.multiSelectValue.find(value => value.id === option.id) + selected: !!attachedProperty.value.multiSelectValue.find(value => value.id === option.id), + searchTags: [option.name] }))} - search={{ searchMapping: value => [value.value.name] }} + isSearchEnabled={true} + useChipDisplay={true} /> ) default: @@ -186,9 +190,9 @@ export type PropertyEntryProps = Omit * It wraps the PropertyEntryDisplay with loading logic */ export const PropertyEntry = ({ - attachedProperty, - ...restProps -}: PropertyEntryProps) => { + attachedProperty, + ...restProps + }: PropertyEntryProps) => { const { data: property, isError, diff --git a/tasks/components/selects/AssigneeSelect.tsx b/tasks/components/selects/AssigneeSelect.tsx index 46f33590b..8537f7042 100644 --- a/tasks/components/selects/AssigneeSelect.tsx +++ b/tasks/components/selects/AssigneeSelect.tsx @@ -1,7 +1,8 @@ import type { SelectProps } from '@helpwave/hightide' +import { Avatar } from '@helpwave/hightide' +import { Select } from '@helpwave/hightide' import { LoadingAndErrorComponent } from '@helpwave/hightide' import clsx from 'clsx' -import { SearchableSelect } from '@helpwave/hightide' import { useMembersByOrganizationQuery } from '@helpwave/api-services/mutations/users/organization_member_mutations' export type AssigneeSelectProps = Omit, 'options'> & { @@ -15,7 +16,6 @@ export const AssigneeSelect = ({ organizationId, value, className, - isHidingCurrentValue = false, onChange, ...selectProps } : AssigneeSelectProps) => { @@ -30,19 +30,23 @@ export const AssigneeSelect = ({ classname: 'bg-gray-100 pulsing max-h-8 rounded-md', }} > - user.id === value)} options={(data ?? []).map(value => ({ value, - label: value.name + label: ( +
+ + {value.name} +
+ ), + searchTags: [value.id, value.email], }))} - isHidingCurrentValue={isHidingCurrentValue} className={clsx('w-full', className)} - searchMapping={value => [value.value.id, value.value.email]} onChange={(user) => { onChange(user.id) }} + isSearchEnabled={true} {...selectProps} /> diff --git a/tasks/package.json b/tasks/package.json index 5f4a2eb8c..40bb6cfbc 100644 --- a/tasks/package.json +++ b/tasks/package.json @@ -15,7 +15,7 @@ "@dnd-kit/sortable": "7.0.2", "@headlessui/react": "1.7.19", "@helpwave/api-services": "workspace:*", - "@helpwave/hightide": "^0.1.7-alpha.1", + "@helpwave/hightide": "0.1.8", "@radix-ui/react-checkbox": "1.1.3", "@tailwindcss/postcss": "^4.1.3", "@tanstack/react-query": "^4.36.1", diff --git a/tasks/pages/index.tsx b/tasks/pages/index.tsx index 190b0494f..31893791c 100644 --- a/tasks/pages/index.tsx +++ b/tasks/pages/index.tsx @@ -54,8 +54,6 @@ const Dashboard: NextPage Date: Wed, 2 Jul 2025 13:40:20 +0200 Subject: [PATCH 2/4] chore: update tasks to hightide version 0.1.10 and remove unused dependencies --- api-services/types/tasks/task.ts | 25 ++++++- pnpm-lock.yaml | 71 ++----------------- tasks/components/BedInRoomIndicator.tsx | 4 +- tasks/components/FeedbackButton.tsx | 4 +- tasks/components/InvitationBanner.tsx | 4 +- tasks/components/KanbanColumn.tsx | 4 +- tasks/components/KanbanHeader.tsx | 10 +-- tasks/components/MobileInterceptor.tsx | 8 +-- tasks/components/OrganizationForm.tsx | 50 ++++++------- .../components/OrganizationInvitationList.tsx | 16 ++--- tasks/components/OrganizationMemberList.tsx | 62 +++++++++------- tasks/components/RoomList.tsx | 69 ++++++++++-------- tasks/components/SubtaskTile.tsx | 6 +- tasks/components/SubtaskView.tsx | 8 +-- tasks/components/TaskTemplateListColumn.tsx | 4 +- tasks/components/TaskTemplateWardPreview.tsx | 24 +++---- tasks/components/UserInvitationList.tsx | 8 +-- tasks/components/UserMenu.tsx | 18 ++--- tasks/components/WardForm.tsx | 25 ++++--- tasks/components/cards/BedCard.tsx | 6 +- tasks/components/cards/OrganizationCard.tsx | 4 +- tasks/components/cards/PatientCard.tsx | 4 +- tasks/components/cards/TaskCard.tsx | 4 +- tasks/components/cards/TaskTemplateCard.tsx | 6 +- tasks/components/layout/DashboardDisplay.tsx | 10 +-- .../layout/InitializationChecker.tsx | 4 +- tasks/components/layout/NewsFeed.tsx | 6 +- .../components/layout/OrganizationDetails.tsx | 16 ++--- .../components/layout/OrganizationDisplay.tsx | 6 +- tasks/components/layout/PatientDetails.tsx | 16 ++--- tasks/components/layout/PatientList.tsx | 29 ++++---- .../components/layout/TaskTemplateDetails.tsx | 63 ++++++++-------- .../components/layout/TaskTemplateDisplay.tsx | 8 +-- tasks/components/layout/WardDetails.tsx | 20 +++--- tasks/components/layout/WardDisplay.tsx | 6 +- tasks/components/layout/WardRoomList.tsx | 8 +-- .../layout/property/PropertyDetails.tsx | 15 ++-- .../property/PropertyDetailsBasicInfo.tsx | 12 ++-- .../layout/property/PropertyDetailsField.tsx | 18 ++--- .../layout/property/PropertyDetailsRules.tsx | 8 +-- .../layout/property/PropertyDisplay.tsx | 22 +++--- .../layout/property/PropertyList.tsx | 6 +- .../property/PropertySubjectTypeSelect.tsx | 4 +- tasks/components/modals/AddPatientModal.tsx | 17 +++-- tasks/components/modals/ManageBedsModal.tsx | 16 ++--- .../modals/OrganizationSwitchModal.tsx | 7 +- .../modals/PatientDischargeModal.tsx | 6 +- tasks/components/modals/ReSignInDialog.tsx | 10 +-- .../modals/StagingDisclaimerModal.tsx | 10 +-- tasks/components/modals/TaskDetailModal.tsx | 34 ++++----- tasks/components/pill/PillLabel.tsx | 26 ++----- tasks/components/selects/RoomBedSelect.tsx | 20 +++--- tasks/components/selects/TaskStatusSelect.tsx | 8 +-- .../selects/TaskVisibilitySelect.tsx | 6 +- tasks/package.json | 18 +---- tasks/pages/404.tsx | 8 +-- tasks/pages/index.tsx | 4 +- tasks/pages/invitations.tsx | 6 +- .../pages/organizations/[organizationId].tsx | 8 +-- tasks/pages/organizations/index.tsx | 6 +- tasks/pages/properties.tsx | 6 +- tasks/pages/templates.tsx | 6 +- tasks/pages/ward/[wardId].tsx | 12 ++-- tasks/pages/ward/[wardId]/templates.tsx | 10 +-- 64 files changed, 462 insertions(+), 503 deletions(-) diff --git a/api-services/types/tasks/task.ts b/api-services/types/tasks/task.ts index 750b1d78e..8bffa8af5 100644 --- a/api-services/types/tasks/task.ts +++ b/api-services/types/tasks/task.ts @@ -1,3 +1,5 @@ +import type { Translation } from '@helpwave/hightide' + export type SubTaskDTO = { id: string, name: string, @@ -8,7 +10,28 @@ export type CreateSubTaskDTO = SubTaskDTO & { taskId?: string, } -export type TaskStatus = 'done' | 'inProgress' | 'todo' +const taskStatus = ['done', 'inProgress', 'todo'] as const + +export type TaskStatus = typeof taskStatus[number] + +export type TaskStatusTranslationType = Record + +const taskStatusTranslation: Translation = { + en: { + todo: 'Todo', + inProgress: 'In Progress', + done: 'Done' + }, + de: { + todo: 'Todo', + inProgress: 'In Arbeit', + done: 'Fertig' + } +} +export const TaskStatusUtil = { + taskStatus, + translation: taskStatusTranslation +} export type TaskDTO = { id: string, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 37097b559..253709387 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -172,18 +172,12 @@ importers: '@dnd-kit/sortable': specifier: 7.0.2 version: 7.0.2(@dnd-kit/core@6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) - '@headlessui/react': - specifier: 1.7.19 - version: 1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@helpwave/api-services': specifier: workspace:* version: link:../api-services '@helpwave/hightide': - specifier: 0.1.8 - version: 0.1.8(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17) - '@radix-ui/react-checkbox': - specifier: 1.1.3 - version: 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^0.1.10 + version: 0.1.10(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17) '@tailwindcss/postcss': specifier: ^4.1.3 version: 4.1.5 @@ -193,36 +187,15 @@ importers: '@tanstack/react-query-devtools': specifier: ^4.36.1 version: 4.36.1(@tanstack/react-query@4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@tanstack/react-table': - specifier: 8.20.6 - version: 8.20.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@types/google-protobuf': - specifier: 3.15.12 - version: 3.15.12 clsx: specifier: ^2.1.1 version: 2.1.1 - cookies-next: - specifier: 2.1.2 - version: 2.1.2 - google-protobuf: - specifier: 3.21.4 - version: 3.21.4 - grpc-web: - specifier: 1.5.0 - version: 1.5.0 - js-cookie: - specifier: 3.0.5 - version: 3.0.5 lucide-react: specifier: 0.468.0 version: 0.468.0(react@18.3.1) next: specifier: ^15.3.2 version: 15.3.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - oauth4webapi: - specifier: 2.17.0 - version: 2.17.0 postcss: specifier: ^8.5.3 version: 8.5.3 @@ -238,31 +211,16 @@ importers: react-dom: specifier: 18.3.1 version: 18.3.1(react@18.3.1) - rxjs: - specifier: 7.8.1 - version: 7.8.1 - simplebar-core: - specifier: 1.3.0 - version: 1.3.0 - simplebar-react: - specifier: 3.3.0 - version: 3.3.0(react@18.3.1) tailwindcss: specifier: ^4.1.3 version: 4.1.7 typescript: specifier: 5.7.2 version: 5.7.2 - zod: - specifier: 3.24.1 - version: 3.24.1 devDependencies: '@helpwave/eslint-config': specifier: ^0.0.11 version: 0.0.11(jiti@2.4.2) - '@types/js-cookie': - specifier: 3.0.6 - version: 3.0.6 '@types/node': specifier: 20.17.10 version: 20.17.10 @@ -372,8 +330,8 @@ packages: '@helpwave/hightide@0.0.17': resolution: {integrity: sha512-FTktcuyJ9/Vh3odP6r+LLFWHdqV+dHSxzJTOQrY9FZ4ikHSbhmAOfrszi4CZG69/K5KjGkv9WMuvmn+cK+YkQw==} - '@helpwave/hightide@0.1.8': - resolution: {integrity: sha512-yohlJe3iZ9nZnX6kI62ahLYWGDkLIBGKLY2r6FzAz6y8sgjRrGjGDvfg5gLWTWH5v/sh1OUmr2wbiTeZUF9cYQ==} + '@helpwave/hightide@0.1.10': + resolution: {integrity: sha512-O5NyOU2SnurxxM0rFQmN8Txj3UVFqpXrYCab03htVKFDGTxwI9ZDzOJ3ocIjePIhUJ5kKPIO/BSG79fvF0Ggdw==} '@helpwave/proto-ts@0.64.0-89e2023.0': resolution: {integrity: sha512-EqHsZDOttnCBqcAZ0WiRO32rGMICwvGUxvhSltU0KahFsbIx8o5DZ3l9N8GdB3c/66qe5tabTvVKbUzxf66Yjw==} @@ -1180,23 +1138,12 @@ packages: react-native: optional: true - '@tanstack/react-table@8.20.6': - resolution: {integrity: sha512-w0jluT718MrOKthRcr2xsjqzx+oEM7B7s/XXyfs19ll++hlId3fjTm+B2zrR3ijpANpkzBAr15j1XGVOMxpggQ==} - engines: {node: '>=12'} - peerDependencies: - react: '>=16.8' - react-dom: '>=16.8' - '@tanstack/react-virtual@3.0.1': resolution: {integrity: sha512-IFOFuRUTaiM/yibty9qQ9BfycQnYXIDHGP2+cU+0LrFFGNhVxCXSQnaY6wkX8uJVteFEBjUondX0Hmpp7TNcag==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - '@tanstack/table-core@8.20.5': - resolution: {integrity: sha512-P9dF7XbibHph2PFRz8gfBKEXEY/HJPOhym8CHmjF8y3q5mWpKx9xtZapXQUWCgkqvsK0R46Azuz+VaxD4Xl+Tg==} - engines: {node: '>=12'} - '@tanstack/virtual-core@3.0.0': resolution: {integrity: sha512-SYXOBTjJb05rXa2vl55TTwO40A6wKu0R5i1qQwhJYNDIqaIGF7D0HsLw+pJAyi2OvntlEIVusx3xtbbgSUi6zg==} @@ -2721,7 +2668,7 @@ snapshots: - babel-plugin-react-compiler - sass - '@helpwave/hightide@0.1.8(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)': + '@helpwave/hightide@0.1.10(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)': dependencies: '@radix-ui/react-checkbox': 1.1.3(@types/react-dom@18.3.5(@types/react@18.3.17))(@types/react@18.3.17)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@tailwindcss/cli': 4.1.10 @@ -3339,20 +3286,12 @@ snapshots: optionalDependencies: react-dom: 18.3.1(react@18.3.1) - '@tanstack/react-table@8.20.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@tanstack/table-core': 8.20.5 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - '@tanstack/react-virtual@3.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@tanstack/virtual-core': 3.0.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@tanstack/table-core@8.20.5': {} - '@tanstack/virtual-core@3.0.0': {} '@types/cookie@0.4.1': {} diff --git a/tasks/components/BedInRoomIndicator.tsx b/tasks/components/BedInRoomIndicator.tsx index b91a8b167..a7d51334e 100644 --- a/tasks/components/BedInRoomIndicator.tsx +++ b/tasks/components/BedInRoomIndicator.tsx @@ -41,13 +41,13 @@ export const BedInRoomIndicator = roomName, bedPosition }: PropsForTranslation) => { - const translation = useTranslation(defaultBedInRoomIndicatorTranslation, overwriteTranslation) + const translation = useTranslation([defaultBedInRoomIndicatorTranslation], overwriteTranslation) return (
{roomName !== undefined && ( - {`${translation.bed} ${bedPosition + 1} ${translation.in} ${roomName}`} + {`${translation('bed')} ${bedPosition + 1} ${translation('in')} ${roomName}`} )}
diff --git a/tasks/components/FeedbackButton.tsx b/tasks/components/FeedbackButton.tsx index 6861ba472..5cd6e1873 100644 --- a/tasks/components/FeedbackButton.tsx +++ b/tasks/components/FeedbackButton.tsx @@ -22,13 +22,13 @@ type FeedbackButtonProps = { export const FeedbackButton = ({ overwriteTranslation, className }: PropsForTranslation) => { const config = getConfig() - const translation = useTranslation(defaultFeedbackButtonTranslation, overwriteTranslation) + const translation = useTranslation([defaultFeedbackButtonTranslation], overwriteTranslation) const onClick = () => window.open(config.feedbackFormUrl, '_blank') return ( - {translation.text} + {translation('text')} ) } diff --git a/tasks/components/InvitationBanner.tsx b/tasks/components/InvitationBanner.tsx index aba245a3b..83fe6663b 100644 --- a/tasks/components/InvitationBanner.tsx +++ b/tasks/components/InvitationBanner.tsx @@ -29,7 +29,7 @@ export const InvitationBanner = ({ overwriteTranslation, invitationCount }: PropsForTranslation) => { - const translation = useTranslation(defaultInvitationBannerTranslation, overwriteTranslation) + const translation = useTranslation([defaultInvitationBannerTranslation], overwriteTranslation) const { data, isError, isLoading } = useInvitationsByUserQuery(InvitationState.INVITATION_STATE_PENDING) let openInvites = invitationCount @@ -51,7 +51,7 @@ export const InvitationBanner = ({ className="w-full bg-primary text-white py-2 px-4 rounded-xl cursor-pointer select-none row gap-x-2 items-center" href="/invitations" > - {`${translation.openInvites}: ${openInvites}`} + {`${translation('openInvites')}: ${openInvites}`} ) } diff --git a/tasks/components/KanbanColumn.tsx b/tasks/components/KanbanColumn.tsx index 369b0db24..f64ac8a7e 100644 --- a/tasks/components/KanbanColumn.tsx +++ b/tasks/components/KanbanColumn.tsx @@ -42,7 +42,7 @@ export const KanbanColumn = ({ draggedTileId, onEditTask }: PropsForTranslation) => { - const translation = useTranslation(defaultKanbanColumnsTranslations, overwriteTranslation) + const translation = useTranslation([defaultKanbanColumnsTranslations], overwriteTranslation) const { setNodeRef } = useDroppable({ id: type, @@ -80,7 +80,7 @@ export const KanbanColumn = ({ className="row ml-1 gap-x-1 text-gray-300" > - {translation.addTask} + {translation('addTask')}
) diff --git a/tasks/components/KanbanHeader.tsx b/tasks/components/KanbanHeader.tsx index 4a540625f..849caf147 100644 --- a/tasks/components/KanbanHeader.tsx +++ b/tasks/components/KanbanHeader.tsx @@ -40,20 +40,20 @@ export const KanbanHeader = ({ searchValue = '', onSearchChange }: PropsForTranslation) => { - const translation = useTranslation(defaultKanbanHeaderTranslations, overwriteTranslation) + const translation = useTranslation([defaultKanbanHeaderTranslations], overwriteTranslation) return (
- {translation.tasks} + {translation('tasks')}
- {translation.status} + {translation('status')}
- {translation.label} + {translation('label')}
- +
) diff --git a/tasks/components/MobileInterceptor.tsx b/tasks/components/MobileInterceptor.tsx index df9ca794f..71c7daac6 100644 --- a/tasks/components/MobileInterceptor.tsx +++ b/tasks/components/MobileInterceptor.tsx @@ -31,16 +31,16 @@ const defaultMobileInterceptorTranslation = { * the helpwave app will be shown */ const MobileInterceptor: NextPage = ({ overwriteTranslation }: PropsForTranslation) => { - const translation = useTranslation(defaultMobileInterceptorTranslation, overwriteTranslation) + const translation = useTranslation([defaultMobileInterceptorTranslation], overwriteTranslation) const config = getConfig() const playStoreLink = config.appstoreLinks.playStore const appstoreLink = config.appstoreLinks.appStore return (
- {translation.pleaseDownloadApp} - {translation.playStore} - {translation.appStore} + {translation('pleaseDownloadApp')} + {translation('playStore')} + {translation('appStore')}
) } diff --git a/tasks/components/OrganizationForm.tsx b/tasks/components/OrganizationForm.tsx index c540e496f..9acefe04f 100644 --- a/tasks/components/OrganizationForm.tsx +++ b/tasks/components/OrganizationForm.tsx @@ -21,8 +21,8 @@ type OrganizationFormTranslation = { contactEmailDescription: string, notVerified: string, required: string, - tooLong: (maxCharacters: number) => string, - tooShort: (minCharacters: number) => string, + tooLong: string, + tooShort: string, invalidEmail: string, } @@ -38,8 +38,8 @@ const defaultOrganizationFormTranslations: Translation `Too long, at most ${maxCharacters} characters`, - tooShort: (minCharacters) => `Too short, at least ${minCharacters} characters`, + tooLong: `Too long, at most {{characters}} characters`, + tooShort: `Too short, at least {{characters}} characters`, invalidEmail: 'Invalid email address' }, de: { @@ -53,8 +53,8 @@ const defaultOrganizationFormTranslations: Translation `Zu lang, maximal ${maxCharacters} Zeichen`, - tooShort: (minCharacters) => `Zu kurz, mindestens ${minCharacters} Zeichen`, + tooLong: `Zu lang, maximal {{characters}} Zeichen`, + tooShort: `Zu kurz, mindestens {{characters}} Zeichen`, invalidEmail: 'Ungültige Email Adresse' } } @@ -98,7 +98,7 @@ export const OrganizationForm = ({ organizationForm = emptyOrganizationForm, onChange = () => undefined, }: PropsForTranslation) => { - const translation = useTranslation(defaultOrganizationFormTranslations, overwriteTranslation) + const translation = useTranslation([defaultOrganizationFormTranslations], overwriteTranslation) const minShortNameLength = 2 const minLongNameLength = 4 @@ -112,32 +112,28 @@ export const OrganizationForm = ({ function validateShortName(organization: OrganizationMinimalDTO) { const shortName = organization.shortName.trim() if (shortName === '') { - return translation.required - } else if (shortName.length < minShortNameLength) { - return translation.tooShort(minShortNameLength) + return translation('required') } else if (shortName.length < minShortNameLength) { + return translation('tooShort', { replacements: { characters: minShortNameLength.toString() } }) } else if (shortName.length > maxShortNameLength) { - return translation.tooLong(maxShortNameLength) + return translation('tooLong', { replacements: { characters: maxShortNameLength.toString() } }) } } function validateLongName(organization: OrganizationMinimalDTO) { const longName = organization.longName.trim() if (longName === '') { - return translation.required - } else if (longName.length < minLongNameLength) { - return translation.tooShort(minLongNameLength) + return translation('required') } else if (longName.length < minLongNameLength) { + return translation('tooShort', { replacements: { characters: minLongNameLength.toString() } }) } else if (longName.length > maxLongNameLength) { - return translation.tooLong(maxLongNameLength) + return translation('tooLong', { replacements: { characters: maxLongNameLength.toString() } }) } } function validateEmailWithOrganization(organization: OrganizationMinimalDTO) { const email = organization.email.trim() if (email === '') { - return translation.required - } else if (!validateEmail(organization.email)) { - return translation.invalidEmail - } + return translation('required') } else if (!validateEmail(organization.email)) { + return translation('invalidEmail') } } function triggerOnChange(newOrganization: OrganizationMinimalDTO, shouldUpdate: boolean, touched: OrganizationFormTouchedType) { @@ -160,12 +156,12 @@ export const OrganizationForm = ({ minimumLoadingDuration={200} // prevents errors flickering >
- {translation.general} + {translation('general')}
triggerOnChange({ ...organizationForm.organization }, false, { ...organizationForm.touched, shortName: true @@ -182,13 +178,13 @@ export const OrganizationForm = ({ className={clsx(inputClasses, { [inputErrorClasses]: isDisplayingShortNameError })} /> {isDisplayingShortNameError && {shortNameErrorMessage}} - {translation.shortNameDescription} + {translation('shortNameDescription')}
triggerOnChange({ ...organizationForm.organization }, false, { ...organizationForm.touched, longName: true @@ -205,7 +201,7 @@ export const OrganizationForm = ({ className={clsx(inputClasses, { [inputErrorClasses]: isDisplayingLongNameError })} /> {isDisplayingLongNameError && {longNameErrorMessage}} - {translation.longNameDescription} + {translation('longNameDescription')}
@@ -213,7 +209,7 @@ export const OrganizationForm = ({ triggerOnChange({ ...organizationForm.organization }, false, { ...organizationForm.touched, @@ -233,11 +229,11 @@ export const OrganizationForm = ({
{ !organizationForm.organization.isVerified && - {translation.notVerified} + {translation('notVerified')} }
{isDisplayingEmailNameError && {emailErrorMessage}} - {translation.contactEmailDescription} + {translation('contactEmailDescription')}
diff --git a/tasks/components/OrganizationInvitationList.tsx b/tasks/components/OrganizationInvitationList.tsx index 08460337c..3c88158fa 100644 --- a/tasks/components/OrganizationInvitationList.tsx +++ b/tasks/components/OrganizationInvitationList.tsx @@ -68,7 +68,7 @@ export const OrganizationInvitationList = ({ invitations, onChange }: PropsForTranslation) => { - const translation = useTranslation(defaultOrganizationInvitationListTranslation, overwriteTranslation) + const translation = useTranslation([defaultOrganizationInvitationListTranslation], overwriteTranslation) const context = useContext(OrganizationContext) const usedOrganizationId = organizationId ?? context.state.organizationId @@ -129,24 +129,24 @@ export const OrganizationInvitationList = ({ setInviteMemberModalEmail('') }} inputs={[{ - label: { name: translation.email }, + label: { name: translation('email') }, value: inviteMemberModalEmail ?? '', onChangeText: text => setInviteMemberModalEmail(text) }]} buttonOverwrites={[ {}, - { disabled: !isValidEmail, color: 'positive', text: translation.addAndNext }, - { disabled: !isValidEmail, color: 'primary', text: translation.add } + { disabled: !isValidEmail, color: 'positive', text: translation('addAndNext') }, + { disabled: !isValidEmail, color: 'primary', text: translation('add') } ]} />
- {`${translation.invitations} (${usedInvitations.length})`} + {`${translation('invitations')} (${usedInvitations.length})`} setInviteMemberModalEmail('')} > - {translation.inviteMember} + {translation('inviteMember')}
{translation.email}, + {translation('email')}, <> ]} rowMappingToCells={invite => [ @@ -171,7 +171,7 @@ export const OrganizationInvitationList = ({ onChange(usedInvitations.filter(value => idMapping(value) !== idMapping(invite))) }} > - {translation.remove} + {translation('remove')} ]} diff --git a/tasks/components/OrganizationMemberList.tsx b/tasks/components/OrganizationMemberList.tsx index 14407f168..8410e9792 100644 --- a/tasks/components/OrganizationMemberList.tsx +++ b/tasks/components/OrganizationMemberList.tsx @@ -1,9 +1,9 @@ import { useContext, useState } from 'react' -import type { Translation } from '@helpwave/hightide' -import { ConfirmModal } from '@helpwave/hightide' +import type { Translation, TranslationPlural } from '@helpwave/hightide' import { Avatar, + ConfirmModal, defaultTableStatePagination, defaultTableStateSelection, LoadingAndErrorComponent, @@ -26,12 +26,11 @@ type OrganizationMemberListTranslation = { removeSelection: string, deselectAll: string, selectAll: string, - members: string, - member: string, + member: TranslationPlural, saveChanges: string, role: string, - dangerZoneText: (single: boolean) => string, - deleteConfirmText: (single: boolean) => string, + dangerZoneText: TranslationPlural, + deleteConfirmText: TranslationPlural, } const defaultOrganizationMemberListTranslations: Translation = { @@ -41,12 +40,20 @@ const defaultOrganizationMemberListTranslations: Translation `Deleting ${single ? `a ${defaultOrganizationMemberListTranslations.en.member}` : defaultOrganizationMemberListTranslations.en.members} is a permanent action and cannot be undone. Be careful!`, - deleteConfirmText: (single) => `Do you really want to delete the selected ${single ? defaultOrganizationMemberListTranslations.en.member : defaultOrganizationMemberListTranslations.en.members}?`, + dangerZoneText: { + one: 'Removing a member is a permanent action and cannot be undone. Be careful!', + other: 'Removing members is a permanent action and cannot be undone. Be careful!' + }, + deleteConfirmText: { + one: 'Do you really want to remove the selected member?', + other: 'Do you really want to remove the selected members?', + }, }, de: { edit: 'Bearbeiten', @@ -54,12 +61,20 @@ const defaultOrganizationMemberListTranslations: Translation `Das Löschen ${single ? `eines ${defaultOrganizationMemberListTranslations.de.member}` : `von ${defaultOrganizationMemberListTranslations.de.member}`} ist permanent und kann nicht rückgängig gemacht werden. Vorsicht!`, - deleteConfirmText: (single) => `Wollen Sie wirklich ${single ? `das ausgewählte ${defaultOrganizationMemberListTranslations.de.member}` : `die ausgewählten ${defaultOrganizationMemberListTranslations.de.members}`} löschen?`, + dangerZoneText: { + one: 'Das Entfernen eines Mitglieds ist a permanent permanent und kann nicht rückgängig gemacht werden. Vorsicht!', + other: 'Das Entfernen von Mitgliedern ist a permanent permanent und kann nicht rückgängig gemacht werden. Vorsicht!' + }, + deleteConfirmText: { + one: 'Wollen Sie wirklich das ausgewählte Mitglied löschen?', + other: 'Wollen Sie wirklich die ausgewählten Mitglieder löschen?', + }, } } @@ -79,7 +94,7 @@ export const OrganizationMemberList = ({ organizationId, members }: PropsForTranslation) => { - const translation = useTranslation(defaultOrganizationMemberListTranslations, overwriteTranslation) + const translation = useTranslation([defaultOrganizationMemberListTranslations], overwriteTranslation) const [tableState, setTableState] = useState({ pagination: defaultTableStatePagination, selection: defaultTableStateSelection @@ -94,7 +109,6 @@ export const OrganizationMemberList = ({ const [deleteDialogState, setDeleteDialogState] = useState(defaultDeleteDialogState) - const hasSelectedMultiple = !!tableState.selection && tableState.selection.currentSelection.length > 1 const idMapping = (dataObject: OrganizationMember) => dataObject.id // TODO move this filtering to the Table component @@ -116,8 +130,8 @@ export const OrganizationMemberList = ({
setDeleteDialogState(defaultDeleteDialogState)} @@ -141,14 +155,14 @@ export const OrganizationMemberList = ({ loadingProps={{ classname: 'border-2 border-gray-600 rounded-xl min-h-[300px]' }} >
- {translation.members + ` (${usedMembers.length})`} + {translation('member', { count: 2 /* Always use plural */ }) + ` (${usedMembers.length})`}
{tableState.selection && tableState.selection.currentSelection.length > 0 && ( setDeleteDialogState({ isShowing: true })} color="negative" > - {translation.removeSelection} + {translation('removeSelection')} )}
@@ -158,10 +172,10 @@ export const OrganizationMemberList = ({ stateManagement={[tableState, setTableState]} header={[
- {translation.member} + {translation('member')}
,
- {translation.role} + {translation('role')}
, <> ]} @@ -181,7 +195,7 @@ export const OrganizationMemberList = ({ onClick={() => { /* TODO allow changing roles */ }} > - {'N.A.' /* translation.roleTypes[orgMember.role] */} + {'N.A.' /* translation("roleTypes")[orgMember.role] */}
,
@@ -190,7 +204,7 @@ export const OrganizationMemberList = ({ color="negative" // disabled={orgMember.role === Role.admin} > - {translation.remove} + {translation('remove')}
]} diff --git a/tasks/components/RoomList.tsx b/tasks/components/RoomList.tsx index 73b0e87b3..40875a4b4 100644 --- a/tasks/components/RoomList.tsx +++ b/tasks/components/RoomList.tsx @@ -1,4 +1,4 @@ -import type { Translation } from '@helpwave/hightide' +import type { Translation, TranslationPlural } from '@helpwave/hightide' import { ConfirmModal } from '@helpwave/hightide' import { useTranslation, type PropsForTranslation } from '@helpwave/hightide' import { useContext, useEffect, useState } from 'react' @@ -28,14 +28,13 @@ type RoomListTranslation = { deselectAll: string, selectAll: string, roomName: string, - room: string, - rooms: string, + room: TranslationPlural, addRoom: string, bedCount: string, manageBeds: string, manage: string, - dangerZoneText: (single: boolean) => string, - deleteConfirmText: (single: boolean) => string, + dangerZoneText: TranslationPlural, + deleteConfirmText: TranslationPlural, } const defaultRoomListTranslations: Translation = { @@ -46,14 +45,22 @@ const defaultRoomListTranslations: Translation = { deselectAll: 'Deselect All', selectAll: 'Select All', roomName: 'Room Name', - room: 'Room', - rooms: 'Rooms', + room: { + one: 'Room', + other: 'Rooms', + }, addRoom: 'Add Room', bedCount: '#Beds', manageBeds: 'Manage Beds', manage: 'Manage', - dangerZoneText: (single) => `Deleting ${single ? defaultRoomListTranslations.en.room : defaultRoomListTranslations.en.rooms} is a permanent action and cannot be undone. Be careful!`, - deleteConfirmText: (single) => `Do you really want to delete the selected ${single ? defaultRoomListTranslations.en.room : defaultRoomListTranslations.en.rooms}?`, + dangerZoneText: { + one: 'Deleting a room is a permanent action and cannot be undone. Be careful!', + other: 'Deleting rooms is a permanent action and cannot be undone. Be careful!', + }, + deleteConfirmText: { + one: 'Do you really want to delete the selected room?', + other: 'Do you really want to delete the selected rooms?', + }, }, de: { edit: 'Bearbeiten', @@ -61,15 +68,23 @@ const defaultRoomListTranslations: Translation = { removeSelection: 'Ausgewählte löschen', deselectAll: 'Auswahl aufheben', selectAll: 'Alle auswählen', - roomName: 'Zimmer', - room: 'Raum', - rooms: 'Zimmer', + roomName: 'Zimmername', + room: { + one: 'Zimmer', + other: 'Zimmer', + }, addRoom: 'Raum hinzufügen', bedCount: 'Bettenanzahl', manageBeds: 'Betten verwalten', manage: 'Verwalten', - dangerZoneText: (single) => `Das Löschen von ${single ? `einem ${defaultRoomListTranslations.de.room}` : defaultRoomListTranslations.de.rooms} ist permanent und kann nicht rückgängig gemacht werden. Vorsicht!`, - deleteConfirmText: (single) => `Wollen Sie wirklich ${single ? 'den' : 'die'} ausgewählten ${single ? defaultRoomListTranslations.de.room : defaultRoomListTranslations.de.rooms} löschen?`, + dangerZoneText: { + one: 'Das Löschen von einem Raum ist permanent und kann nicht rückgängig gemacht werden. Vorsicht!', + other: 'Das Löschen von Räumen ist permanent und kann nicht rückgängig gemacht werden. Vorsicht!', + }, + deleteConfirmText: { + one: 'Willst du wirklich den ausgewählten Raum löschen?', + other: 'Willst du wirklich die ausgewählten Räume löschen?', + }, } } @@ -89,7 +104,7 @@ export const RoomList = ({ overwriteTranslation, rooms }: PropsForTranslation) => { - const translation = useTranslation(defaultRoomListTranslations, overwriteTranslation) + const translation = useTranslation([defaultRoomListTranslations], overwriteTranslation) const context = useContext(OrganizationOverviewContext) const [tableState, setTableState] = useState({ pagination: defaultTableStatePagination, @@ -135,19 +150,17 @@ export const RoomList = ({ // TODO remove below for an actual room add const newRoom = { id: '', - name: translation.room + (usedRooms.length + 1), + name: translation('room') + (usedRooms.length + 1), } creatRoomMutation.mutate(newRoom) } - const multipleInDelete = deletionConfirmDialogElement !== '' || tableState.selection?.currentSelection.length === 1 - return (
setDeletionConfirmDialogElement(undefined)} @@ -177,18 +190,18 @@ export const RoomList = ({ errorProps={{ classname: 'border-2 border-gray-500 rounded-xl min-h-[200px]' }} >
- {translation.rooms + ` (${usedRooms.length})`} + {translation('room', { count: 2 /* Always use plural */ }) + ` (${usedRooms.length})`}
{(tableState.selection && tableState.selection?.currentSelection.length > 0) && ( setDeletionConfirmDialogElement('')} color="negative" > - {translation.removeSelection} + {translation('removeSelection')} )} - {translation.addRoom} + {translation('addRoom')}
@@ -201,9 +214,9 @@ export const RoomList = ({ }]} identifierMapping={identifierMapping} header={[ - {translation.roomName}, - {translation.bedCount}, - {translation.manageBeds}, + {translation('roomName')}, + {translation('bedCount')}, + {translation('manageBeds')}, <> ]} rowMappingToCells={room => [ @@ -236,12 +249,12 @@ export const RoomList = ({
,
setManagedRoom(room.id)}> - {translation.manage} + {translation('manage')}
,
setDeletionConfirmDialogElement(room.id)} color="negative"> - {translation.remove} + {translation('remove')}
]} diff --git a/tasks/components/SubtaskTile.tsx b/tasks/components/SubtaskTile.tsx index f8750a9bc..edc51d8e5 100644 --- a/tasks/components/SubtaskTile.tsx +++ b/tasks/components/SubtaskTile.tsx @@ -33,7 +33,7 @@ export const SubtaskTile = ({ onRemoveClick, onChange, }: PropsForTranslation) => { - const translation = useTranslation(defaultSubtaskTileTranslation, overwriteTranslation) + const translation = useTranslation([defaultSubtaskTileTranslation], overwriteTranslation) const minTaskNameLength = 2 const maxTaskNameLength = 64 @@ -78,10 +78,10 @@ export const SubtaskTile = ({ - {translation.remove} + {translation('remove')}
diff --git a/tasks/components/SubtaskView.tsx b/tasks/components/SubtaskView.tsx index 07eb484fe..3e46d5a71 100644 --- a/tasks/components/SubtaskView.tsx +++ b/tasks/components/SubtaskView.tsx @@ -55,7 +55,7 @@ export const SubtaskView = ({ }: PropsForTranslation) => { const context = useContext(TaskTemplateContext) - const translation = useTranslation(defaultSubtaskViewTranslation, overwriteTranslation) + const translation = useTranslation([defaultSubtaskViewTranslation], overwriteTranslation) const isCreatingTask = taskId === '' const addSubtaskMutation = useSubTaskAddMutation(taskId) const deleteSubtaskMutation = useSubTaskDeleteMutation() @@ -91,10 +91,10 @@ export const SubtaskView = ({ return (
- {translation.subtasks} + {translation('subtasks')} { - const newSubtask = { id: '', name: `${translation.newSubtask} ${subtasks.length + 1}`, isDone: false } + const newSubtask = { id: '', name: `${translation('newSubtask')} ${subtasks.length + 1}`, isDone: false } onChange([...subtasks, newSubtask]) if (!isCreatingTask) { addSubtaskMutation.mutate(newSubtask) @@ -104,7 +104,7 @@ export const SubtaskView = ({ >
- {translation.addSubtask} + {translation('addSubtask')}
diff --git a/tasks/components/TaskTemplateListColumn.tsx b/tasks/components/TaskTemplateListColumn.tsx index 65518cb32..1b3924874 100644 --- a/tasks/components/TaskTemplateListColumn.tsx +++ b/tasks/components/TaskTemplateListColumn.tsx @@ -40,7 +40,7 @@ export const TaskTemplateListColumn = ({ onColumnEditClick, overwriteTranslation: maybeLanguage }: PropsForTranslation) => { - const translation = useTranslation(defaultTaskTemplateListColumnTranslation, maybeLanguage) + const translation = useTranslation([defaultTaskTemplateListColumnTranslation], maybeLanguage) const [height, setHeight] = useState(undefined) const ref = useRef(null) @@ -52,7 +52,7 @@ export const TaskTemplateListColumn = ({
- {translation.template} + {translation('template')} {onColumnEditClick && }
diff --git a/tasks/components/TaskTemplateWardPreview.tsx b/tasks/components/TaskTemplateWardPreview.tsx index 58fd14fd7..24f77d705 100644 --- a/tasks/components/TaskTemplateWardPreview.tsx +++ b/tasks/components/TaskTemplateWardPreview.tsx @@ -1,26 +1,24 @@ import { useContext } from 'react' import { useRouter } from 'next/router' import type { Translation } from '@helpwave/hightide' -import { useTranslation, type PropsForTranslation } from '@helpwave/hightide' -import { SolidButton } from '@helpwave/hightide' -import { LoadingAndErrorComponent } from '@helpwave/hightide' +import { LoadingAndErrorComponent, type PropsForTranslation, SolidButton, useTranslation } from '@helpwave/hightide' import { useWardTaskTemplateQuery } from '@helpwave/api-services/mutations/tasks/task_template_mutations' import { TaskTemplateCard } from './cards/TaskTemplateCard' import { OrganizationOverviewContext } from '@/pages/organizations/[organizationId]' type TaskTemplateWardPreviewTranslation = { showAllTaskTemplates: string, - taskTemplates: (numberOfTemplates: number) => string, + taskTemplatesCount: string, } const defaultTaskTemplateWardPreviewTranslation: Translation = { en: { showAllTaskTemplates: 'Show all Task Templates', - taskTemplates: (numberOfTemplates) => `Task Templates (${numberOfTemplates})` + taskTemplatesCount: `Task Templates ({{amount}})` }, de: { showAllTaskTemplates: 'Alle Vorlagen anzeigen', - taskTemplates: (numberOfTemplates) => `Vorlagen (${numberOfTemplates})` + taskTemplatesCount: `Vorlagen ({{amount}})` } } @@ -32,10 +30,10 @@ export type TaskTemplateWardPreviewProps = { * A TaskTemplateWardPreview for showing all TaskTemplate within a ward */ export const TaskTemplateWardPreview = ({ - overwriteTranslation, - wardId, -}: PropsForTranslation) => { - const translation = useTranslation(defaultTaskTemplateWardPreviewTranslation, overwriteTranslation) + overwriteTranslation, + wardId, + }: PropsForTranslation) => { + const translation = useTranslation([defaultTaskTemplateWardPreviewTranslation], overwriteTranslation) const router = useRouter() const context = useContext(OrganizationOverviewContext) @@ -55,12 +53,14 @@ export const TaskTemplateWardPreview = ({ {taskTemplates && (
- {translation.taskTemplates(taskTemplates.length)} + + {translation('taskTemplatesCount', { replacements: { amount: taskTemplates.length.toString() } })} + router.push(`/ward/${wardId}/templates`)} > - {translation.showAllTaskTemplates} + {translation('showAllTaskTemplates')}
diff --git a/tasks/components/UserInvitationList.tsx b/tasks/components/UserInvitationList.tsx index c64df325c..6f8366965 100644 --- a/tasks/components/UserInvitationList.tsx +++ b/tasks/components/UserInvitationList.tsx @@ -42,7 +42,7 @@ export type UserInvitationListProps = Record export const UserInvitationList = ({ overwriteTranslation, }: PropsForTranslation) => { - const translation = useTranslation(defaultUserInvitationListTranslation, overwriteTranslation) + const translation = useTranslation([defaultUserInvitationListTranslation], overwriteTranslation) const [tableState, setTableState] = useState({ pagination: { ...defaultTableStatePagination, entriesPerPage: 10 } }) const { data, isLoading, isError } = useInvitationsByUserQuery(InvitationState.INVITATION_STATE_PENDING) const [isShowingReSignInDialog, setIsShowingReSignInDialog] = useState(false) @@ -77,7 +77,7 @@ export const UserInvitationList = ({ stateManagement={[tableState, setTableState]} identifierMapping={idMapping} header={[ - {translation.organization}, + {translation('organization')}, <>, <> ]} @@ -91,14 +91,14 @@ export const UserInvitationList = ({ color="positive" onClick={() => acceptInvite(invite.id)} > - {translation.accept} + {translation('accept')} , declineInviteMutation.mutate(invite.id)} > - {translation.decline} + {translation('decline')} ]} /> diff --git a/tasks/components/UserMenu.tsx b/tasks/components/UserMenu.tsx index 7318e2576..635554fc9 100644 --- a/tasks/components/UserMenu.tsx +++ b/tasks/components/UserMenu.tsx @@ -61,7 +61,7 @@ export const UserMenu = ({ overwriteTranslation, className, }: PropsForTranslation) => { - const translation = useTranslation(defaultUserMenuTranslations, overwriteTranslation) + const translation = useTranslation([defaultUserMenuTranslations], overwriteTranslation) const [isLanguageModalOpen, setLanguageModalOpen] = useState(false) const [isThemeModalOpen, setThemeModalOpen] = useState(false) const { user, signOut } = useAuth() @@ -91,31 +91,31 @@ export const UserMenu = ({
)}> router.push(settingsURL, '_blank')}> - {translation.profile} + {translation('profile')} setLanguageModalOpen(true)}> - {translation.language} + {translation('language')} setThemeModalOpen(true)}> - {translation.theme} + {translation('theme')} router.push('/templates')}> - {translation.taskTemplates} + {translation('taskTemplates')} router.push('/properties')}> - {translation.properties} + {translation('properties')} router.push('/organizations')}> - {translation.organizations} + {translation('organizations')} router.push('/invitations')}> - {translation.invitations} + {translation('invitations')} signOut()} > - {translation.signOut} + {translation('signOut')}
diff --git a/tasks/components/WardForm.tsx b/tasks/components/WardForm.tsx index d1986ac82..c324fc0d7 100644 --- a/tasks/components/WardForm.tsx +++ b/tasks/components/WardForm.tsx @@ -8,8 +8,8 @@ type WardFormTranslation = { name: string, nameDescription: string, required: string, - tooLong: (maxCharacters: number) => string, - tooShort: (minCharacters: number) => string, + tooLong: string, + tooShort: string, duplicateName: string, } @@ -19,8 +19,8 @@ const defaultWardFormTranslations: Translation = { name: 'Name', nameDescription: 'Should be short, prefer abbreviations.', required: 'Required Field, cannot be empty', - tooLong: (maxCharacters) => `Too long, at most ${maxCharacters} characters`, - tooShort: (minCharacters) => `Too short, at least ${minCharacters} characters`, + tooLong: `Too long, at most {{characters}} characters`, + tooShort: `Too short, at least {{characters}} characters`, duplicateName: 'Wards can\'t have the same name' }, de: { @@ -28,8 +28,8 @@ const defaultWardFormTranslations: Translation = { name: 'Name', nameDescription: 'Sollte kurz sein, Abbkürzungen werden präferiert.', required: 'Benötigter Wert, darf nicht leer sein', - tooLong: (maxCharacters) => `Zu lang, maximal ${maxCharacters} Zeichen`, - tooShort: (minCharacters) => `Zu kurz, mindestens ${minCharacters} Zeichen`, + tooLong: `Zu lang, maximal {{characters}} Zeichen`, + tooShort: `Zu kurz, mindestens {{characters}} Zeichen`, duplicateName: 'Stationen müssen unterschiedliche Namen haben' } } @@ -53,7 +53,7 @@ export const WardForm = ({ onChange = () => undefined, isShowingErrorsDirectly = false }: PropsForTranslation) => { - const translation = useTranslation(defaultWardFormTranslations, overwriteTranslation) + const translation = useTranslation([defaultWardFormTranslations], overwriteTranslation) const [touched, setTouched] = useState({ name: isShowingErrorsDirectly }) const minWardNameLength = 2 @@ -65,11 +65,10 @@ export const WardForm = ({ function validateName(ward: WardFormInfoDTO) { const wardName = ward.name.trim() if (wardName === '') { - return translation.required - } else if (wardName.length < minWardNameLength) { - return translation.tooShort(minWardNameLength) + return translation('required') } else if (wardName.length < minWardNameLength) { + return translation('tooShort', { replacements: { characters: minWardNameLength.toString() } }) } else if (wardName.length > maxWardNameLength) { - return translation.tooLong(maxWardNameLength) + return translation('tooLong', { replacements: { characters: maxWardNameLength.toString() } }) } } @@ -86,7 +85,7 @@ export const WardForm = ({
setTouched({ ...touched, name: true })} onChangeText={text => triggerOnChange({ ...ward, name: text })} maxLength={maxWardNameLength} @@ -94,7 +93,7 @@ export const WardForm = ({ /> {isDisplayingShortNameError && {nameErrorMessage}}
- {translation.nameDescription} + {translation('nameDescription')} ) } diff --git a/tasks/components/cards/BedCard.tsx b/tasks/components/cards/BedCard.tsx index ba01261f2..a1544bcf4 100644 --- a/tasks/components/cards/BedCard.tsx +++ b/tasks/components/cards/BedCard.tsx @@ -37,7 +37,7 @@ export const BedCard = ({ className, ...restCardProps }: PropsForTranslation) => { - const translation = useTranslation(defaultBedCardTranslation, overwriteTranslation) + const translation = useTranslation([defaultBedCardTranslation], overwriteTranslation) return ( (
{bedName} - {translation.nobody} + {translation('nobody')}
- {translation.addPatient} + {translation('addPatient')}
diff --git a/tasks/components/cards/OrganizationCard.tsx b/tasks/components/cards/OrganizationCard.tsx index cd0359b9b..aeab8a6d3 100644 --- a/tasks/components/cards/OrganizationCard.tsx +++ b/tasks/components/cards/OrganizationCard.tsx @@ -35,7 +35,7 @@ export const OrganizationCard = ({ organization, ...editCardProps }: PropsForTranslation) => { - const translation = useTranslation(defaultOrganizationCardTranslation, overwriteTranslation) + const translation = useTranslation([defaultOrganizationCardTranslation], overwriteTranslation) const organizationMemberCount = organization.members.length return ( @@ -53,7 +53,7 @@ export const OrganizationCard = ({
- {`${organizationMemberCount} ${organizationMemberCount > 1 ? translation.members : translation.member}`} + {`${organizationMemberCount} ${organizationMemberCount > 1 ? translation('members') : translation('member')}`}
({ avatarUrl: user.avatarURL, alt: user.name }))}/>
diff --git a/tasks/components/cards/PatientCard.tsx b/tasks/components/cards/PatientCard.tsx index c91cf1bf9..dcb4ba5ab 100644 --- a/tasks/components/cards/PatientCard.tsx +++ b/tasks/components/cards/PatientCard.tsx @@ -41,11 +41,11 @@ export const PatientCard = ({ className, ...restCardProps }: PropsForTranslation) => { - const translation = useTranslation(defaultPatientCardTranslations, overwriteTranslation) + const translation = useTranslation([defaultPatientCardTranslations], overwriteTranslation) return (
- {bedName ?? translation.bedNotAssigned} + {bedName ?? translation('bedNotAssigned')} {patientName}
diff --git a/tasks/components/cards/TaskCard.tsx b/tasks/components/cards/TaskCard.tsx index 422afa532..901f91587 100644 --- a/tasks/components/cards/TaskCard.tsx +++ b/tasks/components/cards/TaskCard.tsx @@ -35,7 +35,7 @@ export const TaskCard = ({ isSelected = false, onClick = () => undefined }: PropsForTranslation) => { - const translation = useTranslation(defaultTaskCardTranslations, overwriteTranslation) + const translation = useTranslation([defaultTaskCardTranslations], overwriteTranslation) const progress = task.subtasks.length === 0 ? 1 : task.subtasks.filter(value => value.isDone).length / task.subtasks.length const isOverDue = task.dueDate && task.dueDate < new Date() && task.status !== 'done' @@ -61,7 +61,7 @@ export const TaskCard = ({
{assignee && assignee.avatarUrl && - } + } {task.subtasks.length > 0 && ( )} diff --git a/tasks/components/cards/TaskTemplateCard.tsx b/tasks/components/cards/TaskTemplateCard.tsx index 3259b8670..5562554a5 100644 --- a/tasks/components/cards/TaskTemplateCard.tsx +++ b/tasks/components/cards/TaskTemplateCard.tsx @@ -42,7 +42,7 @@ export const TaskTemplateCard = ({ className, ...editCardProps }: PropsForTranslation) => { - const translation = useTranslation(defaultTaskTemplateCardTranslations, overwriteTranslation) + const translation = useTranslation([defaultTaskTemplateCardTranslations], overwriteTranslation) return ( - {typeForLabel === 'ward' ? translation.ward : translation.personal} + {typeForLabel === 'ward' ? translation('ward') : translation('personal')} )}
- {subtaskCount + ' ' + translation.subtask} + {subtaskCount + ' ' + translation('subtask')}
) diff --git a/tasks/components/layout/DashboardDisplay.tsx b/tasks/components/layout/DashboardDisplay.tsx index 7236136a4..a3aaf7a37 100644 --- a/tasks/components/layout/DashboardDisplay.tsx +++ b/tasks/components/layout/DashboardDisplay.tsx @@ -46,7 +46,7 @@ export type DashboardDisplayProps = Record export const DashboardDisplay = ({ overwriteTranslation, }: PropsForTranslation) => { - const translation = useTranslation(defaultDashboardDisplayTranslations, overwriteTranslation) + const translation = useTranslation([defaultDashboardDisplayTranslations], overwriteTranslation) const { organization } = useAuth() const router = useRouter() @@ -63,13 +63,13 @@ export const DashboardDisplay = ({ return (
- {translation.recent} + {translation('recent')} {patients && patients.length > 0 && ( <> - {translation.patients} + {translation('patients')}
{patients?.map(patient => (
- {translation.wards} + {translation('wards')}
{wards && wards.length > 0 && wards?.map(ward => ( ))} router.push(`/organizations/${organization?.id}`)} />
diff --git a/tasks/components/layout/InitializationChecker.tsx b/tasks/components/layout/InitializationChecker.tsx index bbc898ea1..f3e12339b 100644 --- a/tasks/components/layout/InitializationChecker.tsx +++ b/tasks/components/layout/InitializationChecker.tsx @@ -14,13 +14,13 @@ const defaultTranslation: Translation<{ loggingIn: string }> = { } export const InitializationChecker = ({ children }: PropsWithChildren) => { - const translation = useTranslation(defaultTranslation) + const translation = useTranslation([defaultTranslation]) const { user } = useAuth() if(!user) { return (
- +
) } diff --git a/tasks/components/layout/NewsFeed.tsx b/tasks/components/layout/NewsFeed.tsx index 029fc4a1c..8f2bc56f6 100644 --- a/tasks/components/layout/NewsFeed.tsx +++ b/tasks/components/layout/NewsFeed.tsx @@ -34,7 +34,7 @@ export const NewsFeed = ({ localizedNews, width }: PropsForTranslation) => { - const translation = useTranslation(defaultNewsFeedTranslations, overwriteTranslation) + const translation = useTranslation([defaultNewsFeedTranslations], overwriteTranslation) // The value of how much space a FeatureDisplay needs before the title can be displayed on its left // Given in px const widthForAppearanceChange = 600 @@ -43,7 +43,7 @@ export const NewsFeed = ({ const newsFilter = 'tasks' return (
- + {usedLanguage ? filterNews(localizedNews[usedLanguage], [newsFilter]).map(news => ( )) : (
- {translation.noNews} + {translation('noNews')}
)}
diff --git a/tasks/components/layout/OrganizationDetails.tsx b/tasks/components/layout/OrganizationDetails.tsx index 107a6113a..d38c9a55d 100644 --- a/tasks/components/layout/OrganizationDetails.tsx +++ b/tasks/components/layout/OrganizationDetails.tsx @@ -61,7 +61,7 @@ export type OrganizationDetailProps = { export const OrganizationDetail = ({ overwriteTranslation }: PropsForTranslation) => { - const translation = useTranslation(defaultOrganizationDetailTranslations, overwriteTranslation) + const translation = useTranslation([defaultOrganizationDetailTranslations], overwriteTranslation) const { state: contextState, @@ -137,8 +137,8 @@ export const OrganizationDetail = ({ > setIsShowingConfirmDialog(false)} @@ -162,7 +162,7 @@ export const OrganizationDetail = ({ signOut() }} /> - +
isCreatingNewOrganization ? createOrganization(organizationForm.organization) : updateOrganization(organizationForm.organization)} disabled={!organizationForm.isValid}> - {isCreatingNewOrganization ? translation.create : translation.update} + {isCreatingNewOrganization ? translation('create') : translation('update')}
- {translation.dangerZone} - {translation.dangerZoneText} + {translation('dangerZone')} + {translation('dangerZoneText')}
diff --git a/tasks/components/layout/OrganizationDisplay.tsx b/tasks/components/layout/OrganizationDisplay.tsx index e73b6baba..1f3f4fef7 100644 --- a/tasks/components/layout/OrganizationDisplay.tsx +++ b/tasks/components/layout/OrganizationDisplay.tsx @@ -39,7 +39,7 @@ export const OrganizationDisplay = ({ selectedOrganizationId, organizations, }: PropsForTranslation) => { - const translation = useTranslation(defaultOrganizationDisplayTranslations, overwriteTranslation) + const translation = useTranslation([defaultOrganizationDisplayTranslations], overwriteTranslation) const router = useRouter() const context = useContext(OrganizationContext) @@ -55,7 +55,7 @@ export const OrganizationDisplay = ({ const usedSelectedId = selectedOrganizationId ?? context.state.organizationId return (
- +
{usedOrganizations.map(organization => ( context.updateContext({ ...context.state, organizationId: '' })} isSelected={!!usedSelectedId} /> diff --git a/tasks/components/layout/PatientDetails.tsx b/tasks/components/layout/PatientDetails.tsx index c9d2a98cb..4ec102ac2 100644 --- a/tasks/components/layout/PatientDetails.tsx +++ b/tasks/components/layout/PatientDetails.tsx @@ -75,7 +75,7 @@ export const PatientDetail = ({ patient = emptyPatientDetails }: PropsForTranslation) => { const [isShowingDischargeDialog, setIsShowingDischargeDialog] = useState(false) - const translation = useTranslation(defaultPatientDetailTranslations, overwriteTranslation) + const translation = useTranslation([defaultPatientDetailTranslations], overwriteTranslation) const context = useContext(WardOverviewContext) @@ -126,7 +126,7 @@ export const PatientDetail = ({
- {translation.saved} + {translation('saved')}
) } @@ -148,7 +148,7 @@ export const PatientDetail = ({ patientId={newPatient.id} initialStatus={initialTaskStatus} /> - +