From 8500c035b6221895a4ee5c888fb2f0b7b2edd0fc Mon Sep 17 00:00:00 2001 From: Leandro13Silva13 <115784444+Leandro13Silva13@users.noreply.github.com> Date: Tue, 18 Jun 2024 06:53:18 +0200 Subject: [PATCH 01/49] Update dockerImage.yml --- .github/workflows/dockerImage.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/dockerImage.yml b/.github/workflows/dockerImage.yml index 04c8a38ec..9c9923f37 100644 --- a/.github/workflows/dockerImage.yml +++ b/.github/workflows/dockerImage.yml @@ -10,6 +10,7 @@ on: - 'dockerImage.v.*' - 'v*' + jobs: build: name: Build From 5b992d1b131fc776bfbb5571d081ddfa611cb403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Tue, 23 Jul 2024 11:20:32 +0200 Subject: [PATCH 02/49] feat(initializeFeedbackChat): rm initializeFeedbackChat functionality --- cypress/fixtures/registration/consultingType.json | 1 - cypress/fixtures/service.consultingtypes.emigration.json | 1 - cypress/fixtures/service.consultingtypes.pregnancy.json | 1 - cypress/fixtures/service.consultingtypes.u25.json | 1 - 4 files changed, 4 deletions(-) diff --git a/cypress/fixtures/registration/consultingType.json b/cypress/fixtures/registration/consultingType.json index 7235f05f6..eaa00a1c2 100644 --- a/cypress/fixtures/registration/consultingType.json +++ b/cypress/fixtures/registration/consultingType.json @@ -46,7 +46,6 @@ "relation": true, "state": false }, - "initializeFeedbackChat": false, "roles": { "consultant": { "main": ["consultant"], diff --git a/cypress/fixtures/service.consultingtypes.emigration.json b/cypress/fixtures/service.consultingtypes.emigration.json index 8dc7efb54..83f9f2398 100644 --- a/cypress/fixtures/service.consultingtypes.emigration.json +++ b/cypress/fixtures/service.consultingtypes.emigration.json @@ -43,7 +43,6 @@ "sendFurtherStepsMessage": true, "sendSaveSessionDataMessage": true, "sessionDataInitializing": {}, - "initializeFeedbackChat": false, "roles": { "consultant": { "main": ["consultant"], diff --git a/cypress/fixtures/service.consultingtypes.pregnancy.json b/cypress/fixtures/service.consultingtypes.pregnancy.json index 1eabaa92a..47d68f190 100644 --- a/cypress/fixtures/service.consultingtypes.pregnancy.json +++ b/cypress/fixtures/service.consultingtypes.pregnancy.json @@ -47,7 +47,6 @@ "relation": true, "state": false }, - "initializeFeedbackChat": false, "roles": { "consultant": { "main": ["consultant"], diff --git a/cypress/fixtures/service.consultingtypes.u25.json b/cypress/fixtures/service.consultingtypes.u25.json index 4649c0e3b..cb671867b 100644 --- a/cypress/fixtures/service.consultingtypes.u25.json +++ b/cypress/fixtures/service.consultingtypes.u25.json @@ -50,7 +50,6 @@ "relation": false, "state": true }, - "initializeFeedbackChat": true, "roles": { "consultant": { "main": ["consultant", "u25-consultant", "u25-main-consultant"], From cc3fb8cf69ee1bf525ddb5afbb94c2fcac527ff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Tue, 23 Jul 2024 11:24:12 +0200 Subject: [PATCH 03/49] feat(NEW_FEEDBACK_MESSAGE_FROM_ADVICE_SEEKER): rm NEW_FEEDBACK_MESSAGE_FROM_ADVICE_SEEKER functionality --- cypress/fixtures/service.users.data.json | 4 ---- cypress/support/commands/mockApi.ts | 4 ---- src/resources/scripts/config.ts | 3 +-- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/cypress/fixtures/service.users.data.json b/cypress/fixtures/service.users.data.json index eec6202ed..dc2b75f0b 100644 --- a/cypress/fixtures/service.users.data.json +++ b/cypress/fixtures/service.users.data.json @@ -37,10 +37,6 @@ { "name": "NEW_CHAT_MESSAGE_FROM_ADVICE_SEEKER", "state": true - }, - { - "name": "NEW_FEEDBACK_MESSAGE_FROM_ADVICE_SEEKER", - "state": true } ] }, diff --git a/cypress/support/commands/mockApi.ts b/cypress/support/commands/mockApi.ts index 30d2d8b40..845ad802d 100644 --- a/cypress/support/commands/mockApi.ts +++ b/cypress/support/commands/mockApi.ts @@ -38,10 +38,6 @@ const defaultReturns = { { name: 'NEW_CHAT_MESSAGE_FROM_ADVICE_SEEKER', state: false - }, - { - name: 'NEW_FEEDBACK_MESSAGE_FROM_ADVICE_SEEKER', - state: false } ] }, diff --git a/src/resources/scripts/config.ts b/src/resources/scripts/config.ts index 71e1ac3c9..915ddba18 100644 --- a/src/resources/scripts/config.ts +++ b/src/resources/scripts/config.ts @@ -100,8 +100,7 @@ export const config: AppConfigInterface = { { label: 'profile.notifications.follow.up.email.label', types: [ - 'NEW_CHAT_MESSAGE_FROM_ADVICE_SEEKER', - 'NEW_FEEDBACK_MESSAGE_FROM_ADVICE_SEEKER' + 'NEW_CHAT_MESSAGE_FROM_ADVICE_SEEKER' ] } ] From 9da1eee2b7ccc70503f7596c47ef0a896d800b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Tue, 23 Jul 2024 12:03:15 +0200 Subject: [PATCH 04/49] feat(ForwardMessage): rm all related ForwardMessage functionality --- src/api/apiForwardMessage.ts | 29 -- src/api/apiSendAliasMessage.ts | 1 - src/api/index.ts | 1 - src/components/message/ForwardMessage.tsx | 137 ------- src/components/message/MessageDisplayName.tsx | 47 +-- .../message/MessageItemComponent.tsx | 63 +-- src/components/message/message.styles.scss | 55 +-- src/generated/messageservice.d.ts | 129 ++---- src/generated/userservice.d.ts | 388 ++++++++---------- src/resources/i18n/de/common.json | 4 - src/resources/i18n/en/common.json | 4 - src/resources/scripts/endpoints.ts | 1 - src/resources/styles/settings.scss | 11 +- 13 files changed, 258 insertions(+), 612 deletions(-) delete mode 100644 src/api/apiForwardMessage.ts delete mode 100644 src/components/message/ForwardMessage.tsx diff --git a/src/api/apiForwardMessage.ts b/src/api/apiForwardMessage.ts deleted file mode 100644 index 7ada6c679..000000000 --- a/src/api/apiForwardMessage.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { endpoints } from '../resources/scripts/endpoints'; -import { fetchData, FETCH_METHODS } from './fetchData'; - -export const apiForwardMessage = async ( - messageData: string, - messageDate: string, - displayName: string, - userId: string, - rcGroupId: string, - isEncrypted: boolean -): Promise => { - const url = endpoints.forwardMessage; - const headersData = { rcGroupId: rcGroupId }; - const data = JSON.stringify({ - message: messageData, - timestamp: messageDate, - username: displayName, // TODO change to displayName if message service is adjusted - rcUserId: userId, - t: isEncrypted ? 'e2e' : '' - }); - - return fetchData({ - url: url, - method: FETCH_METHODS.POST, - headersData: headersData, - rcValidation: true, - bodyData: data - }); -}; diff --git a/src/api/apiSendAliasMessage.ts b/src/api/apiSendAliasMessage.ts index 9e1037c0f..e46e95893 100644 --- a/src/api/apiSendAliasMessage.ts +++ b/src/api/apiSendAliasMessage.ts @@ -4,7 +4,6 @@ import { fetchData, FETCH_METHODS } from './fetchData'; export enum ALIAS_MESSAGE_TYPES { E2EE_ACTIVATED = 'E2EE_ACTIVATED', FINISHED_CONVERSATION = 'FINISHED_CONVERSATION', - FORWARD = 'FORWARD', FURTHER_STEPS = 'FURTHER_STEPS', UPDATE_SESSION_DATA = 'UPDATE_SESSION_DATA', VIDEOCALL = 'VIDEOCALL', diff --git a/src/api/index.ts b/src/api/index.ts index 0bbb47cae..97799fc16 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -4,7 +4,6 @@ export * from './apiDraftMessages'; export * from './apiEnquiryAcceptance'; export * from './apiFinishAnonymousConversation'; export * from './apiAnonymousConversationAvailability'; -export * from './apiForwardMessage'; export * from './apiGetAgencyConsultantList'; export * from './apiGetAgencyId'; export * from './apiGetAskerSessionList'; diff --git a/src/components/message/ForwardMessage.tsx b/src/components/message/ForwardMessage.tsx deleted file mode 100644 index 545a626ed..000000000 --- a/src/components/message/ForwardMessage.tsx +++ /dev/null @@ -1,137 +0,0 @@ -import * as React from 'react'; -import { useCallback, useContext, useState } from 'react'; - -import { apiForwardMessage } from '../../api'; -import { ReactComponent as ArrowForwardIcon } from '../../resources/img/icons/arrow-forward.svg'; -import { ReactComponent as CheckmarkIcon } from '../../resources/img/icons/checkmark.svg'; -import { encryptText } from '../../utils/encryptionHelpers'; -import { useE2EE } from '../../hooks/useE2EE'; -import { E2EEContext } from '../../globalState'; -import { useTranslation } from 'react-i18next'; -import { apiPostError, ERROR_LEVEL_WARN } from '../../api/apiPostError'; -import { useE2EEViewElements } from '../../hooks/useE2EEViewElements'; -import { Overlay } from '../overlay/Overlay'; -import { useTimeoutOverlay } from '../../hooks/useTimeoutOverlay'; -import { - OVERLAY_E2EE, - OVERLAY_REQUEST -} from '../../globalState/interfaces/AppConfig/OverlaysConfigInterface'; - -interface ForwardMessageProps { - right: boolean; - message: string; - messageTime: string; - displayName: string; - askerRcId: string; - groupId: string; -} - -export const ForwardMessage = (props: ForwardMessageProps) => { - const { t: translate } = useTranslation(); - const [messageForwarded, setMessageForwarded] = useState(false); - const [isRequestInProgress, setIsRequestInProgress] = useState(false); - - const { visible: requestOverlayVisible, overlay: requestOverlay } = - useTimeoutOverlay(isRequestInProgress); - - /* E2EE */ - const { key, keyID, encrypted, encryptRoom } = useE2EE(props.groupId); - const { - visible: e2eeOverlayVisible, - setState: setE2EEState, - overlay: e2eeOverlay - } = useE2EEViewElements(); - - const { isE2eeEnabled } = useContext(E2EEContext); - - const forwardMessage = useCallback(async () => { - if (isRequestInProgress) { - return null; - } - - setIsRequestInProgress(true); - - if (encrypted && !keyID) { - console.error("Can't send message without key"); - setIsRequestInProgress(false); - return null; - } - - let message = props.message; - let isEncrypted = isE2eeEnabled; - try { - message = await encryptText(message, keyID, key); - } catch (e: any) { - apiPostError({ - name: e.name, - message: e.message, - stack: e.stack, - level: ERROR_LEVEL_WARN - }).then(); - - isEncrypted = false; - } - - apiForwardMessage( - message, - props.messageTime, - props.displayName, - props.askerRcId, - props.groupId, - isEncrypted - ).then(() => { - encryptRoom(setE2EEState).then(() => { - setMessageForwarded(true); - setTimeout(() => { - setMessageForwarded(false); - setIsRequestInProgress(false); - }, 3000); - }); - }); - }, [ - isRequestInProgress, - encrypted, - props.message, - props.messageTime, - props.displayName, - props.askerRcId, - props.groupId, - isE2eeEnabled, - key, - keyID, - encryptRoom, - setE2EEState - ]); - - return ( -
- - - - {requestOverlayVisible && ( - - )} - {e2eeOverlayVisible && ( - - )} -
- ); -}; diff --git a/src/components/message/MessageDisplayName.tsx b/src/components/message/MessageDisplayName.tsx index 37074e37a..da60cc6e8 100644 --- a/src/components/message/MessageDisplayName.tsx +++ b/src/components/message/MessageDisplayName.tsx @@ -1,27 +1,19 @@ import { isUserModerator } from '../session/sessionHelpers'; import * as React from 'react'; import { useCallback, useContext } from 'react'; -import { - formatToHHMM, - getPrettyDateFromMessageDate -} from '../../utils/dateHelpers'; -import { ReactComponent as ArrowForwardIcon } from '../../resources/img/icons/arrow-forward.svg'; -import { ForwardMessageDTO } from './MessageItemComponent'; import { ActiveSessionContext } from '../../globalState'; import { useTranslation } from 'react-i18next'; interface MessageDisplayNameProps { - alias?: ForwardMessageDTO; isUser: Boolean; isMyMessage: Boolean; - type: 'forwarded' | 'user' | 'consultant' | 'self' | 'system'; + type: 'user' | 'consultant' | 'self' | 'system'; userId: string; username: string; displayName: string; } export const MessageDisplayName = ({ - alias, isUser, isMyMessage, type, @@ -32,20 +24,6 @@ export const MessageDisplayName = ({ const { t: translate } = useTranslation(); const { activeSession } = useContext(ActiveSessionContext); - const forwardedLabel = useCallback(() => { - const prettyDate = getPrettyDateFromMessageDate( - Math.round(alias.timestamp / 1000) - ); - - return translate('message.forward.label', { - username: alias.displayName || alias.username, - date: prettyDate.str - ? translate(prettyDate.str) - : translate(prettyDate.date), - time: alias.timestamp && formatToHHMM(alias.timestamp) - }); - }, [alias, translate]); - const subscriberIsModerator = isUserModerator({ chatItem: activeSession.item, rcUserId: userId @@ -62,9 +40,9 @@ export const MessageDisplayName = ({ } else { return subscriberIsModerator ? translate('session.groupChat.consultant.prefix') + - (displayName || username) + (displayName || username) : translate('session.consultant.prefix') + - (displayName || username); + (displayName || username); } }, [ displayName, @@ -77,20 +55,11 @@ export const MessageDisplayName = ({ return ( <> - {!alias && displayName && ( -
- {getUsernameWithPrefix()} -
- )} - - {alias && ( -
- - {forwardedLabel()} -
- )} +
+ {getUsernameWithPrefix()} +
); }; diff --git a/src/components/message/MessageItemComponent.tsx b/src/components/message/MessageItemComponent.tsx index ddd10a3c8..d4dab421e 100644 --- a/src/components/message/MessageItemComponent.tsx +++ b/src/components/message/MessageItemComponent.tsx @@ -16,7 +16,6 @@ import { STATUS_ARCHIVED } from '../../globalState/interfaces'; import { isUserModerator, SESSION_LIST_TYPES } from '../session/sessionHelpers'; -import { ForwardMessage } from './ForwardMessage'; import { MessageMetaData } from './MessageMetaData'; import { CopyMessage } from './CopyMessage'; import { MessageDisplayName } from './MessageDisplayName'; @@ -70,14 +69,6 @@ import { BanUser, BanUserOverlay } from '../banUser/BanUser'; import { getValueFromCookie } from '../sessionCookie/accessSessionCookie'; import { VideoChatDetails, VideoChatDetailsAlias } from './VideoChatDetails'; -export interface ForwardMessageDTO { - message: string; - rcUserId: string; - timestamp: any; - username: string; - displayName: string; -} - export interface VideoCallMessageDTO { eventType: 'IGNORED_CALL'; initiatorRcUserId: string; @@ -99,7 +90,6 @@ export interface MessageItem { groupId?: string; isNotRead: boolean; alias?: { - forwardMessageDTO?: ForwardMessageDTO; videoCallMessageDTO?: VideoCallMessageDTO; content?: string; messageType: ALIAS_MESSAGE_TYPES; @@ -213,9 +203,9 @@ export const MessageItemComponent = ({ setRenderedMessage( contentStateMessage.hasText() ? sanitizeHtml( - urlifyLinksInText(stateToHTML(contentStateMessage)), - sanitizeHtmlDefaultOptions - ) + urlifyLinksInText(stateToHTML(contentStateMessage)), + sanitizeHtmlDefaultOptions + ) : '' ); }, [decryptedMessage]); @@ -242,9 +232,6 @@ export const MessageItemComponent = ({ if (isMyMessage) { return 'self'; } - if (alias?.forwardMessageDTO) { - return 'forwarded'; - } if (displayName === 'system') { return 'system'; } @@ -456,7 +443,6 @@ export const MessageItemComponent = ({ <>
)} - {hasRenderedMessage && - hasUserAuthority( - AUTHORITIES.USE_FEEDBACK, - userData - ) && - type !== SESSION_LIST_TYPES.ENQUIRY && - activeSession.isSession && - activeSession.item.feedbackGroupId && - !activeSession.isFeedback && - activeSession.item.status !== - STATUS_ARCHIVED && ( - - )}
); @@ -550,12 +510,10 @@ export const MessageItemComponent = ({ return (
{getMessageDate()}
diff --git a/src/components/message/message.styles.scss b/src/components/message/message.styles.scss index 57265bb98..901a14f0c 100644 --- a/src/components/message/message.styles.scss +++ b/src/components/message/message.styles.scss @@ -19,6 +19,7 @@ $message-attachment-color: $secondary !default; opacity: 0; transform: translate(0, 0) scale(0.98); } + 100% { opacity: 1; transform: translate(0, 0) scale(1); @@ -50,6 +51,7 @@ $message-attachment-color: $secondary !default; line-height: 13px; text-align: center; } + &__username { text-align: left; display: flex; @@ -71,21 +73,6 @@ $message-attachment-color: $secondary !default; color: $message-name-consultant; } - &--forwarded { - font-size: $font-size-secondary; - line-height: $line-height-secondary; - color: $message-name-forwarded; - - svg { - display: inline-block; - margin-right: 8px; - padding-bottom: 4px; - path { - fill: $text-low-emphasis; - } - } - } - .flyoutMenu { margin-left: $grid-base; } @@ -131,8 +118,7 @@ $message-attachment-color: $secondary !default; &::after { content: ''; display: inline-block; - border-top: 1px solid - var(--skin-color-secondary-contrast-safe, $text-divider-color); + border-top: 1px solid var(--skin-color-secondary-contrast-safe, $text-divider-color); width: $grid-base-three; vertical-align: middle; margin: 0 $grid-base; @@ -148,7 +134,7 @@ $message-attachment-color: $secondary !default; } } - & + .messageItem__divider { + &+.messageItem__divider { margin-top: 12px; } } @@ -203,11 +189,11 @@ $message-attachment-color: $secondary !default; display: flex; flex-direction: column; - & > * { + &>* { margin-top: $grid-base; } - & > *:first-child { + &>*:first-child { margin-top: 0; } } @@ -316,10 +302,6 @@ $message-attachment-color: $secondary !default; color: var(--text-color-contrast-switch, $white); } } - - &--forwarded { - background-color: $yellow-4; - } } &__action { @@ -336,12 +318,6 @@ $message-attachment-color: $secondary !default; fill: var(--skin-color-secondary, $secondary); } - &.forward { - &--active { - animation: successReverse 2.5s ease forwards; - } - } - &.copy { &--active { animation: successCopyReverse 2.5s ease forwards; @@ -520,11 +496,13 @@ $message-attachment-color: $secondary !default; } @keyframes success { + 100%, 0% { transform: translate(-50%, 0) scale(0); opacity: 0; } + 33%, 66% { transform: translate(-50%, 0) scale(1); @@ -532,28 +510,17 @@ $message-attachment-color: $secondary !default; } } -@keyframes successReverse { - 100%, - 0% { - transform: scale(1); - opacity: 1; - } - 15%, - 80% { - transform: scale(0) rotate(45deg); - opacity: 0; - } -} - @keyframes successCopyReverse { + 100%, 0% { transform: scale(1); opacity: 1; } + 15%, 80% { transform: scale(0); opacity: 0; } -} +} \ No newline at end of file diff --git a/src/generated/messageservice.d.ts b/src/generated/messageservice.d.ts index 262a916ae..b3e83d1d4 100644 --- a/src/generated/messageservice.d.ts +++ b/src/generated/messageservice.d.ts @@ -1,7 +1,6 @@ declare namespace MessageService { namespace Schemas { export interface AliasMessageDTO { - forwardMessageDTO?: ForwardMessageDTO; videoCallMessageDTO?: VideoCallMessageDTO; messageType?: MessageType; } @@ -72,29 +71,7 @@ declare namespace MessageService { */ type: string; } - export interface ForwardMessageDTO { - /** - * example: - * Lorem ipsum dolor sit amet, consetetur... - */ - message: string; - /** - * Full qualified timestamp - * example: - * 2018-11-15T09:33:00.057Z - */ - timestamp: string; - /** - * example: - * asker23 - */ - username: string; - /** - * example: - * ag89h3tjkerg94t - */ - rcUserId: string; - } + export interface MasterKeyDTO { /** * example: @@ -124,7 +101,6 @@ declare namespace MessageService { } export type MessageType = | 'FINISHED_CONVERSATION' - | 'FORWARD' | 'FURTHER_STEPS' | 'UPDATE_SESSION_DATA' | 'VIDEOCALL'; @@ -210,11 +186,11 @@ declare namespace Paths { } export type RequestBody = MessageService.Schemas.MessageDTO; namespace Responses { - export interface $201 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} + export interface $201 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $500 { } } } namespace CreateMessage { @@ -230,11 +206,11 @@ declare namespace Paths { } export type RequestBody = MessageService.Schemas.MessageDTO; namespace Responses { - export interface $201 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} + export interface $201 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $500 { } } } namespace CreateVideoHintMessage { @@ -246,11 +222,11 @@ declare namespace Paths { } export type RequestBody = MessageService.Schemas.VideoCallMessageDTO; namespace Responses { - export interface $201 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} + export interface $201 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $500 { } } } namespace FindDraftMessage { @@ -262,33 +238,14 @@ declare namespace Paths { } namespace Responses { export type $200 = string; - export interface $204 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} - } - } - namespace ForwardMessage { - export interface HeaderParameters { - rcToken: Parameters.RcToken; - rcUserId: Parameters.RcUserId; - rcGroupId: Parameters.RcGroupId; - } - namespace Parameters { - export type RcGroupId = string; - export type RcToken = string; - export type RcUserId = string; - } - export type RequestBody = MessageService.Schemas.ForwardMessageDTO; - namespace Responses { - export interface $201 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} + export interface $204 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $500 { } } } + namespace GetMessageStream { export interface HeaderParameters { rcToken: Parameters.RcToken; @@ -304,11 +261,11 @@ declare namespace Paths { } namespace Responses { export type $200 = MessageService.Schemas.MessageStreamDTO; - export interface $204 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} + export interface $204 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $500 { } } } namespace SaveAliasOnlyMessage { @@ -320,11 +277,11 @@ declare namespace Paths { } export type RequestBody = MessageService.Schemas.AliasOnlyMessageDTO; namespace Responses { - export interface $201 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} + export interface $201 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $500 { } } } namespace SaveDraftMessage { @@ -336,22 +293,22 @@ declare namespace Paths { } export type RequestBody = string; namespace Responses { - export interface $200 {} - export interface $201 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} + export interface $200 { } + export interface $201 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $500 { } } } namespace UpdateKey { export type RequestBody = MessageService.Schemas.MasterKeyDTO; namespace Responses { - export interface $202 {} - export interface $401 {} - export interface $403 {} - export interface $409 {} - export interface $500 {} + export interface $202 { } + export interface $401 { } + export interface $403 { } + export interface $409 { } + export interface $500 { } } } } diff --git a/src/generated/userservice.d.ts b/src/generated/userservice.d.ts index 4249ac0a6..a7bf624e3 100644 --- a/src/generated/userservice.d.ts +++ b/src/generated/userservice.d.ts @@ -55,7 +55,6 @@ declare namespace UserService { consultingType?: number; } export interface AliasMessageDTO { - forwardMessageDTO?: ForwardMessageDTO; videoCallMessageDTO?: VideoCallMessageDTO; messageType?: MessageType; } @@ -241,7 +240,7 @@ declare namespace UserService { */ groupId: string; } - export interface Date {} + export interface Date { } export interface DeleteUserAccountDTO { /** * example: @@ -256,30 +255,8 @@ declare namespace UserService { */ message: string; } - export interface ForwardMessageDTO { - /** - * example: - * Lorem ipsum dolor sit amet, consetetur... - */ - message: string; - /** - * Full qualified timestamp - * example: - * 2018-11-15T09:33:00.057Z - */ - timestamp: string; - /** - * example: - * asker23 - */ - username: string; - /** - * example: - * ag89h3tjkerg94t - */ - rcUserId: string; - } - export interface HttpStatus {} + + export interface HttpStatus { } export interface MandatorySessionDataDTO { /** * mandatory depending on the consulting type @@ -304,7 +281,6 @@ declare namespace UserService { export type MessageType = | 'FURTHER_STEPS' | 'UPDATE_SESSION_DATA' - | 'FORWARD' | 'VIDEOCALL'; export interface MobileTokenDTO { /** @@ -795,12 +771,12 @@ declare namespace Paths { sessionId: Parameters.SessionId /* int64 */; } namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $409 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $409 { } + export interface $500 { } } } namespace AssignSession { @@ -813,22 +789,22 @@ declare namespace Paths { consultantId: Parameters.ConsultantId; } namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $409 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $409 { } + export interface $500 { } } } namespace CreateChat { export type RequestBody = UserService.Schemas.ChatDTO; namespace Responses { export type $201 = UserService.Schemas.CreateChatResponseDTO; - export interface $400 {} - export interface $403 {} - export interface $409 {} - export interface $500 {} + export interface $400 { } + export interface $403 { } + export interface $409 { } + export interface $500 { } } } namespace CreateEnquiryMessage { @@ -846,22 +822,22 @@ declare namespace Paths { } export type RequestBody = UserService.Schemas.EnquiryMessageDTO; namespace Responses { - export interface $201 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $409 {} - export interface $500 {} + export interface $201 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $409 { } + export interface $500 { } } } namespace DeactivateAndFlagUserAccountForDeletion { export type RequestBody = UserService.Schemas.DeleteUserAccountDTO; namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $500 { } } } namespace FetchSessionForConsultant { @@ -873,11 +849,11 @@ declare namespace Paths { } namespace Responses { export type $200 = UserService.Schemas.ConsultantSessionDTO; - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $404 {} - export interface $500 {} + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $404 { } + export interface $500 { } } } namespace GetChat { @@ -889,11 +865,11 @@ declare namespace Paths { } namespace Responses { export type $200 = UserService.Schemas.ChatInfoResponseDTO; - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $404 {} - export interface $500 {} + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $404 { } + export interface $500 { } } } namespace GetChatMembers { @@ -905,12 +881,12 @@ declare namespace Paths { } namespace Responses { export type $200 = UserService.Schemas.ChatMembersResponseDTO; - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $404 {} - export interface $409 {} - export interface $500 {} + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $404 { } + export interface $409 { } + export interface $500 { } } } namespace GetConsultants { @@ -922,11 +898,11 @@ declare namespace Paths { } namespace Responses { export type $200 = UserService.Schemas.ConsultantResponseDTO[]; - export interface $204 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} + export interface $204 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $500 { } } } namespace GetMonitoring { @@ -938,11 +914,11 @@ declare namespace Paths { } namespace Responses { export type $200 = UserService.Schemas.MonitoringDTO; - export interface $204 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} + export interface $204 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $500 { } } } namespace GetSessionsForAuthenticatedConsultant { @@ -965,10 +941,10 @@ declare namespace Paths { namespace Responses { export type $200 = UserService.Schemas.ConsultantSessionListResponseDTO; - export interface $204 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} + export interface $204 { } + export interface $401 { } + export interface $403 { } + export interface $500 { } } } namespace GetSessionsForAuthenticatedUser { @@ -980,11 +956,11 @@ declare namespace Paths { } namespace Responses { export type $200 = UserService.Schemas.UserSessionListResponseDTO; - export interface $204 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} + export interface $204 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $500 { } } } namespace GetTeamSessionsForAuthenticatedConsultant { @@ -1005,43 +981,43 @@ declare namespace Paths { namespace Responses { export type $200 = UserService.Schemas.ConsultantSessionListResponseDTO; - export interface $204 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} + export interface $204 { } + export interface $401 { } + export interface $403 { } + export interface $500 { } } } namespace GetUserData { namespace Responses { export type $200 = UserService.Schemas.UserDataResponseDTO; - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $500 { } } } namespace ImportAskers { namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $401 { } + export interface $500 { } } } namespace ImportAskersWithoutSession { namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $401 { } + export interface $500 { } } } namespace ImportConsultants { namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $401 { } + export interface $500 { } } } namespace JoinChat { @@ -1052,13 +1028,13 @@ declare namespace Paths { chatId: Parameters.ChatId /* int64 */; } namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $404 {} - export interface $409 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $404 { } + export interface $409 { } + export interface $500 { } } } namespace LeaveChat { @@ -1069,13 +1045,13 @@ declare namespace Paths { chatId: Parameters.ChatId /* int64 */; } namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $404 {} - export interface $409 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $404 { } + export interface $409 { } + export interface $500 { } } } namespace RegisterNewConsultingType { @@ -1090,20 +1066,20 @@ declare namespace Paths { export type RequestBody = UserService.Schemas.NewRegistrationDto; namespace Responses { export type $201 = UserService.Schemas.NewRegistrationResponseDto; - export interface $400 {} - export interface $403 {} - export interface $409 {} - export interface $500 {} + export interface $400 { } + export interface $403 { } + export interface $409 { } + export interface $500 { } } } namespace RegisterUser { export type RequestBody = UserService.Schemas.UserDTO; namespace Responses { - export interface $201 {} - export interface $400 {} - export interface $403 {} - export interface $409 {} - export interface $500 {} + export interface $201 { } + export interface $400 { } + export interface $403 { } + export interface $409 { } + export interface $500 { } } } namespace SendLiveEvent { @@ -1114,31 +1090,31 @@ declare namespace Paths { rcGroupId: Parameters.RcGroupId; } namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $403 {} - export interface $409 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $403 { } + export interface $409 { } + export interface $500 { } } } namespace SendNewFeedbackMessageNotification { export type RequestBody = UserService.Schemas.NewMessageNotificationDTO; namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $409 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $401 { } + export interface $409 { } + export interface $500 { } } } namespace SendNewMessageNotification { export type RequestBody = UserService.Schemas.NewMessageNotificationDTO; namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $409 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $401 { } + export interface $409 { } + export interface $500 { } } } namespace StartChat { @@ -1149,12 +1125,12 @@ declare namespace Paths { chatId: Parameters.ChatId /* int64 */; } namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $409 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $409 { } + export interface $500 { } } } namespace StopChat { @@ -1165,22 +1141,22 @@ declare namespace Paths { chatId: Parameters.ChatId /* int64 */; } namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $409 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $409 { } + export interface $500 { } } } namespace UpdateAbsence { export type RequestBody = UserService.Schemas.AbsenceDTO; namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $500 { } } } namespace UpdateChat { @@ -1193,52 +1169,52 @@ declare namespace Paths { export type RequestBody = UserService.Schemas.ChatDTO; namespace Responses { export type $200 = UserService.Schemas.UpdateChatResponseDTO; - export interface $400 {} - export interface $403 {} - export interface $409 {} - export interface $500 {} + export interface $400 { } + export interface $403 { } + export interface $409 { } + export interface $500 { } } } namespace UpdateConsultantData { export type RequestBody = UserService.Schemas.UpdateConsultantDTO; namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $409 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $409 { } + export interface $500 { } } } namespace UpdateEmailAddress { export type RequestBody = string; namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $409 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $409 { } + export interface $500 { } } } namespace UpdateKey { export type RequestBody = UserService.Schemas.MasterKeyDTO; namespace Responses { - export interface $202 {} - export interface $401 {} - export interface $403 {} - export interface $409 {} - export interface $500 {} + export interface $202 { } + export interface $401 { } + export interface $403 { } + export interface $409 { } + export interface $500 { } } } namespace UpdateMobileToken { export type RequestBody = UserService.Schemas.MobileTokenDTO; namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $500 { } } } namespace UpdateMonitoring { @@ -1250,21 +1226,21 @@ declare namespace Paths { } export type RequestBody = UserService.Schemas.MonitoringDTO; namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $500 { } } } namespace UpdatePassword { export type RequestBody = UserService.Schemas.PasswordDTO; namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $500 { } } } namespace UpdateSessionData { @@ -1276,12 +1252,12 @@ declare namespace Paths { } export type RequestBody = UserService.Schemas.SessionDataDTO; namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $404 {} - export interface $500 {} + export interface $200 { } + export interface $400 { } + export interface $401 { } + export interface $403 { } + export interface $404 { } + export interface $500 { } } } } diff --git a/src/resources/i18n/de/common.json b/src/resources/i18n/de/common.json index be687102c..89ba4390e 100644 --- a/src/resources/i18n/de/common.json +++ b/src/resources/i18n/de/common.json @@ -1264,10 +1264,6 @@ "headline": "Nachricht löschen" } }, - "forward": { - "label": "Weitergeleitete Nachricht von {{username}}, {{date}} um {{time}}", - "title": "Textnachricht an\nFeedback weiterleiten" - }, "groupChat": "Gruppenchat", "isMyMessage": { "name": "Ich" diff --git a/src/resources/i18n/en/common.json b/src/resources/i18n/en/common.json index 0dbf02480..753cf5256 100644 --- a/src/resources/i18n/en/common.json +++ b/src/resources/i18n/en/common.json @@ -1249,10 +1249,6 @@ "headline": "Delete message" } }, - "forward": { - "label": "Forwarded message from {{username}}, {{date}} at {{time}}", - "title": "Forward text message to\nFeedback" - }, "groupChat": "Group chat", "isMyMessage": { "name": "Me" diff --git a/src/resources/scripts/endpoints.ts b/src/resources/scripts/endpoints.ts index fb0cba15a..dc9ad3255 100644 --- a/src/resources/scripts/endpoints.ts +++ b/src/resources/scripts/endpoints.ts @@ -54,7 +54,6 @@ export const endpoints = { draftMessages: apiUrl + '/service/messages/draft', email: apiUrl + '/service/users/email', error: apiUrl + '/service/logstash', - forwardMessage: apiUrl + '/service/messages/forward', groupChatBase: apiUrl + '/service/users/chat/', keycloakAccessToken: apiUrl + '/auth/realms/online-beratung/protocol/openid-connect/token', diff --git a/src/resources/styles/settings.scss b/src/resources/styles/settings.scss index c4e73daac..52ddf478d 100644 --- a/src/resources/styles/settings.scss +++ b/src/resources/styles/settings.scss @@ -80,7 +80,6 @@ $message-name-self: $text-low-emphasis; $message-name-system: var(--skin-color-default, $primary); $message-name-consultant: var(--skin-color-default, $primary); $message-name-user: #167a6f; -$message-name-forwarded: $text-low-emphasis; $message-system: #8c878c; // FONT SIZES @@ -233,11 +232,9 @@ $max-input-width: 320px; $message-background-primary: $primary; $message-background-secondary: black; $message-background-rate: 0%; -$message-background: mix( - $message-background-secondary, - $primary, - $message-background-rate -); +$message-background: mix($message-background-secondary, + $primary, + $message-background-rate); $message-submit-interface-textarea-background-color: $dark-grey; $message-submit-interface-textarea-background-color-yellow: $yellow-3; $message-submit-interface-textarea-placeholder-color: $light-grey; @@ -290,4 +287,4 @@ $text-divider-font-weight: $font-weight-regular; $text-divider-text-transform: none; $upload-progress: #80dd92; $waiting-room-illustration-display-after: block; -$welcome-screen-icon-background: $primary; +$welcome-screen-icon-background: $primary; \ No newline at end of file From 92bd00c1d5a98680247afb1d96f09b6744a2d625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Tue, 23 Jul 2024 12:04:42 +0200 Subject: [PATCH 05/49] feat(initializeFeedbackChat): rm initializeFeedbackChat functionality --- cypress/fixtures/service.consultingtypes.addiction.json | 1 - 1 file changed, 1 deletion(-) diff --git a/cypress/fixtures/service.consultingtypes.addiction.json b/cypress/fixtures/service.consultingtypes.addiction.json index 7235f05f6..eaa00a1c2 100644 --- a/cypress/fixtures/service.consultingtypes.addiction.json +++ b/cypress/fixtures/service.consultingtypes.addiction.json @@ -46,7 +46,6 @@ "relation": true, "state": false }, - "initializeFeedbackChat": false, "roles": { "consultant": { "main": ["consultant"], From 8ede5c9ef566e42280f494c749f16e0df8fd24f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Tue, 23 Jul 2024 12:13:48 +0200 Subject: [PATCH 06/49] feat(feedbackRead): rm feedbackRead functionality --- .../fixtures/service.users.sessions.room.json | 1 - cypress/support/sessions.ts | 2 -- .../SessionListItemComponent.tsx | 29 +++++++++---------- src/generated/userservice.d.ts | 5 ---- .../interfaces/SessionsDataInterface.ts | 11 ++++--- src/hooks/useSession.tsx | 6 +--- 6 files changed, 19 insertions(+), 35 deletions(-) diff --git a/cypress/fixtures/service.users.sessions.room.json b/cypress/fixtures/service.users.sessions.room.json index 7f29441d3..83e8dc8ad 100644 --- a/cypress/fixtures/service.users.sessions.room.json +++ b/cypress/fixtures/service.users.sessions.room.json @@ -14,7 +14,6 @@ "lastMessage": null, "messageDate": 0, "messagesRead": false, - "feedbackRead": true, "isTeamSession": false, "registrationType": "REGISTERED", "createDate": "2022-06-15T08:09:18Z", diff --git a/cypress/support/sessions.ts b/cypress/support/sessions.ts index 39b512220..a8bbf0202 100644 --- a/cypress/support/sessions.ts +++ b/cypress/support/sessions.ts @@ -48,7 +48,6 @@ export const generateConsultantSession = ({ lastMessage: 'lastMessage', messageDate: 1606900238, messagesRead: messagesRead === undefined ? true : messagesRead, - feedbackRead: true, isTeamSession: true, isFeedbackSession: false, isPeerChat: false, @@ -117,7 +116,6 @@ export const generateAskerSession = ({ lastMessage: null, messageDate: null, messagesRead: messagesRead === undefined ? true : messagesRead, - feedbackRead: null, isTeamSession: isTeamSession === undefined ? true : isTeamSession, isFeedbackSession: false, isPeerChat: false, diff --git a/src/components/sessionsListItem/SessionListItemComponent.tsx b/src/components/sessionsListItem/SessionListItemComponent.tsx index ca288065b..b59bb498a 100644 --- a/src/components/sessionsListItem/SessionListItemComponent.tsx +++ b/src/components/sessionsListItem/SessionListItemComponent.tsx @@ -92,7 +92,7 @@ export const SessionListItemComponent = ({ const { key, keyID, encrypted, ready } = useE2EE( activeSession.item.groupId, activeSession.item.lastMessageType === - ALIAS_MESSAGE_TYPES.MASTER_KEY_LOST + ALIAS_MESSAGE_TYPES.MASTER_KEY_LOST ); const [plainTextLastMessage, setPlainTextLastMessage] = useState(null); @@ -169,8 +169,7 @@ export const SessionListItemComponent = ({ const handleOnClick = () => { if (activeSession.item.groupId && activeSession.item.id !== undefined) { history.push( - `${listPath}/${activeSession.item.groupId}/${ - activeSession.item.id + `${listPath}/${activeSession.item.groupId}/${activeSession.item.id }${getSessionListTab()}` ); } else if ( @@ -293,7 +292,7 @@ export const SessionListItemComponent = ({ className={clsx( 'sessionsListItem__username', activeSession.item.messagesRead && - 'sessionsListItem__username--readLabel' + 'sessionsListItem__username--readLabel' )} > {activeSession.item.topic} @@ -326,9 +325,8 @@ export const SessionListItemComponent = ({ ); } - const feedbackPath = `${listPath}/${activeSession.item.feedbackGroupId}/${ - activeSession.item.id - }${getSessionListTab()}`; + const feedbackPath = `${listPath}/${activeSession.item.feedbackGroupId}/${activeSession.item.id + }${getSessionListTab()}`; const hasConsultantData = !!activeSession.consultant; let sessionTopic = ''; @@ -367,11 +365,11 @@ export const SessionListItemComponent = ({ >
{type === SESSION_LIST_TYPES.TEAMSESSION && - hasUserAuthority( - AUTHORITIES.VIEW_ALL_PEER_SESSIONS, - userData - ) && - activeSession.consultant ? ( + hasUserAuthority( + AUTHORITIES.VIEW_ALL_PEER_SESSIONS, + userData + ) && + activeSession.consultant ? (
{translate('sessionList.user.peer')}:{' '} {activeSession.consultant.firstName}{' '} @@ -380,8 +378,8 @@ export const SessionListItemComponent = ({ ) : (
{!isAsker && - !activeSession.isLive && - !autoSelectPostcode + !activeSession.isLive && + !autoSelectPostcode ? activeSession.item.postcode : null}
@@ -413,7 +411,7 @@ export const SessionListItemComponent = ({ className={clsx( 'sessionsListItem__username', activeSession.item.messagesRead && - 'sessionsListItem__username--readLabel' + 'sessionsListItem__username--readLabel' )} > {sessionTopic} @@ -453,7 +451,6 @@ export const SessionListItemComponent = ({ {!isAsker && type !== SESSION_LIST_TYPES.ENQUIRY && !activeSession.isLive && - !activeSession.item.feedbackRead && !activeSession.isFeedback && ( Date: Tue, 23 Jul 2024 14:58:04 +0200 Subject: [PATCH 07/49] feat(sendFeedback): rm sendFeedback functionality and yellowTheme --- src/api/apiSendMessage.ts | 9 +- src/api/apiUploadAttachment.ts | 5 +- src/components/form/textarea.styles.scss | 11 +- ...ageSubmitInterface.yellowTheme.styles.scss | 23 ---- .../messageSubmitInterfaceComponent.tsx | 116 +++--------------- .../session/SessionItemComponent.tsx | 24 ++-- .../session/session.yellowTheme.styles.scss | 15 --- src/resources/i18n/de/common.json | 15 --- src/resources/i18n/en/common.json | 15 --- 9 files changed, 33 insertions(+), 200 deletions(-) delete mode 100644 src/components/messageSubmitInterface/messageSubmitInterface.yellowTheme.styles.scss delete mode 100644 src/components/session/session.yellowTheme.styles.scss diff --git a/src/api/apiSendMessage.ts b/src/api/apiSendMessage.ts index 74cd68058..fe628591f 100644 --- a/src/api/apiSendMessage.ts +++ b/src/api/apiSendMessage.ts @@ -4,16 +4,11 @@ import { fetchData, FETCH_METHODS } from './fetchData'; export const apiSendMessage = ( messageData: string, rcGroupIdOrSessionId: string | number, - isFeedback: boolean, sendMailNotification: boolean, isEncrypted: boolean ): Promise => { - const url = isFeedback - ? endpoints.sendMessageToFeedback - : endpoints.sendMessage; - const activeGroupId = isFeedback - ? { rcFeedbackGroupId: rcGroupIdOrSessionId } - : { rcGroupId: rcGroupIdOrSessionId }; + const url = endpoints.sendMessage; + const activeGroupId = { rcGroupId: rcGroupIdOrSessionId }; const message = JSON.stringify({ message: messageData, t: isEncrypted ? 'e2e' : '', diff --git a/src/api/apiUploadAttachment.ts b/src/api/apiUploadAttachment.ts index 2ccb8e3f3..341b76751 100644 --- a/src/api/apiUploadAttachment.ts +++ b/src/api/apiUploadAttachment.ts @@ -11,7 +11,6 @@ const isLocalDevelopment = nodeEnv === 'development'; export const apiUploadAttachment = ( attachment: File, rcGroupIdOrSessionId: string | number, - isFeedback: boolean, sendMailNotification: boolean, uploadProgress: Function, handleXhr: (xhr) => void, @@ -24,9 +23,7 @@ export const apiUploadAttachment = ( const rcUid = getValueFromCookie('rc_uid'); const csrfToken = generateCsrfToken(); - const url = isFeedback - ? endpoints.attachmentUploadFeedbackRoom + rcGroupIdOrSessionId - : endpoints.attachmentUpload + rcGroupIdOrSessionId; + const url = endpoints.attachmentUpload + rcGroupIdOrSessionId; let data = new FormData(); data.append('file', attachment); diff --git a/src/components/form/textarea.styles.scss b/src/components/form/textarea.styles.scss index f13eaefc5..8834d1ef9 100644 --- a/src/components/form/textarea.styles.scss +++ b/src/components/form/textarea.styles.scss @@ -49,8 +49,8 @@ color: transparent; } - &:focus + label, - &:not(:placeholder-shown) + label { + &:focus+label, + &:not(:placeholder-shown)+label { font-size: 12px; top: 2px; transition: @@ -60,13 +60,13 @@ padding-top: $grid-base; } - &:placeholder-shown + label { + &:placeholder-shown+label { top: 4px; } } /* stylelint-disable */ - label:not(.requestFeedbackLabel) { + label { width: calc(100% - #{$grid-base-three * 2}); position: absolute; left: $grid-base-three; @@ -77,5 +77,6 @@ text-align: left; background-color: white; } + /* stylelint-enable */ -} +} \ No newline at end of file diff --git a/src/components/messageSubmitInterface/messageSubmitInterface.yellowTheme.styles.scss b/src/components/messageSubmitInterface/messageSubmitInterface.yellowTheme.styles.scss deleted file mode 100644 index 392c51695..000000000 --- a/src/components/messageSubmitInterface/messageSubmitInterface.yellowTheme.styles.scss +++ /dev/null @@ -1,23 +0,0 @@ -.session--yellowTheme { - .textarea { - background-color: $message-submit-interface-textarea-background-color-yellow; - } -} - -.session { - .textarea--yellowTheme { - animation: yellowThemeHighlight 1.5s forwards; - } - - @keyframes yellowThemeHighlight { - 0% { - background: $dark-grey; - } - 20% { - background: $yellow-4; - } - 100% { - background: var(--skin-color-secondary-light, $yellow-3); - } - } -} diff --git a/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx b/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx index 3cde178c6..f99d30f8d 100644 --- a/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx +++ b/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx @@ -69,7 +69,6 @@ import { ReactComponent as RemoveIcon } from '../../resources/img/icons/x.svg'; import { ReactComponent as CalendarMonthIcon } from '../../resources/img/icons/calendar-month-navigation.svg'; import './emojiPicker.styles'; import './messageSubmitInterface.styles'; -import './messageSubmitInterface.yellowTheme.styles'; import clsx from 'clsx'; import { mobileListView } from '../app/navigationHandler'; import { Button, ButtonItem, BUTTON_TYPES } from '../button/Button'; @@ -97,7 +96,6 @@ import { OVERLAY_REQUEST } from '../../globalState/interfaces/AppConfig/OverlaysConfigInterface'; import { getIconForAttachmentType } from '../message/messageHelpers'; -import classNames from 'classnames'; //Linkify Plugin const omitKey = (key, { [key]: _, ...obj }) => obj; @@ -182,7 +180,7 @@ export const MessageSubmitInterfaceComponent = ({ const [isRichtextActive, setIsRichtextActive] = useState(false); const [isConsultantAbsent, setIsConsultantAbsent] = useState( hasUserAuthority(AUTHORITIES.ASKER_DEFAULT, userData) && - activeSession.consultant?.absent + activeSession.consultant?.absent ); const [isSessionArchived, setIsSessionArchived] = useState( activeSession.item.status === STATUS_ARCHIVED @@ -193,8 +191,6 @@ export const MessageSubmitInterfaceComponent = ({ const [isLiveChatFinished, setIsLiveChatFinished] = useState( activeSession.isLive && activeSession.item.status === STATUS_FINISHED ); - const [requestFeedbackCheckboxChecked, setRequestFeedbackCheckboxChecked] = - useState(false); const [showAppointmentButton, setShowAppointmentButton] = useState(false); //Emoji Picker Plugin @@ -229,15 +225,6 @@ export const MessageSubmitInterfaceComponent = ({ ready: e2EEReady } = useE2EE(activeSession.rid || null); - // This loads keys for feedback chat to have the ability to encrypt - // the feedback chat when checkbox "Request feedback" is checked - const { - keyID: feedbackChatKeyId, - key: feedbackChatKey, - encryptRoom: feedbackEncryptRoom, - ready: feedbackE2EEReady - } = useE2EE(activeSession.item.feedbackGroupId); - const { visible: e2eeOverlayVisible, setState: setE2EEState, @@ -248,7 +235,7 @@ export const MessageSubmitInterfaceComponent = ({ useTimeoutOverlay( // Disable the request overlay if upload is in progess because upload progress is shown in the ui already isRequestInProgress && - !(uploadProgress > 0 && uploadProgress < 100), + !(uploadProgress > 0 && uploadProgress < 100), null, null, null, @@ -258,13 +245,13 @@ export const MessageSubmitInterfaceComponent = ({ useEffect(() => { setIsConsultantAbsent( hasUserAuthority(AUTHORITIES.ASKER_DEFAULT, userData) && - activeSession.consultant?.absent + activeSession.consultant?.absent ); setIsSessionArchived(activeSession.item.status === STATUS_ARCHIVED); setIsTypingActive(activeSession.isGroup || activeSession.isLive); setIsLiveChatFinished( activeSession.isLive && - activeSession.item.status === STATUS_FINISHED + activeSession.item.status === STATUS_FINISHED ); }, [activeSession, activeSession.item.status, userData]); @@ -387,7 +374,7 @@ export const MessageSubmitInterfaceComponent = ({ if ( draftLoaded && currentEditorState.getCurrentContent() !== - editorState.getCurrentContent() && + editorState.getCurrentContent() && isTyping ) { isTyping(!currentEditorState.getCurrentContent().hasText()); @@ -455,11 +442,11 @@ export const MessageSubmitInterfaceComponent = ({ let textInputStyles = `min-height: ${currentInputHeight}px; ${currentOverflow} ${textInputMarginTop} ${textInputMarginBottom}`; textInputStyles = isRichtextActive ? textInputStyles + - `border-top: none; border-top-right-radius: 0; box-shadow: none;` + `border-top: none; border-top-right-radius: 0; box-shadow: none;` : textInputStyles; textInputStyles = attachmentSelected ? textInputStyles + - `border-bottom: none; border-bottom-right-radius: 0;` + `border-bottom: none; border-bottom-right-radius: 0;` : textInputStyles; textInput?.setAttribute('style', textInputStyles); @@ -511,35 +498,19 @@ export const MessageSubmitInterfaceComponent = ({ const handleMessageSendSuccess = useCallback(() => { onMessageSendSuccess?.(); - if (requestFeedbackCheckboxChecked) { - const feedbackButton = document.querySelector( - '.sessionInfo__feedbackButton' - ); - feedbackButton?.classList.add( - 'sessionInfo__feedbackButton--active' - ); - setTimeout(() => { - feedbackButton?.classList.remove( - 'sessionInfo__feedbackButton--active' - ); - }, 700); - } setEditorState(EditorState.createEmpty()); setActiveInfo(''); resizeTextarea(); setTimeout(() => setIsRequestInProgress(false), 1200); - }, [onMessageSendSuccess, requestFeedbackCheckboxChecked, resizeTextarea]); + }, [onMessageSendSuccess, resizeTextarea]); const sendMessage = useCallback( async ( - sendToFeedbackEndpoint, message, attachment: File, isEncrypted ) => { - const sendToRoomWithId = sendToFeedbackEndpoint - ? activeSession.item.feedbackGroupId - : activeSession.rid || activeSession.item.id; + const sendToRoomWithId = activeSession.rid || activeSession.item.id; const getSendMailNotificationStatus = () => !activeSession.isGroup && !activeSession.isLive; @@ -577,7 +548,6 @@ export const MessageSubmitInterfaceComponent = ({ res = await apiUploadAttachment( attachmentFile, sendToRoomWithId, - sendToFeedbackEndpoint, getSendMailNotificationStatus(), setUploadProgress, setAttachmentUpload, @@ -617,7 +587,6 @@ export const MessageSubmitInterfaceComponent = ({ await apiSendMessage( message, sendToRoomWithId, - sendToFeedbackEndpoint, getSendMailNotificationStatus() && !attachment, isEncrypted ) @@ -673,21 +642,11 @@ export const MessageSubmitInterfaceComponent = ({ return null; } - const sendToFeedbackEndpoint = - requestFeedbackCheckboxChecked || activeSession.isFeedback; - - const messageKeyId = requestFeedbackCheckboxChecked - ? feedbackChatKeyId - : keyID; - const messageKey = requestFeedbackCheckboxChecked - ? feedbackChatKey - : key; - let message = getTypedMarkdownMessage().trim(); let isEncrypted = isE2eeEnabled; if (message.length > 0 && isE2eeEnabled) { try { - message = await encryptText(message, messageKeyId, messageKey); + message = await encryptText(message, keyID, key); } catch (e: any) { apiPostError({ name: e.name, @@ -709,27 +668,18 @@ export const MessageSubmitInterfaceComponent = ({ } await sendMessage( - sendToFeedbackEndpoint, message, attachment, isEncrypted ); - - if (requestFeedbackCheckboxChecked) { - await feedbackEncryptRoom(setE2EEState); - } }, [ activeSession.isFeedback, encrypted, - feedbackChatKey, - feedbackChatKeyId, - feedbackEncryptRoom, getTypedMarkdownMessage, isE2eeEnabled, key, keyID, preselectedFile, - requestFeedbackCheckboxChecked, sendEnquiry, sendMessage, setE2EEState, @@ -782,12 +732,6 @@ export const MessageSubmitInterfaceComponent = ({ userData ]); - const handleRequestFeedbackCheckbox = useCallback(() => { - setRequestFeedbackCheckboxChecked( - (requestFeedbackCheckboxChecked) => !requestFeedbackCheckboxChecked - ); - }, []); - const handleAttachmentSelect = useCallback(() => { const attachmentInput: any = attachmentInputRef.current; attachmentInput.click(); @@ -840,11 +784,10 @@ export const MessageSubmitInterfaceComponent = ({ const contact = getContact(activeSession); infoData = { isInfo: true, - infoHeadline: `${ - contact?.displayName || + infoHeadline: `${contact?.displayName || contact?.username || translate('sessionList.user.consultantUnknown') - } ${translate('consultant.absent.message')} `, + } ${translate('consultant.absent.message')} `, infoMessage: activeSession.consultant.absenceMessage }; } else if (activeInfo === INFO_TYPES.ATTACHMENT_SIZE_ERROR) { @@ -901,12 +844,6 @@ export const MessageSubmitInterfaceComponent = ({ !hasUserAuthority(AUTHORITIES.ASKER_DEFAULT, userData))) && !tenant?.settings?.featureAttachmentUploadDisabled; - const hasRequestFeedbackCheckbox = - hasUserAuthority(AUTHORITIES.USE_FEEDBACK, userData) && - !hasUserAuthority(AUTHORITIES.VIEW_ALL_PEER_SESSIONS, userData) && - activeSession.item.feedbackGroupId && - (activeSession.isGroup || !activeSession.isFeedback); - const bookingButton: ButtonItem = useMemo( () => ({ label: translate('message.submit.booking.buttonLabel'), @@ -923,7 +860,7 @@ export const MessageSubmitInterfaceComponent = ({ return null; }, []); - if (!e2EEReady || !feedbackE2EEReady) { + if (!e2EEReady) { return null; } @@ -953,24 +890,8 @@ export const MessageSubmitInterfaceComponent = ({ {activeInfo && } {!isLiveChatFinished && (
- {hasRequestFeedbackCheckbox && ( - - )}
@@ -1026,14 +947,7 @@ export const MessageSubmitInterfaceComponent = ({ handleKeyCommand={ handleEditorKeyCommand } - placeholder={ - hasRequestFeedbackCheckbox && - requestFeedbackCheckboxChecked - ? translate( - 'enquiry.write.input.placeholder.feedback.peer' - ) - : placeholder - } + placeholder={placeholder} stripPastedStyles={true} spellCheck={true} handleBeforeInput={() => diff --git a/src/components/session/SessionItemComponent.tsx b/src/components/session/SessionItemComponent.tsx index b835cf15e..ca2d96ffe 100644 --- a/src/components/session/SessionItemComponent.tsx +++ b/src/components/session/SessionItemComponent.tsx @@ -30,7 +30,6 @@ import { } from '../../globalState'; import { ConsultingTypeInterface } from '../../globalState/interfaces'; import './session.styles'; -import './session.yellowTheme.styles'; import { useDebouncedCallback } from 'use-debounce'; import { ReactComponent as ArrowDoubleDownIcon } from '../../resources/img/icons/arrow-double-down.svg'; import smoothScroll from './smoothScrollHelper'; @@ -85,7 +84,7 @@ export const SessionItemComponent = (props: SessionItemProps) => { useEffect(() => { setCanWriteMessage( type !== SESSION_LIST_TYPES.ENQUIRY || - hasUserAuthority(AUTHORITIES.VIEW_ALL_PEER_SESSIONS, userData) + hasUserAuthority(AUTHORITIES.VIEW_ALL_PEER_SESSIONS, userData) ); }, [type, userData]); @@ -322,7 +321,7 @@ export const SessionItemComponent = (props: SessionItemProps) => { if ( trackedErrorIndex >= 0 && acc[trackedErrorIndex][1].message === - collectedError.message + collectedError.message ) { if (timestamp > acc[trackedErrorIndex][0]) { acc.splice( @@ -356,17 +355,13 @@ export const SessionItemComponent = (props: SessionItemProps) => { return (
{ ))}
{newMessages > 0 && ( @@ -476,7 +470,7 @@ export const SessionItemComponent = (props: SessionItemProps) => { className={clsx( 'session__submit-interface', !isScrolledToBottom && - 'session__submit-interface--scrolled-up' + 'session__submit-interface--scrolled-up' )} placeholder={getPlaceholder()} typingUsers={props.typingUsers} diff --git a/src/components/session/session.yellowTheme.styles.scss b/src/components/session/session.yellowTheme.styles.scss deleted file mode 100644 index f41209a2c..000000000 --- a/src/components/session/session.yellowTheme.styles.scss +++ /dev/null @@ -1,15 +0,0 @@ -.session--yellowTheme { - background-color: var(--skin-color-secondary-light, $yellow-2); - .session__content { - background-color: var(--skin-color-secondary-light, $yellow-2); - } -} - -.sessionsListItem--yellowTheme { - .sessionsListItem__content { - background-color: var(--skin-color-secondary-light, $yellow-2); - } - &:after { - background-color: var(--skin-color-secondary-light, $yellow-2); - } -} diff --git a/src/resources/i18n/de/common.json b/src/resources/i18n/de/common.json index 89ba4390e..841bd29e3 100644 --- a/src/resources/i18n/de/common.json +++ b/src/resources/i18n/de/common.json @@ -374,7 +374,6 @@ "dataProtection": "Datenschutz", "dearchive": "Dearchivieren", "editGroupChat": "Chat-Einstellungen", - "feedback": "Feedback", "groupChatInfo": "Chat-Info", "imprint": "Impressum", "leaveGroupChat": "Chat verlassen", @@ -595,10 +594,6 @@ "placeholder": { "asker": "Schreiben Sie uns, was Sie bewegt.", "consultant": "Nachricht an Klient:in schreiben", - "feedback": { - "main": "Nachricht an Peer schreiben", - "peer": "Nachricht an Teamleiter:in schreiben" - }, "groupChat": "Nachricht schreiben" } }, @@ -1291,13 +1286,6 @@ "moderatorEndedTitle": "Videokonferenz wurde beendet: {{time}}", "moderatorStartedTitle": "Moderator:in {{name}} hat eine Videokonferenz gestartet" }, - "write": { - "peer": { - "checkbox": { - "label": "Feedback anfordern" - } - } - }, "yesterday": "Gestern" }, "navigation": { @@ -2120,9 +2108,6 @@ "restrictions": ".jpg, .png, .pdf, .docx, .xlsx bis maximal {{attachment_filesize}} MB" }, "empty": "Bitte wählen Sie eine Nachricht aus", - "feedback": { - "label": "Feedback" - }, "groupChat": { "consultant": { "prefix": "Moderatorin oder Moderator - " diff --git a/src/resources/i18n/en/common.json b/src/resources/i18n/en/common.json index 753cf5256..01000d99a 100644 --- a/src/resources/i18n/en/common.json +++ b/src/resources/i18n/en/common.json @@ -362,7 +362,6 @@ "dataProtection": "Data protection", "dearchive": "Dearchive", "editGroupChat": "Chat settings", - "feedback": "Feedback", "groupChatInfo": "Chat info", "imprint": "Imprint", "leaveGroupChat": "Leave chat", @@ -583,10 +582,6 @@ "placeholder": { "asker": "Write us what moves you.", "consultant": "Write a message to client", - "feedback": { - "main": "Send a message to Peer", - "peer": "Send a message to Teamleader" - }, "groupChat": "Write message" } }, @@ -1269,13 +1264,6 @@ "today": "Today", "tomorrow": "Tomorrow", "unread": "unread", - "write": { - "peer": { - "checkbox": { - "label": "Request feedback" - } - } - }, "yesterday": "Yesterday" }, "navigation": { @@ -2001,9 +1989,6 @@ "restrictions": ".jpg, .png, .pdf, .docx, .xlsx up to a maximum of {{attachment_filesize}}MB" }, "empty": "Please select a message", - "feedback": { - "label": "Feedback" - }, "groupChat": { "consultant": { "prefix": "Moderator - " From 4c8aba1fd20f3de39b1a58d9391c4e7dd06982d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Tue, 23 Jul 2024 15:25:13 +0200 Subject: [PATCH 08/49] feat(session-header,-menu-and-copy-message): rm feedback functionality from session header, menu and copy message --- .../fixtures/service.users.sessions.room.json | 1 - cypress/support/sessions.ts | 4 - src/components/message/CopyMessage.tsx | 54 --------- .../message/MessageItemComponent.tsx | 7 -- src/components/message/MessageMetaData.tsx | 1 - .../messageSubmitInterfaceComponent.tsx | 3 - .../sessionHeader/SessionHeaderComponent.tsx | 113 +++++++----------- .../sessionHeader/sessionHeader.styles.scss | 51 +------- .../sessionHeader.yellowTheme.styles.scss | 9 -- src/components/sessionMenu/SessionMenu.tsx | 44 +------ .../SessionListItemComponent.tsx | 16 +-- src/generated/userservice.d.ts | 12 -- src/globalState/helpers/stateHelpers.ts | 9 +- .../interfaces/SessionsDataInterface.ts | 1 - 14 files changed, 52 insertions(+), 273 deletions(-) delete mode 100644 src/components/message/CopyMessage.tsx delete mode 100644 src/components/sessionHeader/sessionHeader.yellowTheme.styles.scss diff --git a/cypress/fixtures/service.users.sessions.room.json b/cypress/fixtures/service.users.sessions.room.json index 83e8dc8ad..09d009609 100644 --- a/cypress/fixtures/service.users.sessions.room.json +++ b/cypress/fixtures/service.users.sessions.room.json @@ -7,7 +7,6 @@ "postcode": "12345", "language": "de", "groupId": "someGroupId", - "feedbackGroupId": null, "isPeerChat": false, "askerRcId": "askerRcId", "e2eLastMessage": null, diff --git a/cypress/support/sessions.ts b/cypress/support/sessions.ts index a8bbf0202..692afa88b 100644 --- a/cypress/support/sessions.ts +++ b/cypress/support/sessions.ts @@ -43,13 +43,11 @@ export const generateConsultantSession = ({ status, postcode: 12345, groupId: rcGroupId, - feedbackGroupId: null, askerRcId: 'askerRcId', lastMessage: 'lastMessage', messageDate: 1606900238, messagesRead: messagesRead === undefined ? true : messagesRead, isTeamSession: true, - isFeedbackSession: false, isPeerChat: false, attachment: null, registrationType: 'REGISTERED', @@ -111,13 +109,11 @@ export const generateAskerSession = ({ status: 2, postcode: 12345, groupId: rcGroupId, - feedbackGroupId: 'feedbackGroupId1', askerRcId: 'askerRcId1', lastMessage: null, messageDate: null, messagesRead: messagesRead === undefined ? true : messagesRead, isTeamSession: isTeamSession === undefined ? true : isTeamSession, - isFeedbackSession: false, isPeerChat: false, attachment: null, registrationType: 'REGISTERED', diff --git a/src/components/message/CopyMessage.tsx b/src/components/message/CopyMessage.tsx deleted file mode 100644 index 08046986d..000000000 --- a/src/components/message/CopyMessage.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import * as React from 'react'; -import { useEffect, useState } from 'react'; -import { ReactComponent as CopyIcon } from '../../resources/img/icons/documents.svg'; -import { ReactComponent as CheckmarkIcon } from '../../resources/img/icons/checkmark.svg'; -import { copyTextToClipboard } from '../../utils/clipboardHelpers'; -import { useTranslation } from 'react-i18next'; - -interface CopyMessageProps { - right: Boolean; - message: string; -} - -export const CopyMessage = (props: CopyMessageProps) => { - const { t: translate } = useTranslation(); - const [messageCopied, setMessageCopied] = useState(false); - let timeoutId: number = null; - - useEffect(() => { - return () => { - // Unset timeout on unmounting to prevent state change on unmounted components - if (timeoutId) window.clearTimeout(timeoutId); - }; - }); - - const copyText = async (content) => { - await copyTextToClipboard(content, () => { - setMessageCopied(true); - timeoutId = window.setTimeout(() => setMessageCopied(false), 3000); - }); - }; - - return ( -
copyText(props.message)} - > - - -
- ); -}; diff --git a/src/components/message/MessageItemComponent.tsx b/src/components/message/MessageItemComponent.tsx index d4dab421e..486d9f2a2 100644 --- a/src/components/message/MessageItemComponent.tsx +++ b/src/components/message/MessageItemComponent.tsx @@ -17,7 +17,6 @@ import { } from '../../globalState/interfaces'; import { isUserModerator, SESSION_LIST_TYPES } from '../session/sessionHelpers'; import { MessageMetaData } from './MessageMetaData'; -import { CopyMessage } from './CopyMessage'; import { MessageDisplayName } from './MessageDisplayName'; import { markdownToDraft } from 'markdown-draft-js'; import { stateToHTML } from 'draft-js-export-html'; @@ -484,12 +483,6 @@ export const MessageItemComponent = ({ hasRenderedMessage={hasRenderedMessage} /> ))} - {activeSession.isFeedback && ( - - )}
); diff --git a/src/components/message/MessageMetaData.tsx b/src/components/message/MessageMetaData.tsx index 8f82c8e45..03b3a5b2e 100644 --- a/src/components/message/MessageMetaData.tsx +++ b/src/components/message/MessageMetaData.tsx @@ -28,7 +28,6 @@ export const MessageMetaData = (props: MessageMetaDataProps) => { if ( hasUserAuthority(AUTHORITIES.ASKER_DEFAULT, userData) || hasUserAuthority(AUTHORITIES.ANONYMOUS_DEFAULT, userData) || - (!activeSession.isGroup && activeSession.isFeedback) || props.isReadStatusDisabled ) { return null; diff --git a/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx b/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx index f99d30f8d..abf8bf813 100644 --- a/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx +++ b/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx @@ -214,7 +214,6 @@ export const MessageSubmitInterfaceComponent = ({ // This loads the keys for current activeSession.rid which is already set: // to groupChat.groupId on group chats // to session.groupId on session chats - // to session.feebackGroupId on feedback chats const { keyID, key, @@ -610,7 +609,6 @@ export const MessageSubmitInterfaceComponent = ({ [ activeSession.isGroup, activeSession.isLive, - activeSession.item.feedbackGroupId, activeSession.item.id, activeSession.rid, cleanupAttachment, @@ -673,7 +671,6 @@ export const MessageSubmitInterfaceComponent = ({ isEncrypted ); }, [ - activeSession.isFeedback, encrypted, getTypedMarkdownMessage, isE2eeEnabled, diff --git a/src/components/sessionHeader/SessionHeaderComponent.tsx b/src/components/sessionHeader/SessionHeaderComponent.tsx index 9b360487d..882e9b891 100644 --- a/src/components/sessionHeader/SessionHeaderComponent.tsx +++ b/src/components/sessionHeader/SessionHeaderComponent.tsx @@ -29,7 +29,6 @@ import { } from '../profile/profileHelpers'; import { ReactComponent as BackIcon } from '../../resources/img/icons/arrow-left.svg'; import './sessionHeader.styles'; -import './sessionHeader.yellowTheme.styles'; import { useSearchParam } from '../../hooks/useSearchParams'; import { useTranslation } from 'react-i18next'; import { GroupChatHeader } from './GroupChatHeader'; @@ -62,8 +61,8 @@ export const SessionHeaderComponent = (props: SessionHeaderProps) => { const preparedUserSessionData = hasUserAuthority(AUTHORITIES.CONSULTANT_DEFAULT, userData) && - userSessionData && - !activeSession.isLive + userSessionData && + !activeSession.isLive ? convertUserDataObjectToArray(userSessionData) : null; const translateBase = getUserDataTranslateBase( @@ -85,9 +84,8 @@ export const SessionHeaderComponent = (props: SessionHeaderProps) => { }, [isSubscriberFlyoutOpen]); const sessionView = getViewPathForType(type); - const userProfileLink = `/sessions/consultant/${sessionView}/${ - activeSession.item.groupId - }/${activeSession.item.id}/userProfile${getSessionListTab()}`; + const userProfileLink = `/sessions/consultant/${sessionView}/${activeSession.item.groupId + }/${activeSession.item.id}/userProfile${getSessionListTab()}`; const handleBackButton = () => { mobileListView(); @@ -131,35 +129,6 @@ export const SessionHeaderComponent = (props: SessionHeaderProps) => { ); } - if (activeSession.isFeedback) { - return ( -
-
- - - -
-

{translate('session.feedback.label')}

-
-
-
- {activeSession.user.username ? ( -
- {activeSession.user.username} -
- ) : null} -
-
- ); - } - return (
@@ -181,12 +150,12 @@ export const SessionHeaderComponent = (props: SessionHeaderProps) => { AUTHORITIES.ANONYMOUS_DEFAULT, userData )) && ( -

- {contact?.displayName || - contact?.username || - translate('sessionList.user.consultantUnknown')} -

- )} +

+ {contact?.displayName || + contact?.username || + translate('sessionList.user.consultantUnknown')} +

+ )} {hasUserAuthority( AUTHORITIES.CONSULTANT_DEFAULT, userData @@ -221,18 +190,18 @@ export const SessionHeaderComponent = (props: SessionHeaderProps) => { {(hasUserAuthority(AUTHORITIES.ASKER_DEFAULT, userData) || hasUserAuthority(AUTHORITIES.CONSULTANT_DEFAULT, userData)) && ( -
- {!activeSession.agency ? ( -
- {topic?.name || ''} -
- ) : null} - {preparedUserSessionData - ? preparedUserSessionData.map((item, index) => +
+ {!activeSession.agency ? ( +
+ {topic?.name || ''} +
+ ) : null} + {preparedUserSessionData + ? preparedUserSessionData.map((item, index) => item.value && - !( - item.type === 'age' && item.value === 'null' - ) ? ( + !( + item.type === 'age' && item.value === 'null' + ) ? (
{
) : null ) - : null} - {activeSession.agency?.name && ( -
- {' '} - {translate( - [ - `agency.${activeSession.agency.id}.name`, - activeSession.agency.name - ], - { ns: 'agencies' } - )}{' '} -
- )} - {activeSession.agency && ( -
- {translate('consultant.jobTitle')} -
- )} -
- )} + : null} + {activeSession.agency?.name && ( +
+ {' '} + {translate( + [ + `agency.${activeSession.agency.id}.name`, + activeSession.agency.name + ], + { ns: 'agencies' } + )}{' '} +
+ )} + {activeSession.agency && ( +
+ {translate('consultant.jobTitle')} +
+ )} +
+ )}
); }; diff --git a/src/components/sessionHeader/sessionHeader.styles.scss b/src/components/sessionHeader/sessionHeader.styles.scss index da3791554..491f14422 100644 --- a/src/components/sessionHeader/sessionHeader.styles.scss +++ b/src/components/sessionHeader/sessionHeader.styles.scss @@ -57,8 +57,7 @@ $iconSize: 24px; } } - &__backButton, - &__feedbackBackButton { + &__backButton { svg { width: $iconSize; height: $iconSize; @@ -78,14 +77,6 @@ $iconSize: 24px; } } - &__feedbackBackButton { - padding-right: 10px; - - @include breakpoint($fromLarge) { - display: block; - } - } - &__username { cursor: pointer; overflow: hidden; @@ -98,6 +89,7 @@ $iconSize: 24px; &--deactivate { cursor: unset; } + a { text-decoration: none; } @@ -124,32 +116,6 @@ $iconSize: 24px; margin-right: 20px; } - &__feedbackButton { - display: none; - - @include breakpoint($fromLarge) { - display: inline-block; - } - - &--active .button__item { - transform: scale(1.2); - animation: yellowThemeHighlight 1.5s forwards; - - @keyframes yellowThemeHighlight { - 0% { - background-color: $yellow-3; - } - 20% { - background-color: $yellow-4; - } - 100% { - background-color: $yellow-3; - } - } - } - } - - &__feedbackMetaInfo, &__metaInfo { width: 100%; max-width: $xlarge; @@ -174,10 +140,8 @@ $iconSize: 24px; } &--red { - color: var( - --skin-color-primary-contrast-safe, - $primary - ) !important; + color: var(--skin-color-primary-contrast-safe, + $primary) !important; text-transform: uppercase; } @@ -291,9 +255,4 @@ $iconSize: 24px; } } } - &__feedbackMetaInfo { - @include breakpoint($fromLarge) { - padding-left: 36px; - } - } -} +} \ No newline at end of file diff --git a/src/components/sessionHeader/sessionHeader.yellowTheme.styles.scss b/src/components/sessionHeader/sessionHeader.yellowTheme.styles.scss deleted file mode 100644 index 449e576fe..000000000 --- a/src/components/sessionHeader/sessionHeader.yellowTheme.styles.scss +++ /dev/null @@ -1,9 +0,0 @@ -.session--yellowTheme { - .sessionInfo { - background-color: $yellow-1; - - @include breakpoint($fromLarge) { - background-color: var(--skin-color-secondary-light, $yellow-2); - } - } -} diff --git a/src/components/sessionMenu/SessionMenu.tsx b/src/components/sessionMenu/SessionMenu.tsx index d2b19ed51..58a6bca4e 100644 --- a/src/components/sessionMenu/SessionMenu.tsx +++ b/src/components/sessionMenu/SessionMenu.tsx @@ -356,18 +356,6 @@ export const SessionMenu = (props: SessionMenuProps) => { ) }; - const buttonFeedback: ButtonItem = { - type: BUTTON_TYPES.SMALL_ICON, - smallIconBackgroundColor: 'yellow', - icon: ( - - ), - label: translate('chatFlyout.feedback') - }; - const hasVideoCallFeatures = () => hasUserAuthority(AUTHORITIES.CONSULTANT_DEFAULT, userData) && activeSession.isSession && @@ -440,20 +428,6 @@ export const SessionMenu = (props: SessionMenuProps) => {
)} - {!hasUserAuthority(AUTHORITIES.ASKER_DEFAULT, userData) && - type !== SESSION_LIST_TYPES.ENQUIRY && - activeSession.item.feedbackGroupId && ( - -
{requestOverlayVisible && ( diff --git a/src/components/session/AcceptLiveChatView.tsx b/src/components/session/AcceptLiveChatView.tsx index d50bc87cc..977f3c6da 100644 --- a/src/components/session/AcceptLiveChatView.tsx +++ b/src/components/session/AcceptLiveChatView.tsx @@ -76,15 +76,13 @@ export const AcceptLiveChatView = ({ semanticLevel="3" text={`${translate( 'enquiry.anonymous.infoLabel.start' - )}${ - getContact(activeSession)?.username || - translate('sessionList.user.consultantUnknown') - }${translate('enquiry.anonymous.infoLabel.end')}`} + )}${getContact(activeSession)?.username || + translate('sessionList.user.consultantUnknown') + }${translate('enquiry.anonymous.infoLabel.end')}`} />
{ - const { t: translate } = useTranslation(); - const history = useHistory(); - - const { activeSession } = useContext(ActiveSessionContext); - const { userData } = useContext(UserDataContext); - const { path: listPath } = useContext(SessionTypeContext); - const { consultantList, setConsultantList } = useContext( - ConsultantListContext - ); - const [overlayActive, setOverlayActive] = useState(false); - const [overlayItem, setOverlayItem] = useState({}); - const [selectedOption, setSelectedOption] = useState(); - const [isRequestInProgress, setIsRequestInProgress] = useState(false); - - const { isE2eeEnabled } = useContext(E2EEContext); - - const { addNewUsersToEncryptedRoom, encryptRoom } = useE2EE( - activeSession.item.groupId - ); - - const { - visible: e2eeOverlayVisible, - setState: setE2EEState, - overlay: e2eeOverlay - } = useE2EEViewElements(); - - const { visible: requestOverlayVisible, overlay: requestOverlay } = - useTimeoutOverlay( - isRequestInProgress, - null, - userData.userId === selectedOption - ? translate('session.assignSelf.inProgress') - : translate('session.assignOther.inProgress'), - null, - 0 - ); - - const sessionListTab = useSearchParam('sessionListTab'); - const getSessionListTab = () => - `${sessionListTab ? `?sessionListTab=${sessionListTab}` : ''}`; - - const assignOtherOverlay: OverlayItem = useMemo( - () => ({ - svg: CheckIcon, - headline: translate('session.assignOther.overlay.headline.2'), - buttonSet: [ - { - label: translate('session.assignOther.button.label'), - function: OVERLAY_FUNCTIONS.CLOSE, - functionArgs: { - gotoOverview: true - }, - type: BUTTON_TYPES.AUTO_CLOSE - } - ] - }), - [translate] - ); - - const assignSelfOverlay: OverlayItem = useMemo( - () => ({ - svg: CheckIcon, - headline: translate('session.assignSelf.overlay.headline1'), - buttonSet: [ - { - label: translate('session.assignSelf.button1.label'), - function: OVERLAY_FUNCTIONS.REDIRECT, - type: BUTTON_TYPES.PRIMARY - }, - { - label: translate('session.assignSelf.button2.label'), - function: OVERLAY_FUNCTIONS.CLOSE, - type: BUTTON_TYPES.SECONDARY - } - ] - }), - [translate] - ); - - const assignSession: OverlayItem = useMemo( - () => ({ - headline: translate('session.assignSelf.overlay.headline2'), - copy: translate('session.assignSelf.overlay.subtitle'), - buttonSet: [ - { - label: translate( - 'session.assignSelf.overlay.button.cancel' - ), - function: OVERLAY_FUNCTIONS.CLOSE, - type: BUTTON_TYPES.SECONDARY - }, - { - label: translate( - 'session.assignSelf.overlay.button.assign' - ), - function: 'ASSIGN', - type: BUTTON_TYPES.PRIMARY - } - ] - }), - [translate] - ); - - const alreadyAssignedSession: OverlayItem = useMemo( - () => ({ - headline: translate('session.alreadyAssigned.overlay.headline'), - buttonSet: [ - { - label: translate( - 'session.alreadyAssigned.overlay.button.cancel' - ), - function: OVERLAY_FUNCTIONS.CLOSE, - type: BUTTON_TYPES.SECONDARY - }, - { - label: translate( - 'session.alreadyAssigned.overlay.button.redirect' - ), - function: OVERLAY_FUNCTIONS.REDIRECT, - type: BUTTON_TYPES.PRIMARY - } - ] - }), - [translate] - ); - - useEffect(() => { - const agencyId = activeSession.item.agencyId.toString(); - if (consultantList && consultantList.length <= 0) { - apiGetAgencyConsultantList(agencyId) - .then((response) => { - const consultants = - prepareConsultantDataForSelect(response); - setConsultantList(consultants); - }) - .catch((error) => { - console.log(error); - }); - } - }, []); // eslint-disable-line react-hooks/exhaustive-deps - - const initOverlays = useCallback(() => { - const overlay = - userData.userId === selectedOption - ? assignSelfOverlay - : assignOtherOverlay; - setOverlayActive(true); - setOverlayItem(overlay); - }, [ - assignOtherOverlay, - assignSelfOverlay, - selectedOption, - userData.userId - ]); - - const handleE2EEAssign = async (sessionId, userId) => { - if (isE2eeEnabled) { - try { - // If already encrypted this will be skipped - await encryptRoom(setE2EEState); - // If room was already encrypted add new users - await addNewUsersToEncryptedRoom(); - await apiDeleteUserFromRoom(sessionId, userId); - } catch (e) { - console.log('error encrypting new user key'); - } - } - }; - - const handleDatalistSelect = (selectedOption) => { - if ( - userData.userId === activeSession?.consultant?.id && - userData.userId === selectedOption.value - ) { - setOverlayItem(alreadyAssignedSession); - } else { - setOverlayItem(assignSession); - } - setOverlayActive(true); - setSelectedOption(selectedOption.value); - }; - - const handleOverlayAction = ( - buttonFunction: string, - buttonArgs: { [key: string]: any } - ) => { - switch (buttonFunction) { - case 'ASSIGN': - setIsRequestInProgress(true); - apiSessionAssign(activeSession.item.id, selectedOption) - .then(() => - handleE2EEAssign(activeSession.item.id, userData.userId) - ) - .then(() => initOverlays()) - .catch((error) => { - if (error === FETCH_ERRORS.CONFLICT) { - return null; - } else console.log(error); - }) - .finally(() => setIsRequestInProgress(false)); - break; - case OVERLAY_FUNCTIONS.REDIRECT: - setOverlayItem(null); - setOverlayActive(false); - history.push( - `/sessions/consultant/sessionView/${activeSession.item.groupId}/${activeSession.item.id}` - ); - break; - case OVERLAY_FUNCTIONS.CLOSE: - if (buttonArgs?.gotoOverview) { - history.push(listPath + getSessionListTab()); - } - setOverlayItem(null); - setOverlayActive(false); - break; - } - }; - - return ( -
- - {requestOverlayVisible && ( - - )} - {e2eeOverlayVisible && ( - - )} - {overlayActive && ( - - )} -
- ); -}; From 18b687670d7b91c7a2f9d0a65fe51d47b92d1dd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Thu, 25 Jul 2024 11:54:56 +0200 Subject: [PATCH 12/49] feat(sessionList-filter): removed sessionList filter / feedback filter --- src/api/apiGetConsultantSessionList.ts | 33 ++--- src/components/sessionsList/SessionsList.tsx | 123 ++++--------------- src/resources/i18n/de/common.json | 8 -- src/resources/i18n/en/common.json | 8 -- 4 files changed, 38 insertions(+), 134 deletions(-) diff --git a/src/api/apiGetConsultantSessionList.ts b/src/api/apiGetConsultantSessionList.ts index a21f2f6fe..bf7b50547 100644 --- a/src/api/apiGetConsultantSessionList.ts +++ b/src/api/apiGetConsultantSessionList.ts @@ -7,15 +7,12 @@ import { import { ListItemsResponseInterface } from '../globalState/interfaces'; import { FETCH_ERRORS, FETCH_METHODS, fetchData } from './fetchData'; -export const INITIAL_FILTER: string = 'all'; -export const FILTER_FEEDBACK: string = 'feedback'; export const INITIAL_OFFSET: number = 0; export const SESSION_COUNT: number = 15; export const TIMEOUT: number = 10000; export interface ApiGetConsultantSessionListInterface { type: SESSION_LIST_TYPES; - filter?: typeof INITIAL_FILTER | typeof FILTER_FEEDBACK; offset?: number; sessionListTab?: string; count?: number; @@ -24,7 +21,6 @@ export interface ApiGetConsultantSessionListInterface { export const apiGetConsultantSessionList = async ({ type, - filter = INITIAL_FILTER, offset = INITIAL_OFFSET, sessionListTab, count = SESSION_COUNT, @@ -33,25 +29,22 @@ export const apiGetConsultantSessionList = async ({ const isTeamSession: boolean = type === SESSION_LIST_TYPES.TEAMSESSION; let url: string; if (isTeamSession) { - url = `${ - sessionListTab === SESSION_LIST_TAB_ARCHIVE - ? `${endpoints.teamSessionsBase}${SESSION_LIST_TAB_ARCHIVE}?` - : `${endpoints.consultantTeamSessions}` - }`; + url = `${sessionListTab === SESSION_LIST_TAB_ARCHIVE + ? `${endpoints.teamSessionsBase}${SESSION_LIST_TAB_ARCHIVE}?` + : `${endpoints.consultantTeamSessions}` + }`; } else if (type === SESSION_LIST_TYPES.MY_SESSION) { - url = `${ - sessionListTab === SESSION_LIST_TAB_ARCHIVE - ? `${endpoints.myMessagesBase}${SESSION_LIST_TAB_ARCHIVE}?` - : `${endpoints.consultantSessions}` - }`; + url = `${sessionListTab === SESSION_LIST_TAB_ARCHIVE + ? `${endpoints.myMessagesBase}${SESSION_LIST_TAB_ARCHIVE}?` + : `${endpoints.consultantSessions}` + }`; } else { - url = `${endpoints.consultantEnquiriesBase}${ - sessionListTab && sessionListTab === SESSION_LIST_TAB_ANONYMOUS - ? `${SESSION_LIST_TAB_ANONYMOUS}` - : 'registered' - }?`; + url = `${endpoints.consultantEnquiriesBase}${sessionListTab && sessionListTab === SESSION_LIST_TAB_ANONYMOUS + ? `${SESSION_LIST_TAB_ANONYMOUS}` + : 'registered' + }?`; } - url = url + `count=${count}&filter=${filter}&offset=${offset}`; + url = url + `count=${count}&filter=all&offset=${offset}`; return fetchData({ url: url, diff --git a/src/components/sessionsList/SessionsList.tsx b/src/components/sessionsList/SessionsList.tsx index f35b6807b..9739cb330 100644 --- a/src/components/sessionsList/SessionsList.tsx +++ b/src/components/sessionsList/SessionsList.tsx @@ -39,15 +39,12 @@ import { } from '../../globalState'; import { ListItemInterface, STATUS_EMPTY } from '../../globalState/interfaces'; import { apiPatchUserData } from '../../api/apiPatchUserData'; -import { SelectDropdown, SelectDropdownItem } from '../select/SelectDropdown'; import { SessionListItemComponent } from '../sessionsListItem/SessionListItemComponent'; import { SessionsListSkeleton } from '../sessionsListItem/SessionsListItemSkeleton'; import { apiGetAskerSessionList, apiGetConsultantSessionList, FETCH_ERRORS, - FILTER_FEEDBACK, - INITIAL_FILTER, SESSION_COUNT } from '../../api'; import { Button } from '../button/Button'; @@ -112,9 +109,6 @@ export const SessionsList = ({ unsubscribe, ready: socketReady } = useContext(RocketChatContext); - const [filter, setFilter] = useState< - typeof INITIAL_FILTER | typeof FILTER_FEEDBACK - >(INITIAL_FILTER); const sessionListTab = useSearchParam('sessionListTab'); @@ -160,7 +154,6 @@ export const SessionsList = ({ return apiGetConsultantSessionList({ type, - filter, offset, sessionListTab: sessionListTab, count: count ?? SESSION_COUNT, @@ -199,13 +192,13 @@ export const SessionsList = ({ return { sessions, total }; }); }, - [filter, sessionListTab, type] + [sessionListTab, type] ); useLiveChatWatcher( !isLoading && - type === SESSION_LIST_TYPES.ENQUIRY && - sessionListTab === SESSION_LIST_TAB_ANONYMOUS, + type === SESSION_LIST_TYPES.ENQUIRY && + sessionListTab === SESSION_LIST_TAB_ANONYMOUS, getConsultantSessionList, currentOffset ); @@ -219,15 +212,15 @@ export const SessionsList = ({ ); const firstItemId = document.querySelector('.sessionsListItem') ? document - .querySelector('.sessionsListItem') - .getAttribute('data-group-id') + .querySelector('.sessionsListItem') + .getAttribute('data-group-id') : null; const lastItemId = wrapper.lastElementChild.querySelector( '.sessionsListItem' ) ? wrapper.lastElementChild - .querySelector('.sessionsListItem') - .getAttribute('data-group-id') + .querySelector('.sessionsListItem') + .getAttribute('data-group-id') : null; if ( initialId.current !== firstItemId && @@ -374,7 +367,7 @@ export const SessionsList = ({ sessionTypes.indexOf(sessionType) < 0 || (sessionType === SESSION_TYPE_ARCHIVED && sessionListTab !== - SESSION_LIST_TAB_ARCHIVE) || + SESSION_LIST_TAB_ARCHIVE) || (sessionType !== SESSION_TYPE_ARCHIVED && sessionListTab === SESSION_LIST_TAB_ARCHIVE) ) { @@ -568,27 +561,6 @@ export const SessionsList = ({ unsubscribe ]); - const [showFilter, setShowFilter] = useState(false); - - useEffect(() => { - const showFilter = - type !== SESSION_LIST_TYPES.ENQUIRY && - sessionListTab !== SESSION_LIST_TAB_ARCHIVE && - ((hasUserAuthority(AUTHORITIES.VIEW_ALL_PEER_SESSIONS, userData) && - type === SESSION_LIST_TYPES.TEAMSESSION) || - (hasUserAuthority(AUTHORITIES.USE_FEEDBACK, userData) && - !hasUserAuthority( - AUTHORITIES.VIEW_ALL_PEER_SESSIONS, - userData - ))); - - setShowFilter(showFilter); - - if (!showFilter) { - setFilter(INITIAL_FILTER); - } - }, [sessionListTab, type, userData]); - const loadMoreSessions = useCallback(() => { setIsLoading(true); getConsultantSessionList(currentOffset + SESSION_COUNT) @@ -633,48 +605,11 @@ export const SessionsList = ({ totalItems ]); - const handleSelect = (selectedOption) => { - setCurrentOffset(0); - setFilter(selectedOption.value); - history.push(listPath); - }; - const handleReloadButton = useCallback(() => { setIsReloadButtonVisible(false); loadMoreSessions(); }, [loadMoreSessions]); - const selectedOptionsSet = [ - { - value: FILTER_FEEDBACK, - label: hasUserAuthority( - AUTHORITIES.VIEW_ALL_PEER_SESSIONS, - userData - ) - ? translate('sessionList.filter.option.feedbackMain') - : translate('sessionList.filter.option.feedbackPeer') - }, - { - value: INITIAL_FILTER, - label: translate('sessionList.filter.option.all') - } - ]; - - const preSelectedOption = - selectedOptionsSet.find((option) => option.value === filter) ?? - selectedOptionsSet[1]; - - const selectDropdown: SelectDropdownItem = { - id: 'listFilterSelect', - selectedOptions: selectedOptionsSet, - handleDropdownSelect: handleSelect, - selectInputLabel: translate('sessionList.filter.placeholder'), - useIconOption: false, - isSearchable: false, - menuPlacement: 'bottom', - defaultValue: preSelectedOption - }; - const showEnquiryTabs = useMemo(() => { return ( hasUserAuthority(AUTHORITIES.CONSULTANT_DEFAULT, userData) && @@ -829,7 +764,7 @@ export const SessionsList = ({ return (
- {(showFilter || showEnquiryTabs || showSessionListTabs) && ( + {(showEnquiryTabs || showSessionListTabs) && (
{showEnquiryTabs && (
@@ -880,11 +815,10 @@ export const SessionsList = ({ 'sessionsList__tabs--active': !sessionListTab })} - to={`/sessions/consultant/${ - type === SESSION_LIST_TYPES.TEAMSESSION - ? 'teamSessionView' - : 'sessionView' - }`} + to={`/sessions/consultant/${type === SESSION_LIST_TYPES.TEAMSESSION + ? 'teamSessionView' + : 'sessionView' + }`} onKeyDown={(e) => handleKeyDownTabs(e)} ref={(el) => (ref_tab_first.current = el)} tabIndex={0} @@ -903,11 +837,10 @@ export const SessionsList = ({ sessionListTab === SESSION_LIST_TAB_ARCHIVE })} - to={`/sessions/consultant/${ - type === SESSION_LIST_TYPES.TEAMSESSION - ? 'teamSessionView' - : 'sessionView' - }?sessionListTab=${SESSION_LIST_TAB_ARCHIVE}`} + to={`/sessions/consultant/${type === SESSION_LIST_TYPES.TEAMSESSION + ? 'teamSessionView' + : 'sessionView' + }?sessionListTab=${SESSION_LIST_TAB_ARCHIVE}`} onKeyDown={(e) => handleKeyDownTabs(e)} ref={(el) => (ref_tab_second.current = el)} tabIndex={-1} @@ -923,11 +856,6 @@ export const SessionsList = ({
)} - {showFilter && ( -
- -
- )}
)}
)}
0 - ? '' - : 'sessionsList__itemsWrapper--centered' - }`} + ? '' + : 'sessionsList__itemsWrapper--centered' + }`} data-cy="sessions-list-items-wrapper" role="tablist" > @@ -988,9 +915,9 @@ export const SessionsList = ({ defaultLanguage } itemRef={(el) => - (ref_list_array.current[ - index - ] = el) + (ref_list_array.current[ + index + ] = el) } handleKeyDownLisItemContent={( e diff --git a/src/resources/i18n/de/common.json b/src/resources/i18n/de/common.json index e82b18126..406f9f012 100644 --- a/src/resources/i18n/de/common.json +++ b/src/resources/i18n/de/common.json @@ -2193,14 +2193,6 @@ "mySessions": "Sie haben zurzeit keine aktiven Beratungen", "teamSessions": "Ihr Team hat keine aktiven Beratungen", }, - "filter": { - "option": { - "all": "Alle Beratungen", - "feedbackMain": "Feedback benötigt", - "feedbackPeer": "Feedback vorhanden" - }, - "placeholder": "Filter" - }, "preview": { "anonymous": { "tab": "Live-Chat Anfragen" diff --git a/src/resources/i18n/en/common.json b/src/resources/i18n/en/common.json index ff43397bb..79eeb9bfb 100644 --- a/src/resources/i18n/en/common.json +++ b/src/resources/i18n/en/common.json @@ -2074,14 +2074,6 @@ "mySessions": "You currently have no active consultations", "teamSessions": "Your team has no active consultations" }, - "filter": { - "option": { - "all": "All consultations", - "feedbackMain": "Feedback needed", - "feedbackPeer": "Feedback available" - }, - "placeholder": "Filter" - }, "preview": { "anonymous": { "tab": "Live chat requests" From 65fccb22e28a73250cf9b46eed9b8d63e8405a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Thu, 25 Jul 2024 11:56:45 +0200 Subject: [PATCH 13/49] feat(cypress-fixtures): remove consulting type u25 --- .../fixtures/service.consultingtypes.u25.json | 146 ------------------ 1 file changed, 146 deletions(-) delete mode 100644 cypress/fixtures/service.consultingtypes.u25.json diff --git a/cypress/fixtures/service.consultingtypes.u25.json b/cypress/fixtures/service.consultingtypes.u25.json deleted file mode 100644 index e7e6ca018..000000000 --- a/cypress/fixtures/service.consultingtypes.u25.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "id": 1, - "titles": { - "default": "U25", - "short": "U25", - "long": "Beratung für suizidgefährdete junge Menschen [U25]", - "welcome": "Willkommen bei der U25-Hilfe", - "registrationDropdown": "Beratung für suizidgefährdete junge Menschen [U25]" - }, - "urls": { - "requiredAidMissingRedirectUrl": "https://www.u25-deutschland.de/helpmail/" - }, - "registration": { - "minPostcodeSize": 5, - "autoSelectAgency": true, - "autoSelectPostcode": true, - "notes": { - "password": "Bitte notiere Dir Deine Zugangsdaten – ein Passwort-Reset ist nicht möglich!" - }, - "mandatoryFields": { - "age": true, - "state": true - } - }, - "isSubsequentRegistrationAllowed": false, - "isAnonymousConversationAllowed": false, - "isSetEmailAllowed": false, - "slug": "u25", - "languageFormal": false, - "lockedAgencies": false, - "whiteSpot": { - "whiteSpotAgencyAssigned": false - }, - "groupChat": { - "isGroupChat": false, - "groupChatRules": [] - }, - "consultantBoundedToConsultingType": false, - "welcomeMessage": { - "sendWelcomeMessage": true, - "welcomeMessageText": "Lorem ipsum" - }, - "sendFurtherStepsMessage": false, - "sendSaveSessionDataMessage": true, - "sessionDataInitializing": { - "addictiveDrugs": false, - "age": true, - "gender": true, - "relation": false, - "state": true - }, - "roles": { - "consultant": { - "main": ["consultant", "u25-consultant", "u25-main-consultant"], - "peer": ["consultant", "u25-consultant"] - } - }, - "notifications": { - "teamSessions": { - "newMessage": { - "allTeamConsultants": false - } - } - }, - "showAskerProfile": true, - "requiredComponents": { - "age": { - "isEnabled": true, - "options": [ - { - "value": "0", - "label": "unter 12" - }, - { - "value": "1", - "label": "12" - }, - { - "value": "2", - "label": "13" - }, - { - "value": "3", - "label": "14" - }, - { - "value": "4", - "label": "15" - }, - { - "value": "5", - "label": "16" - }, - { - "value": "6", - "label": "17" - }, - { - "value": "7", - "label": "18" - }, - { - "value": "8", - "label": "19" - }, - { - "value": "9", - "label": "20" - }, - { - "value": "10", - "label": "21" - }, - { - "value": "11", - "label": "22" - }, - { - "value": "12", - "label": "23" - }, - { - "value": "13", - "label": "24" - }, - { - "value": "14", - "label": "25" - }, - { - "value": "15", - "label": "über 25" - } - ] - }, - "state": { - "isEnabled": true - } - }, - "welcomeScreen": { - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Du bleibst anonym und erhältst kostenfreie Beratung und Hilfe" - } - } -} From 2e6e119cf9cbe341f409ddc274adaed2b734e3b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Thu, 25 Jul 2024 12:06:07 +0200 Subject: [PATCH 14/49] style(removed-feedback-features): prettier fixes --- src/api/apiGetConsultantSessionList.ts | 27 +- src/components/askerInfo/AskerInfoContent.tsx | 8 +- src/components/devToolbar/DevToolbar.tsx | 2 +- src/components/form/textarea.styles.scss | 8 +- src/components/message/MessageDisplayName.tsx | 4 +- .../message/MessageItemComponent.tsx | 25 +- src/components/message/message.styles.scss | 13 +- .../messageSubmitInterfaceComponent.tsx | 35 +- src/components/session/AcceptLiveChatView.tsx | 7 +- .../session/SessionItemComponent.tsx | 23 +- src/components/session/sessionHelpers.ts | 6 +- .../sessionHeader/SessionHeaderComponent.tsx | 83 +++-- .../sessionHeader/sessionHeader.styles.scss | 8 +- src/components/sessionMenu/SessionMenu.tsx | 5 +- src/components/sessionsList/SessionsList.tsx | 49 +-- .../sessionsList/SessionsListWrapper.tsx | 7 +- .../SessionListItemComponent.tsx | 13 +- .../sessionsListItem.styles.scss | 14 +- src/generated/messageservice.d.ts | 72 ++-- src/generated/uploadservice.d.ts | 24 +- src/generated/userservice.d.ts | 352 +++++++++--------- src/globalState/helpers/stateHelpers.ts | 8 +- .../interfaces/SessionsDataInterface.ts | 10 +- .../provider/RocketChatUnreadProvider.tsx | 4 +- src/resources/i18n/de/common.json | 2 +- src/resources/scripts/config.ts | 4 +- src/resources/styles/settings.scss | 10 +- 27 files changed, 412 insertions(+), 411 deletions(-) diff --git a/src/api/apiGetConsultantSessionList.ts b/src/api/apiGetConsultantSessionList.ts index bf7b50547..dd2383185 100644 --- a/src/api/apiGetConsultantSessionList.ts +++ b/src/api/apiGetConsultantSessionList.ts @@ -29,20 +29,23 @@ export const apiGetConsultantSessionList = async ({ const isTeamSession: boolean = type === SESSION_LIST_TYPES.TEAMSESSION; let url: string; if (isTeamSession) { - url = `${sessionListTab === SESSION_LIST_TAB_ARCHIVE - ? `${endpoints.teamSessionsBase}${SESSION_LIST_TAB_ARCHIVE}?` - : `${endpoints.consultantTeamSessions}` - }`; + url = `${ + sessionListTab === SESSION_LIST_TAB_ARCHIVE + ? `${endpoints.teamSessionsBase}${SESSION_LIST_TAB_ARCHIVE}?` + : `${endpoints.consultantTeamSessions}` + }`; } else if (type === SESSION_LIST_TYPES.MY_SESSION) { - url = `${sessionListTab === SESSION_LIST_TAB_ARCHIVE - ? `${endpoints.myMessagesBase}${SESSION_LIST_TAB_ARCHIVE}?` - : `${endpoints.consultantSessions}` - }`; + url = `${ + sessionListTab === SESSION_LIST_TAB_ARCHIVE + ? `${endpoints.myMessagesBase}${SESSION_LIST_TAB_ARCHIVE}?` + : `${endpoints.consultantSessions}` + }`; } else { - url = `${endpoints.consultantEnquiriesBase}${sessionListTab && sessionListTab === SESSION_LIST_TAB_ANONYMOUS - ? `${SESSION_LIST_TAB_ANONYMOUS}` - : 'registered' - }?`; + url = `${endpoints.consultantEnquiriesBase}${ + sessionListTab && sessionListTab === SESSION_LIST_TAB_ANONYMOUS + ? `${SESSION_LIST_TAB_ANONYMOUS}` + : 'registered' + }?`; } url = url + `count=${count}&filter=all&offset=${offset}`; diff --git a/src/components/askerInfo/AskerInfoContent.tsx b/src/components/askerInfo/AskerInfoContent.tsx index 286e1dd1f..2fc88ba24 100644 --- a/src/components/askerInfo/AskerInfoContent.tsx +++ b/src/components/askerInfo/AskerInfoContent.tsx @@ -34,11 +34,9 @@ export const AskerInfoContent = () => { } if (isEnquiryListView) { - return ( - hasUserAuthority( - AUTHORITIES.ASSIGN_CONSULTANT_TO_ENQUIRY, - userData - ) + return hasUserAuthority( + AUTHORITIES.ASSIGN_CONSULTANT_TO_ENQUIRY, + userData ); } diff --git a/src/components/devToolbar/DevToolbar.tsx b/src/components/devToolbar/DevToolbar.tsx index a7a6e7e7e..5d2284c24 100644 --- a/src/components/devToolbar/DevToolbar.tsx +++ b/src/components/devToolbar/DevToolbar.tsx @@ -219,7 +219,7 @@ const LOCAL_STORAGE_SWITCHES: (TLocalStorageSwitches | null)[] = [ i18n.changeLanguage( value === 'cimode' ? 'cimode' - : localStorage.getItem(STORAGE_KEY_LOCALE) ?? 'de' + : (localStorage.getItem(STORAGE_KEY_LOCALE) ?? 'de') ); } }, diff --git a/src/components/form/textarea.styles.scss b/src/components/form/textarea.styles.scss index 8834d1ef9..fc1ba3add 100644 --- a/src/components/form/textarea.styles.scss +++ b/src/components/form/textarea.styles.scss @@ -49,8 +49,8 @@ color: transparent; } - &:focus+label, - &:not(:placeholder-shown)+label { + &:focus + label, + &:not(:placeholder-shown) + label { font-size: 12px; top: 2px; transition: @@ -60,7 +60,7 @@ padding-top: $grid-base; } - &:placeholder-shown+label { + &:placeholder-shown + label { top: 4px; } } @@ -79,4 +79,4 @@ } /* stylelint-enable */ -} \ No newline at end of file +} diff --git a/src/components/message/MessageDisplayName.tsx b/src/components/message/MessageDisplayName.tsx index da60cc6e8..5403789ff 100644 --- a/src/components/message/MessageDisplayName.tsx +++ b/src/components/message/MessageDisplayName.tsx @@ -40,9 +40,9 @@ export const MessageDisplayName = ({ } else { return subscriberIsModerator ? translate('session.groupChat.consultant.prefix') + - (displayName || username) + (displayName || username) : translate('session.consultant.prefix') + - (displayName || username); + (displayName || username); } }, [ displayName, diff --git a/src/components/message/MessageItemComponent.tsx b/src/components/message/MessageItemComponent.tsx index 486d9f2a2..bb7aa4ca3 100644 --- a/src/components/message/MessageItemComponent.tsx +++ b/src/components/message/MessageItemComponent.tsx @@ -202,9 +202,9 @@ export const MessageItemComponent = ({ setRenderedMessage( contentStateMessage.hasText() ? sanitizeHtml( - urlifyLinksInText(stateToHTML(contentStateMessage)), - sanitizeHtmlDefaultOptions - ) + urlifyLinksInText(stateToHTML(contentStateMessage)), + sanitizeHtmlDefaultOptions + ) : '' ); }, [decryptedMessage]); @@ -464,7 +464,9 @@ export const MessageItemComponent = ({
{getMessageDate()}
diff --git a/src/components/message/message.styles.scss b/src/components/message/message.styles.scss index 901a14f0c..ca70b459d 100644 --- a/src/components/message/message.styles.scss +++ b/src/components/message/message.styles.scss @@ -118,7 +118,8 @@ $message-attachment-color: $secondary !default; &::after { content: ''; display: inline-block; - border-top: 1px solid var(--skin-color-secondary-contrast-safe, $text-divider-color); + border-top: 1px solid + var(--skin-color-secondary-contrast-safe, $text-divider-color); width: $grid-base-three; vertical-align: middle; margin: 0 $grid-base; @@ -134,7 +135,7 @@ $message-attachment-color: $secondary !default; } } - &+.messageItem__divider { + & + .messageItem__divider { margin-top: 12px; } } @@ -189,11 +190,11 @@ $message-attachment-color: $secondary !default; display: flex; flex-direction: column; - &>* { + & > * { margin-top: $grid-base; } - &>*:first-child { + & > *:first-child { margin-top: 0; } } @@ -496,7 +497,6 @@ $message-attachment-color: $secondary !default; } @keyframes success { - 100%, 0% { transform: translate(-50%, 0) scale(0); @@ -511,7 +511,6 @@ $message-attachment-color: $secondary !default; } @keyframes successCopyReverse { - 100%, 0% { transform: scale(1); @@ -523,4 +522,4 @@ $message-attachment-color: $secondary !default; transform: scale(0); opacity: 0; } -} \ No newline at end of file +} diff --git a/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx b/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx index abf8bf813..04b4791be 100644 --- a/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx +++ b/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx @@ -180,7 +180,7 @@ export const MessageSubmitInterfaceComponent = ({ const [isRichtextActive, setIsRichtextActive] = useState(false); const [isConsultantAbsent, setIsConsultantAbsent] = useState( hasUserAuthority(AUTHORITIES.ASKER_DEFAULT, userData) && - activeSession.consultant?.absent + activeSession.consultant?.absent ); const [isSessionArchived, setIsSessionArchived] = useState( activeSession.item.status === STATUS_ARCHIVED @@ -234,7 +234,7 @@ export const MessageSubmitInterfaceComponent = ({ useTimeoutOverlay( // Disable the request overlay if upload is in progess because upload progress is shown in the ui already isRequestInProgress && - !(uploadProgress > 0 && uploadProgress < 100), + !(uploadProgress > 0 && uploadProgress < 100), null, null, null, @@ -244,13 +244,13 @@ export const MessageSubmitInterfaceComponent = ({ useEffect(() => { setIsConsultantAbsent( hasUserAuthority(AUTHORITIES.ASKER_DEFAULT, userData) && - activeSession.consultant?.absent + activeSession.consultant?.absent ); setIsSessionArchived(activeSession.item.status === STATUS_ARCHIVED); setIsTypingActive(activeSession.isGroup || activeSession.isLive); setIsLiveChatFinished( activeSession.isLive && - activeSession.item.status === STATUS_FINISHED + activeSession.item.status === STATUS_FINISHED ); }, [activeSession, activeSession.item.status, userData]); @@ -373,7 +373,7 @@ export const MessageSubmitInterfaceComponent = ({ if ( draftLoaded && currentEditorState.getCurrentContent() !== - editorState.getCurrentContent() && + editorState.getCurrentContent() && isTyping ) { isTyping(!currentEditorState.getCurrentContent().hasText()); @@ -441,11 +441,11 @@ export const MessageSubmitInterfaceComponent = ({ let textInputStyles = `min-height: ${currentInputHeight}px; ${currentOverflow} ${textInputMarginTop} ${textInputMarginBottom}`; textInputStyles = isRichtextActive ? textInputStyles + - `border-top: none; border-top-right-radius: 0; box-shadow: none;` + `border-top: none; border-top-right-radius: 0; box-shadow: none;` : textInputStyles; textInputStyles = attachmentSelected ? textInputStyles + - `border-bottom: none; border-bottom-right-radius: 0;` + `border-bottom: none; border-bottom-right-radius: 0;` : textInputStyles; textInput?.setAttribute('style', textInputStyles); @@ -504,11 +504,7 @@ export const MessageSubmitInterfaceComponent = ({ }, [onMessageSendSuccess, resizeTextarea]); const sendMessage = useCallback( - async ( - message, - attachment: File, - isEncrypted - ) => { + async (message, attachment: File, isEncrypted) => { const sendToRoomWithId = activeSession.rid || activeSession.item.id; const getSendMailNotificationStatus = () => !activeSession.isGroup && !activeSession.isLive; @@ -665,11 +661,7 @@ export const MessageSubmitInterfaceComponent = ({ return; } - await sendMessage( - message, - attachment, - isEncrypted - ); + await sendMessage(message, attachment, isEncrypted); }, [ encrypted, getTypedMarkdownMessage, @@ -781,10 +773,11 @@ export const MessageSubmitInterfaceComponent = ({ const contact = getContact(activeSession); infoData = { isInfo: true, - infoHeadline: `${contact?.displayName || + infoHeadline: `${ + contact?.displayName || contact?.username || translate('sessionList.user.consultantUnknown') - } ${translate('consultant.absent.message')} `, + } ${translate('consultant.absent.message')} `, infoMessage: activeSession.consultant.absenceMessage }; } else if (activeInfo === INFO_TYPES.ATTACHMENT_SIZE_ERROR) { @@ -886,9 +879,7 @@ export const MessageSubmitInterfaceComponent = ({ )} {activeInfo && } {!isLiveChatFinished && ( - +
diff --git a/src/components/session/AcceptLiveChatView.tsx b/src/components/session/AcceptLiveChatView.tsx index 977f3c6da..86cd2db8a 100644 --- a/src/components/session/AcceptLiveChatView.tsx +++ b/src/components/session/AcceptLiveChatView.tsx @@ -76,9 +76,10 @@ export const AcceptLiveChatView = ({ semanticLevel="3" text={`${translate( 'enquiry.anonymous.infoLabel.start' - )}${getContact(activeSession)?.username || - translate('sessionList.user.consultantUnknown') - }${translate('enquiry.anonymous.infoLabel.end')}`} + )}${ + getContact(activeSession)?.username || + translate('sessionList.user.consultantUnknown') + }${translate('enquiry.anonymous.infoLabel.end')}`} />
diff --git a/src/components/session/SessionItemComponent.tsx b/src/components/session/SessionItemComponent.tsx index 7dca7e695..7fe93dea3 100644 --- a/src/components/session/SessionItemComponent.tsx +++ b/src/components/session/SessionItemComponent.tsx @@ -82,9 +82,7 @@ export const SessionItemComponent = (props: SessionItemProps) => { ); useEffect(() => { - setCanWriteMessage( - type !== SESSION_LIST_TYPES.ENQUIRY - ); + setCanWriteMessage(type !== SESSION_LIST_TYPES.ENQUIRY); }, [type, userData]); const resetUnreadCount = () => { @@ -310,7 +308,7 @@ export const SessionItemComponent = (props: SessionItemProps) => { if ( trackedErrorIndex >= 0 && acc[trackedErrorIndex][1].message === - collectedError.message + collectedError.message ) { if (timestamp > acc[trackedErrorIndex][0]) { acc.splice( @@ -343,14 +341,12 @@ export const SessionItemComponent = (props: SessionItemProps) => { ); return ( -
+
{ ))}
{newMessages > 0 && ( @@ -452,7 +449,7 @@ export const SessionItemComponent = (props: SessionItemProps) => { className={clsx( 'session__submit-interface', !isScrolledToBottom && - 'session__submit-interface--scrolled-up' + 'session__submit-interface--scrolled-up' )} placeholder={getPlaceholder()} typingUsers={props.typingUsers} diff --git a/src/components/session/sessionHelpers.ts b/src/components/session/sessionHelpers.ts index dd58d0139..7e845cde4 100644 --- a/src/components/session/sessionHelpers.ts +++ b/src/components/session/sessionHelpers.ts @@ -96,9 +96,7 @@ export const isLiveChat = ( export const isGroupChat = ( chatItem: SessionItemInterface | GroupChatItemInterface ): chatItem is GroupChatItemInterface => { - return ( - (chatItem as GroupChatItemInterface) && 'moderators' in chatItem - ); + return (chatItem as GroupChatItemInterface) && 'moderators' in chatItem; }; export const isTeamSession = ( @@ -176,7 +174,7 @@ const findLastVideoCallIndex = (messagesData) => message?.alias?.messageType === 'VIDEOCALL' && (!message?.alias?.videoCallMessageDTO || message?.alias?.videoCallMessageDTO?.eventType !== - 'IGNORED_CALL') + 'IGNORED_CALL') ); export const prepareMessages = (messagesData): MessageItem[] => { diff --git a/src/components/sessionHeader/SessionHeaderComponent.tsx b/src/components/sessionHeader/SessionHeaderComponent.tsx index 882e9b891..408943bb8 100644 --- a/src/components/sessionHeader/SessionHeaderComponent.tsx +++ b/src/components/sessionHeader/SessionHeaderComponent.tsx @@ -61,8 +61,8 @@ export const SessionHeaderComponent = (props: SessionHeaderProps) => { const preparedUserSessionData = hasUserAuthority(AUTHORITIES.CONSULTANT_DEFAULT, userData) && - userSessionData && - !activeSession.isLive + userSessionData && + !activeSession.isLive ? convertUserDataObjectToArray(userSessionData) : null; const translateBase = getUserDataTranslateBase( @@ -84,8 +84,9 @@ export const SessionHeaderComponent = (props: SessionHeaderProps) => { }, [isSubscriberFlyoutOpen]); const sessionView = getViewPathForType(type); - const userProfileLink = `/sessions/consultant/${sessionView}/${activeSession.item.groupId - }/${activeSession.item.id}/userProfile${getSessionListTab()}`; + const userProfileLink = `/sessions/consultant/${sessionView}/${ + activeSession.item.groupId + }/${activeSession.item.id}/userProfile${getSessionListTab()}`; const handleBackButton = () => { mobileListView(); @@ -150,12 +151,12 @@ export const SessionHeaderComponent = (props: SessionHeaderProps) => { AUTHORITIES.ANONYMOUS_DEFAULT, userData )) && ( -

- {contact?.displayName || - contact?.username || - translate('sessionList.user.consultantUnknown')} -

- )} +

+ {contact?.displayName || + contact?.username || + translate('sessionList.user.consultantUnknown')} +

+ )} {hasUserAuthority( AUTHORITIES.CONSULTANT_DEFAULT, userData @@ -190,18 +191,18 @@ export const SessionHeaderComponent = (props: SessionHeaderProps) => { {(hasUserAuthority(AUTHORITIES.ASKER_DEFAULT, userData) || hasUserAuthority(AUTHORITIES.CONSULTANT_DEFAULT, userData)) && ( -
- {!activeSession.agency ? ( -
- {topic?.name || ''} -
- ) : null} - {preparedUserSessionData - ? preparedUserSessionData.map((item, index) => +
+ {!activeSession.agency ? ( +
+ {topic?.name || ''} +
+ ) : null} + {preparedUserSessionData + ? preparedUserSessionData.map((item, index) => item.value && - !( - item.type === 'age' && item.value === 'null' - ) ? ( + !( + item.type === 'age' && item.value === 'null' + ) ? (
{
) : null ) - : null} - {activeSession.agency?.name && ( -
- {' '} - {translate( - [ - `agency.${activeSession.agency.id}.name`, - activeSession.agency.name - ], - { ns: 'agencies' } - )}{' '} -
- )} - {activeSession.agency && ( -
- {translate('consultant.jobTitle')} -
- )} -
- )} + : null} + {activeSession.agency?.name && ( +
+ {' '} + {translate( + [ + `agency.${activeSession.agency.id}.name`, + activeSession.agency.name + ], + { ns: 'agencies' } + )}{' '} +
+ )} + {activeSession.agency && ( +
+ {translate('consultant.jobTitle')} +
+ )} +
+ )}
); }; diff --git a/src/components/sessionHeader/sessionHeader.styles.scss b/src/components/sessionHeader/sessionHeader.styles.scss index 491f14422..d7cef697a 100644 --- a/src/components/sessionHeader/sessionHeader.styles.scss +++ b/src/components/sessionHeader/sessionHeader.styles.scss @@ -140,8 +140,10 @@ $iconSize: 24px; } &--red { - color: var(--skin-color-primary-contrast-safe, - $primary) !important; + color: var( + --skin-color-primary-contrast-safe, + $primary + ) !important; text-transform: uppercase; } @@ -255,4 +257,4 @@ $iconSize: 24px; } } } -} \ No newline at end of file +} diff --git a/src/components/sessionMenu/SessionMenu.tsx b/src/components/sessionMenu/SessionMenu.tsx index bdcbb7854..2f48a0bca 100644 --- a/src/components/sessionMenu/SessionMenu.tsx +++ b/src/components/sessionMenu/SessionMenu.tsx @@ -466,8 +466,9 @@ export const SessionMenu = (props: SessionMenuProps) => {
{activeSession.isLive && activeSession.item.status !== STATUS_FINISHED && diff --git a/src/components/sessionsList/SessionsList.tsx b/src/components/sessionsList/SessionsList.tsx index 9739cb330..ab15f2873 100644 --- a/src/components/sessionsList/SessionsList.tsx +++ b/src/components/sessionsList/SessionsList.tsx @@ -197,8 +197,8 @@ export const SessionsList = ({ useLiveChatWatcher( !isLoading && - type === SESSION_LIST_TYPES.ENQUIRY && - sessionListTab === SESSION_LIST_TAB_ANONYMOUS, + type === SESSION_LIST_TYPES.ENQUIRY && + sessionListTab === SESSION_LIST_TAB_ANONYMOUS, getConsultantSessionList, currentOffset ); @@ -212,15 +212,15 @@ export const SessionsList = ({ ); const firstItemId = document.querySelector('.sessionsListItem') ? document - .querySelector('.sessionsListItem') - .getAttribute('data-group-id') + .querySelector('.sessionsListItem') + .getAttribute('data-group-id') : null; const lastItemId = wrapper.lastElementChild.querySelector( '.sessionsListItem' ) ? wrapper.lastElementChild - .querySelector('.sessionsListItem') - .getAttribute('data-group-id') + .querySelector('.sessionsListItem') + .getAttribute('data-group-id') : null; if ( initialId.current !== firstItemId && @@ -367,7 +367,7 @@ export const SessionsList = ({ sessionTypes.indexOf(sessionType) < 0 || (sessionType === SESSION_TYPE_ARCHIVED && sessionListTab !== - SESSION_LIST_TAB_ARCHIVE) || + SESSION_LIST_TAB_ARCHIVE) || (sessionType !== SESSION_TYPE_ARCHIVED && sessionListTab === SESSION_LIST_TAB_ARCHIVE) ) { @@ -815,10 +815,11 @@ export const SessionsList = ({ 'sessionsList__tabs--active': !sessionListTab })} - to={`/sessions/consultant/${type === SESSION_LIST_TYPES.TEAMSESSION - ? 'teamSessionView' - : 'sessionView' - }`} + to={`/sessions/consultant/${ + type === SESSION_LIST_TYPES.TEAMSESSION + ? 'teamSessionView' + : 'sessionView' + }`} onKeyDown={(e) => handleKeyDownTabs(e)} ref={(el) => (ref_tab_first.current = el)} tabIndex={0} @@ -837,10 +838,11 @@ export const SessionsList = ({ sessionListTab === SESSION_LIST_TAB_ARCHIVE })} - to={`/sessions/consultant/${type === SESSION_LIST_TYPES.TEAMSESSION - ? 'teamSessionView' - : 'sessionView' - }?sessionListTab=${SESSION_LIST_TAB_ARCHIVE}`} + to={`/sessions/consultant/${ + type === SESSION_LIST_TYPES.TEAMSESSION + ? 'teamSessionView' + : 'sessionView' + }?sessionListTab=${SESSION_LIST_TAB_ARCHIVE}`} onKeyDown={(e) => handleKeyDownTabs(e)} ref={(el) => (ref_tab_second.current = el)} tabIndex={-1} @@ -870,17 +872,18 @@ export const SessionsList = ({ {hasUserAuthority(AUTHORITIES.ASKER_DEFAULT, userData) && !isLoading && finalSessionsList.length <= - MAX_ITEMS_TO_SHOW_WELCOME_ILLUSTRATION && ( + MAX_ITEMS_TO_SHOW_WELCOME_ILLUSTRATION && ( )}
0 - ? '' - : 'sessionsList__itemsWrapper--centered' - }`} + ? '' + : 'sessionsList__itemsWrapper--centered' + }`} data-cy="sessions-list-items-wrapper" role="tablist" > @@ -915,9 +918,9 @@ export const SessionsList = ({ defaultLanguage } itemRef={(el) => - (ref_list_array.current[ - index - ] = el) + (ref_list_array.current[ + index + ] = el) } handleKeyDownLisItemContent={( e diff --git a/src/components/sessionsList/SessionsListWrapper.tsx b/src/components/sessionsList/SessionsListWrapper.tsx index f76ccbe1d..54c54f0df 100644 --- a/src/components/sessionsList/SessionsListWrapper.tsx +++ b/src/components/sessionsList/SessionsListWrapper.tsx @@ -75,14 +75,15 @@ export const SessionsListWrapper = ({ : null} {type === SESSION_LIST_TYPES.MY_SESSION && - hasUserAuthority(AUTHORITIES.CREATE_NEW_CHAT, userData) ? ( + hasUserAuthority(AUTHORITIES.CREATE_NEW_CHAT, userData) ? ( { if (activeSession.item.groupId && activeSession.item.id !== undefined) { history.push( - `${listPath}/${activeSession.item.groupId}/${activeSession.item.id + `${listPath}/${activeSession.item.groupId}/${ + activeSession.item.id }${getSessionListTab()}` ); } else if ( @@ -292,7 +293,7 @@ export const SessionListItemComponent = ({ className={clsx( 'sessionsListItem__username', activeSession.item.messagesRead && - 'sessionsListItem__username--readLabel' + 'sessionsListItem__username--readLabel' )} > {activeSession.item.topic} @@ -362,8 +363,8 @@ export const SessionListItemComponent = ({
{!isAsker && - !activeSession.isLive && - !autoSelectPostcode + !activeSession.isLive && + !autoSelectPostcode ? activeSession.item.postcode : null}
@@ -394,7 +395,7 @@ export const SessionListItemComponent = ({ className={clsx( 'sessionsListItem__username', activeSession.item.messagesRead && - 'sessionsListItem__username--readLabel' + 'sessionsListItem__username--readLabel' )} > {sessionTopic} diff --git a/src/components/sessionsListItem/sessionsListItem.styles.scss b/src/components/sessionsListItem/sessionsListItem.styles.scss index 374f7b7f5..fbbe492b1 100644 --- a/src/components/sessionsListItem/sessionsListItem.styles.scss +++ b/src/components/sessionsListItem/sessionsListItem.styles.scss @@ -213,7 +213,7 @@ $icon-size-small: 16px; font-style: italic !important; } - &>span { + & > span { display: inline-block; font-style: normal; font-weight: $font-weight-bold; @@ -267,10 +267,12 @@ $icon-size-small: 16px; background-color: $dark-grey; width: 100%; min-height: 18px; - background: linear-gradient(-90deg, - $dark-grey 0%, - $session-list-item-background-active 50%, - $dark-grey 100%); + background: linear-gradient( + -90deg, + $dark-grey 0%, + $session-list-item-background-active 50%, + $dark-grey 100% + ); background-size: 400% 400%; animation: pulse 1.2s ease-in-out infinite; @@ -310,4 +312,4 @@ $icon-size-small: 16px; .skeleton { margin-top: 0; } -} \ No newline at end of file +} diff --git a/src/generated/messageservice.d.ts b/src/generated/messageservice.d.ts index 774d33ef9..0134007bf 100644 --- a/src/generated/messageservice.d.ts +++ b/src/generated/messageservice.d.ts @@ -186,11 +186,11 @@ declare namespace Paths { } export type RequestBody = MessageService.Schemas.MessageDTO; namespace Responses { - export interface $201 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $500 { } + export interface $201 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $500 {} } } namespace CreateVideoHintMessage { @@ -202,11 +202,11 @@ declare namespace Paths { } export type RequestBody = MessageService.Schemas.VideoCallMessageDTO; namespace Responses { - export interface $201 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $500 { } + export interface $201 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $500 {} } } namespace FindDraftMessage { @@ -218,11 +218,11 @@ declare namespace Paths { } namespace Responses { export type $200 = string; - export interface $204 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $500 { } + export interface $204 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $500 {} } } @@ -241,11 +241,11 @@ declare namespace Paths { } namespace Responses { export type $200 = MessageService.Schemas.MessageStreamDTO; - export interface $204 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $500 { } + export interface $204 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $500 {} } } namespace SaveAliasOnlyMessage { @@ -257,11 +257,11 @@ declare namespace Paths { } export type RequestBody = MessageService.Schemas.AliasOnlyMessageDTO; namespace Responses { - export interface $201 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $500 { } + export interface $201 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $500 {} } } namespace SaveDraftMessage { @@ -273,22 +273,22 @@ declare namespace Paths { } export type RequestBody = string; namespace Responses { - export interface $200 { } - export interface $201 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $500 { } + export interface $200 {} + export interface $201 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $500 {} } } namespace UpdateKey { export type RequestBody = MessageService.Schemas.MasterKeyDTO; namespace Responses { - export interface $202 { } - export interface $401 { } - export interface $403 { } - export interface $409 { } - export interface $500 { } + export interface $202 {} + export interface $401 {} + export interface $403 {} + export interface $409 {} + export interface $500 {} } } } diff --git a/src/generated/uploadservice.d.ts b/src/generated/uploadservice.d.ts index ceda09f4d..6fb37da0e 100644 --- a/src/generated/uploadservice.d.ts +++ b/src/generated/uploadservice.d.ts @@ -13,11 +13,11 @@ declare namespace Paths { namespace UpdateKey { export type RequestBody = UploadService.Schemas.MasterKeyDto; namespace Responses { - export interface $202 { } - export interface $401 { } - export interface $403 { } - export interface $409 { } - export interface $500 { } + export interface $202 {} + export interface $401 {} + export interface $403 {} + export interface $409 {} + export interface $500 {} } } @@ -57,13 +57,13 @@ declare namespace Paths { sendNotification: string; } namespace Responses { - export interface $201 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $413 { } - export interface $415 { } - export interface $500 { } + export interface $201 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $413 {} + export interface $415 {} + export interface $500 {} } } } diff --git a/src/generated/userservice.d.ts b/src/generated/userservice.d.ts index 8ccae7376..aea1caf63 100644 --- a/src/generated/userservice.d.ts +++ b/src/generated/userservice.d.ts @@ -234,7 +234,7 @@ declare namespace UserService { */ groupId: string; } - export interface Date { } + export interface Date {} export interface DeleteUserAccountDTO { /** * example: @@ -250,7 +250,7 @@ declare namespace UserService { message: string; } - export interface HttpStatus { } + export interface HttpStatus {} export interface MandatorySessionDataDTO { /** * mandatory depending on the consulting type @@ -754,12 +754,12 @@ declare namespace Paths { sessionId: Parameters.SessionId /* int64 */; } namespace Responses { - export interface $200 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $409 { } - export interface $500 { } + export interface $200 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $409 {} + export interface $500 {} } } namespace AssignSession { @@ -772,22 +772,22 @@ declare namespace Paths { consultantId: Parameters.ConsultantId; } namespace Responses { - export interface $200 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $409 { } - export interface $500 { } + export interface $200 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $409 {} + export interface $500 {} } } namespace CreateChat { export type RequestBody = UserService.Schemas.ChatDTO; namespace Responses { export type $201 = UserService.Schemas.CreateChatResponseDTO; - export interface $400 { } - export interface $403 { } - export interface $409 { } - export interface $500 { } + export interface $400 {} + export interface $403 {} + export interface $409 {} + export interface $500 {} } } namespace CreateEnquiryMessage { @@ -805,22 +805,22 @@ declare namespace Paths { } export type RequestBody = UserService.Schemas.EnquiryMessageDTO; namespace Responses { - export interface $201 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $409 { } - export interface $500 { } + export interface $201 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $409 {} + export interface $500 {} } } namespace DeactivateAndFlagUserAccountForDeletion { export type RequestBody = UserService.Schemas.DeleteUserAccountDTO; namespace Responses { - export interface $200 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $500 { } + export interface $200 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $500 {} } } namespace FetchSessionForConsultant { @@ -832,11 +832,11 @@ declare namespace Paths { } namespace Responses { export type $200 = UserService.Schemas.ConsultantSessionDTO; - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $404 { } - export interface $500 { } + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $404 {} + export interface $500 {} } } namespace GetChat { @@ -848,11 +848,11 @@ declare namespace Paths { } namespace Responses { export type $200 = UserService.Schemas.ChatInfoResponseDTO; - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $404 { } - export interface $500 { } + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $404 {} + export interface $500 {} } } namespace GetChatMembers { @@ -864,12 +864,12 @@ declare namespace Paths { } namespace Responses { export type $200 = UserService.Schemas.ChatMembersResponseDTO; - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $404 { } - export interface $409 { } - export interface $500 { } + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $404 {} + export interface $409 {} + export interface $500 {} } } namespace GetConsultants { @@ -881,11 +881,11 @@ declare namespace Paths { } namespace Responses { export type $200 = UserService.Schemas.ConsultantResponseDTO[]; - export interface $204 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $500 { } + export interface $204 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $500 {} } } namespace GetMonitoring { @@ -897,11 +897,11 @@ declare namespace Paths { } namespace Responses { export type $200 = UserService.Schemas.MonitoringDTO; - export interface $204 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $500 { } + export interface $204 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $500 {} } } namespace GetSessionsForAuthenticatedConsultant { @@ -924,10 +924,10 @@ declare namespace Paths { namespace Responses { export type $200 = UserService.Schemas.ConsultantSessionListResponseDTO; - export interface $204 { } - export interface $401 { } - export interface $403 { } - export interface $500 { } + export interface $204 {} + export interface $401 {} + export interface $403 {} + export interface $500 {} } } namespace GetSessionsForAuthenticatedUser { @@ -939,11 +939,11 @@ declare namespace Paths { } namespace Responses { export type $200 = UserService.Schemas.UserSessionListResponseDTO; - export interface $204 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $500 { } + export interface $204 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $500 {} } } namespace GetTeamSessionsForAuthenticatedConsultant { @@ -964,43 +964,43 @@ declare namespace Paths { namespace Responses { export type $200 = UserService.Schemas.ConsultantSessionListResponseDTO; - export interface $204 { } - export interface $401 { } - export interface $403 { } - export interface $500 { } + export interface $204 {} + export interface $401 {} + export interface $403 {} + export interface $500 {} } } namespace GetUserData { namespace Responses { export type $200 = UserService.Schemas.UserDataResponseDTO; - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $500 { } + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $500 {} } } namespace ImportAskers { namespace Responses { - export interface $200 { } - export interface $400 { } - export interface $401 { } - export interface $500 { } + export interface $200 {} + export interface $400 {} + export interface $401 {} + export interface $500 {} } } namespace ImportAskersWithoutSession { namespace Responses { - export interface $200 { } - export interface $400 { } - export interface $401 { } - export interface $500 { } + export interface $200 {} + export interface $400 {} + export interface $401 {} + export interface $500 {} } } namespace ImportConsultants { namespace Responses { - export interface $200 { } - export interface $400 { } - export interface $401 { } - export interface $500 { } + export interface $200 {} + export interface $400 {} + export interface $401 {} + export interface $500 {} } } namespace JoinChat { @@ -1011,13 +1011,13 @@ declare namespace Paths { chatId: Parameters.ChatId /* int64 */; } namespace Responses { - export interface $200 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $404 { } - export interface $409 { } - export interface $500 { } + export interface $200 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $404 {} + export interface $409 {} + export interface $500 {} } } namespace LeaveChat { @@ -1028,13 +1028,13 @@ declare namespace Paths { chatId: Parameters.ChatId /* int64 */; } namespace Responses { - export interface $200 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $404 { } - export interface $409 { } - export interface $500 { } + export interface $200 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $404 {} + export interface $409 {} + export interface $500 {} } } namespace RegisterNewConsultingType { @@ -1049,20 +1049,20 @@ declare namespace Paths { export type RequestBody = UserService.Schemas.NewRegistrationDto; namespace Responses { export type $201 = UserService.Schemas.NewRegistrationResponseDto; - export interface $400 { } - export interface $403 { } - export interface $409 { } - export interface $500 { } + export interface $400 {} + export interface $403 {} + export interface $409 {} + export interface $500 {} } } namespace RegisterUser { export type RequestBody = UserService.Schemas.UserDTO; namespace Responses { - export interface $201 { } - export interface $400 { } - export interface $403 { } - export interface $409 { } - export interface $500 { } + export interface $201 {} + export interface $400 {} + export interface $403 {} + export interface $409 {} + export interface $500 {} } } namespace SendLiveEvent { @@ -1073,22 +1073,22 @@ declare namespace Paths { rcGroupId: Parameters.RcGroupId; } namespace Responses { - export interface $200 { } - export interface $400 { } - export interface $403 { } - export interface $409 { } - export interface $500 { } + export interface $200 {} + export interface $400 {} + export interface $403 {} + export interface $409 {} + export interface $500 {} } } namespace SendNewMessageNotification { export type RequestBody = UserService.Schemas.NewMessageNotificationDTO; namespace Responses { - export interface $200 { } - export interface $400 { } - export interface $401 { } - export interface $409 { } - export interface $500 { } + export interface $200 {} + export interface $400 {} + export interface $401 {} + export interface $409 {} + export interface $500 {} } } namespace StartChat { @@ -1099,12 +1099,12 @@ declare namespace Paths { chatId: Parameters.ChatId /* int64 */; } namespace Responses { - export interface $200 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $409 { } - export interface $500 { } + export interface $200 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $409 {} + export interface $500 {} } } namespace StopChat { @@ -1115,22 +1115,22 @@ declare namespace Paths { chatId: Parameters.ChatId /* int64 */; } namespace Responses { - export interface $200 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $409 { } - export interface $500 { } + export interface $200 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $409 {} + export interface $500 {} } } namespace UpdateAbsence { export type RequestBody = UserService.Schemas.AbsenceDTO; namespace Responses { - export interface $200 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $500 { } + export interface $200 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $500 {} } } namespace UpdateChat { @@ -1143,52 +1143,52 @@ declare namespace Paths { export type RequestBody = UserService.Schemas.ChatDTO; namespace Responses { export type $200 = UserService.Schemas.UpdateChatResponseDTO; - export interface $400 { } - export interface $403 { } - export interface $409 { } - export interface $500 { } + export interface $400 {} + export interface $403 {} + export interface $409 {} + export interface $500 {} } } namespace UpdateConsultantData { export type RequestBody = UserService.Schemas.UpdateConsultantDTO; namespace Responses { - export interface $200 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $409 { } - export interface $500 { } + export interface $200 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $409 {} + export interface $500 {} } } namespace UpdateEmailAddress { export type RequestBody = string; namespace Responses { - export interface $200 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $409 { } - export interface $500 { } + export interface $200 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $409 {} + export interface $500 {} } } namespace UpdateKey { export type RequestBody = UserService.Schemas.MasterKeyDTO; namespace Responses { - export interface $202 { } - export interface $401 { } - export interface $403 { } - export interface $409 { } - export interface $500 { } + export interface $202 {} + export interface $401 {} + export interface $403 {} + export interface $409 {} + export interface $500 {} } } namespace UpdateMobileToken { export type RequestBody = UserService.Schemas.MobileTokenDTO; namespace Responses { - export interface $200 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $500 { } + export interface $200 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $500 {} } } namespace UpdateMonitoring { @@ -1200,21 +1200,21 @@ declare namespace Paths { } export type RequestBody = UserService.Schemas.MonitoringDTO; namespace Responses { - export interface $200 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $500 { } + export interface $200 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $500 {} } } namespace UpdatePassword { export type RequestBody = UserService.Schemas.PasswordDTO; namespace Responses { - export interface $200 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $500 { } + export interface $200 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $500 {} } } namespace UpdateSessionData { @@ -1226,12 +1226,12 @@ declare namespace Paths { } export type RequestBody = UserService.Schemas.SessionDataDTO; namespace Responses { - export interface $200 { } - export interface $400 { } - export interface $401 { } - export interface $403 { } - export interface $404 { } - export interface $500 { } + export interface $200 {} + export interface $400 {} + export interface $401 {} + export interface $403 {} + export interface $404 {} + export interface $500 {} } } } diff --git a/src/globalState/helpers/stateHelpers.ts b/src/globalState/helpers/stateHelpers.ts index 087606746..ba65c65fe 100644 --- a/src/globalState/helpers/stateHelpers.ts +++ b/src/globalState/helpers/stateHelpers.ts @@ -26,9 +26,9 @@ export type ExtendedSessionInterface = Omit< 'session' | 'chat' > & { item?: Partial> & - Partial> & { - topic: string | TopicSessionInterface; - }; + Partial> & { + topic: string | TopicSessionInterface; + }; rid: string; type: typeof CHAT_TYPE_GROUP_CHAT | typeof CHAT_TYPE_SINGLE_CHAT; isGroup?: boolean; @@ -144,7 +144,7 @@ export const AUTHORITIES = { CONSULTANT_DEFAULT: 'AUTHORIZATION_CONSULTANT_DEFAULT', CREATE_NEW_CHAT: 'AUTHORIZATION_CREATE_NEW_CHAT', ASKER_DEFAULT: 'AUTHORIZATION_USER_DEFAULT', - VIEW_AGENCY_CONSULTANTS: 'AUTHORIZATION_VIEW_AGENCY_CONSULTANTS', + VIEW_AGENCY_CONSULTANTS: 'AUTHORIZATION_VIEW_AGENCY_CONSULTANTS' }; export const isAnonymousSession = ( diff --git a/src/globalState/interfaces/SessionsDataInterface.ts b/src/globalState/interfaces/SessionsDataInterface.ts index 7c0ec60a2..0d5c4bb2e 100644 --- a/src/globalState/interfaces/SessionsDataInterface.ts +++ b/src/globalState/interfaces/SessionsDataInterface.ts @@ -86,11 +86,11 @@ export interface SessionItemInterface { postcode: number; registrationType: registrationTypeAnonymous | registrationTypeRegistered; status: - | statusEmpty - | statusEnquiry - | statusActive - | statusFinished - | statusArchived; + | statusEmpty + | statusEnquiry + | statusActive + | statusFinished + | statusArchived; isTeamSession: boolean; videoCallMessageDTO: VideoCallMessageDTO; language?: string; diff --git a/src/globalState/provider/RocketChatUnreadProvider.tsx b/src/globalState/provider/RocketChatUnreadProvider.tsx index bad41f3dc..db63a9a12 100644 --- a/src/globalState/provider/RocketChatUnreadProvider.tsx +++ b/src/globalState/provider/RocketChatUnreadProvider.tsx @@ -93,9 +93,7 @@ export function RocketChatUnreadProvider({ const session = sessions.find((s) => { const chatItem = getChatItemForSession(s); - return ( - chatItem.groupId === subscription.rid - ); + return chatItem.groupId === subscription.rid; }); if (!session) { diff --git a/src/resources/i18n/de/common.json b/src/resources/i18n/de/common.json index 406f9f012..531acd332 100644 --- a/src/resources/i18n/de/common.json +++ b/src/resources/i18n/de/common.json @@ -2191,7 +2191,7 @@ "archived": "Es sind noch keine Beratungen archiviert", "known": "Aktuell liegen keine Erstanfragen vor", "mySessions": "Sie haben zurzeit keine aktiven Beratungen", - "teamSessions": "Ihr Team hat keine aktiven Beratungen", + "teamSessions": "Ihr Team hat keine aktiven Beratungen" }, "preview": { "anonymous": { diff --git a/src/resources/scripts/config.ts b/src/resources/scripts/config.ts index 915ddba18..563525604 100644 --- a/src/resources/scripts/config.ts +++ b/src/resources/scripts/config.ts @@ -99,9 +99,7 @@ export const config: AppConfigInterface = { notifications: [ { label: 'profile.notifications.follow.up.email.label', - types: [ - 'NEW_CHAT_MESSAGE_FROM_ADVICE_SEEKER' - ] + types: ['NEW_CHAT_MESSAGE_FROM_ADVICE_SEEKER'] } ] }, diff --git a/src/resources/styles/settings.scss b/src/resources/styles/settings.scss index 52ddf478d..3d610c9bc 100644 --- a/src/resources/styles/settings.scss +++ b/src/resources/styles/settings.scss @@ -232,9 +232,11 @@ $max-input-width: 320px; $message-background-primary: $primary; $message-background-secondary: black; $message-background-rate: 0%; -$message-background: mix($message-background-secondary, - $primary, - $message-background-rate); +$message-background: mix( + $message-background-secondary, + $primary, + $message-background-rate +); $message-submit-interface-textarea-background-color: $dark-grey; $message-submit-interface-textarea-background-color-yellow: $yellow-3; $message-submit-interface-textarea-placeholder-color: $light-grey; @@ -287,4 +289,4 @@ $text-divider-font-weight: $font-weight-regular; $text-divider-text-transform: none; $upload-progress: #80dd92; $waiting-room-illustration-display-after: block; -$welcome-screen-icon-background: $primary; \ No newline at end of file +$welcome-screen-icon-background: $primary; From a758381fb64e4ec084b09bac8f54a0544ce4acc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Thu, 25 Jul 2024 12:18:25 +0200 Subject: [PATCH 15/49] fix(prettier-and-build-error): removed deprecated parameter, prettier fix --- .github/workflows/dockerImage.yml | 1 - src/components/sessionsList/SessionsList.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/.github/workflows/dockerImage.yml b/.github/workflows/dockerImage.yml index 9c9923f37..04c8a38ec 100644 --- a/.github/workflows/dockerImage.yml +++ b/.github/workflows/dockerImage.yml @@ -10,7 +10,6 @@ on: - 'dockerImage.v.*' - 'v*' - jobs: build: name: Build diff --git a/src/components/sessionsList/SessionsList.tsx b/src/components/sessionsList/SessionsList.tsx index ab15f2873..4297c05f8 100644 --- a/src/components/sessionsList/SessionsList.tsx +++ b/src/components/sessionsList/SessionsList.tsx @@ -358,7 +358,6 @@ export const SessionsList = ({ const sessionType = getSessionType( session, - rid, userData.userId ); From 14e25ec902e68f73c3ee4be0d8c2f485441efc3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Thu, 25 Jul 2024 13:06:46 +0200 Subject: [PATCH 16/49] style(devToolbar): prettier fix --- src/components/devToolbar/DevToolbar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/devToolbar/DevToolbar.tsx b/src/components/devToolbar/DevToolbar.tsx index 5d2284c24..a7a6e7e7e 100644 --- a/src/components/devToolbar/DevToolbar.tsx +++ b/src/components/devToolbar/DevToolbar.tsx @@ -219,7 +219,7 @@ const LOCAL_STORAGE_SWITCHES: (TLocalStorageSwitches | null)[] = [ i18n.changeLanguage( value === 'cimode' ? 'cimode' - : (localStorage.getItem(STORAGE_KEY_LOCALE) ?? 'de') + : localStorage.getItem(STORAGE_KEY_LOCALE) ?? 'de' ); } }, From 12f6d745225a3008bb5b8aec9d51905ee82585c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Thu, 25 Jul 2024 13:33:36 +0200 Subject: [PATCH 17/49] fix(list-filter): removed deprecated styles --- src/components/sessionsList/SessionsList.tsx | 1 - src/components/sessionsList/sessionsList.styles.scss | 4 ---- 2 files changed, 5 deletions(-) diff --git a/src/components/sessionsList/SessionsList.tsx b/src/components/sessionsList/SessionsList.tsx index 4297c05f8..8d303d741 100644 --- a/src/components/sessionsList/SessionsList.tsx +++ b/src/components/sessionsList/SessionsList.tsx @@ -861,7 +861,6 @@ export const SessionsList = ({ )}
Date: Thu, 25 Jul 2024 13:59:31 +0200 Subject: [PATCH 18/49] fix(remove-feedback-chat-functions): cleanup, removde unused import, fix eslint issues --- .../message/MessageItemComponent.tsx | 11 ++--------- .../messageSubmitInterfaceComponent.tsx | 2 -- .../session/SessionItemComponent.tsx | 19 ------------------- src/components/sessionsList/EmptyListItem.tsx | 8 +------- src/components/sessionsList/SessionsList.tsx | 2 +- src/globalState/helpers/stateHelpers.ts | 1 - .../provider/RocketChatUnreadProvider.tsx | 1 - 7 files changed, 4 insertions(+), 40 deletions(-) diff --git a/src/components/message/MessageItemComponent.tsx b/src/components/message/MessageItemComponent.tsx index bb7aa4ca3..c886d5c6e 100644 --- a/src/components/message/MessageItemComponent.tsx +++ b/src/components/message/MessageItemComponent.tsx @@ -7,15 +7,11 @@ import { hasUserAuthority, AUTHORITIES, E2EEContext, - SessionTypeContext, RocketChatGlobalSettingsContext, ActiveSessionContext } from '../../globalState'; -import { - ConsultingTypeInterface, - STATUS_ARCHIVED -} from '../../globalState/interfaces'; -import { isUserModerator, SESSION_LIST_TYPES } from '../session/sessionHelpers'; +import { STATUS_ARCHIVED } from '../../globalState/interfaces'; +import { isUserModerator } from '../session/sessionHelpers'; import { MessageMetaData } from './MessageMetaData'; import { MessageDisplayName } from './MessageDisplayName'; import { markdownToDraft } from 'markdown-draft-js'; @@ -104,7 +100,6 @@ interface MessageItemComponentProps extends MessageItem { isOnlyEnquiry?: boolean; isMyMessage: boolean; clientName: string; - resortData: ConsultingTypeInterface; isUserBanned: boolean; handleDecryptionErrors: ( id: string, @@ -122,7 +117,6 @@ export const MessageItemComponent = ({ message, messageDate, messageTime, - resortData, isMyMessage, displayName, username, @@ -142,7 +136,6 @@ export const MessageItemComponent = ({ const { activeSession, reloadActiveSession } = useContext(ActiveSessionContext); const { userData } = useContext(UserDataContext); - const { type } = useContext(SessionTypeContext); const [renderedMessage, setRenderedMessage] = useState(null); const [decryptedMessage, setDecryptedMessage] = useState< diff --git a/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx b/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx index 04b4791be..85d9be55b 100644 --- a/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx +++ b/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx @@ -11,7 +11,6 @@ import { useHistory } from 'react-router-dom'; import { SendMessageButton } from './SendMessageButton'; import { SESSION_LIST_TYPES } from '../session/sessionHelpers'; -import { Checkbox } from '../checkbox/Checkbox'; import { AUTHORITIES, getContact, @@ -671,7 +670,6 @@ export const MessageSubmitInterfaceComponent = ({ preselectedFile, sendEnquiry, sendMessage, - setE2EEState, type, userData ]); diff --git a/src/components/session/SessionItemComponent.tsx b/src/components/session/SessionItemComponent.tsx index 7fe93dea3..9128ddd75 100644 --- a/src/components/session/SessionItemComponent.tsx +++ b/src/components/session/SessionItemComponent.tsx @@ -18,7 +18,6 @@ import { } from '../message/MessageItemComponent'; import { SessionHeaderComponent } from '../sessionHeader/SessionHeaderComponent'; import { Button, BUTTON_TYPES, ButtonItem } from '../button/Button'; -import { apiGetConsultingType } from '../../api'; import { AUTHORITIES, getContact, @@ -28,7 +27,6 @@ import { useTenant, ActiveSessionContext } from '../../globalState'; -import { ConsultingTypeInterface } from '../../globalState/interfaces'; import './session.styles'; import { useDebouncedCallback } from 'use-debounce'; import { ReactComponent as ArrowDoubleDownIcon } from '../../resources/img/icons/arrow-double-down.svg'; @@ -167,22 +165,6 @@ export const SessionItemComponent = (props: SessionItemProps) => { } }, [isScrolledToBottom]); // eslint-disable-line - const [resortData, setResortData] = useState(); - useEffect(() => { - if (activeSession.item.consultingType) { - let isCanceled = false; - apiGetConsultingType({ - consultingTypeId: activeSession.item.consultingType - }).then((response) => { - if (isCanceled) return; - setResortData(response); - }); - return () => { - isCanceled = true; - }; - } - }, [activeSession.item.consultingType]); - const getPlaceholder = () => { if (activeSession.isGroup) { return translate('enquiry.write.input.placeholder.groupChat'); @@ -382,7 +364,6 @@ export const SessionItemComponent = (props: SessionItemProps) => { askerRcId={activeSession.item.askerRcId} isOnlyEnquiry={isOnlyEnquiry} isMyMessage={isMyMessage(message.userId)} - resortData={resortData} isUserBanned={props.bannedUsers.includes( message.username )} diff --git a/src/components/sessionsList/EmptyListItem.tsx b/src/components/sessionsList/EmptyListItem.tsx index c79e481cd..abc2c328d 100644 --- a/src/components/sessionsList/EmptyListItem.tsx +++ b/src/components/sessionsList/EmptyListItem.tsx @@ -9,11 +9,6 @@ import { SESSION_LIST_TYPES, SESSION_LIST_TAB_ANONYMOUS } from '../session/sessionHelpers'; -import { - AUTHORITIES, - hasUserAuthority, - UserDataContext -} from '../../globalState'; interface EmptyListItemProps { type: SESSION_LIST_TYPES; @@ -22,7 +17,6 @@ interface EmptyListItemProps { export const EmptyListItem = ({ type, sessionListTab }: EmptyListItemProps) => { const { t } = useTranslation(); - const { userData } = useContext(UserDataContext); const emptyTitle = useMemo(() => { if (sessionListTab === SESSION_LIST_TAB_ARCHIVE) { @@ -38,7 +32,7 @@ export const EmptyListItem = ({ type, sessionListTab }: EmptyListItemProps) => { default: return t('sessionList.empty.mySessions'); } - }, [sessionListTab, userData, type, t]); + }, [sessionListTab, type, t]); return ( (); const { sessions, dispatch } = useContext(SessionsDataContext); - const { type, path: listPath } = useContext(SessionTypeContext); + const { type } = useContext(SessionTypeContext); const { subscribe, diff --git a/src/globalState/helpers/stateHelpers.ts b/src/globalState/helpers/stateHelpers.ts index ba65c65fe..b5e6bca67 100644 --- a/src/globalState/helpers/stateHelpers.ts +++ b/src/globalState/helpers/stateHelpers.ts @@ -17,7 +17,6 @@ import { CHAT_TYPE_SINGLE_CHAT, getChatItemForSession, getChatTypeForListItem, - isSessionChat, SESSION_LIST_TYPES } from '../../components/session/sessionHelpers'; diff --git a/src/globalState/provider/RocketChatUnreadProvider.tsx b/src/globalState/provider/RocketChatUnreadProvider.tsx index db63a9a12..6381cd52c 100644 --- a/src/globalState/provider/RocketChatUnreadProvider.tsx +++ b/src/globalState/provider/RocketChatUnreadProvider.tsx @@ -12,7 +12,6 @@ import { apiGetSessionRoomsByGroupIds } from '../../api/apiGetSessionRooms'; import { getChatItemForSession, getSessionType, - isGroupChat, SESSION_TYPE_ARCHIVED, SESSION_TYPE_ENQUIRY, SESSION_TYPE_GROUP, From b957eb152812a7ee5a05de7881dec2e993606786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Thu, 25 Jul 2024 15:00:51 +0200 Subject: [PATCH 19/49] style(EmptyListItem): remove unused import --- src/components/sessionsList/EmptyListItem.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/sessionsList/EmptyListItem.tsx b/src/components/sessionsList/EmptyListItem.tsx index abc2c328d..0d6a4aa0c 100644 --- a/src/components/sessionsList/EmptyListItem.tsx +++ b/src/components/sessionsList/EmptyListItem.tsx @@ -1,4 +1,3 @@ -import React, { useContext } from 'react'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { ListInfo } from '../listInfo/ListInfo'; From 2c625b326c25ae0113c0ec4d76e15c0e3fe56366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Thu, 25 Jul 2024 15:29:25 +0200 Subject: [PATCH 20/49] fix(EmptyListItem): missing import --- src/components/sessionsList/EmptyListItem.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/sessionsList/EmptyListItem.tsx b/src/components/sessionsList/EmptyListItem.tsx index 0d6a4aa0c..a03fbe01a 100644 --- a/src/components/sessionsList/EmptyListItem.tsx +++ b/src/components/sessionsList/EmptyListItem.tsx @@ -1,3 +1,4 @@ +import * as React from 'react'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { ListInfo } from '../listInfo/ListInfo'; From 3e4f0ced05a4669034c132186fcb824569e1f6d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Wed, 7 Aug 2024 16:29:21 +0200 Subject: [PATCH 21/49] test(u25-cypress-fixture): revert ct u25 removal --- .../fixtures/service.consultingtypes.u25.json | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 cypress/fixtures/service.consultingtypes.u25.json diff --git a/cypress/fixtures/service.consultingtypes.u25.json b/cypress/fixtures/service.consultingtypes.u25.json new file mode 100644 index 000000000..e7e6ca018 --- /dev/null +++ b/cypress/fixtures/service.consultingtypes.u25.json @@ -0,0 +1,146 @@ +{ + "id": 1, + "titles": { + "default": "U25", + "short": "U25", + "long": "Beratung für suizidgefährdete junge Menschen [U25]", + "welcome": "Willkommen bei der U25-Hilfe", + "registrationDropdown": "Beratung für suizidgefährdete junge Menschen [U25]" + }, + "urls": { + "requiredAidMissingRedirectUrl": "https://www.u25-deutschland.de/helpmail/" + }, + "registration": { + "minPostcodeSize": 5, + "autoSelectAgency": true, + "autoSelectPostcode": true, + "notes": { + "password": "Bitte notiere Dir Deine Zugangsdaten – ein Passwort-Reset ist nicht möglich!" + }, + "mandatoryFields": { + "age": true, + "state": true + } + }, + "isSubsequentRegistrationAllowed": false, + "isAnonymousConversationAllowed": false, + "isSetEmailAllowed": false, + "slug": "u25", + "languageFormal": false, + "lockedAgencies": false, + "whiteSpot": { + "whiteSpotAgencyAssigned": false + }, + "groupChat": { + "isGroupChat": false, + "groupChatRules": [] + }, + "consultantBoundedToConsultingType": false, + "welcomeMessage": { + "sendWelcomeMessage": true, + "welcomeMessageText": "Lorem ipsum" + }, + "sendFurtherStepsMessage": false, + "sendSaveSessionDataMessage": true, + "sessionDataInitializing": { + "addictiveDrugs": false, + "age": true, + "gender": true, + "relation": false, + "state": true + }, + "roles": { + "consultant": { + "main": ["consultant", "u25-consultant", "u25-main-consultant"], + "peer": ["consultant", "u25-consultant"] + } + }, + "notifications": { + "teamSessions": { + "newMessage": { + "allTeamConsultants": false + } + } + }, + "showAskerProfile": true, + "requiredComponents": { + "age": { + "isEnabled": true, + "options": [ + { + "value": "0", + "label": "unter 12" + }, + { + "value": "1", + "label": "12" + }, + { + "value": "2", + "label": "13" + }, + { + "value": "3", + "label": "14" + }, + { + "value": "4", + "label": "15" + }, + { + "value": "5", + "label": "16" + }, + { + "value": "6", + "label": "17" + }, + { + "value": "7", + "label": "18" + }, + { + "value": "8", + "label": "19" + }, + { + "value": "9", + "label": "20" + }, + { + "value": "10", + "label": "21" + }, + { + "value": "11", + "label": "22" + }, + { + "value": "12", + "label": "23" + }, + { + "value": "13", + "label": "24" + }, + { + "value": "14", + "label": "25" + }, + { + "value": "15", + "label": "über 25" + } + ] + }, + "state": { + "isEnabled": true + } + }, + "welcomeScreen": { + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Du bleibst anonym und erhältst kostenfreie Beratung und Hilfe" + } + } +} From c7a0fb75d258991b52fc2b84665885dd5ed89f30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Thu, 8 Aug 2024 11:03:55 +0200 Subject: [PATCH 22/49] feat(livechat): rm waiting room/routes/livechat session --- src/components/app/RouterConfig.tsx | 8 +- src/components/app/app.tsx | 14 +- src/components/askerInfo/AskerInfoContent.tsx | 3 +- .../messageSubmitInterfaceComponent.tsx | 328 ++++++------- src/components/session/SessionStream.tsx | 11 - src/components/session/sessionHelpers.ts | 15 - src/components/sessionsList/EmptyListItem.tsx | 13 +- src/components/sessionsList/SessionsList.tsx | 16 +- .../SessionListItemComponent.tsx | 12 +- src/components/waitingRoom/WaitingRoom.tsx | 443 ------------------ .../waitingRoom/WaitingRoomLoader.tsx | 50 -- .../waitingRoom/waitingRoom.styles.scss | 230 --------- .../waitingRoom/waitingRoomHelpers.ts | 32 -- src/globalState/helpers/stateHelpers.ts | 12 +- .../interfaces/SessionsDataInterface.ts | 5 +- .../provider/RocketChatUnreadProvider.tsx | 6 - src/resources/i18n/de/common.json | 46 -- src/resources/i18n/en/common.json | 55 --- src/resources/styles/settings.scss | 1 - 19 files changed, 163 insertions(+), 1137 deletions(-) delete mode 100644 src/components/waitingRoom/WaitingRoom.tsx delete mode 100644 src/components/waitingRoom/WaitingRoomLoader.tsx delete mode 100644 src/components/waitingRoom/waitingRoom.styles.scss delete mode 100644 src/components/waitingRoom/waitingRoomHelpers.ts diff --git a/src/components/app/RouterConfig.tsx b/src/components/app/RouterConfig.tsx index e6ac96284..b56db8bae 100644 --- a/src/components/app/RouterConfig.tsx +++ b/src/components/app/RouterConfig.tsx @@ -6,7 +6,6 @@ import { SESSION_TYPE_ARCHIVED, SESSION_TYPE_ENQUIRY, SESSION_TYPE_GROUP, - SESSION_TYPE_LIVECHAT, SESSION_TYPE_SESSION, SESSION_TYPE_TEAMSESSION } from '../session/sessionHelpers'; @@ -158,7 +157,6 @@ export const RouterConfigUser = ( SESSION_TYPE_SESSION, SESSION_TYPE_ARCHIVED, SESSION_TYPE_GROUP, - SESSION_TYPE_LIVECHAT, SESSION_TYPE_ENQUIRY, SESSION_TYPE_TEAMSESSION ] @@ -171,7 +169,6 @@ export const RouterConfigUser = ( SESSION_TYPE_SESSION, SESSION_TYPE_ARCHIVED, SESSION_TYPE_GROUP, - SESSION_TYPE_LIVECHAT, SESSION_TYPE_ENQUIRY, SESSION_TYPE_TEAMSESSION ] @@ -271,7 +268,7 @@ export const RouterConfigConsultant = (settings: AppConfigInterface): any => { { path: '/sessions/consultant/sessionPreview/:rcGroupId?/:sessionId?', component: SessionsListWrapper, - sessionTypes: [SESSION_TYPE_ENQUIRY, SESSION_TYPE_LIVECHAT], + sessionTypes: [SESSION_TYPE_ENQUIRY], type: SESSION_LIST_TYPES.ENQUIRY, exact: false }, @@ -440,7 +437,7 @@ export const RouterConfigTeamConsultant = ( { path: '/sessions/consultant/sessionPreview/:rcGroupId?/:sessionId?', component: SessionsListWrapper, - sessionTypes: [SESSION_TYPE_LIVECHAT, SESSION_TYPE_ENQUIRY], + sessionTypes: [SESSION_TYPE_ENQUIRY], type: SESSION_LIST_TYPES.ENQUIRY, exact: false }, @@ -592,7 +589,6 @@ export const RouterConfigAnonymousAsker = (): any => { SESSION_TYPE_SESSION, SESSION_TYPE_ARCHIVED, SESSION_TYPE_GROUP, - SESSION_TYPE_LIVECHAT, SESSION_TYPE_ENQUIRY, SESSION_TYPE_TEAMSESSION ] diff --git a/src/components/app/app.tsx b/src/components/app/app.tsx index 014c49253..e5ea578cb 100644 --- a/src/components/app/app.tsx +++ b/src/components/app/app.tsx @@ -46,11 +46,7 @@ const Registration = lazy(() => default: m.Registration })) ); -const WaitingRoomLoader = lazy(() => - import('../waitingRoom/WaitingRoomLoader').then((m) => ({ - default: m.WaitingRoomLoader - })) -); + const VideoConference = lazy( () => import('../videoConference/VideoConference') ); @@ -171,14 +167,6 @@ const RouterWrapper = ({ extraRoutes }: RouterWrapperProps) => { - - - setStartWebsocket(true) - } - /> - - diff --git a/src/components/askerInfo/AskerInfoContent.tsx b/src/components/askerInfo/AskerInfoContent.tsx index 2fc88ba24..e327e6faa 100644 --- a/src/components/askerInfo/AskerInfoContent.tsx +++ b/src/components/askerInfo/AskerInfoContent.tsx @@ -24,12 +24,11 @@ export const AskerInfoContent = () => { const { type } = useContext(SessionTypeContext); const isSessionAssignAvailable = useMemo(() => { - const isLiveChat = activeSession.isLive; const isGroupChat = activeSession.isGroup; const isEnquiryListView = type === SESSION_LIST_TYPES.ENQUIRY; const isAsker = hasUserAuthority(AUTHORITIES.ASKER_DEFAULT, userData); - if (isAsker || isLiveChat || isGroupChat) { + if (isAsker || isGroupChat) { return false; } diff --git a/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx b/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx index 85d9be55b..b54deca06 100644 --- a/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx +++ b/src/components/messageSubmitInterface/messageSubmitInterfaceComponent.tsx @@ -187,9 +187,6 @@ export const MessageSubmitInterfaceComponent = ({ const [isTypingActive, setIsTypingActive] = useState( activeSession.isGroup || activeSession.isLive ); - const [isLiveChatFinished, setIsLiveChatFinished] = useState( - activeSession.isLive && activeSession.item.status === STATUS_FINISHED - ); const [showAppointmentButton, setShowAppointmentButton] = useState(false); //Emoji Picker Plugin @@ -247,10 +244,6 @@ export const MessageSubmitInterfaceComponent = ({ ); setIsSessionArchived(activeSession.item.status === STATUS_ARCHIVED); setIsTypingActive(activeSession.isGroup || activeSession.isLive); - setIsLiveChatFinished( - activeSession.isLive && - activeSession.item.status === STATUS_FINISHED - ); }, [activeSession, activeSession.item.status, userData]); const { onChange: onDraftMessageChange, loaded: draftLoaded } = @@ -267,18 +260,10 @@ export const MessageSubmitInterfaceComponent = ({ setActiveInfo(INFO_TYPES.ARCHIVED); } else if (isConsultantAbsent) { setActiveInfo(INFO_TYPES.ABSENT); - } else if (isLiveChatFinished) { - setActiveInfo(INFO_TYPES.FINISHED_CONVERSATION); } else { setActiveInfo(null); } - }, [isConsultantAbsent, isLiveChatFinished, isSessionArchived, userData]); - - useEffect(() => { - if (isLiveChatFinished) { - setActiveInfo(INFO_TYPES.FINISHED_CONVERSATION); - } - }, [isLiveChatFinished]); + }, [isConsultantAbsent, isSessionArchived, userData]); const getTypedMarkdownMessage = useCallback( (currentEditorState?: EditorState) => { @@ -876,177 +861,166 @@ export const MessageSubmitInterfaceComponent = ({ /> )} {activeInfo && } - {!isLiveChatFinished && ( - -
-
- - - - setIsRichtextActive( - !isRichtextActive - ) - } - title={translate( - 'enquiry.write.input.format' - )} - aria-label={translate( - 'enquiry.write.input.format' - )} - /> - - + + +
+
+ + + + setIsRichtextActive(!isRichtextActive) + } + title={translate( + 'enquiry.write.input.format' + )} + aria-label={translate( + 'enquiry.write.input.format' + )} + /> - + + +
resizeTextarea()} + onFocus={toggleAbsentMessage} + onBlur={toggleAbsentMessage} > -
resizeTextarea()} - onFocus={toggleAbsentMessage} - onBlur={toggleAbsentMessage} - > - - {(externalProps) => ( -
- - - -
- )} -
- - handleEditorBeforeInput(editorState) - } - handlePastedText={( - text: string, - html?: string - ): DraftHandleValue => { - const newEditorState = - handleEditorPastedText( - editorState, - text, - html - ); - if (newEditorState) { - setEditorState(newEditorState); - } - return 'handled'; - }} - plugins={[ - linkifyPlugin, - staticToolbarPlugin, - emojiPlugin - ]} - tabIndex={0} - /> -
- {hasUploadFunctionality && - (!attachmentSelected ? ( - - + {(externalProps) => ( +
+ + + - - ) : ( -
- - - - {getAttachmentIcon( - attachmentSelected.type - )} -

- { - attachmentSelected.name - } -

- - - -
-
- ))} - -
- + + handleEditorBeforeInput(editorState) } + handlePastedText={( + text: string, + html?: string + ): DraftHandleValue => { + const newEditorState = + handleEditorPastedText( + editorState, + text, + html + ); + if (newEditorState) { + setEditorState(newEditorState); + } + return 'handled'; + }} + plugins={[ + linkifyPlugin, + staticToolbarPlugin, + emojiPlugin + ]} + tabIndex={0} />
+ {hasUploadFunctionality && + (!attachmentSelected ? ( + + + + ) : ( +
+ + + + {getAttachmentIcon( + attachmentSelected.type + )} +

+ {attachmentSelected.name} +

+ + + +
+
+
+ ))} + +
+
- {showAppointmentButton && ( -
- -
- )}
- {hasUploadFunctionality && ( - + {showAppointmentButton && ( +
+ +
)} - - )} +
+ {hasUploadFunctionality && ( + + )} + {requestOverlayVisible && ( diff --git a/src/components/session/SessionStream.tsx b/src/components/session/SessionStream.tsx index 6eb3b52d6..00de562fd 100644 --- a/src/components/session/SessionStream.tsx +++ b/src/components/session/SessionStream.tsx @@ -138,17 +138,6 @@ export const SessionStream = ({ return; } - const isLiveChatFinished = - activeSession.isLive && - activeSession.item.status === STATUS_FINISHED; - - if ( - !hasUserAuthority(AUTHORITIES.CONSULTANT_DEFAULT, userData) && - isLiveChatFinished - ) { - return; - } - readActiveSession(); }, [activeSession, readActiveSession, readonly, userData]); diff --git a/src/components/session/sessionHelpers.ts b/src/components/session/sessionHelpers.ts index 7e845cde4..bf9d459a8 100644 --- a/src/components/session/sessionHelpers.ts +++ b/src/components/session/sessionHelpers.ts @@ -1,7 +1,6 @@ import { GroupChatItemInterface, ListItemInterface, - REGISTRATION_TYPE_ANONYMOUS, SessionItemInterface, STATUS_ARCHIVED, STATUS_EMPTY, @@ -30,7 +29,6 @@ export type ChatTypes = | typeof CHAT_TYPE_SINGLE_CHAT; export const SESSION_TYPE_ENQUIRY = 'enquiry'; -export const SESSION_TYPE_LIVECHAT = 'livechat'; export const SESSION_TYPE_ARCHIVED = 'archived'; export const SESSION_TYPE_GROUP = 'group'; export const SESSION_TYPE_SESSION = 'session'; @@ -38,7 +36,6 @@ export const SESSION_TYPE_TEAMSESSION = 'teamsession'; export const SESSION_TYPE_UNKNOWN = 'unknown'; export type SESSION_TYPES = - | typeof SESSION_TYPE_LIVECHAT | typeof SESSION_TYPE_ENQUIRY | typeof SESSION_TYPE_ARCHIVED | typeof SESSION_TYPE_GROUP @@ -54,9 +51,6 @@ export const getSessionType = ( switch (!isGroupChat(chatItem) && chatItem.status) { case STATUS_ENQUIRY: case STATUS_EMPTY: - if (isLiveChat(chatItem)) { - return SESSION_TYPE_LIVECHAT; - } return SESSION_TYPE_ENQUIRY; case STATUS_ARCHIVED: return SESSION_TYPE_ARCHIVED; @@ -84,15 +78,6 @@ export const isSessionChat = ( return chatItem && 'askerRcId' in chatItem; }; -export const isLiveChat = ( - chatItem: SessionItemInterface | GroupChatItemInterface -): chatItem is SessionItemInterface => { - return ( - isSessionChat(chatItem) && - chatItem.registrationType === REGISTRATION_TYPE_ANONYMOUS - ); -}; - export const isGroupChat = ( chatItem: SessionItemInterface | GroupChatItemInterface ): chatItem is GroupChatItemInterface => { diff --git a/src/components/sessionsList/EmptyListItem.tsx b/src/components/sessionsList/EmptyListItem.tsx index a03fbe01a..35f1fe988 100644 --- a/src/components/sessionsList/EmptyListItem.tsx +++ b/src/components/sessionsList/EmptyListItem.tsx @@ -2,12 +2,10 @@ import * as React from 'react'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { ListInfo } from '../listInfo/ListInfo'; -import { ReactComponent as ChatWaitingIllustration } from '../../resources/img/illustrations/chat-waiting.svg'; import { ReactComponent as NoMessagesIllustration } from '../../resources/img/illustrations/no-messages.svg'; import { SESSION_LIST_TAB_ARCHIVE, - SESSION_LIST_TYPES, - SESSION_LIST_TAB_ANONYMOUS + SESSION_LIST_TYPES } from '../session/sessionHelpers'; interface EmptyListItemProps { @@ -34,13 +32,6 @@ export const EmptyListItem = ({ type, sessionListTab }: EmptyListItemProps) => { } }, [sessionListTab, type, t]); return ( - + ); }; diff --git a/src/components/sessionsList/SessionsList.tsx b/src/components/sessionsList/SessionsList.tsx index e1796311b..4d28e0e28 100644 --- a/src/components/sessionsList/SessionsList.tsx +++ b/src/components/sessionsList/SessionsList.tsx @@ -27,7 +27,6 @@ import { ExtendedSessionInterface, getExtendedSession, hasUserAuthority, - isAnonymousSession, REMOVE_SESSIONS, RocketChatContext, SessionsDataContext, @@ -249,25 +248,12 @@ export const SessionsList = ({ ready: true, sessions }); + // TODO can be reduced? if ( sessions?.length === 1 && sessions[0]?.session?.status === STATUS_EMPTY ) { history.push(`/sessions/user/view/write/`); - } else if ( - sessions.length === 1 && - isAnonymousSession(sessions[0]?.session) && - hasUserAuthority( - AUTHORITIES.ANONYMOUS_DEFAULT, - userData - ) - ) { - const extendedSession = buildExtendedSession( - sessions[0] - ); - history.push( - `/sessions/user/view/${extendedSession?.rid}/${extendedSession?.item?.id}` - ); } }) .then(() => setIsLoading(false)); diff --git a/src/components/sessionsListItem/SessionListItemComponent.tsx b/src/components/sessionsListItem/SessionListItemComponent.tsx index 010a3ecc7..b692c164b 100644 --- a/src/components/sessionsListItem/SessionListItemComponent.tsx +++ b/src/components/sessionsListItem/SessionListItemComponent.tsx @@ -222,8 +222,7 @@ export const SessionListItemComponent = ({ const prettyPrintDate = ( messageDate: number, // seconds since epoch - createDate: string, // ISO8601 string - isLiveChat: boolean + createDate: string // ISO8601 string ) => { const newestDate = Math.max( messageDate * MILLISECONDS_PER_SECOND, @@ -234,11 +233,7 @@ export const SessionListItemComponent = ({ newestDate / MILLISECONDS_PER_SECOND ); - return isLiveChat - ? prettyPrintTimeDifference(newestDate, Date.now()) - : prettyDate.str - ? translate(prettyDate.str) - : prettyDate.date; + return prettyDate.str ? translate(prettyDate.str) : prettyDate.date; }; // Hide sessions if consultingType has been switched to group chat. @@ -382,8 +377,7 @@ export const SessionListItemComponent = ({
{prettyPrintDate( activeSession.item.messageDate, - activeSession.item.createDate, - activeSession.isLive + activeSession.item.createDate )}
diff --git a/src/components/waitingRoom/WaitingRoom.tsx b/src/components/waitingRoom/WaitingRoom.tsx deleted file mode 100644 index e42dc205c..000000000 --- a/src/components/waitingRoom/WaitingRoom.tsx +++ /dev/null @@ -1,443 +0,0 @@ -import * as React from 'react'; -import { Text } from '../text/Text'; -import { v4 as uuid } from 'uuid'; -import './waitingRoom.styles'; -import { ReactComponent as WaitingIllustration } from '../../resources/img/illustrations/waiting.svg'; -import { ReactComponent as ErrorIllustration } from '../../resources/img/illustrations/not-found.svg'; -import { ReactComponent as SecurityIllustration } from '../../resources/img/illustrations/security.svg'; -import { ReactComponent as ClosedIllustration } from '../../resources/img/illustrations/closed.svg'; -import { useCallback, useContext, useEffect, useRef, useState } from 'react'; -import { - AnonymousConversationAvailabilityInterface, - AnonymousRegistrationResponse, - apiAnonymousConversationAvailability, - apiPostAnonymousRegistration, - FETCH_ERRORS -} from '../../api'; -import { Button, ButtonItem, BUTTON_TYPES } from '../button/Button'; -import { decodeUsername } from '../../utils/encryptionHelpers'; -import { - deleteCookieByName, - getValueFromCookie, - removeAllCookies, - setValueInCookie -} from '../sessionCookie/accessSessionCookie'; -import { Overlay, OverlayItem, OVERLAY_FUNCTIONS } from '../overlay/Overlay'; -import { - AnonymousConversationFinishedContext, - AnonymousEnquiryAcceptedContext, - WebsocketConnectionDeactivatedContext, - AnonymousConversationStartedContext -} from '../../globalState'; -import { capitalizeFirstLetter } from '../../utils/capitalizeFirstLetter'; -import { - acceptanceOverlayItem, - rejectionOverlayItem -} from './waitingRoomHelpers'; -import { handleTokenRefresh, setTokens } from '../auth/auth'; -import { handleE2EESetup } from '../registration/autoLogin'; -import { useTranslation } from 'react-i18next'; -import { useHistory } from 'react-router-dom'; -import { LegalLinksContext } from '../../globalState/provider/LegalLinksProvider'; -import { WaitingRoomContent } from './WaitingRoomContent'; -import { StageLayout } from '../stageLayout/StageLayout'; -import { appConfig } from '../../utils/appConfig'; -import { Loading } from '../app/Loading'; -import { GlobalComponentContext } from '../../globalState/provider/GlobalComponentContext'; -import LegalLinks from '../legalLinks/LegalLinks'; -export interface WaitingRoomProps { - consultingTypeSlug: string; - consultingTypeId: number; - onAnonymousRegistration: Function; -} - -// How many retries should run until 409 requests are failing -const USERNAME_CONFLICT_RETRY_LIMIT = 20; -// Slowdown request after every 5 requests to prevent 429 -const USERNAME_CONFLICT_RETRY_SLOWDOWN = 5; - -export const WaitingRoom = (props: WaitingRoomProps) => { - const { t: translate } = useTranslation(); - const history = useHistory(); - - const legalLinks = useContext(LegalLinksContext); - const { Stage } = useContext(GlobalComponentContext); - - const [isDataProtectionViewActive, setIsDataProtectionViewActive] = - useState(true); - const [username, setUsername] = useState(); - const [isConsultantAvailable, setIsConsultantAvailable] = - useState(); - const [isRequestInProgress, setIsRequestInProgress] = useState(false); - const [isErrorPageActive, setIsErrorPageActive] = useState(false); - const [isOverlayActive, setIsOverlayActive] = useState(false); - const [overlayItem, setOverlayItem] = useState(); - const { anonymousEnquiryAccepted, setAnonymousEnquiryAccepted } = - useContext(AnonymousEnquiryAcceptedContext); - const { anonymousConversationFinished, setAnonymousConversationFinished } = - useContext(AnonymousConversationFinishedContext); - const { - websocketConnectionDeactivated, - setWebsocketConnectionDeactivated - } = useContext(WebsocketConnectionDeactivatedContext); - const { anonymousConversationStarted, setAnonymousConversationStarted } = - useContext(AnonymousConversationStartedContext); - const registrationUrl = `/${props.consultingTypeSlug}/registration`; - - const getPseudoPasswordForUser = (rc_uid) => { - let pseudoPassword = localStorage.getItem(`pseudoPassword_${rc_uid}`); - if (!pseudoPassword) { - pseudoPassword = uuid(); - localStorage.setItem(`pseudoPassword_${rc_uid}`, pseudoPassword); - } - return pseudoPassword; - }; - - const afterRegistrationHandler = () => { - const rc_uid = getValueFromCookie('rc_uid'); - const pseuodPassword = getPseudoPasswordForUser(rc_uid); - handleE2EESetup(pseuodPassword, rc_uid, null, true).then(() => - props.onAnonymousRegistration() - ); - }; - - useEffect(() => { - const registeredUsername = getValueFromCookie('registeredUsername'); - const sessionId = getValueFromCookie('anonymousSessionId'); - - // handle a refresh as registered user and not initialize a new user - if (registeredUsername && getValueFromCookie('keycloak') && sessionId) { - setIsDataProtectionViewActive(false); - setUsername(registeredUsername); - handleTokenRefresh() - .then(afterRegistrationHandler) - .then(() => { - return apiAnonymousConversationAvailability( - parseInt(sessionId, 10) - ); - }) - .then( - (response: AnonymousConversationAvailabilityInterface) => { - setIsConsultantAvailable( - response.numAvailableConsultants > 0 - ); - } - ); - } - - document.title = `${translate( - 'anonymous.waitingroom.title.start' - )} ${capitalizeFirstLetter(props.consultingTypeSlug)}`; - }, []); // eslint-disable-line react-hooks/exhaustive-deps - - useEffect(() => { - if (anonymousEnquiryAccepted) { - setOverlayItem(acceptanceOverlayItem); - setIsOverlayActive(true); - setAnonymousEnquiryAccepted(false); - } - }, [anonymousEnquiryAccepted, setAnonymousEnquiryAccepted]); - - useEffect(() => { - if (anonymousConversationStarted) { - setAnonymousConversationStarted(false); - } - }, [anonymousConversationStarted, setAnonymousConversationStarted]); - - useEffect(() => { - if (anonymousConversationFinished === 'NEW') { - setOverlayItem(rejectionOverlayItem); - setIsOverlayActive(true); - removeAllCookies(); - } else { - setIsOverlayActive(false); - } - }, [anonymousConversationFinished, setAnonymousConversationFinished]); - - useEffect(() => { - if (websocketConnectionDeactivated) { - setIsErrorPageActive(true); - setWebsocketConnectionDeactivated(null); - } - }, [websocketConnectionDeactivated, setWebsocketConnectionDeactivated]); - - const getUsernameText = () => { - return ` - ${translate('anonymous.waitingroom.username.text')} -
- ${ - username - ? username - : `${translate( - 'anonymous.waitingroom.username.loading' - )}` - } -
- `; - }; - - const confirmButton: ButtonItem = { - label: translate('anonymous.waitingroom.dataProtection.button'), - type: BUTTON_TYPES.PRIMARY - }; - - const reloadButton: ButtonItem = { - label: translate('anonymous.waitingroom.errorPage.button'), - type: BUTTON_TYPES.PRIMARY - }; - - const retryCount = useRef(1); - const registerAnonymous = useCallback(() => { - return apiPostAnonymousRegistration(props.consultingTypeId).catch( - (err: Error) => { - if ( - err.message === FETCH_ERRORS.CONFLICT && - retryCount.current <= USERNAME_CONFLICT_RETRY_LIMIT - ) { - retryCount.current += 1; - return new Promise( - (resolve) => { - setTimeout( - () => { - resolve(registerAnonymous()); - }, - Math.ceil( - retryCount.current / - USERNAME_CONFLICT_RETRY_SLOWDOWN - ) * 500 - ); - } - ); - } else { - throw err; - } - } - ); - }, [props.consultingTypeId]); - - const handleConfirmButton = () => { - if (!isRequestInProgress) { - setIsRequestInProgress(true); - setIsDataProtectionViewActive(false); - window.scrollTo(0, 0); - registerAnonymous() - .then((response: AnonymousRegistrationResponse) => { - const decodedUsername = decodeUsername(response.userName); - setUsername(decodedUsername); - setValueInCookie('registeredUsername', decodedUsername); - setValueInCookie('rc_token', response.rcToken); - setValueInCookie('rc_uid', response.rcUserId); - setValueInCookie( - 'anonymousSessionId', - `${response.sessionId}` - ); - - setTokens( - response.accessToken, - response.expiresIn, - response.refreshToken, - response.refreshExpiresIn - ); - - handleTokenRefresh().then(afterRegistrationHandler); - return response.sessionId; - }) - .then(apiAnonymousConversationAvailability) - .then( - (response: AnonymousConversationAvailabilityInterface) => { - setIsConsultantAvailable( - response.numAvailableConsultants > 0 - ); - } - ) - .catch((err: Error) => { - console.log(err); - }) - .finally(() => { - retryCount.current = 1; - setIsRequestInProgress(false); - }); - } - }; - - const handleReloadButton = () => { - window.location.reload(); - }; - - const handleOverlayAction = (buttonFunction: string) => { - if (buttonFunction === OVERLAY_FUNCTIONS.REDIRECT) { - history.push(`/app`); - deleteCookieByName('registeredUsername'); - } else if (buttonFunction === OVERLAY_FUNCTIONS.REDIRECT_TO_URL) { - window.location.href = registrationUrl; - } - }; - - const getContent = () => { - if (isDataProtectionViewActive) { - return ( - - } - > - - legalLink.registration} - legalLinks={legalLinks} - params={{ aid: null }} - > - {(label, url) => ( - - - - )} - - -
@@ -277,6 +283,7 @@

Ohh!

width: 40vw; height: 40vw; } + .errorPage__headline { font-size: 40px; } @@ -337,6 +344,7 @@

Ohh!

from { opacity: 0; } + to { opacity: 1; } diff --git a/src/generated/userservice.d.ts b/src/generated/userservice.d.ts index 4249ac0a6..d1e0301dd 100644 --- a/src/generated/userservice.d.ts +++ b/src/generated/userservice.d.ts @@ -203,11 +203,6 @@ declare namespace UserService { * false */ isTeamSession?: boolean; - /** - * example: - * true - */ - isMonitoring?: boolean; } export interface ConsultantSessionListResponseDTO { sessions: ConsultantSessionResponseDTO[]; @@ -313,9 +308,7 @@ declare namespace UserService { */ token?: string; } - export interface MonitoringDTO { - additionalProperties?: Properties; - } + export interface NewMessageNotificationDTO { /** * example: @@ -480,11 +473,6 @@ declare namespace UserService { * false */ isTeamSession?: boolean; - /** - * example: - * true - */ - monitoring?: boolean; /** * example: * ANONYMOUS @@ -929,22 +917,7 @@ declare namespace Paths { export interface $500 {} } } - namespace GetMonitoring { - namespace Parameters { - export type SessionId = number; // int64 - } - export interface PathParameters { - sessionId: Parameters.SessionId /* int64 */; - } - namespace Responses { - export type $200 = UserService.Schemas.MonitoringDTO; - export interface $204 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} - } - } + namespace GetSessionsForAuthenticatedConsultant { export interface HeaderParameters { RCToken: Parameters.RCToken; @@ -1241,22 +1214,7 @@ declare namespace Paths { export interface $500 {} } } - namespace UpdateMonitoring { - namespace Parameters { - export type SessionId = number; // int64 - } - export interface PathParameters { - sessionId: Parameters.SessionId /* int64 */; - } - export type RequestBody = UserService.Schemas.MonitoringDTO; - namespace Responses { - export interface $200 {} - export interface $400 {} - export interface $401 {} - export interface $403 {} - export interface $500 {} - } - } + namespace UpdatePassword { export type RequestBody = UserService.Schemas.PasswordDTO; namespace Responses { diff --git a/src/globalState/interfaces/ConsultingSessionDataInterface.ts b/src/globalState/interfaces/ConsultingSessionDataInterface.ts index f69a59034..d79354ca0 100644 --- a/src/globalState/interfaces/ConsultingSessionDataInterface.ts +++ b/src/globalState/interfaces/ConsultingSessionDataInterface.ts @@ -14,7 +14,6 @@ export interface ConsultingSessionDataInterface { gender: string; groupId: string; id: number; - isMonitoring: boolean; isTeamSession: boolean; mainTopic: TopicsDataInterface; postcode: string; diff --git a/src/resources/i18n/de/common.json b/src/resources/i18n/de/common.json index be687102c..c3da6261e 100644 --- a/src/resources/i18n/de/common.json +++ b/src/resources/i18n/de/common.json @@ -487,7 +487,7 @@ }, "successOverlay": { "button": "Schließen", - "headline": "Sie haben Ihren Account bei der Diakonie Beratung erfolgreich gelöscht." + "headline": "Sie haben Ihren Account bei der Caritas Beratung erfolgreich gelöscht." } }, "deleteSession": { @@ -1881,7 +1881,7 @@ "success": { "button": "Nachricht verfassen", "copy": "Sie haben sich erfolgreich registriert.", - "headline": "Herzlich willkommen
bei der Beratung der Diakonie." + "headline": "Herzlich willkommen
bei der Beratung der Caritas." } }, "overline": "Willkommen bei der Online-Beratung", @@ -1969,7 +1969,7 @@ "buttonLabel": "Registrieren", "helperText": "Neu bei der Online-Beratung?" }, - "subline": "So läuft die Beratung der Diakonie ab", + "subline": "So läuft die Beratung der Caritas ab", "login": { "buttonLabel": "Einloggen", "helperText": "Bereits registriert?" @@ -2802,10 +2802,10 @@ } }, "consultingTypes": { - "title": "Willkommen bei den Online-Beratungsangeboten der Diakonie", + "title": "Willkommen bei den Online-Beratungsangeboten der Caritas", "intro": "Ich suche Beratung für folgendes Thema:", "selectGroup": "Bitte Thema auswählen", - "learnMore": "Mehr über den Ablauf bei der Beratung der Diakonie erfahren", + "learnMore": "Mehr über den Ablauf bei der Beratung der Caritas erfahren", "info": "Info", "details": { "explanation": { @@ -2814,72 +2814,9 @@ } }, "overlay": { - "title": "So läuft die Beratung der Diakonie ab", + "title": "So läuft die Beratung der Caritas ab", "close": "Schliessen" }, "register": "Registrieren" - }, - "dataProtection": { - "title": "Datenschutz", - "subtitle1": "Allgemeine Hinweise", - "title1": "Zielsetzung und verantwortliche Stelle", - "text1": "Für uns ist der Schutz Ihrer im Rahmen der Nutzung unserer Webangebote bereitgestellten \npersonenbezogenen Daten ein wichtiges Anliegen. \nDeshalb möchten wir Sie nachfolgend über die Art, den Umfang und Zweck der Erhebung und Verwendung \nvon Daten sowie Verwendung von Cookies innerhalb unseres Internetangebotes und mit diesem \nzusammenhängenden Datenerhebung und -verwendung informieren.

\nVerantwortliche Stelle im Sinne der Datenschutzvorschriften ist das Evangelische Werk für Diakonie \nund Entwicklung e.V., Caroline-Michaelis-Str.1, 10115 Berlin, \nImpressum (nachfolgend bezeichnet als \"Diakonie Deutschland\", \"wir\" oder \"uns\").", - "title2": "Grundsätzliche Angaben zur Datenverarbeitung", - "text2": "Grundlage unserer Datenverarbeitung sind die geltenden Datenschutznormen, insbesondere das Kirchengesetz über den Datenschutz der Evangelischen Kirche in Deutschland (DSG-EKD).

\nDie nachfolgende Bezeichnung als \"Nutzer\", umfasst sowohl unsere Mitglieder, Spender als auch die Besucher unserer Onlineangebote und ist geschlechtsneutral zu verstehen.

\nNeben dieser Datenschutzerklärung kann unser Internetangebot weitere und speziellere Datenschutzhinweise enthalten, auf die Sie gesondert hingewiesen werden.

\nWir verarbeiten personenbezogene Daten der Nutzer nur unter Einhaltung der einschlägigen Datenschutzbestimmungen. Das bedeutet, die Daten der Nutzer werden nur beim Vorliegen einer gesetzlichen Erlaubnis oder Vorliegen einer Einwilligung verwendet.

\nWir treffen organisatorische, vertragliche und technische Sicherheitsmaßnahmen entsprechend dem Stand der Technik, um sicher zu stellen, dass die Vorschriften der Datenschutzgesetze eingehalten werden und um damit die durch uns verwalteten Daten gegen zufällige oder vorsätzliche Manipulationen, Verlust, Zerstörung oder gegen den Zugriff unberechtigter Personen zu schützen.", - "title3": "Verarbeitung personenbezogener Daten", - "text3": "Die personenbezogenen Daten der Nutzer werden, neben den in dieser Datenschutzerklärung ausdrücklich genannten Verwendungen, für die folgenden Zwecke verwendet:

\n
    \n
  • Die Wahrnehmung unserer satzungsmäßigen Aufgaben, Ausführung unserer Dienste-, Service- und Nutzerleistungen;
  • \n
  • technische und geschäftsbezogene Benachrichtigungen betreffend unserer Angebote.

  • \n
\nDie uns online zur Verfügung gestellten personenbezogenen Daten werden nur für die im konkreten Fall mitgeteilten Zwecke erhoben, verarbeitet und genutzt. Eine darüberhinausgehende Erhebung, Verarbeitung oder Nutzung erfolgt nur im Einklang mit dem Gesetz.

\nDabei ist die Verarbeitung gemäß § 6 DSG-EKD nur rechtmäßig, wenn mindestens eine der nachstehenden Bedingungen erfüllt ist:

\n
    \n
  1. eine Rechtsvorschrift erlaubt die Verarbeitung der personenbezogenen Daten oder ordnet sie an;
  2. \n
  3. die betroffene Person hat ihre Einwilligung zu der Verarbeitung der sie betreffenden personenbezogenen Daten für einen oder mehrere bestimmte Zwecke gegeben;
  4. \n
  5. die Verarbeitung ist zur Erfüllung der Aufgaben der verantwortlichen Stelle erforderlich, einschließlich der Ausübung kirchlicher Aufsicht,
  6. \n
  7. die Verarbeitung ist für die Wahrnehmung einer sonstigen Aufgabe erforderlich, die im kirchlichen Interesse liegt,
  8. \n
  9. die Verarbeitung ist für die Erfüllung eines Vertrags, dessen Vertragspartei die betroffene Person ist, oder zur Durchführung vorvertraglicher Maßnahmen erforderlich, die auf Anfrage der betroffenen Person erfolgt;
  10. \n
  11. die Verarbeitung ist zur Erfüllung einer rechtlichen Verpflichtung erforderlich, der die kirchliche Stelle unterliegt;
  12. \n
  13. die Verarbeitung ist erforderlich, um lebenswichtige Interessen der betroffenen Person oder einer anderen natürlichen Person zu schützen;
  14. \n
  15. die Verarbeitung ist zur Wahrung der berechtigten Interessen eines Dritten erforderlich, sofern nicht die schutzwürdigen Interessen der betroffenen Person überwiegen, insbesondere dann, wenn diese minderjährig ist.
  16. \n

\nWir übermitteln Daten ferner an Dritte, wenn dies auf Grundlage einer Einwilligung geschieht oder dies für Abrechnungszwecke (z.B. Durchführung von Banktransaktionen oder postalischer Versand von Waren und Rechnungen) oder sonst notwendig ist, um unsere vertraglichen Pflichten den Nutzern gegenüber zu erfüllen.

\nBei Kontaktaufnahme mit uns werden die Angaben zwecks Bearbeitung der Anfrage sowie für den Fall, dass Anschlussfragen entstehen, gespeichert.

\nSofern innerhalb des Internetangebotes die Möglichkeit zur Eingabe persönlicher oder geschäftlicher Daten (zum Beispiel im Rahmen einer persönlichen Registrierung, Bestellung, Anforderung oder Mitteilung) besteht, so erfolgt die Angabe dieser Daten seitens des Nutzers auf ausdrücklich freiwilliger Basis.

\nPersonenbezogene Daten werden gelöscht, sofern sie ihren Verwendungszweck erfüllt haben und der Löschung keine Aufbewahrungspflichten entgegenstehen.", - "title4": "Änderungen der Datenschutzerklärung", - "text4": "Wir behalten uns vor die Datenschutzerklärung zu ändern, um sie an geänderte Rechtslagen, oder bei Änderungen des Dienstes sowie der Datenverarbeitung anzupassen.

\nDie Nutzer werden daher gebeten sich regelmäßig über deren Inhalt zu informieren, insbesondere wenn sie erneut personenbezogene Informationen mitteilen.", - "title5": "Rechte der betroffenen Person", - "text5": "Sie haben das Recht über die personenbezogenen Daten, die von uns über sie gespeichert \nwurden, auf Antrag unentgeltlich Auskunft zu erhalten.

\nSie haben das Recht, Ihre datenschutzrechtliche Einwilligungserklärung jederzeit zu widerrufen \n(s.a. z.B. Newsletter). \nDurch den Widerruf der Einwilligung wird die Rechtmäßigkeit der aufgrund der Einwilligung bis \nzum Widerruf erfolgten Verarbeitung nicht berührt.

\nZusätzlich haben Sie in berechtigten Fällen das Recht auf Berichtigung, auf Löschung, auf \nEinschränkung der Verarbeitung, auf Datenübertragbarkeit sowie eines Widerspruchsrechts gegen \ndie Verarbeitung.

\nDie Kontaktdaten sind dem Impressum zu entnehmen.

\nIm Falle datenschutzrechtlicher Verstöße steht dem Betroffenen ein Beschwerderecht bei der\nzuständigen Aufsichtsbehörde zu.\nZuständige Aufsichtsbehörde ist die oder der

\nBeauftragte für den Datenschutz der EKD
\nLange Laube 20, 30159 Hannover
\nTelefon: 0511 768128-0
\nhttps://datenschutz.ekd.de", - "title6": "Ansprechpartner", - "text6": "Für Fragen zum Datenschutz wenden Sie sich bitte an den Betriebsbeauftragten für den Datenschutz im Evangelischen Werk für Diakonie und Entwicklung:

\nDie oder Der örtlich Beauftragte für den Datenschutz
\nCaroline-Michaelis-Str. 1
\n10115 Berlin
\nE-Mail: datenschutz@ewde.de", - "subtitle2": "Datenerfassung auf der Webseite", - "title7": "Was sind Cookies und Co?", - "subtitle7": "Web-Browser-Cookies", - "text7": "Cookies sind Informationen, die von unserem Webserver an Ihren Web-Browser übertragen und dort für einen späteren Abruf gespeichert werden. \nInformationen können zum Beispiel Ihre IP-Adresse oder eine andere Kennung, Ihren Browsertyp und Informationen über digitale Inhalte, mit denen Sie interagieren, enthalten. \nDurch das Speichern solcher Informationen können Webbrowser-Cookies Ihre Präferenzen und Einstellungen für Online-Dienste speichern und analysieren, wie Sie Online-Dienste nutzen.", - "title8": "Verwendung, Rechtsgrundlage und Zweck", - "subtitle8": "Technisch notwendige Cookies", - "text8": "Die Verwendung technisch notweniger Cookies dient dazu, die Nutzung der Webseiten für die Webseitenbesucher zu vereinfachen. \nEinige Funktionen unserer Webseite erfordern den Einsatz von technisch notwendigen Cookies. \nDer Browser des Nutzers muss dafür auch nach einem Seitenwechsel wiedererkannt werden. \nWir erheben Daten über jeden Zugriff auf den Server, auf dem sich dieses Angebot befindet (so genannte Serverlogfiles).

\nDie Rechtsgrundlage für die Verarbeitung personenbezogener Daten unter Verwendung technisch notweniger Cookies ist § 6 Nr.4 DSG-EKD.

\nZu den Zugriffsdaten gehören Name der abgerufenen Webseite, Datei, Datum und Uhrzeit des Abrufs, übertragene Datenmenge, Meldung über erfolgreichen Abruf, Browsertyp nebst Version, das Betriebssystem des Nutzers, Referrer URL (die zuvor besuchte Seite), IP-Adresse und der anfragende Provider. Diese Daten werden nicht gespeichert, sind jedoch zur Laufzeit verfügbar.

\nWir verwenden die Protokolldaten ohne Zuordnung zur Person des Nutzers oder sonstiger Profilerstellung entsprechend den gesetzlichen Bestimmungen nur für statistische Auswertungen zum Zweck des Betriebs, der Sicherheit und der Optimierung des Angebotes. \nWir behalten uns jedoch vor, die Protokolldaten nachträglich zu überprüfen, wenn aufgrund konkreter Anhaltspunkte der berechtigte Verdacht einer rechtswidrigen Nutzung besteht. \nDie durch technisch notwendige Cookies erhobenen Nutzerdaten werden nicht zur Erstellung von Nutzerprofilen verwendet.", - "title9": "Dauer der Speicherung, Widerspruchs- und Beseitigungsmöglichkeit", - "text9": "Cookies werden auf dem Rechner des Nutzers gespeichert und von diesem an unserer Seite übermittelt. \nDaher haben Sie als Nutzer auch die volle Kontrolle über die Verwendung von Cookies. \nDurch eine Änderung der Einstellungen in Ihrem Internetbrowser können Sie die Übertragung von Cookies deaktivieren oder einschränken. \nBereits gespeicherte Cookies können jederzeit gelöscht werden. \nDies kann auch automatisiert erfolgen. Werden Cookies für unsere Website deaktiviert, können möglicherweise nicht mehr alle Funktionen der Website vollumfänglich genutzt werden.", - "title10": "Verwendete Cookies", - "text10": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
NameSpeicherdauerZugriff Dritter
CSRF-TOKENSessionnein
keycloakSessionnein
KEYCLOAK_LOCALESessionnein
rc_tokenSessionnein
rc_uidSessionnein
refreshTokenSessionnein
useInformalSessionnein
userRolesSessionnein
registeredUsernameSessionnein
hideInfoBannerSessionnein
public_keySessionnein
private_keySessionnein
visitedSessionnein
anonymousSessionIdSessionnein
auth.access_token_valid_untilDauerhaftnein
auth.refresh_token_valid_untilDauerhaftnein
mk_*Dauerhaftnein
localeDauerhaftnein
releaseNoteDauerhaftnein
pseudoPassword_*Dauerhaftnein
\n", - "title11": "Registrierung und Kommunikation über die Beratungsplattform", - "text11": "Das Beratungsportal ist ein geschlossenes und verschlüsseltes System, über das Ratsuchende anonymen Kontakt zu einer Beratungsstelle der Diakonie herstellen können. \nDie Diakonie Deutschland stellt dieses System zur Verfügung und gewährleistet die technische Sicherheit, hat aber keinen Einblick in die Beratungsvorgänge. \nDiese liegen in der Verantwortung der einzelnen Beratungsstellen. \nBei Fragen zu einem Beratungsvorgang wenden Sie sich daher bitte direkt an die jeweilige Beratungsstelle.", - "title12": "Umfang und Zweck der Datenverarbeitung, Rechtsgrundlage", - "text12": "Ziel des Beratungsportals ist es, in der Online-Kommunikation einen Grad der Vertraulichkeit herzustellen, der mit einem Vier-Augen-Gespräch innerhalb einer Beratungsstelle vergleichbar ist.

\nAuf technischem Wege wird dabei sichergestellt, dass Beratungsanfragen nach der Fallverteilung nur von dem oder der Ratsuchenden und einer Beraterin oder einem Berater gelesen werden können. \nEin Mitlesen von Beratungsinhalten durch Dritte ist technisch nicht möglich.

\nBeratungsstellen haben zusätzlich die Möglichkeit einer Teamberatung. Alle Beraterinnen und Berater einer Teamberatungsstelle können die Beratung einsehen. Dies wird dem oder der Ratsuchenden vor der Beratungsanfrage angezeigt.

\nBei einer Videoberatung kann eine Beraterin oder ein Berater Dritte hinzuschalten, z.B. Dolmetscher. Die Zuschaltung erfolgt für die Ratsuchende oder den Ratsuchenden sichtbar.

\nZur Aufrechterhaltung des Mailserver-Betriebs, zur Fehlerdiagnose und zur Verhinderung von Missbrauch werden Mail-Server-Logs maximal 30 Tage gespeichert. \nZur Sicherstellung des Betriebs, zur Verhinderung von Missbrauch und zur Besucherauswertung werden IP-Adressen der Benutzer während der Session verarbeitet. Eine Speicherung der IP-Adressen erfolgt nicht.

\nRechtsgrundlage für die Verarbeitung der Daten ist bei Vorliegen einer Einwilligung § 6 Nr. 2 DSG-EKD.", - "title13": "Anonymität", - "text13": "Ratsuchende brauchen ihren Namen nicht anzugeben, es wird lediglich ein Benutzername zur Identifizierung des oder der Ratsuchenden verlangt. \nDazu kann ein frei wählbares Pseudonym genutzt werden, welches keinen Rückschluss auf den tatsächlichen Namen zulässt.

\nRatsuchende können darüber hinaus freiwillig eine eigene E-Mail-Adresse angeben, an die sie automatisierte Benachrichtigungen erhalten, sobald eine Antwort auf Ihre Anfrage vorliegt. Diese E-Mail-Adresse ist von den Beraterinnen oder Beratern nicht zu sehen und es werden niemals Beratungsinhalte an diese E-Mail-Adresse gesendet.

\nDie IP-Adresse von Ratsuchenden wird nicht zusammen mit der Anfrage gespeichert.

\nEs werden keine Benutzerprofile angelegt, die es ermöglichen, eine Verbindung zwischen verschiedene Anfragen herzustellen.", - "title14": "Datenlöschung", - "text14": "Alle Nachrichten einer Anfrage werden automatisch 180 Tage nach der letzten Nachricht gelöscht. \nDurch die \"Schutzfrist\" von 180 Tagen ist gewährleistet, dass eine Anfrage auch dann fortgesetzt werden kann, wenn sie durch Urlaub oder Krankheit der Beraterin, des Beraters, des oder der Ratsuchenden einige Wochen unterbrochen wird.

\nEventuelle Dokumentations- und Archivierungspflichten verbleiben bei der Beratungsstelle.", - "text15": "Stand der Datenschutzerklärung: November 2022" - }, - "imprint": { - "title": "Impressum", - "title1": "Anbieterkennzeichnung gemäß den gesetzlichen Bestimmungen", - "text1": "Diakonie Deutschland
\nEvangelisches Werk für Diakonie und Entwicklung e.V.
\nCaroline-Michaelis-Str. 1
\n10115 Berlin

\nTelefon: 030 65211-0
\nTelefax: 030 65211-3333
\nE-Mail: diakonie@diakonie.de", - "title2": "Das Werk wird durch den Vorstand vertreten. Er besteht aus folgenden Mitgliedern", - "text2": "Vorsitzende: Präsidentin Pfarrerin Dr. Dagmar Pruin
\nstellvertretender Vorsitzender: Präsident Pfarrer Rüdiger Schuch

\nDr. Jörg Kruttschnitt
\nMaria Loheide

\nJeweils zwei Mitglieder des Vorstandes vertreten das Evangelische Werk für Diakonie und Entwicklung e.V. im Rechtsverkehr gemeinsam.", - "title3": "Registergericht", - "text3": "Amtsgericht Berlin-Charlottenburg, Vereinsregister 31924 B

\nUSt-IdNr.: DE 147801862

\nDas Evangelische Werk für Diakonie und Entwicklung verfolgt ausschließlich und unmittelbar gemeinnützige, mildtätige und kirchliche Zwecke im Sinne des Abschnitts \"steuerbegünstigte Zwecke\" der Abgabenordnung.", - "title4": "Verantwortlich für den Web-Auftritt", - "text4": "Dr. Thomas Schiller
\nLeiter Kommunikation
\nEvangelisches Werk für Diakonie und Entwicklung e.V.
\nCaroline-Michaelis-Str.1
\n10115 Berlin

\nTelefon: 030 65211-1356
\nFax: 030 65211-3356
\nE-Mail: thomas.schiller@diakonie.de", - "title5": "Copyright-Hinweis", - "text5": "Alle auf unseren Seiten verwendeten Bilder, Fotos, Logos, Texte etc. unterliegen dem Copyright des Evangelischen Werkes für Diakonie und Entwicklung e.V. bzw. von Dritten. Sie dürfen nicht bzw. nur nach Rücksprache mit der Redaktion weiter verwendet werden. Die verschiedenen Logos der Diakonie sowie das Kronenkreuz sind eingetragene Marken, deren Eigentümer das Evangelische Werk für Diakonie und Entwicklung e.V. ist. Die unberechtigte Nutzung und Verwendung ist unzulässig.", - "title6": "Rechtlicher Hinweis zur Haftung", - "text6": "Die Inhalte externer Links werden von uns sorgfältig geprüft. Wir übernehmen dennoch keine Haftung für die Inhalte der mit oder von unserer Website verlinkten externen Seiten. Für die Inhalte dieser Seiten sind ausschließlich deren Anbieter verantwortlich.

\nDie Diakonie Deutschland ist Dachorganisation der Diakonie in Deutschland. Als evangelischer Wohlfahrtsverband ist sie der soziale Dienst der Kirchen in Deutschland und vertritt die Interessen der Menschen für die die diakonischen Dienste und Einrichtungen tätig sind. Der Online-Auftritt richtet sich deshalb an alle, die an den Angeboten der Diakonie in Deutschland interessiert sind." - }, - "monitoring": { - "monitoringU25": { - "deceaseLovedOne": "Tod einer oder eines Nahestehenden", - "concernLovedOne": "Sorge um Nahestehende:n", - "relationshipRelative": "Beziehungssituation mit Angehörige:n", - "noAnswer": "Klient:in hat sich nicht mehr gemeldet", - "partnerLivingCommunity": "mit Partner:in in WG", - "concern": "Sorge um Suizidgefährdete:n", - "noFirstAnswer": "Klient:in hat auf Erstmail nicht reagiert", - "helpfulness": "Wie hilfreich war der Kontakt für Klient:in?" - } } } diff --git a/src/resources/i18n/de@informal/common.json b/src/resources/i18n/de@informal/common.json index 29b7faec5..dbea4a679 100644 --- a/src/resources/i18n/de@informal/common.json +++ b/src/resources/i18n/de@informal/common.json @@ -118,7 +118,7 @@ } }, "successOverlay": { - "headline": "Du hast Deinen Account bei der Diakonie Beratung erfolgreich gelöscht." + "headline": "Du hast Deinen Account bei der Caritas Beratung erfolgreich gelöscht." } }, "deleteSession": { From 2a98043b785a2c3556a24512d37a57d1a3eb4a45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Tue, 17 Sep 2024 15:08:48 +0200 Subject: [PATCH 40/49] feat(caritas-theme): remove release notes, update public assets and cypress tests --- .storybook/preview.tsx | 2 +- cypress/cypress.json | 12 +++++++++++ cypress/e2e/login.cy.ts | 10 +++++----- public/favicon.ico | Bin 22382 -> 1150 bytes public/logo192.png | Bin 2129 -> 13086 bytes public/logo512.png | Bin 5904 -> 43184 bytes public/manifest.json | 4 ++-- public/releases/19700101001.md | 26 ------------------------ public/releases/20220427001.md | 35 --------------------------------- public/releases/20220505001.md | 20 ------------------- public/releases/20221124001.md | 15 -------------- public/releases/20221212001.md | 3 --- public/releases/20230117001.md | 3 --- public/releases/releases.json | 18 +---------------- 14 files changed, 21 insertions(+), 127 deletions(-) create mode 100644 cypress/cypress.json delete mode 100644 public/releases/19700101001.md delete mode 100644 public/releases/20220427001.md delete mode 100644 public/releases/20220505001.md delete mode 100644 public/releases/20221124001.md delete mode 100644 public/releases/20221212001.md delete mode 100644 public/releases/20230117001.md diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index d07a75576..f438d8f7b 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -4,7 +4,7 @@ import i18n from 'i18next'; import { ThemeProvider } from '@mui/material'; import { Preview } from '@storybook/react'; import * as React from 'react'; -import theme from '../src/extensions/theme'; +import theme from '../src/resources/scripts/theme'; import { config } from '../src/resources/scripts/config'; import { LegalLinksProvider } from '../src/globalState/provider/LegalLinksProvider'; import { init, FALLBACK_LNG } from '../src/i18n'; diff --git a/cypress/cypress.json b/cypress/cypress.json new file mode 100644 index 000000000..e11cdcc0a --- /dev/null +++ b/cypress/cypress.json @@ -0,0 +1,12 @@ +{ + "e2e": { + "excludeSpecPattern": [ + "cypress/e2e/**/registration/base.cy.ts", + "cypress/e2e/**/registration/consultingType.cy.ts", + "cypress/e2e/**/registration/topic.cy.ts", + "cypress/e2e/**/messages/attachments/informal.cy.ts", + "cypress/e2e/**/login.cy.ts" + ], + "specPattern": ["src/extensions/cypress/e2e/**/*.cy.ts"] + } +} diff --git a/cypress/e2e/login.cy.ts b/cypress/e2e/login.cy.ts index be54d30d4..9154383c8 100644 --- a/cypress/e2e/login.cy.ts +++ b/cypress/e2e/login.cy.ts @@ -2,7 +2,8 @@ import { closeWebSocketServer, mockWebSocket, startWebSocketServer -} from '../support/websocket'; +} from '../../cypress/support/websocket'; +import { config } from '../../src/resources/scripts/config'; describe('Login', () => { before(() => { @@ -14,6 +15,7 @@ describe('Login', () => { }); beforeEach(() => { + cy.willReturn('frontend.settings', config); mockWebSocket(); }); @@ -23,11 +25,9 @@ describe('Login', () => { cy.get('#appRoot').should('exist'); }); - it('displays the login at the root', () => { + it('displays the consultingtype page at the root', () => { cy.visit('/'); - cy.contains('Login'); - cy.contains('Impressum'); - cy.contains('Datenschutzerklärung'); + cy.contains('Willkommen bei der Online-Beratung'); }); it('displays the login for resorts', () => { diff --git a/public/favicon.ico b/public/favicon.ico index 31709449cc17ea6bb6c15566c6e16ae2bd9ea359..416b50eedaa933aab024d2378ba40ab66e17236d 100644 GIT binary patch literal 1150 zcmbu8!7D^j6vnSuYgX2lHWnnYn8hTe6j8IFC`DK(DN<_6LRp9?B`aA-k}Nby(kKhI zZ1^u`JvHZezjwO5=bG0jZ#r}DJNJCwIp@3QIoA^Xayb|MceYUUY6o;&pjJbY#fh*>kqKV(W0Bt|7jVuWNC_FvM@Ji%u0qcXx~f z?8cgL^mhNo<0Cg1a=`^=yCgb0Z9dM3$-?6gjaoxrGdx=K_lSPHi@v>DKHk$jVgH;B z^obtsi++8IPL7GzYNFMu^#WIEOJd%v{9wsfz7u_XNbr>>(d#SYg`*js{KrQL{`|~% z;bz|mKRznTy**bfh8leR_hr$`3o~Mf4f}_e_`eu^hIsCo+|-CxnCJ5Mz)B3W72@fM zxuN&lo1gljCB_*u-Kc+jK8`%6CrSTk@9za&vhduw&y&{wV9)BNc4jLJj~@;+W|qAE e%pM%+Sq}T>`vadgc+e#6V~++NUukvjKlTlax=|hg literal 22382 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 diff --git a/public/logo192.png b/public/logo192.png index 9b0d39576e91bbac24725e17bd388aed86c3a5db..23a9a1fea340db4e1ca5cc34a556037c3e1742b5 100644 GIT binary patch literal 13086 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 Ki&u#n1pE&~{dOY& literal 2129 zcmc(gc{J3G8pnS#8H};3!wb-v&VJK3w%VxC2x&7vU=UbyCDZ=sTKFI+Vk6^g8J$5nz2U^Y!LAx(;r zsBS3%L$2m0N~+RVD~@r;$cJp1#VMjV08OrQ_aV7RWLEk*61HyOecl4BqA@V7ktA2>`c{#IR zJQ6D*TT=PA;KYdFMAiHH>r+eBtGxHi9}Vc3NKIYj>2`~e)ynD5Z`U@834zb4XvU1; zV{nwZ=^|$%XJb8uZR^3WxVtc#!gCThDL;|7PZg5x zwQWb#N!>8F9P~Pf@esRc=fh$BvJz3>xJka|Z-n8s_&8pxGYJ*``8$E+6sM3au=Izz zoG-a)foq zcf^iHxeV>`<;PjLYu`3GSpU73n-(_CMjw5XNyoO5uEjN`_||E&)0+h)HIW55XJCd% zd@bZvx&n=-i@gep#cEkqWj(oauZPo*XR9sC7BzsSNsYd4cBVZ$)XZk)4GEA_i~pA+ zVHZxJ>zH4r2g4*)Qz(oG$hV#_Q)X4av(Cg$*}^c$^CGpiCX~(n^Q$g;0J9Ol#lN6& zf7`&%)|wF%4Ecc&HxTmc67$mq?Ikt6c-t`eFkKGCUW+H@)2|tmq^7h`sFOo3yBvocs=xh4}(Fg$5f+70-u6Dt53@*Uv)~MA*=5M$Ui{ zm>yVPpxrif`C28-{VY4Fm-MhGK?XfNH5wMKE`k+Rs8=}x{t3>Xj+#oS+%C5PZ7Ma> zP?JRoq?*a%c;F~fZOql4U7d|TpyC9pRBQVj#%n_3&~oq>Wo?|VHu34Pj4 zy&Bc@e73hk4oqv{9J;mMIXh(MVn$x7m{n}bSA5zlqa6&L96DG7du$yO#6KFn7ycUI z0Su3AFF@AYuO%|wGQdoQcyQltr}2!F?5l{V1Wgy9Q9Pn6Yj{5g@qbsh(j0OtMJ8Vw zrL(+Z&xvJJa{_wBzoy`r zS8NpSmCI2%h2TpoE#o>*<^{4ApPv|pDvLUkUP{uPs?y(KS8KkA}imm3qU1xR3bL~+X zoiVBl)j85Av~7f7xl4#oM@81w_#)KOLS9q+nf|ED44<%N_+EOonMl)L7!`SxSmd@# z4fowV1D7GHebih?a>m!DnZd1ZwyVLoPsW`KA=N|vN-tWH`Wrsg2-87Q-Kitt1EbeH z5Z7LlF;gj{}utg<+ai=N<+EssUE$%W;8V6VqjPi)@9uEBdDvYg@%~Lck F`QHwxh0Xu~ diff --git a/public/logo512.png b/public/logo512.png index 060f96f19f171d973efd74c099532f7de686d6d5..1413c0f25cc421f819a5ea1b245dc5ac4eb688b8 100644 GIT binary patch literal 43184 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 ISu?-?0dG}Gu>b%7 literal 5904 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 VW{23OY~^_erY06gi;O8({tHE#F?Rp} diff --git a/public/manifest.json b/public/manifest.json index d0b604b92..139e5c67e 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,5 +1,5 @@ { - "short_name": "Caritas Online-Beratung", + "short_name": "Online-Beratung", "name": "Caritas Online-Beratung – Online. Anonym. Sicher.", "icons": [ { @@ -20,6 +20,6 @@ ], "start_url": ".", "display": "standalone", - "theme_color": "#5a2572", + "theme_color": "#cc1e1c", "background_color": "#ffffff" } diff --git a/public/releases/19700101001.md b/public/releases/19700101001.md deleted file mode 100644 index 6ace49477..000000000 --- a/public/releases/19700101001.md +++ /dev/null @@ -1,26 +0,0 @@ -**Anzeigename** -Im Profil gibt es nun den Anzeigenamen den Sie frei wählen können. Dieser wird den Ratsuchenden angezeigt. [Verlinkung nach extern](https://www.google.de) - -**Feature Name** -Maximal zwei Sätze zur Erklärung des Features... Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore. [Verlinkung nach extern](https://www.google.de) - -**Feature Name** -Maximal zwei Sätze zur Erklärung des Features... Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore. - -**Anzeigename** -Im Profil gibt es nun den Anzeigenamen den Sie frei wählen können. Dieser wird den Ratsuchenden angezeigt. [Verlinkung nach extern](https://www.google.de) - -**Feature Name** -Maximal zwei Sätze zur Erklärung des Features... Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore. [Verlinkung nach extern](https://www.google.de) - -**Feature Name** -Maximal zwei Sätze zur Erklärung des Features... Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore. - -**Anzeigename** -Im Profil gibt es nun den Anzeigenamen den Sie frei wählen können. Dieser wird den Ratsuchenden angezeigt. [Verlinkung nach extern](https://www.google.de) - -**Feature Name** -Maximal zwei Sätze zur Erklärung des Features... Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore. [Verlinkung nach extern](https://www.google.de) - -**Feature Name** -Maximal zwei Sätze zur Erklärung des Features... Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore. diff --git a/public/releases/20220427001.md b/public/releases/20220427001.md deleted file mode 100644 index fc3fecf50..000000000 --- a/public/releases/20220427001.md +++ /dev/null @@ -1,35 +0,0 @@ -# Überschrift 1 - -**Anzeigename** -Im Profil gibt es nun den Anzeigenamen den Sie frei wählen können. Dieser wird den Ratsuchenden angezeigt. [Verlinkung nach extern](https://www.google.de) - -**Feature Name** -Maximal zwei Sätze zur Erklärung des Features... Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore. [Verlinkung nach extern](https://www.google.de) - -## Überschrift 2 - -Dies ist ein Absatz. ...Lorem ipsum dolor sit amet, _consetetur sadipscing_ elitr -Mit einem Linebreak zwischen drin. ...Lorem **ipsum dolor sit amet**, consetetur sadipscing elitr - -- Eine Aufzählungsliste -- ohne Nummerierung -- ...Lorem ipsum dolor sit amet, consetetur sadipscing - - eingerückt - - eingerückt - -### Überschrift 3 - -Dies ist ein Absatz. ...Lorem ipsum dolor sit amet, _consetetur sadipscing_ elitr -Mit einem Linebreak zwischen drin. ...Lorem **ipsum dolor sit amet**, consetetur sadipscing elitr - -1. Eine Aufzählungsliste -2. mit Numerierung -3. ...Lorem ipsum dolor sit amet, consetetur sadipscing - -Hier nochmal ein paar Textformatierungen: z.B. **fetter Text** oder _kursiver Text_. - -#### Überschrift 4 - -##### Überschrift 5 - -###### Überschrift 6 diff --git a/public/releases/20220505001.md b/public/releases/20220505001.md deleted file mode 100644 index 88313a17f..000000000 --- a/public/releases/20220505001.md +++ /dev/null @@ -1,20 +0,0 @@ -**Neuigkeiten-Fenster** -An dieser Stelle informieren wir Sie zukünftig über neue Funktionen und Änderungen im Beratungsportal. - -**Video-Termine** -Sie können Video-Termine jetzt auch unabhängig von Textberatungen planen und starten. Den zugehörigen Video-Link können Sie im Voraus an Ratsuchende versenden. Eine Registrierung ist für Ratsuchende an dieser Stelle nicht erforderlich. - -**Profil** -Das Profil wurde umgebaut, um es für Sie übersichtlicher zu gestalten. - -**QR-Code** -Neben Ihrem persönlichen Kontakt-Link und dem Direktlink der Beratungsstelle finden Sie jetzt auch einen entsprechenden QR-Code. - -**Anzeigename** -Im Profil können Sie Ihren Anzeigename, der bei Beratungen auf Seiten der Ratsuchenden erscheint, nun selbst festlegen. - -**2-Faktor-Authentifizierung** -Neben der 2-Faktor-Authentifizierung per App können Sie jetzt auch Ihre E-Mail-Adresse als zweiten Faktor nutzen. - -**Sicherheit der Video-Beratung** -Um die bestmögliche Verschlüsselung bei der Video-Beratung anzubieten, müssen Sie als Browser Chrome oder Edge nutzen. Wenn sich die Verschlüsselung in anderen Browsern wie Firefox zukünftig verbessert, werden wir diese natürlich hinzunehmen. diff --git a/public/releases/20221124001.md b/public/releases/20221124001.md deleted file mode 100644 index 271f6b97e..000000000 --- a/public/releases/20221124001.md +++ /dev/null @@ -1,15 +0,0 @@ -**Weitergabe von Beratungen** - -Sie können einen Beratungsvorgang nun an Kolleginnen und Kollegen weitergeben. Rufen Sie dazu eine laufende Beratung unter "Meine Beratungen" auf und klicken dann im Chatverlauf dieser Beratung rechts oben auf das Drei-Punkt-Menü. Dort wählen Sie "Ratsuchendenprofil" aus und können unter "Zuweisung" die Beratung an eine Kollegin oder einen Kollegen übergeben. Die ratsuchende Person bekommt daraufhin eine Systemnachricht und muss der Weitergabe zustimmen oder diese ablehnen. - -**Verpflichtende Zwei-Faktor-Authentifizierung** - -Um die Beratungsdaten noch stärker zu schützen, müssen Sie in Ihrem Account ab 1.2.2023 einen zweiten Faktor zur Anmeldung hinterlegt haben. Für Ratsuchende bleibt die Zwei-Faktor-Authentifizierung weiterhin freiwillig. - -**E-Mail-Benachrichtigungen** - -Wenn Sie im Beratungsportal eingeloggt sind, werden nun keine Benachrichtigungsmails bei laufenden Beratungen gesendet. Somit wird verhindert, dass Sie während eines Live-Chats im Hintergrund ständig E-Mails bekommen. Darüber hinaus können Sie in Ihrem Profil unter "Einstellungen" E-Mail-Benachrichtigungen für laufende Beratungen deaktivieren. Sie bekommen dann nur noch E-Mails bei Erstanfragen. - -**Mehrsprachige Oberfläche** - -Wir haben das Beratungsportal fit für die Mehrsprachigkeit gemacht. Im ersten Schritt ist neben Deutsch nun auch Englisch auswählbar. Bitte wundern Sie sich nicht über einige holprige Formulierungen, die Übersetzung haben wir bisher nur maschinell durchführen lassen. Im nächsten Schritt werden wir das Englisch verbessern und Stück für Stück auch weitere Sprachen hinterlegen. diff --git a/public/releases/20221212001.md b/public/releases/20221212001.md deleted file mode 100644 index 770a0736f..000000000 --- a/public/releases/20221212001.md +++ /dev/null @@ -1,3 +0,0 @@ -**Löschen einzelner Nachrichten und Dokumente** - -Es lassen sich nun eigene Nachrichten und gesendete Dokumente einzeln löschen. Klicken Sie dazu auf das Drei-Punkte-Menü direkt über einer Nachricht und wählen Sie "Löschen". diff --git a/public/releases/20230117001.md b/public/releases/20230117001.md deleted file mode 100644 index 88d8bdd0e..000000000 --- a/public/releases/20230117001.md +++ /dev/null @@ -1,3 +0,0 @@ -**Verpflichtende Zwei-Faktor-Authentifizierung aufgehoben** - -Da es in einigen Beratungsstellen zu verzögertem Empfang der Authentifizierungscodes kommt, haben wir die angekündigte Pflicht zur Zwei-Faktor-Authentifizierung vorerst aufgehoben. Sie können sich also weiterhin ohne zweiten Faktor einloggen bis wir die Probleme analysiert und ggf. auch mit den zuständigen IT-Abteilungen vor Ort behoben haben. diff --git a/public/releases/releases.json b/public/releases/releases.json index de9a3bf44..0967ef424 100644 --- a/public/releases/releases.json +++ b/public/releases/releases.json @@ -1,17 +1 @@ -{ - "20220427001": { - "file": "20220427001.md" - }, - "20220505001": { - "file": "20220505001.md" - }, - "20221124001": { - "file": "20221124001.md" - }, - "20221212001": { - "file": "20221212001.md" - }, - "20230117001": { - "file": "20230117001.md" - } -} +{} From 83e2c3bdf0c010a8781c73cf78956a0f014c6187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Tue, 17 Sep 2024 15:10:41 +0200 Subject: [PATCH 41/49] feat(caritas-theme): remove deprecated registration --- .../formAccordion/FormAccordion.tsx | 404 ------------------ .../formAccordion/FormAccordionItem.tsx | 78 ---- .../FormAccordionRegistrationText.tsx | 12 - .../formAccordion/formAccordion.styles.scss | 7 - .../formAccordionItem.styles.scss | 160 ------- .../formAccordionRegistrationText.styles.scss | 1 - .../registration/RegistrationAge.tsx | 59 --- .../registration/RegistrationForm.tsx | 291 ------------- .../registration/RegistrationPassword.tsx | 222 ---------- .../registration/RegistrationState.tsx | 58 --- .../registration/RegistrationUsername.tsx | 103 ----- src/components/registration/WelcomeScreen.tsx | 92 ---- .../registration/prefillPostcode.ts | 6 - .../registration/registrationForm.styles.scss | 133 ------ .../registrationPassword.styles.scss | 46 -- .../registration/welcomeScreen.styles.scss | 77 ---- 16 files changed, 1749 deletions(-) delete mode 100644 src/components/formAccordion/FormAccordion.tsx delete mode 100644 src/components/formAccordion/FormAccordionItem.tsx delete mode 100644 src/components/formAccordion/FormAccordionRegistrationText.tsx delete mode 100644 src/components/formAccordion/formAccordion.styles.scss delete mode 100644 src/components/formAccordion/formAccordionItem.styles.scss delete mode 100644 src/components/formAccordion/formAccordionRegistrationText.styles.scss delete mode 100644 src/components/registration/RegistrationAge.tsx delete mode 100644 src/components/registration/RegistrationForm.tsx delete mode 100644 src/components/registration/RegistrationPassword.tsx delete mode 100644 src/components/registration/RegistrationState.tsx delete mode 100644 src/components/registration/RegistrationUsername.tsx delete mode 100644 src/components/registration/WelcomeScreen.tsx delete mode 100644 src/components/registration/prefillPostcode.ts delete mode 100644 src/components/registration/registrationForm.styles.scss delete mode 100644 src/components/registration/registrationPassword.styles.scss delete mode 100644 src/components/registration/welcomeScreen.styles.scss diff --git a/src/components/formAccordion/FormAccordion.tsx b/src/components/formAccordion/FormAccordion.tsx deleted file mode 100644 index 90d9a3fdd..000000000 --- a/src/components/formAccordion/FormAccordion.tsx +++ /dev/null @@ -1,404 +0,0 @@ -import * as React from 'react'; -import { - Dispatch, - SetStateAction, - useCallback, - useContext, - useEffect, - useMemo, - useState -} from 'react'; -import './formAccordion.styles'; -import { useTenant, AgencySpecificContext } from '../../globalState'; -import { - RequiredComponentsInterface, - RegistrationNotesInterface -} from '../../globalState/interfaces'; -import { FormAccordionItem } from '../formAccordion/FormAccordionItem'; -import { RegistrationUsername } from '../registration/RegistrationUsername'; -import { RegistrationAge } from '../registration/RegistrationAge'; -import { RegistrationState } from '../registration/RegistrationState'; -import { RegistrationPassword } from '../registration/RegistrationPassword'; -import { - AccordionItemValidity, - VALIDITY_INITIAL, - VALIDITY_VALID -} from '../registration/registrationHelpers'; -import { MainTopicSelection } from '../mainTopicSelection/MainTopicSelection'; -import { useTranslation } from 'react-i18next'; -import { Checkbox } from '../checkbox/Checkbox'; -import { Button, BUTTON_TYPES, ButtonItem } from '../button/Button'; -import { FormAccordionRegistrationText } from './FormAccordionRegistrationText'; -import { setValueInCookie } from '../sessionCookie/accessSessionCookie'; -import { ProposedAgencies } from '../../containers/registration/components/ProposedAgencies/ProposedAgencies'; -import { useConsultantRegistrationData } from '../../containers/registration/hooks/useConsultantRegistrationData'; -import { FormAccordionData } from '../registration/RegistrationForm'; -import { UrlParamsContext } from '../../globalState/provider/UrlParamsProvider'; -import { TProvidedLegalLink } from '../../globalState/provider/LegalLinksProvider'; -import LegalLinks from '../legalLinks/LegalLinks'; -import { useAppConfig } from '../../hooks/useAppConfig'; - -interface FormAccordionProps { - formAccordionData: FormAccordionData; - isUsernameAlreadyInUse: boolean; - onChange: (data: Partial) => void; - onValidation: Dispatch>; - additionalStepsData?: RequiredComponentsInterface; - registrationNotes?: RegistrationNotesInterface; - legalLinks: TProvidedLegalLink[]; - handleSubmitButtonClick: Function; - isSubmitButtonDisabled: boolean; - setIsDataProtectionSelected: Dispatch>; - isDataProtectionSelected: boolean; -} - -export const FormAccordion = ({ - formAccordionData, - isUsernameAlreadyInUse, - onChange, - onValidation, - additionalStepsData, - registrationNotes, - legalLinks, - handleSubmitButtonClick, - isSubmitButtonDisabled, - setIsDataProtectionSelected, - isDataProtectionSelected -}: FormAccordionProps) => { - const { t: translate } = useTranslation(['common', 'consultingTypes']); - const tenantData = useTenant(); - const settings = useAppConfig(); - - const { consultingType, consultant } = useContext(UrlParamsContext); - const { autoSelectPostcode, autoSelectAgency } = - consultingType?.registration || - settings.registration.consultingTypeDefaults; - const { setSpecificAgency, specificAgency } = useContext( - AgencySpecificContext - ); - const { consultingTypes } = useConsultantRegistrationData({}); - - const [activeItem, setActiveItem] = useState(1); - - const topicsAreRequired = useMemo( - () => - tenantData?.settings?.topicsInRegistrationEnabled && - tenantData?.settings?.featureTopicsEnabled, - [tenantData?.settings] - ); - - const buttonItemSubmit: ButtonItem = { - label: translate('registration.submitButton.label'), - type: BUTTON_TYPES.PRIMARY - }; - - const [validity, setValidity] = useState({ - username: VALIDITY_INITIAL, - password: VALIDITY_INITIAL, - state: additionalStepsData?.state?.isEnabled - ? VALIDITY_INITIAL - : VALIDITY_VALID, - age: additionalStepsData?.age?.isEnabled - ? VALIDITY_INITIAL - : VALIDITY_VALID, - mainTopic: topicsAreRequired ? VALIDITY_INITIAL : VALIDITY_VALID, - agency: VALIDITY_INITIAL, - dataProtection: VALIDITY_INITIAL - }); - - useEffect(() => { - // different data protection between agencies - formAccordionData.agency?.tenantId && - setValueInCookie( - 'tenantId', - formAccordionData.agency?.tenantId - ? formAccordionData.agency?.tenantId?.toString() - : '0' - ); - formAccordionData.agency?.tenantId && - setIsDataProtectionSelected(false); - setSpecificAgency(formAccordionData.agency); - }, [ - formAccordionData.agency, - setSpecificAgency, - setIsDataProtectionSelected - ]); - - useEffect(() => { - onValidation( - Object.values(validity).every( - (validity) => validity === VALIDITY_VALID - ) - ); - }, [onValidation, validity]); - - const handleValidity = useCallback((key, value) => { - setValidity((prevState) => ({ - ...prevState, - [key]: value - })); - }, []); - - useEffect(() => { - if (isUsernameAlreadyInUse) { - setActiveItem(1); - } - }, [isUsernameAlreadyInUse]); - - useEffect(() => { - handleValidity( - 'dataProtection', - isDataProtectionSelected ? VALIDITY_VALID : VALIDITY_INITIAL - ); - }, [handleValidity, isDataProtectionSelected]); - - const handleKeyDown = (e, isLastInput = true, isFirstInput = true) => { - if ( - e.key === 'Tab' && - !e.shiftKey && - isLastInput && - activeItem !== accordionItemData.length - ) { - setActiveItem(activeItem + 1); - } else if ( - e.key === 'Tab' && - e.shiftKey && - isFirstInput && - activeItem !== 1 - ) { - setActiveItem(activeItem - 1); - } - }; - - const accordionItemData = [ - { - title: translate('registration.username.headline'), - nestedComponent: ( - onChange({ username })} - onValidityChange={(validity) => - handleValidity('username', validity) - } - onKeyDown={handleKeyDown} - /> - ), - isValid: validity.username - }, - { - title: translate('registration.password.headline'), - nestedComponent: ( - onChange({ password })} - onValidityChange={(validity) => - handleValidity('password', validity) - } - passwordNote={registrationNotes?.password} - onKeyDown={handleKeyDown} - /> - ), - isValid: validity.password - } - ]; - - if (topicsAreRequired) { - accordionItemData.push({ - title: translate('registration.mainTopic.headline'), - nestedComponent: ( - onChange({ mainTopic: topic })} - onValidityChange={handleValidity} - /> - ), - isValid: validity.mainTopic - }); - } - - const agencySelectionTitle = useMemo(() => { - let key = 'agency'; - if (consultant) { - key = - consultingTypes.length > 1 - ? 'consultingTypeAgencySelection.consultingType' - : 'consultingTypeAgencySelection.agency'; - } else if (!autoSelectPostcode) { - key = autoSelectAgency ? 'agencyPreselected' : 'agencySelection'; - } - return `registration.${key}.headline`; - }, [ - autoSelectPostcode, - consultant, - autoSelectAgency, - consultingTypes.length - ]); - - if (additionalStepsData?.age?.isEnabled) { - accordionItemData.push({ - title: translate('registration.age.headline'), - nestedComponent: ( - ({ - ...option, - label: translate( - [ - `consultingType.${consultingType.id}.requiredComponents.age.${option.value}`, - `consultingType.fallback.requiredComponents.age.${option.value}`, - option.label - ], - { ns: 'consultingTypes' } - ) - }) - ) - }} - onAgeChange={(age) => onChange({ age })} - onValidityChange={(validity) => - handleValidity('age', validity) - } - onKeyDown={handleKeyDown} - /> - ), - isValid: validity.age - }); - } - - if (additionalStepsData?.state?.isEnabled) { - // we want an array from 1 to 16 and the 0 at the end - let countiesArray = Array.from(Array(17).keys()); - countiesArray.push(countiesArray.shift()); - - accordionItemData.push({ - title: translate('registration.state.headline'), - nestedComponent: ( - ({ - value: `${value}`, - label: translate( - `registration.state.options.${value}` - ) - })) - }} - onStateChange={(state) => onChange({ state })} - onValidityChange={(validity) => - handleValidity('state', validity) - } - onKeyDown={handleKeyDown} - /> - ), - isValid: validity.state - }); - } - - accordionItemData.push({ - title: translate(agencySelectionTitle), - nestedComponent: ( - - ), - isValid: validity.agency - }); - - accordionItemData.push({ - title: translate('registration.form.title'), - nestedComponent: ( -
-
- - setIsDataProtectionSelected( - !isDataProtectionSelected - ) - } - onKeyPress={(event) => { - if (event.key === 'Enter') { - setIsDataProtectionSelected( - !isDataProtectionSelected - ); - } - }} - inputId={'dataProtectionCheckbox'} - name={'dataProtectionCheckbox'} - labelId={'dataProtectionLabel'} - checked={isDataProtectionSelected} - > - legalLink.registration} - legalLinks={legalLinks} - params={{ aid: specificAgency?.id }} - > - {(label, url) => ( - - - - )} - - -
- -
- ), - isValid: validity.dataProtection - }); - - const handleItemHeaderClick = (indexOfItem) => { - setActiveItem(indexOfItem); - }; - - return ( -
- {accordionItemData.map((accordionItem, i) => { - return ( - setActiveItem(i + 1)} - onItemHeaderClick={handleItemHeaderClick} - title={accordionItem.title} - nestedComponent={accordionItem.nestedComponent} - key={i} - isValid={accordionItem.isValid as AccordionItemValidity} - /> - ); - })} -
- ); -}; diff --git a/src/components/formAccordion/FormAccordionItem.tsx b/src/components/formAccordion/FormAccordionItem.tsx deleted file mode 100644 index 445838895..000000000 --- a/src/components/formAccordion/FormAccordionItem.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import * as React from 'react'; -import './formAccordionItem.styles'; -import { ReactComponent as ValidIcon } from '../../resources/img/icons/checkmark_filled.svg'; -import { ReactComponent as InvalidIcon } from '../../resources/img/icons/exclamation-mark.svg'; -import { Button, ButtonItem, BUTTON_TYPES } from '../button/Button'; -import { AccordionItemValidity } from '../registration/registrationHelpers'; -import { useTranslation } from 'react-i18next'; - -interface FormAccordionItemProps { - title: string; - nestedComponent: React.ReactNode; - index: number; - isActive: boolean; - onStepSubmit: Function; - onItemHeaderClick: Function; - isLastItem: boolean; - isValid: AccordionItemValidity; -} - -export const FormAccordionItem = (props: FormAccordionItemProps) => { - const { t: translate } = useTranslation(); - const handleStepSubmit = () => { - props.onStepSubmit(props.index); - }; - - const handleOnHeaderClick = () => { - props.onItemHeaderClick(props.index); - }; - - const buttonNextStep: ButtonItem = { - title: translate('registration.accordion.item.continueButton.title'), - label: translate('registration.accordion.item.continueButton.label'), - type: BUTTON_TYPES.SECONDARY - }; - - return ( -
-
- {props.index} -

{props.title}

- {props.isValid === 'valid' && ( - - )} - {props.isValid === 'invalid' && ( - - )} -
-
- {props.nestedComponent} - {!props.isLastItem && ( -
-
- ); -}; diff --git a/src/components/formAccordion/FormAccordionRegistrationText.tsx b/src/components/formAccordion/FormAccordionRegistrationText.tsx deleted file mode 100644 index 4a4d8b60e..000000000 --- a/src/components/formAccordion/FormAccordionRegistrationText.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { AgencyDataInterface } from '../../globalState/interfaces'; -import './formAccordionRegistrationText.styles'; - -interface FormAccordionRegistrationTextProps { - agency: AgencyDataInterface; -} - -export const FormAccordionRegistrationText = ( - props: FormAccordionRegistrationTextProps -) => { - return null; -}; diff --git a/src/components/formAccordion/formAccordion.styles.scss b/src/components/formAccordion/formAccordion.styles.scss deleted file mode 100644 index e1ed2245c..000000000 --- a/src/components/formAccordion/formAccordion.styles.scss +++ /dev/null @@ -1,7 +0,0 @@ -.formAccordion { - border-top: 1px solid $black-25-opacity; - - @include breakpoint($fromLarge) { - min-width: 560px; - } -} diff --git a/src/components/formAccordion/formAccordionItem.styles.scss b/src/components/formAccordion/formAccordionItem.styles.scss deleted file mode 100644 index 104e1ffbf..000000000 --- a/src/components/formAccordion/formAccordionItem.styles.scss +++ /dev/null @@ -1,160 +0,0 @@ -$form-accordion-item-title-color: var( - --skin-color-secondary-contrast-safe, - $secondary -) !default; -$form-accordion-title-font-weight: $font-weight-medium !default; -$form-accordion-item-input-margin-right: $grid-base-four !default; -$form-accordion-item-input-margin-left: 0 !default; - -.formAccordionItem { - width: 100%; - border-bottom: 1px solid $black-25-opacity; - - @include breakpoint($fromMedium) { - min-width: 560px; - } - - &__header { - position: relative; - display: flex; - align-items: center; - width: 100%; - cursor: pointer; - padding: $grid-base-three 0; - &:hover span { - color: var(--skin-color-primary-hover, $hover-primary); - cursor: pointer; - } - } - - &__index { - display: flex; - align-items: center; - justify-content: center; - width: $grid-base-four; - height: $grid-base-four; - margin-right: 12px; - border: $form-accordion-index-border; - border-radius: 100%; - font-weight: $font-weight-regular; - color: $text-high-emphasis; - } - - &__title { - font-weight: $font-weight-regular; - } - - &__validationIcon { - position: absolute; - top: $grid-base-four; - right: 0; - height: 24px; - width: 24px; - - &--valid { - fill: $form-success; - top: 35%; - } - - &--invalid { - fill: $form-error; - top: 35%; - } - } - - &__content { - display: none; - margin-bottom: $grid-base-four; - align-items: center; - transition: opacity 0.6s ease; - .text, - ul, - .button__wrapper { - margin-left: $registration-form-margin-left; - } - - ul .text { - margin-left: 0; - } - - .inputField, - .consultingTypeSelection__possibleConsultingTypes .select__wrapper, - .consultingTypeSelection__possibleConsultingTypes + .agencySelection { - margin-top: $grid-base-two; - margin-left: $form-accordion-item-input-margin-left; - - @include breakpoint($fromMedium) { - margin-right: $form-accordion-item-input-margin-right; - } - } - } - - .select__wrapper { - width: 100%; - - @include breakpoint($fromMedium) { - width: 320px; - } - } - &__nextbutton { - align-self: flex-end; - margin-top: $grid-base-three; - - @include breakpoint($fromMedium) { - margin-right: 0; - } - - .button__item { - white-space: nowrap; - min-width: 100px; - width: 100%; - max-width: 535px; - - @include breakpoint($fromMedium) { - width: auto; - } - } - - .button__item--disabled { - background-color: white; - border: 2px solid rgba(0, 0, 0, 0.4); - color: rgba(0, 0, 0, 0.4); - padding: 0; - } - } - - &--active & { - &__index { - background: $form-accordion-index-background-active; - border: none; - color: $form-accordion-index-color-active; - font-weight: $form-accordion-title-font-weight; - } - - &__title { - font-weight: $form-accordion-title-font-weight; - color: $form-accordion-index-background-active; - } - - &__content { - display: block; - transition: opacity 0.6s ease; - - @include breakpoint($fromMedium) { - display: flex; - justify-content: space-between; - } - } - &__header { - &:hover span { - color: $form-accordion-index-color-active; - } - } - } - - .inputField { - @include breakpoint($fromMedium) { - width: 65%; - } - } -} diff --git a/src/components/formAccordion/formAccordionRegistrationText.styles.scss b/src/components/formAccordion/formAccordionRegistrationText.styles.scss deleted file mode 100644 index 210bd14c7..000000000 --- a/src/components/formAccordion/formAccordionRegistrationText.styles.scss +++ /dev/null @@ -1 +0,0 @@ -/* Empty because it's not used at the moment */ diff --git a/src/components/registration/RegistrationAge.tsx b/src/components/registration/RegistrationAge.tsx deleted file mode 100644 index 0111f833a..000000000 --- a/src/components/registration/RegistrationAge.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import * as React from 'react'; -import { useEffect, useState } from 'react'; -import { SelectDropdown, SelectDropdownItem } from '../select/SelectDropdown'; -import { - AccordionItemValidity, - RegistrationDropdownSelectData, - VALIDITY_INITIAL, - VALIDITY_VALID -} from './registrationHelpers'; - -interface RegistrationAgeProps { - onAgeChange: Function; - onValidityChange: Function; - dropdownSelectData: RegistrationDropdownSelectData; - onKeyDown: Function; -} - -export const RegistrationAge = ({ - onValidityChange, - onAgeChange, - dropdownSelectData, - onKeyDown -}: RegistrationAgeProps) => { - const [age, setAge] = useState(); - const [isValid, setIsValid] = - useState(VALIDITY_INITIAL); - - useEffect(() => { - onValidityChange(isValid); - }, [isValid]); // eslint-disable-line react-hooks/exhaustive-deps - - useEffect(() => { - setIsValid(age ? VALIDITY_VALID : VALIDITY_INITIAL); - onAgeChange(age); - }, [age]); // eslint-disable-line react-hooks/exhaustive-deps - - const getOptionOfSelectedAge = () => { - return dropdownSelectData.options.filter( - (option: any) => option.value === age - )[0]; - }; - - const ageSelectDropdown: SelectDropdownItem = { - handleDropdownSelect: (e) => setAge(e.value), - id: 'ageSelect', - selectedOptions: dropdownSelectData.options, - selectInputLabel: dropdownSelectData.label, - useIconOption: false, - isSearchable: false, - menuPlacement: 'bottom', - defaultValue: getOptionOfSelectedAge() - }; - - return ( -
- -
- ); -}; diff --git a/src/components/registration/RegistrationForm.tsx b/src/components/registration/RegistrationForm.tsx deleted file mode 100644 index 5b39b10bd..000000000 --- a/src/components/registration/RegistrationForm.tsx +++ /dev/null @@ -1,291 +0,0 @@ -import * as React from 'react'; -import { useState, useEffect, useCallback, useContext } from 'react'; -import { BUTTON_TYPES } from '../button/Button'; -import { apiPostRegistration, FETCH_ERRORS, X_REASON } from '../../api'; -import { endpoints } from '../../resources/scripts/endpoints'; -import { Overlay, OVERLAY_FUNCTIONS, OverlayItem } from '../overlay/Overlay'; -import { redirectToApp } from './autoLogin'; -import { - NOTIFICATION_TYPE_ERROR, - NotificationsContext, - TenantContext, - useLocaleData -} from '../../globalState'; -import { - AgencyDataInterface, - ConsultingTypeInterface, - TopicsDataInterface -} from '../../globalState/interfaces'; -import { FormAccordion } from '../formAccordion/FormAccordion'; -import { ReactComponent as WelcomeIcon } from '../../resources/img/illustrations/welcome.svg'; -import './registrationForm.styles'; -import { - getErrorCaseForStatus, - redirectToErrorPage -} from '../error/errorHandling'; -import { useTranslation } from 'react-i18next'; -import { LegalLinksContext } from '../../globalState/provider/LegalLinksProvider'; -import { useAppConfig } from '../../hooks/useAppConfig'; -import { getTenantSettings } from '../../utils/tenantSettingsHelper'; -import { budibaseLogout } from '../budibase/budibaseLogout'; -import { getUrlParameter } from '../../utils/getUrlParameter'; -import { UrlParamsContext } from '../../globalState/provider/UrlParamsProvider'; -import { apiPostError, ERROR_LEVEL_ERROR } from '../../api/apiPostError'; - -export interface FormAccordionData { - username?: string; - password?: string; - agency?: AgencyDataInterface; - consultingType?: ConsultingTypeInterface; - mainTopic?: TopicsDataInterface; - postcode?: string; - state?: string; - age?: string; -} - -export const RegistrationForm = () => { - const { t: translate } = useTranslation(['common', 'consultingTypes']); - const { locale } = useLocaleData(); - const settings = useAppConfig(); - const postcode = getUrlParameter('postcode'); - - const legalLinks = useContext(LegalLinksContext); - const { addNotification } = useContext(NotificationsContext); - - const { agency, consultingType, consultant, topic, slugFallback } = - useContext(UrlParamsContext); - - const [formAccordionData, setFormAccordionData] = - useState(() => { - const initData = { - agency: agency || null, - consultingType: consultingType || null, - mainTopic: topic || null, - postcode: postcode - }; - - const { autoSelectPostcode } = - consultingType?.registration || - settings.registration.consultingTypeDefaults; - if ( - consultingType && - agency && - postcode === null && - autoSelectPostcode - ) { - initData.postcode = agency.postcode; - } - - return initData; - }); - const [formAccordionValid, setFormAccordionValid] = useState(false); - const [isUsernameAlreadyInUse, setIsUsernameAlreadyInUse] = - useState(false); - const [isDataProtectionSelected, setIsDataProtectionSelected] = - useState(false); - const [isSubmitButtonDisabled, setIsSubmitButtonDisabled] = useState(true); - const [overlayActive, setOverlayActive] = useState(false); - const [missingFieldsErrorPosted, setMissingFieldsErrorPosted] = useState< - string[] - >([]); - - const { tenant } = useContext(TenantContext); - const { featureToolsEnabled } = getTenantSettings(); - - // Logout from budibase - useEffect(() => { - featureToolsEnabled && budibaseLogout(); - }, [featureToolsEnabled]); - - useEffect(() => { - setIsSubmitButtonDisabled( - !(formAccordionValid && isDataProtectionSelected) - ); - }, [formAccordionValid, isDataProtectionSelected]); - - const overlayItemRegistrationSuccess: OverlayItem = { - svg: WelcomeIcon, - headline: translate('registration.overlay.success.headline'), - copy: translate('registration.overlay.success.copy'), - buttonSet: [ - { - label: translate('registration.overlay.success.button'), - function: OVERLAY_FUNCTIONS.REDIRECT_WITH_BLUR, - type: BUTTON_TYPES.PRIMARY - } - ] - }; - - const handleOverlayAction = (buttonFunction: string) => { - if (buttonFunction === OVERLAY_FUNCTIONS.REDIRECT_WITH_BLUR) { - redirectToApp(); - } - }; - - const handleSubmitButtonClick = () => { - setIsUsernameAlreadyInUse(false); - setIsSubmitButtonDisabled(true); - - const { autoSelectPostcode } = - formAccordionData.consultingType?.registration || - settings.registration.consultingTypeDefaults; - - const registrationData = { - username: formAccordionData.username, - password: encodeURIComponent(formAccordionData.password), - postcode: formAccordionData.postcode, - agencyId: formAccordionData?.agency.id.toString(), - termsAccepted: isDataProtectionSelected.toString(), - consultingType: formAccordionData.consultingType?.id?.toString(), - mainTopicId: formAccordionData.mainTopic?.id?.toString(), - preferredLanguage: locale, - ...(formAccordionData.state && { state: formAccordionData.state }), - ...(formAccordionData.age && { age: formAccordionData.age }), - ...(consultant && { consultantId: consultant.consultantId }), - ...(slugFallback && { - consultingType: - formAccordionData.agency.consultingTypeRel?.id?.toString(), - postcode: autoSelectPostcode - ? formAccordionData.agency.postcode - : formAccordionData.postcode - }) - }; - - const missingFields = [ - 'username', - 'password', - 'postcode', - 'agencyId', - 'termsAccepted', - 'consultingType' - ].filter( - (required) => - !registrationData[required] || registrationData[required] === '' - ); - if (missingFields.length > 0) { - addNotification({ - notificationType: NOTIFICATION_TYPE_ERROR, - title: translate( - 'registration.error.required_field_missing.title' - ), - text: translate( - 'registration.error.required_field_missing.text' - ) - }); - - // prevent sending error multiple times with the same fields. - if ( - missingFields - .filter((x) => !missingFieldsErrorPosted.includes(x)) - .concat( - missingFieldsErrorPosted.filter( - (x) => !missingFields.includes(x) - ) - ).length > 0 - ) { - const { agencyId, consultingType } = registrationData; - void apiPostError( - { - name: `REGISTRATION_MISSING_FIELDS`, - message: `User got error while trying to register (consultingTypeId: "${consultingType}", agencyId: "${agencyId}") because there where some fields (${missingFields.join( - ', ' - )}) missing.`, - level: ERROR_LEVEL_ERROR - }, - null - ); - } - - setMissingFieldsErrorPosted(missingFields); - setIsSubmitButtonDisabled(false); - return; - } - - apiPostRegistration( - endpoints.registerAsker, - registrationData, - settings.multitenancyWithSingleDomainEnabled, - tenant - ) - .then(() => setOverlayActive(true)) - .catch((errorRes) => { - if ( - errorRes.status === 409 && - errorRes.headers?.get(FETCH_ERRORS.X_REASON) === - X_REASON.USERNAME_NOT_AVAILABLE - ) { - setIsUsernameAlreadyInUse(true); - setIsSubmitButtonDisabled(true); - window.scrollTo({ top: 0 }); - return; - } - - const error = getErrorCaseForStatus(errorRes.status); - redirectToErrorPage(error); - }); - }; - - const handleChange = useCallback( - (data: Partial) => { - setFormAccordionData({ - ...formAccordionData, - ...data - }); - }, - [formAccordionData] - ); - - return ( - <> -
-

- {consultingType - ? translate( - [ - `consultingType.${consultingType.id}.titles.long`, - `consultingType.fallback.titles.long`, - consultingType.titles.long - ], - { ns: 'consultingTypes' } - ) - : translate('registration.overline')} -

-

- {translate('registration.headline')} -

- {consultant && ( -

{translate('registration.teaser.consultant')}

- )} - - {(consultingType || consultant) && ( - - )} - - - {overlayActive && ( - - )} - - ); -}; diff --git a/src/components/registration/RegistrationPassword.tsx b/src/components/registration/RegistrationPassword.tsx deleted file mode 100644 index 4719fcd15..000000000 --- a/src/components/registration/RegistrationPassword.tsx +++ /dev/null @@ -1,222 +0,0 @@ -import * as React from 'react'; -import { useEffect, useState } from 'react'; -import { - InputField, - InputFieldItem, - InputFieldLabelState -} from '../inputField/InputField'; -import { ReactComponent as LockIcon } from '../../resources/img/icons/lock.svg'; -import { LABEL_TYPES, Text } from '../text/Text'; -import { - inputValuesFit, - passwordCriteria, - validatePasswordCriteria -} from '../../utils/validateInputValue'; -import { - AccordionItemValidity, - VALIDITY_INITIAL, - VALIDITY_INVALID, - VALIDITY_VALID -} from './registrationHelpers'; -import './registrationPassword.styles'; -import { useTranslation } from 'react-i18next'; - -interface RegistrationPasswordProps { - onPasswordChange: Function; - onValidityChange: Function; - passwordNote: string; - onKeyDown?: Function; -} - -export const RegistrationPassword = ({ - onPasswordChange, - onValidityChange, - passwordNote, - onKeyDown -}: RegistrationPasswordProps) => { - const { t: translate } = useTranslation(); - const [isValid, setIsValid] = - useState(VALIDITY_INITIAL); - const [password, setPassword] = useState(''); - const [passwordLabel, setPasswordLabel] = useState(null); - const [passwordLabelState, setPasswordLabelState] = - useState(null); - const [passwordCriteriaValidation, setPasswordCriteriaValidation] = - useState(); - const [passwordConfirmation, setPasswordConfirmation] = - useState(''); - const [passwordConfirmationLabel, setPasswordConfirmationLabel] = - useState(null); - const [passwordConfirmationLabelState, setPasswordConfirmationLabelState] = - useState(null); - - useEffect(() => { - if (passwordCriteriaValidation) { - const areAllCriteriaValid = Object.values( - passwordCriteriaValidation - ).every((criteria) => criteria); - - if (password.length >= 1 && !areAllCriteriaValid) { - setPasswordLabelState(VALIDITY_INVALID); - setPasswordLabel(translate('registration.password.insecure')); - } else if (password.length >= 1) { - setPasswordLabelState(VALIDITY_VALID); - setPasswordLabel(translate('registration.password.secure')); - } else { - setPasswordLabelState(null); - setPasswordLabel(null); - } - } - }, [passwordCriteriaValidation, password, translate]); - - useEffect(() => { - let passwordFits = inputValuesFit(passwordConfirmation, password); - if (passwordConfirmation.length >= 1 && !passwordFits) { - setPasswordConfirmationLabelState(VALIDITY_INVALID); - setPasswordConfirmationLabel( - translate('registration.password.notSame') - ); - } else if (passwordConfirmation.length >= 1) { - setPasswordConfirmationLabelState(VALIDITY_VALID); - setPasswordConfirmationLabel( - translate('registration.password.same') - ); - } else { - setPasswordConfirmationLabelState(null); - setPasswordConfirmationLabel(null); - } - }, [passwordConfirmation, password, translate]); - - useEffect(() => { - onValidityChange(isValid); - }, [isValid]); // eslint-disable-line react-hooks/exhaustive-deps - - useEffect(() => { - onPasswordChange(password); - }, [password]); // eslint-disable-line react-hooks/exhaustive-deps - - useEffect(() => { - if ( - passwordLabelState === VALIDITY_VALID && - passwordConfirmationLabelState === VALIDITY_VALID - ) { - setIsValid(VALIDITY_VALID); - } else if (!passwordLabelState && !passwordConfirmationLabelState) { - setIsValid(VALIDITY_INITIAL); - } else { - setIsValid(VALIDITY_INVALID); - } - }, [passwordLabelState, passwordConfirmationLabelState]); - - const inputItemPassword: InputFieldItem = { - content: password, - icon: , - id: 'passwordInput', - label: passwordLabel - ? `${passwordLabel}` - : translate('registration.password.input.label'), - name: 'passwordInput', - type: 'password', - ...(passwordLabelState && { labelState: passwordLabelState }) - }; - - const inputItemPasswordConfirmation: InputFieldItem = { - content: passwordConfirmation, - icon: , - id: 'passwordConfirmation', - label: passwordConfirmationLabel - ? `${passwordConfirmationLabel}` - : translate('registration.password.confirmation.label'), - name: 'passwordConfirmation', - type: 'password', - ...(passwordConfirmationLabelState && { - labelState: passwordConfirmationLabelState - }) - }; - - const handlepasswordChange = (event) => { - setPasswordCriteriaValidation( - validatePasswordCriteria(event.target.value) - ); - setPassword(event.target.value); - }; - - const passwordCriteria = [ - { - content: translate('registration.password.criteria.upperLowerCase'), - isValidCondition: passwordCriteriaValidation?.hasUpperLowerCase - }, - { - content: translate('registration.password.criteria.number'), - isValidCondition: passwordCriteriaValidation?.hasNumber - }, - { - content: translate('registration.password.criteria.specialChar'), - isValidCondition: passwordCriteriaValidation?.hasSpecialChar - }, - { - content: translate('registration.password.criteria.length'), - isValidCondition: passwordCriteriaValidation?.hasMinLength - } - ]; - - const passwordCriteriaList = passwordCriteria.map((criteria, index) => { - return ( -
  • - {criteria.content} -
  • - ); - }); - - return ( -
    - -
      - {passwordCriteriaList} -
    - onKeyDown(e, false)} - /> - setPasswordConfirmation(e.target.value)} - onKeyDown={(e) => onKeyDown(e, true, false)} - /> - {passwordNote && ( -
    - -
    - )} -
    - ); -}; diff --git a/src/components/registration/RegistrationState.tsx b/src/components/registration/RegistrationState.tsx deleted file mode 100644 index 7fba86860..000000000 --- a/src/components/registration/RegistrationState.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import * as React from 'react'; -import { useEffect, useState } from 'react'; -import { SelectDropdown, SelectDropdownItem } from '../select/SelectDropdown'; -import { - AccordionItemValidity, - RegistrationDropdownSelectData, - VALIDITY_INITIAL, - VALIDITY_VALID -} from './registrationHelpers'; - -interface RegistrationStateProps { - onStateChange: Function; - onValidityChange: Function; - dropdownSelectData: RegistrationDropdownSelectData; - onKeyDown: Function; -} - -export const RegistrationState = ({ - onStateChange, - onValidityChange, - dropdownSelectData, - onKeyDown -}: RegistrationStateProps) => { - const [state, setState] = useState(); - const [isValid, setIsValid] = - useState(VALIDITY_INITIAL); - const stateData = dropdownSelectData.options; - - useEffect(() => { - onValidityChange(isValid); - }, [isValid]); // eslint-disable-line react-hooks/exhaustive-deps - - useEffect(() => { - state ? setIsValid(VALIDITY_VALID) : setIsValid(VALIDITY_INITIAL); - onStateChange(state); - }, [state]); // eslint-disable-line react-hooks/exhaustive-deps - - const getOptionOfSelectedState = () => { - return stateData.filter((option) => option.value === state)[0]; - }; - - const stateSelectDropdown: SelectDropdownItem = { - handleDropdownSelect: (e) => setState(e.value), - id: 'stateSelect', - selectedOptions: stateData, - selectInputLabel: dropdownSelectData.label, - useIconOption: false, - isSearchable: false, - menuPlacement: 'bottom', - defaultValue: getOptionOfSelectedState() - }; - - return ( -
    - -
    - ); -}; diff --git a/src/components/registration/RegistrationUsername.tsx b/src/components/registration/RegistrationUsername.tsx deleted file mode 100644 index d0570247e..000000000 --- a/src/components/registration/RegistrationUsername.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import * as React from 'react'; -import { useEffect, useState } from 'react'; -import { - InputField, - InputFieldItem, - InputFieldLabelState -} from '../inputField/InputField'; -import { ReactComponent as PersonIcon } from '../../resources/img/icons/person.svg'; -import { - AccordionItemValidity, - MIN_USERNAME_LENGTH, - VALIDITY_INITIAL, - VALIDITY_INVALID, - VALIDITY_VALID -} from './registrationHelpers'; -import { Text } from '../text/Text'; -import { useTranslation } from 'react-i18next'; - -interface RegistrationUsernameProps { - isUsernameAlreadyInUse: boolean; - onUsernameChange: Function; - onValidityChange: Function; - onKeyDown?: Function; -} - -export const RegistrationUsername = ({ - isUsernameAlreadyInUse, - onUsernameChange, - onValidityChange, - onKeyDown -}: RegistrationUsernameProps) => { - const { t: translate } = useTranslation(); - const [username, setUsername] = useState(''); - const [isValid, setIsValid] = - useState(VALIDITY_INITIAL); - const [labelContent, setLabelContent] = useState(null); - const [labelState, setLabelState] = useState(null); - - useEffect(() => { - if (isUsernameAlreadyInUse) { - setIsValid(VALIDITY_INVALID); - setLabelState(VALIDITY_INVALID); - setLabelContent(translate('registration.user.unavailable')); - } - }, [isUsernameAlreadyInUse, translate]); - - useEffect(() => { - onUsernameChange(username); - }, [username]); // eslint-disable-line react-hooks/exhaustive-deps - - useEffect(() => { - onValidityChange(isValid); - }, [isValid]); // eslint-disable-line react-hooks/exhaustive-deps - - const inputItemUsername: InputFieldItem = { - content: username, - icon: , - id: 'username', - label: labelContent - ? `${labelContent}` - : translate('registration.user.label'), - maxLength: 30, - name: 'username', - type: 'text', - ...(labelState && { labelState: labelState }) - }; - - const handleUsernameChange = (event) => { - validateUsername(event.target.value); - setUsername(event.target.value); - }; - - const validateUsername = (username) => { - if (username.length >= MIN_USERNAME_LENGTH) { - setIsValid(VALIDITY_VALID); - setLabelState(VALIDITY_VALID); - setLabelContent(translate('registration.user.suitable')); - } else if (username.length > 0) { - setIsValid(VALIDITY_INVALID); - setLabelState(VALIDITY_INVALID); - setLabelContent(translate('registration.user.unsuitable')); - } else { - setIsValid(VALIDITY_INITIAL); - setLabelState(null); - setLabelContent(null); - } - }; - - return ( -
    - - -
    - ); -}; diff --git a/src/components/registration/WelcomeScreen.tsx b/src/components/registration/WelcomeScreen.tsx deleted file mode 100644 index 641551471..000000000 --- a/src/components/registration/WelcomeScreen.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import * as React from 'react'; -import { Button, ButtonItem, BUTTON_TYPES } from '../button/Button'; -import { Text } from '../text/Text'; -import { Headline } from '../headline/Headline'; -import { ServiceExplanation } from '../serviceExplanation/ServiceExplanation'; -import { RegistrationWelcomeScreenInterface } from '../../globalState/interfaces'; -import './welcomeScreen.styles'; -import { useTranslation } from 'react-i18next'; -import { useHistory } from 'react-router-dom'; -import { useAppConfig } from '../../hooks/useAppConfig'; - -interface WelcomeScreenProps { - title: string; - handleForwardToRegistration: Function; - welcomeScreenConfig?: RegistrationWelcomeScreenInterface; - loginParams?: string; - consultingTypeId: number; - consultingTypeName: string; -} - -export const WelcomeScreen = ({ - title, - handleForwardToRegistration, - welcomeScreenConfig, - loginParams, - consultingTypeId, - consultingTypeName -}: WelcomeScreenProps) => { - const { t: translate } = useTranslation(); - const history = useHistory(); - const settings = useAppConfig(); - - const registrationButton: ButtonItem = { - label: translate('registration.welcomeScreen.register.buttonLabel'), - type: BUTTON_TYPES.PRIMARY - }; - - const loginButton: ButtonItem = { - label: translate('registration.login.label'), - type: BUTTON_TYPES.SECONDARY - }; - - return ( -
    - {consultingTypeName && - !settings.welcomeScreen.consultingType.hidden && ( -
    - {consultingTypeName}{' '} -
    - )} - -

    {translate('registration.welcomeScreen.subline')}

    - -
    -
    - -
    -
    - -
    -
    -
    - ); -}; diff --git a/src/components/registration/prefillPostcode.ts b/src/components/registration/prefillPostcode.ts deleted file mode 100644 index 110fccf75..000000000 --- a/src/components/registration/prefillPostcode.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const DEFAULT_POSTCODE = '00000'; - -export const redirectToRegistrationWithoutAid = () => { - const url = window.location.href; - window.location.href = url.split('?')[0]; -}; diff --git a/src/components/registration/registrationForm.styles.scss b/src/components/registration/registrationForm.styles.scss deleted file mode 100644 index d9e988e26..000000000 --- a/src/components/registration/registrationForm.styles.scss +++ /dev/null @@ -1,133 +0,0 @@ -$registration-form-overline-display: block !default; -$registration-form-headline-margin-bottom: 24px; - -.registrationForm { - margin: 32px 0; - max-width: $registration-form-max-width; - animation: fadeIn linear 0.5s; - - @keyframes fadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } - } - - &__dataProtection { - margin-left: 4px; - text-align: left; - - .checkbox__label { - line-height: $line-height-primary; - } - - .button-as-link { - border: none; - background: none; - padding: 0; - color: $link-color; - text-decoration: $link-text-decoration; - font-weight: $link-font-weight; - - &:hover { - color: var(--skin-color-primary-hover, $hover-primary); - text-decoration: $link-text-decoration-hover; - cursor: pointer; - } - - &:focus { - outline: $focus-outline; - outline-offset: 4px; - border-radius: 4px; - } - - &:focus:not(:focus-visible) { - outline: none; - } - } - - .checkbox__input { - &:focus { - outline: $focus-outline; - outline-offset: 5px; - } - - &:focus:not(:focus-visible) { - outline: none; - } - } - } - - &__submit { - margin-top: $grid-base-four; - - .button__item { - width: 100%; - } - - @include breakpoint($fromMedium) { - display: flex; - justify-content: flex-end; - - .button__item { - width: auto; - } - } - } - - &__overline, - &__headline { - margin-left: $registration-form-margin-left; - } - - &__overline { - display: $registration-form-overline-display; - color: $text-low-emphasis; - margin: 0; - font-size: $font-size-secondary; - font-weight: $font-weight-medium; - line-height: 14px; - letter-spacing: 1.5px; - text-transform: uppercase; - padding-bottom: $grid-base; - } - - &__headline { - margin-bottom: $registration-form-headline-margin-bottom; - } - - &__passwordNote { - margin: -20px $grid-base-five $grid-base-five 52px; - } - - &__contentRow { - margin: 0 auto $grid-base-five; - max-width: 690px; - } - - .select__wrapper { - padding: 0; - margin: 0; - margin-right: 32px; - max-width: 535px; - } - - .formWrapper__infoText { - &__text { - &--tertiary { - color: $tertiary; - } - } - } - - .select__content { - margin-right: 32px; - align-self: end; - } - - .text__registration_user { - margin-bottom: 24px; - } -} diff --git a/src/components/registration/registrationPassword.styles.scss b/src/components/registration/registrationPassword.styles.scss deleted file mode 100644 index b6dce1083..000000000 --- a/src/components/registration/registrationPassword.styles.scss +++ /dev/null @@ -1,46 +0,0 @@ -.registrationPassword { - &__validation { - text-align: left; - margin: $grid-base 0 0; - padding: 0; - list-style: none; - margin-bottom: 24px; - } - - &__validationItem { - display: flex; - align-items: center; - font-size: $font-size-primary; - line-height: $line-height-primary; - - &::before { - content: ''; - display: inline-block; - height: 5px; - width: 5px; - margin-left: 6px; - margin-right: 12px; - background-color: $form-secondary; - background-image: url('../../resources/img/icons/checkmark_circle.svg'); - border-radius: 100%; - } - - &--valid { - color: $form-success; - &::before { - height: 18px; - width: 18px; - margin-left: 0; - margin-right: 5px; - background-color: $white; - background-size: 18px 18px; - background-position: center; - } - } - } - - &__note { - margin-top: $grid-base-three; - width: 360px; - } -} diff --git a/src/components/registration/welcomeScreen.styles.scss b/src/components/registration/welcomeScreen.styles.scss deleted file mode 100644 index f59215f42..000000000 --- a/src/components/registration/welcomeScreen.styles.scss +++ /dev/null @@ -1,77 +0,0 @@ -$welcome-screen-button-text-align: center !default; - -.registrationWelcome { - margin: 0; - h2 { - margin-bottom: $grid-base-two; - } - - h4 { - line-height: 28px; - font-weight: 400; - } - - & > * { - max-width: 500px; - margin: auto; - } - - &__explanation, - &__buttonsWrapper { - margin: $grid-base-five auto 0; - max-width: 500px; - display: grid; - grid-template-columns: auto; - column-gap: $grid-base-three; - row-gap: $grid-base-three; - - @include breakpoint($fromMedium) { - margin: $grid-base-six auto 0; - grid-template-columns: auto auto; - row-gap: $grid-base-four; - width: 100%; - } - } - - &__buttonsWrapper { - border: 1px solid $border-default; - border-radius: $input-field-border-radius; - padding: $grid-base-four; - - .text { - text-align: $welcome-screen-button-text-align; - margin-bottom: 14px; - color: $text-high-emphasis; - font-weight: 600; - } - - .buttonWrapper { - text-align: center; - } - - button { - min-width: auto; - width: 100%; - } - - .button__wrapper { - &:focus { - outline: $focus-outline; - outline-offset: 4px; - } - } - - &:focus:not(:focus-visible) { - outline: none; - } - } - &__consultingType { - font-size: $font-size-secondary; - font-weight: $font-weight-medium; - line-height: 14px; - letter-spacing: 1.5px; - text-transform: uppercase; - padding-bottom: $grid-base; - color: $text-low-emphasis; - } -} From 4cdf9a57c9d38e3a2c76d835ed22ded802070a66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Tue, 17 Sep 2024 15:25:13 +0200 Subject: [PATCH 42/49] feat(caritas-theme): moved legal pages from extensions to core --- .../components/legalInformationLinks/Imprint.tsx | 4 ++-- .../components/legalInformationLinks/Privacy.tsx | 4 ++-- .../components/legalInformationLinks/TermsAndConditions.tsx | 5 ++--- .../components/legalPageWrapper/LegalPageWrapper.tsx | 0 .../components/legalPageWrapper/legalPageWrapper.styles.scss | 0 src/{extensions => resources/scripts}/theme.jsx | 0 src/{extensions => }/resources/scripts/util/htmlParser.tsx | 0 src/{extensions/resources => }/utils/useDocumentTitle.tsx | 0 8 files changed, 6 insertions(+), 7 deletions(-) rename src/{extensions => }/components/legalInformationLinks/Imprint.tsx (79%) rename src/{extensions => }/components/legalInformationLinks/Privacy.tsx (80%) rename src/{extensions => }/components/legalInformationLinks/TermsAndConditions.tsx (80%) rename src/{extensions => }/components/legalPageWrapper/LegalPageWrapper.tsx (100%) rename src/{extensions => }/components/legalPageWrapper/legalPageWrapper.styles.scss (100%) rename src/{extensions => resources/scripts}/theme.jsx (100%) rename src/{extensions => }/resources/scripts/util/htmlParser.tsx (100%) rename src/{extensions/resources => }/utils/useDocumentTitle.tsx (100%) diff --git a/src/extensions/components/legalInformationLinks/Imprint.tsx b/src/components/legalInformationLinks/Imprint.tsx similarity index 79% rename from src/extensions/components/legalInformationLinks/Imprint.tsx rename to src/components/legalInformationLinks/Imprint.tsx index 5b2634f15..67de1b37d 100644 --- a/src/extensions/components/legalInformationLinks/Imprint.tsx +++ b/src/components/legalInformationLinks/Imprint.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import { useTranslation } from 'react-i18next'; -import { useTenant } from '../../../..'; +import { useTenant } from '../../../'; +import useDocumentTitle from '../../utils/useDocumentTitle'; import { LegalPageWrapper } from '../legalPageWrapper/LegalPageWrapper'; -import useDocumentTitle from '../../resources/utils/useDocumentTitle'; export const Imprint = () => { const [t] = useTranslation(); diff --git a/src/extensions/components/legalInformationLinks/Privacy.tsx b/src/components/legalInformationLinks/Privacy.tsx similarity index 80% rename from src/extensions/components/legalInformationLinks/Privacy.tsx rename to src/components/legalInformationLinks/Privacy.tsx index 530db948a..521b39c33 100644 --- a/src/extensions/components/legalInformationLinks/Privacy.tsx +++ b/src/components/legalInformationLinks/Privacy.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import { useTranslation } from 'react-i18next'; -import { useTenant } from '../../../..'; +import { useTenant } from '../../../'; +import useDocumentTitle from '../../utils/useDocumentTitle'; import { LegalPageWrapper } from '../legalPageWrapper/LegalPageWrapper'; -import useDocumentTitle from '../../resources/utils/useDocumentTitle'; export const Privacy = () => { const [t] = useTranslation(); diff --git a/src/extensions/components/legalInformationLinks/TermsAndConditions.tsx b/src/components/legalInformationLinks/TermsAndConditions.tsx similarity index 80% rename from src/extensions/components/legalInformationLinks/TermsAndConditions.tsx rename to src/components/legalInformationLinks/TermsAndConditions.tsx index 64c8afe0d..764827e10 100644 --- a/src/extensions/components/legalInformationLinks/TermsAndConditions.tsx +++ b/src/components/legalInformationLinks/TermsAndConditions.tsx @@ -1,9 +1,8 @@ import * as React from 'react'; import { useTranslation } from 'react-i18next'; -import { useTenant } from '../../../..'; - +import { useTenant } from '../../..'; +import useDocumentTitle from '../../utils/useDocumentTitle'; import { LegalPageWrapper } from '../legalPageWrapper/LegalPageWrapper'; -import useDocumentTitle from '../../resources/utils/useDocumentTitle'; export const TermsAndConditions = () => { const [t] = useTranslation(); diff --git a/src/extensions/components/legalPageWrapper/LegalPageWrapper.tsx b/src/components/legalPageWrapper/LegalPageWrapper.tsx similarity index 100% rename from src/extensions/components/legalPageWrapper/LegalPageWrapper.tsx rename to src/components/legalPageWrapper/LegalPageWrapper.tsx diff --git a/src/extensions/components/legalPageWrapper/legalPageWrapper.styles.scss b/src/components/legalPageWrapper/legalPageWrapper.styles.scss similarity index 100% rename from src/extensions/components/legalPageWrapper/legalPageWrapper.styles.scss rename to src/components/legalPageWrapper/legalPageWrapper.styles.scss diff --git a/src/extensions/theme.jsx b/src/resources/scripts/theme.jsx similarity index 100% rename from src/extensions/theme.jsx rename to src/resources/scripts/theme.jsx diff --git a/src/extensions/resources/scripts/util/htmlParser.tsx b/src/resources/scripts/util/htmlParser.tsx similarity index 100% rename from src/extensions/resources/scripts/util/htmlParser.tsx rename to src/resources/scripts/util/htmlParser.tsx diff --git a/src/extensions/resources/utils/useDocumentTitle.tsx b/src/utils/useDocumentTitle.tsx similarity index 100% rename from src/extensions/resources/utils/useDocumentTitle.tsx rename to src/utils/useDocumentTitle.tsx From 78790e6bfc4b30942e60a84be6c41ad1c2281f6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Tue, 17 Sep 2024 15:29:36 +0200 Subject: [PATCH 43/49] feat(caritas-theme): remove extension, move i18n to core --- src/extensions/cypress/cypress.json | 12 - src/extensions/cypress/e2e/login.cy.ts | 37 -- src/extensions/pages/app.html | 60 --- src/extensions/pages/under-construction.html | 352 -------------- src/extensions/resources/i18n/de/agency.json | 3 - .../resources/i18n/de/consultingTypes.json | 410 ---------------- .../resources/i18n/de/languages.json | 4 - src/extensions/resources/i18n/en/agency.json | 3 - .../resources/i18n/en/consultingTypes.json | 438 ------------------ .../resources/i18n/en/languages.json | 4 - src/extensions/resources/scripts/config.ts | 108 ----- src/resources/i18n/de/consultingTypes.json | 409 +++++++++++++++- src/resources/i18n/de/languages.json | 3 +- src/resources/i18n/en/consultingTypes.json | 437 ++++++++++++++++- src/resources/scripts/config.ts | 58 ++- src/resources/styles/_layout.scss | 4 +- 16 files changed, 894 insertions(+), 1448 deletions(-) delete mode 100644 src/extensions/cypress/cypress.json delete mode 100644 src/extensions/cypress/e2e/login.cy.ts delete mode 100644 src/extensions/pages/app.html delete mode 100644 src/extensions/pages/under-construction.html delete mode 100644 src/extensions/resources/i18n/de/agency.json delete mode 100644 src/extensions/resources/i18n/de/consultingTypes.json delete mode 100644 src/extensions/resources/i18n/de/languages.json delete mode 100644 src/extensions/resources/i18n/en/agency.json delete mode 100644 src/extensions/resources/i18n/en/consultingTypes.json delete mode 100644 src/extensions/resources/i18n/en/languages.json delete mode 100644 src/extensions/resources/scripts/config.ts diff --git a/src/extensions/cypress/cypress.json b/src/extensions/cypress/cypress.json deleted file mode 100644 index e11cdcc0a..000000000 --- a/src/extensions/cypress/cypress.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "e2e": { - "excludeSpecPattern": [ - "cypress/e2e/**/registration/base.cy.ts", - "cypress/e2e/**/registration/consultingType.cy.ts", - "cypress/e2e/**/registration/topic.cy.ts", - "cypress/e2e/**/messages/attachments/informal.cy.ts", - "cypress/e2e/**/login.cy.ts" - ], - "specPattern": ["src/extensions/cypress/e2e/**/*.cy.ts"] - } -} diff --git a/src/extensions/cypress/e2e/login.cy.ts b/src/extensions/cypress/e2e/login.cy.ts deleted file mode 100644 index 1dbab6164..000000000 --- a/src/extensions/cypress/e2e/login.cy.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { - closeWebSocketServer, - mockWebSocket, - startWebSocketServer -} from '../../../../cypress/support/websocket'; -import { config } from '../../resources/scripts/config'; - -describe('Login', () => { - before(() => { - startWebSocketServer(); - }); - - after(() => { - closeWebSocketServer(); - }); - - beforeEach(() => { - cy.willReturn('frontend.settings', config); - mockWebSocket(); - }); - - it('should be able to login', () => { - cy.login(); - - cy.get('#appRoot').should('exist'); - }); - - it('displays the consultingtype page at the root', () => { - cy.visit('/'); - cy.contains('Willkommen bei der Online-Beratung'); - }); - - it('displays the login for resorts', () => { - cy.visit('/suchtberatung'); - cy.contains('Login'); - }); -}); diff --git a/src/extensions/pages/app.html b/src/extensions/pages/app.html deleted file mode 100644 index 7d37f67a4..000000000 --- a/src/extensions/pages/app.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - <%= htmlWebpackPlugin.options.title %> - - - - - - - - - - - - - - - - - -
    - - - <% if(type === 'error') { %> -
    - <% } else { %> -
    - <% } %> -
    - -
    - - diff --git a/src/extensions/pages/under-construction.html b/src/extensions/pages/under-construction.html deleted file mode 100644 index d98c627a5..000000000 --- a/src/extensions/pages/under-construction.html +++ /dev/null @@ -1,352 +0,0 @@ - - - - - - - Beratung & Hilfe – Wartungsarbeiten - - - -
    -
    - - - - - - baustelle - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -

    Ohh!

    -

    - Wir arbeiten gerade an unserer Online-Beratung. -
    - Leider können Sie währenddessen die Anwendung nicht - nutzen. -
    - Versuchen Sie es später noch einmal. -

    - - - -
    -
    -
    - - - - diff --git a/src/extensions/resources/i18n/de/agency.json b/src/extensions/resources/i18n/de/agency.json deleted file mode 100644 index 19e8f11ac..000000000 --- a/src/extensions/resources/i18n/de/agency.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "agency": {} -} diff --git a/src/extensions/resources/i18n/de/consultingTypes.json b/src/extensions/resources/i18n/de/consultingTypes.json deleted file mode 100644 index 4971dfd86..000000000 --- a/src/extensions/resources/i18n/de/consultingTypes.json +++ /dev/null @@ -1,410 +0,0 @@ -{ - "consultingType": { - "0": {}, - "1": { - "description": "Sie möchten ein Kind adoptieren oder ein Pflegekind in Ihrem Zuhause aufnehmen? Sie sind unsicher, ob Sie ihr Kind gut versorgen können? Sie sind selbst adoptiert und möchten Einblick in Ihre Akte nehmen? Wir beraten Sie vertraulich und kostenfrei hier in der Online-Beratung.", - "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\"]", - "titles": { - "default": "Adoption und Pflegekind", - "short": "Adoption und Pflegekind", - "long": "Adoptions- und Pflegekindberatung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Adoptions- und Pflegekindberatung" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "2": { - "description": "Sie haben ein persönliches Problem, sind in einer schwierigen finanziellen Lage oder haben Schwierigkeiten mit einer Behörde? Egal welches Problem Sie plagt, wir beraten Sie kostenfrei und vertraulich hier in der Online-Beratung.", - "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\", \"Existenzsicherung\"]", - "titles": { - "default": "Allgemeine Sozialberatung", - "short": "Allgemeine Sozialberatung", - "long": "Allgemeine Sozialberatung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Allgemeine Sozialberatung" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "3": { - "description": "Sie haben Ihren Job verloren? Sie haben Fragen zum Arbeitslosengeld I und II? Sie brauchen Hilfe bei der Arbeitsplatzsuche oder arbeiten prekär? Wir helfen Ihnen vertraulich und kostenfrei hier in der Online-Beratung.", - "groups": "[\"Existenzsicherung\"]", - "titles": { - "default": "Arbeitslos, erwerbslos", - "short": "Arbeitslos, erwerbslos", - "long": "Arbeitslosenberatung/Erwerbslosenberatung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Arbeitslosenberatung/Erwerbslosenberatung" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "4": { - "description": "Sie müssen oder wollen Deutschland verlassen? Sie überlegen, ob Sie in Deutschland oder in Ihrem Herkunftsland leben möchten? Wir beraten Sie unabhängig von Ihrem Aufenthaltsstatus vertraulich und kostenfrei hier in der Online-Beratung.", - "groups": "[\"Migration, Flucht, Asyl\"]", - "titles": { - "default": "Ausreise und Perspektive", - "short": "Ausreise und Perspektive", - "long": "Ausreise- und Perspektivberatung - Rückkehrberatung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Ausreise- und Perspektivberatung - Rückkehrberatung" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "5": { - "description": "Sie haben keine Wohnung oder Angst Ihr Zuhause zu verlieren? Sie leben in unzumutbaren Wohnverhältnissen? Sie sind in einer Notlage? Wir helfen Ihnen vertraulich und kostenfrei hier in der Online-Beratung.", - "groups": "[\"Existenzsicherung\", \"Besondere Lebenssituationen und Krisen\"]", - "titles": { - "default": "Wohnungsnotfall", - "short": "Wohnungsnotfall", - "long": "Beratung bei Wohnungsnotfällen", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Beratung bei Wohnungsnotfällen" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "6": { - "description": "Sie sind Sexarbeiter:in und erleben häufig Stigmatisierung, Diskriminierung und Abwertung? Sie wollen nicht mehr als Sexarbeiter:in arbeiten? Wir unterstützen sie darin, Ihre Rechte durchzusetzen, organisieren notwendige Hilfen und helfen beim Ausstieg.", - "groups": "[\"Besondere Lebenssituationen und Krisen\"]", - "titles": { - "default": "Prostitution", - "short": "Prostitution", - "long": "Beratung für Menschen in Prostitution und Menschenhandel", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Beratung für Menschen in Prostitution und Menschenhandel" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "7": { - "description": "Sie waren in Haft und haben Fragen zu Ansprüchen auf Sozialleistungen? Sie brauchen Unterstützung bei der Wohnungs- und Arbeitssuche? Sie haben persönliche Probleme? Rund um die Haft gibt es Situationen, die man nicht alleine stemmen kann. Wir helfen Ihnen vertraulich und kostenfrei.", - "groups": "[\"Existenzsicherung\", \"Besondere Lebenssituationen und Krisen\"]", - "titles": { - "default": "Straffälligkeit", - "short": "Straffälligkeit", - "long": "Beratung für straffällig gewordene Menschen und ihre Angehörigen", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Beratung für straffällig gewordene Menschen und ihre Angehörigen" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "8": { - "description": "Ihre Familie braucht eine Auszeit, die bezahlbar ist? Wir beraten Sie gerne zu Ihrer individuellen Auszeit und Fördermöglichkeiten für Familien mit geringem Einkommen. Alle Familien sind in den Ferienstätten willkommen. Konfession und Familienkonstellation spielen keine Rolle.", - "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\"]", - "titles": { - "default": "Familienerholung", - "short": "Familienerholung", - "long": "Beratung zu Fragen der Familienerholung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Beratung zu Fragen der Familienerholung" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "9": { - "description": "Sie haben einen zermürbenden Konflikt oder Sorgen lassen Sie nicht zur Ruhe kommen? Sie haben Probleme in der Partnerschaft, die Sie nicht lösen können? Wir helfen Ihnen, wenn Ängste Ihren Alltag bestimmen, wenn die Trauer über den Verlust eines Menschen oder Einsamkeit Ihnen die Lebensfreude nehmen.", - "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\"]", - "titles": { - "default": "Ehe, Paar und Leben", - "short": "Ehe, Paar und Leben", - "long": "Ehe-, Paar- und Lebensberatung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Ehe-, Paar- und Lebensberatung" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "10": { - "description": "Hat Ihr Kind Schwierigkeiten im Kindergarten oder in der Schule? Fühlen Sie sich im Familienalltag überfordert? Stehen Sie vor einer Trennung oder brauchen Sie wegen einer Trennung Unterstützung für sich und Ihre Kinder? Wir helfen Ihnen vertraulich und kostenfrei hier in der Online-Beratung.", - "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\"]", - "titles": { - "default": "Erziehung und Familie", - "short": "Erziehung und Familie", - "long": "Erziehungs- und Familienberatung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Erziehungs- und Familienberatung" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "11": { - "description": "Sie sind geflüchtet und haben Fragen zum Asylverfahren? Sie brauchen Hilfe bei der Vorbereitung zur Anhörung im Asylverfahren? Das Asylverfahren ist abgeschlossen und Sie brauchen Unterstützung in Deutschland? Wir beraten Menschen jeder Herkunft und unabhängig von der Konfession.", - "groups": "[\"Migration, Flucht, Asyl\"]", - "titles": { - "default": "Flucht und Asyl", - "short": "Flucht und Asyl", - "long": "Flüchtlings- & Asylverfahrensberatung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Flüchtlings- & Asylverfahrensberatung" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "12": { - "description": "Sie haben ein positives Testergebnis erhalten und fragen sich, wie es weitergeht? Sie sind Angehörige:r einer HIV-positiven Person und haben offene Fragen? Sie möchten wissen, wie Sie sich vor HIV oder anderen sexuell übertragbaren Infektionen schützen können? Wir helfen Ihnen vertraulich und kostenfrei.", - "groups": "[\"Gesundheitliche Beeinträchtigung\"]", - "titles": { - "default": "HIV und Aids", - "short": "HIV und Aids", - "long": "HIV und Aids", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "HIV und Aids" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "13": { - "description": "Sie sind schwerkrank, haben nicht mehr lange zu leben oder sind Angehörige:r und brauchen Unterstützung? Sie möchten in dieser Situation die bestmögliche Lebensqualität erreichen? Sie haben Fragen zur Vorsorgeplanung? Wir beraten Sie vertraulich und kostenfrei hier in der Online-Beratung.", - "groups": "[\"Gesundheitliche Beeinträchtigung\", \"Kinder, Jugendliche, Erwachsene und Familie\", \"Alter\"]", - "titles": { - "default": "Hospiz und Palliativ", - "short": "Hospiz und Palliativ", - "long": "Hospiz- und Palliativberatung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Hospiz- und Palliativberatung" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "14": { - "description": "Sind Sie von sexualisierter Gewalt betroffen? Wurden Sie von einer anderen Person durch physische Gewalt verletzt? Droht Ihnen jemand, beleidigt Sie oder schreit Sie an? Kennen Sie eine Person, die unter häuslicher oder sexualisierter Gewalt leidet? Wir helfen Ihnen vertraulich und kostenfrei.", - "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\"]", - "titles": { - "default": "Gewalt", - "short": "Gewalt", - "long": "Beratung bei häuslicher und sexualisierter Gewalt", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Beratung bei häuslicher und sexualisierter Gewalt" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "15": { - "description": "Du bist zwischen 12 und 27 Jahren alt, hast Migrationshintergrund und Fragen zu schulischen Abschlüssen, Ausbildung oder Sprachkursen? Wir beraten dich zu Bildungs- und Freizeitangeboten kostenfrei und vertraulich hier in der Online-Beratung.", - "groups": "[\"Migration, Flucht, Asyl\"]", - "titles": { - "default": "Jugendmigrationsdienste", - "short": "Jugendmigrationsdienste", - "long": "Jugendmigrationsdienste (JMD)", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Jugendmigrationsdienste (JMD)" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "16": { - "description": "Weißt Du einfach nicht mehr weiter? Fühlst Du Dich nicht verstanden? Machst Du Dir Sorgen um eine Freundin oder einen Freund? Hast Du Schwierigkeiten mit deinen Eltern? Wirst Du geschlagen? Hast Du Stress in der Schule, mit Freunden oder wegen Geld? Wir beraten Dich vertraulich und kostenfrei.", - "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\"]", - "titles": { - "default": "Kinder und Jugend", - "short": "Kinder und Jugend", - "long": "Kinder- und Jugendberatung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Kinder- und Jugendberatung" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "17": { - "description": "Sie fühlen sich von Ihren Aufgaben durch Job, Familie oder die Pflege von Angehörigen ausgelaugt? Sie sind krank und brauchen eine Auszeit vom Alltag? Eine Kur kann helfen, wieder Kräfte zu sammeln. Wir beraten Mütter, Väter und pflegende Angehörige vertraulich und kostenfrei hier in der Online-Beratung.", - "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\", \"Gesundheitliche Beeinträchtigung\"]", - "titles": { - "default": "Kurberatung", - "short": "Kurberatung", - "long": "Kurberatung für Mütter und Väter", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Kurberatung für Mütter und Väter" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "18": { - "description": "Sie brauchen Beratung zum Thema Wohnen im Alter? Sie haben Fragen zu Hilfen im Haushalt? Sie wollen Ihre Freizeit oder die Freizeit eines älteren Familienangehörigen abwechslungsreicher gestalten? Sie suchen Information zu Themen wie Demenz? Wir beraten Sie vertraulich und kostenfrei hier in der Online-Beratung.", - "groups": "[\"Gesundheitliche Beeinträchtigung\", \"Alter\"]", - "titles": { - "default": "Alter und Pflegeberatung", - "short": "Alter und Pflegeberatung", - "long": "Leben im Alter und Pflegeberatung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Leben im Alter und Pflegeberatung" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "19": { - "description": "Sie sind über 26 Jahre alt und brauchen Hilfe sich in Deutschland zurecht zu finden? Sie brauchen Hilfe bei der Suche nach Arbeit oder einem Sprachkurs? Wir beraten Neu-Zugewanderte, aber auch Personen, die schon lange in Deutschland leben, Spätaussiedler:innen sowie Unionsbürger:innen.", - "groups": "[\"Migration, Flucht, Asyl\"]", - "titles": { - "default": "Migrationsberatung", - "short": "Migrationsberatung", - "long": "Migrationsberatung für Erwachsene und Familien", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Migrationsberatung für Erwachsene und Familien" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "20": { - "description": "Sie möchten ein selbstbestimmtes Leben führen und brauchen dabei Hilfe? Sie haben Fragen zu Finanzierung, Hilfsmitteln und Assistenz? Wir beraten Sie vertraulich und kostenfrei zu Ihren Fragen zur Selbsthilfe in den Lebensbereichen Arbeiten, Wohnen, Bildung und Freizeit.", - "groups": "[\"Gesundheitliche Beeinträchtigung\"]", - "titles": { - "default": "Psychische Beeintr.", - "short": "Psychische Beeintr.", - "long": "Psychische Beeinträchtigung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Psychische Beeinträchtigung" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "21": { - "description": "Sie haben während Ihrer Flucht traumatische Erfahrungen gemacht? Sie haben in Ihrem Herkunftsland unter Folter, Gewalt und Rassismus gelitten? Sie kennen eine geflüchtete Person, die traumatisiert ist? Wir helfen Ihnen mit einer psychologischen und sozalpädagogischen Beratung.", - "groups": "[\"Migration, Flucht, Asyl\"]", - "titles": { - "default": "Psychosoziale Beratung", - "short": "Psychosoziale Beratung", - "long": "Psychosoziale Beratung für Geflüchtete und Migrant:innen", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Psychosoziale Beratung für Geflüchtete und Migrant:innen" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "22": { - "description": "Sie möchten als rechtliche:r Betreuer:in eingesetzt werden und möchten wissen, wie eine Betreuung eingerichtet wird und welche Aufgaben auf Sie zukommen? Sie möchten selbst vorsorgen und eine Patientenverfügung erstellen? Wir beraten Sie vertraulich und kostenfrei hier in der Online-Beratung.", - "groups": "[\"Teilhabe für Menschen mit Beeinträchtigung\"]", - "titles": { - "default": "Rechtliche Betreuung", - "short": "Rechtliche Betreuung", - "long": "Rechtliche Betreuung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Rechtliche Betreuung" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "23": { - "description": "Sie haben Schulden, die Wohnung wurde gekündigt oder der Gerichtsvollzieher kommt? Wir beraten Sie vertraulich und kostenfrei hier in der Online-Beratung.", - "groups": "[\"Existenzsicherung\"]", - "titles": { - "default": "Schulden und Insolvenz", - "short": "Schulden und Insolvenz", - "long": "Schuldnerberatung und Insolvenzberatung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Schuldnerberatung und Insolvenzberatung" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "24": { - "description": "Sie sind schwanger und haben Fragen? Sie fürchten um Ihre Partnerschaft? Sie haben Angst vor finanziellen Schwierigkeiten, wenn das Kind kommt. Sie möchten Beratung zu vorgeburtlichen Untersuchungen? Sie überlegen die Schwangerschaft abzubrechen? Wir beraten Sie vertraulich und kostenfrei.", - "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\"]", - "titles": { - "default": "Schwangerschaft", - "short": "Schwangerschaft", - "long": "Schwangeren- und Schwangerschaftskonfliktberatung", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Schwangeren- und Schwangerschaftskonfliktberatung" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "25": { - "description": "Sie haben ein Suchtproblem oder machen sich Sorgen um betroffene Freunde und Verwandte? Sie haben Fragen zu Sucht und Abhängigkeit - Alkohol, Drogen, Medikamente, Glücksspiel, Computer-/Medienkonsum? Wir beraten Sie vertraulich und kostenfrei hier in der Online-Beratung.", - "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\", \"Besondere Lebenssituationen und Krisen\", \"Gesundheitliche Beeinträchtigung\"]", - "titles": { - "default": "Sucht", - "short": "Sucht", - "long": "Suchtberatung und -prävention", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Suchtberatung und -prävention" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "26": { - "description": "Sie möchten ein selbstbestimmtes Leben führen und brauchen dabei Hilfe? Sie haben Fragen zu Finanzierung, Hilfsmitteln und Assistenz? Wir beraten Sie vertraulich und kostenfrei zu Ihren Fragen zur Selbsthilfe in den Lebensbereichen Arbeiten, Wohnen, Bildung und Freizeit.", - "groups": "[\"Teilhabe für Menschen mit Beeinträchtigung\"]", - "titles": { - "default": "Teilhabe", - "short": "Teilhabe", - "long": "Teilhabe von Menschen mit Beeinträchtigungen", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Teilhabe von Menschen mit Beeinträchtigungen" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - }, - "27": { - "description": "Du hast Fragen rund um Schule, Ausbildung und Beruf? Wie stellst Du Dir Deine Zukunft vor? Was brauchst Du dafür? Wir helfen Dir vertraulich und kostenfrei hier in der Online-Beratung.", - "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\"]", - "titles": { - "default": "von Schule zu Beruf", - "short": "von Schule zu Beruf", - "long": "Übergang von Schule zu Beruf", - "welcome": "Willkommen bei der Online-Beratung", - "registrationDropdown": "Übergang von Schule zu Beruf" - }, - "anonymous": { - "title": "Anonym und kostenfrei", - "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" - } - } - } -} diff --git a/src/extensions/resources/i18n/de/languages.json b/src/extensions/resources/i18n/de/languages.json deleted file mode 100644 index 524c6949b..000000000 --- a/src/extensions/resources/i18n/de/languages.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "de": "(DE) Deutsch", - "en": "(EN) Englisch" -} diff --git a/src/extensions/resources/i18n/en/agency.json b/src/extensions/resources/i18n/en/agency.json deleted file mode 100644 index 19e8f11ac..000000000 --- a/src/extensions/resources/i18n/en/agency.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "agency": {} -} diff --git a/src/extensions/resources/i18n/en/consultingTypes.json b/src/extensions/resources/i18n/en/consultingTypes.json deleted file mode 100644 index 3ba7e603f..000000000 --- a/src/extensions/resources/i18n/en/consultingTypes.json +++ /dev/null @@ -1,438 +0,0 @@ -{ - "consultingTypeGroup": { - "Teilhabe für Menschen mit Beeinträchtigung": { - "title": "Participation for people with disabilities" - }, - "Alter": { - "title": "Age" - }, - "Gesundheitliche Beeinträchtigung": { - "title": "Health impairment" - }, - "Besondere Lebenssituationen und Krisen": { - "title": "Special life situations and crises" - }, - "Hilfe in besonderen sozialen Situationen": { - "title": "Help in special social situations" - }, - "Kinder, Jugendliche, Erwachsene und Familie": { - "title": "Children, young people, adults and families" - }, - "Migration, Flucht, Asyl": { - "title": "Migration, flight, asylum" - }, - "Existenzsicherung": { - "title": "Livelihood security" - }, - "Hilfe für Kinder, Erwachsene und Familien": { - "title": "Help for children, adults and families" - } - }, - "consultingType": { - "1": { - "description": "You want to adopt a child or take in a foster child in your home? You are unsure whether you can take good care of your child? You are adopted yourself and would like to take a look at your file? We can advise you confidentially and free of charge here in online consulting.", - "groups": "[\"Children, Adolescents, Adults and Family\"]", - "titles": { - "default": "Adoption and foster child", - "short": "Adoption and foster child", - "long": "adoption and foster child consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Adoption and foster child consulting" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and assistance" - } - }, - "2": { - "description": "You have a personal problem, are in a difficult financial situation or have difficulties with an authority? No matter what problem is plaguing you, we will advise you free of charge and confidentially here in online consulting.", - "groups": "[\"Children, Adolescents, Adults and Family\", \"Livelihood\"]", - "titles": { - "default": "General social counseling", - "short": "General social counseling", - "long": "General social consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "General Social Counseling" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and help" - } - }, - "3": { - "description": "You have lost your job? You have questions about unemployment benefits I and II? Do you need help with your job search or are you working precariously? We can help you confidentially and free of charge here in the online consulting service.", - "groups": "[\"Existenzsicherung\"]", - "titles": { - "default": "Unemployed, unemployable", - "short": "Unemployed, unemployable", - "long": "Unemployment consulting/unemployed consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "unemployment counseling/unemployment counseling" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and help" - } - }, - "4": { - "description": "You have to or want to leave Germany? You are considering whether you want to live in Germany or in your country of origin? We will advise you confidentially and free of charge here in online consulting, regardless of your residence status.", - "groups": "[\"Migration, Flight, Asylum\"]", - "titles": { - "default": "Departure and perspective", - "short": "Departure and perspective", - "long": "Exit and perspective consulting - return consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Exit and perspective consulting - return consulting" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and help" - } - }, - "5": { - "description": "You don't have a home or you are afraid to lose your home? You live in unacceptable housing conditions? You are in an emergency situation? We can help you confidentially and free of charge here in the online consulting service.", - "groups": "[\"Livelihood security\", \"Special life situations and crises\"]", - "titles": { - "default": "Housing emergency", - "short": "Housing emergency", - "long": "housing emergency consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "consulting in housing emergencies" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and assistance" - } - }, - "6": { - "description": "You are a sex worker:in and often experience stigmatization, discrimination and devaluation? You no longer want to work as a sex worker? We support you in asserting your rights, organize necessary assistance and help you to get out.", - "groups": "[\"Special life situations and crises\"]", - "titles": { - "default": "Prostitution", - "short": "Prostitution", - "long": "Consulting for people in prostitution and human trafficking", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Consulting for people in prostitution and human trafficking" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and help" - } - }, - "7": { - "description": "You have been in custody and have questions about claims for social benefits? You need assistance in finding housing and employment? Do you have personal problems? There are situations around detention that you can't handle on your own. We can help you confidentially and free of charge.", - "groups": "[\"Securing livelihood\", \"Special life situations and crises\"]", - "titles": { - "default": "delinquency", - "short": "delinquency", - "long": "Consulting for people who have committed crimes and their relatives", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Consulting for people who have committed crimes and their relatives" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and help" - } - }, - "8": { - "description": "Your family needs time off that is affordable? We'll be happy to advise you on your individual time away and funding options for low-income families. All families are welcome at the resorts. Denomination and family constellation do not matter.", - "groups": "[\"Children, youth, adults and family\"]", - "titles": { - "default": "Family recreation", - "short": "Family recovery", - "long": "consulting on family recovery issues", - "welcome": "Welcome to online consulting", - "registrationDropdown": "consulting on family recovery issues" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and help" - } - }, - "9": { - "description": "You have a grueling conflict or worries won't let you rest? You have problems in your partnership that you can't solve? We help you when fears determine your everyday life, when grief over the loss of a person or loneliness take away your joy of life.", - "groups": "[\"Children, adolescents, adults and family\"]", - "titles": { - "default": "Marriage, couple and life", - "short": "Marriage, couple and life", - "long": "Marriage, couple and life consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "marriage, couple and life counseling" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and help" - } - }, - "10": { - "description": "Does your child have difficulties in kindergarten or school? Do you feel overwhelmed in everyday family life? Are you facing a separation or do you need support for yourself and your children because of a separation? We can help you confidentially and free of charge here in online consulting.", - "groups": "[\"children, adolescents, adults and family\"]", - "titles": { - "default": "Education and family", - "short": "Education and family", - "long": "education and family consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Educational and family consulting" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and help" - } - }, - "11": { - "description": "You are a refugee and have questions about the asylum procedure? You need help with the preparation for the hearing in the asylum procedure? The asylum procedure has been completed and you need support in Germany? We advise people of all origins and regardless of denomination.", - "groups": "[\"Migration, flight, asylum\"]", - "titles": { - "default": "Flight and asylum", - "short": "Flight and Asylum", - "long": "Refugee & asylum process consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Refugee & asylum procedure consulting" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and assistance" - } - }, - "12": { - "description": "You have received a positive test result and are wondering what to do next? You are a family member of a HIV-positive person and have unanswered questions? Would you like to know how you can protect yourself from HIV or other sexually transmitted infections? We will help you confidentially and free of charge.", - "groups": "[\"Health impairment\"]", - "titles": { - "default": "HIV and AIDS", - "short": "HIV and Aids", - "long": "HIV and Aids", - "welcome": "Welcome to online consulting", - "registrationDropdown": "HIV and Aids" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and help" - } - }, - "13": { - "description": "You are seriously ill, do not have long to live or are a relative:r and need support? You would like to achieve the best possible quality of life in this situation? Do you have questions about advance care planning? We will advise you confidentially and free of charge here in the online consultation.", - "groups": "[\"Health Impairment\", \"Children, Adolescents, Adults and Family\", \"Age\"]", - "titles": { - "default": "Hospice and palliative", - "short": "Hospice and Palliative", - "long": "Hospice and palliative consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Hospice and palliative consulting" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and assistance" - } - }, - "14": { - "description": "Have you been affected by sexual violence? Have you been hurt by physical violence by another person? Does someone threaten you, insult you, or yell at you? Do you know a person who suffers from domestic or sexualized violence? We can help you confidentially and free of charge.", - "groups": "[\"Children, youth, adults and family\"]", - "titles": { - "default": "violence", - "short": "Violence", - "long": "Domestic and sexual violence consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Domestic and sexual violence consulting" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and help" - } - }, - "15": { - "description": "You are between 12 and 27 years old, have a migration background and questions about school qualifications, training or language courses? We advise you on educational and leisure opportunities free of charge and confidentially here in the online consulting.", - "groups": "[\"Migration, flight, asylum\"]", - "titles": { - "default": "Youth migration services", - "short": "Youth migration services", - "long": "Youth Migration Services (JMD)", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Youth Migration Services (JMD)" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and help" - } - }, - "16": { - "description": "Do you just not know what to do? Do you feel not understood? Are you worried about a friend? Are you having trouble with your parents? Are you being beaten? Do you have stress at school, with friends or because of money? We advise you confidentially and free of charge.", - "groups": "[\"Children, youth, adults and family\"]", - "titles": { - "default": "Children and youth", - "short": "children and youth", - "long": "Children and youth consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "child and youth consulting" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and help" - } - }, - "17": { - "description": "You feel drained by your tasks due to job, family or caring for relatives? You are ill and need a break from everyday life? A cure can help you regain your strength. We advise mothers, fathers and caring relatives confidentially and free of charge here in the online consulting service.", - "groups": "[\"Children, Adolescents, Adults and Family\", \"Health Impairment\"]", - "titles": { - "default": "Cure counseling", - "short": "spa counseling", - "long": "Cure consulting for mothers and fathers", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Cure consulting for mothers and fathers" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and help" - } - }, - "18": { - "description": "You need advice about living in old age? Do you have questions about help in the household? Do you want to diversify your leisure time or the leisure time of an elderly family member? Are you looking for information on topics such as dementia? We will advise you confidentially and free of charge here in the online consulting service.", - "groups": "[\"Health impairment\", \"age\"]", - "titles": { - "default": "Age and care consulting", - "short": "Age and care consulting", - "long": "Living in old age and care consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Life in old age and care consulting" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and assistance" - } - }, - "19": { - "description": "You are over 26 years old and need help to find your way in Germany? Do you need help finding a job or a language course? We advise new immigrants, but also people who have been living in Germany for a long time, late repatriates and citizens of the EU", - "groups": "[\"Migration, Flight, Asylum\"]", - "titles": { - "default": "Migration consulting", - "short": "Migration consulting", - "long": "Migration counseling for adults and families", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Migration consulting for adults and families" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and assistance" - } - }, - "20": { - "description": "You want to lead a self-determined life and need help? Do you have questions about financing, aids and assistance? We advise you confidentially and free of charge on your questions about self-help in the areas of work, housing, education and leisure.", - "groups": "[\"Health impairment\"]", - "titles": { - "default": "Mental impairment", - "short": "Mental impairment", - "long": "Mental impairment", - "welcome": "Welcome to online consulting", - "registrationDropdown": "mental impairment" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and help" - } - }, - "21": { - "description": "You have had traumatic experiences during your flight? You have suffered from torture, violence and racism in your country of origin? You know a refugee who is traumatized? We can help you with psychological and socio-educational counseling.", - "groups": "[\"Migration, flight, asylum\"]", - "titles": { - "default": "Psychosocial counseling", - "short": "Psychosocial counseling", - "long": "Psychosocial counseling for refugees and migrants", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Psychosocial counseling for refugees and migrants" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and help" - } - }, - "22": { - "description": "You would like to be appointed as a legal guardian and would like to know how a guardianship is set up and what tasks await you? Would you like to make your own provisions and draw up a living will? We will advise you confidentially and free of charge here in the online consultation.", - "groups": "[\"Participation for people with impairments\"]", - "titles": { - "default": "Legal care", - "short": "Legal care", - "long": "Legal support", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Legal support" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and help" - } - }, - "23": { - "description": "You have debts, the apartment was canceled or the bailiff comes? We advise you confidentially and free of charge here in the online consulting.", - "groups": "[\"Existenzsicherung\"]", - "titles": { - "default": "Debt and insolvency", - "short": "Debt and insolvency", - "long": "Debt and insolvency consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "debtor and insolvency consulting" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and help" - } - }, - "24": { - "description": "You are pregnant and have questions? You fear for your partnership? You are afraid of financial difficulties when the child comes? You want advice on prenatal examinations? Are you considering terminating the pregnancy? We will advise you confidentially and free of charge.", - "groups": "[\"Children, adolescents, adults and family\"]", - "titles": { - "default": "Pregnancy", - "short": "Pregnancy", - "long": "Pregnancy and pregnancy conflict consulting", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Pregnancy and pregnancy conflict consulting" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and help" - } - }, - "25": { - "description": "Do you have an addiction problem or are you worried about friends and relatives who are affected? You have questions about addiction and dependence - alcohol, drugs, medication, gambling, computer/media use? We can advise you confidentially and free of charge here in the online consulting service.", - "groups": "[\"Children, adolescents, adults and family\", \"Special life situations and crises\", \"Health impairment\"]", - "titles": { - "default": "Addiction", - "short": "Addiction", - "long": "Addiction consulting and prevention", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Addiction counseling and prevention" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and help" - } - }, - "26": { - "description": "You want to lead a self-determined life and need help? Do you have questions about financing, aids and assistance? We advise you confidentially and free of charge on your questions about self-help in the areas of work, housing, education and leisure.", - "groups": "[\"Participation for people with impairments\"]", - "titles": { - "default": "participation", - "short": "participation", - "long": "Participation of people with impairments", - "welcome": "Welcome to online consulting", - "registrationDropdown": "Participation of people with impairments" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and assistance" - } - }, - "27": { - "description": "You have questions about school, training and career? How do you imagine your future? What do you need for it? We will help you confidentially and free of charge here in the online consulting.", - "groups": "[\"Children, youth, adults and family\"]", - "titles": { - "default": "from school to work", - "short": "from school to work", - "long": "school-to-work transition", - "welcome": "Welcome to online consulting", - "registrationDropdown": "transition from school to work" - }, - "anonymous": { - "title": "Anonymous and free of charge", - "text": "You remain anonymous and receive free advice and assistance" - } - } - } -} diff --git a/src/extensions/resources/i18n/en/languages.json b/src/extensions/resources/i18n/en/languages.json deleted file mode 100644 index 212abcaca..000000000 --- a/src/extensions/resources/i18n/en/languages.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "de": "(DE) German", - "en": "(EN) English" -} diff --git a/src/extensions/resources/scripts/config.ts b/src/extensions/resources/scripts/config.ts deleted file mode 100644 index d4e5bb5b0..000000000 --- a/src/extensions/resources/scripts/config.ts +++ /dev/null @@ -1,108 +0,0 @@ -import _ from 'lodash'; -import { AppConfigInterface } from '../../../globalState/interfaces'; - -// Files completely overwritten in extension -import deAgency from '../i18n/de/agency.json'; -import deConsultingTypes from '../i18n/de/consultingTypes.json'; -import deLanguages from '../i18n/de/languages.json'; -import enAgency from '../i18n/en/agency.json'; -import enConsultingTypes from '../i18n/en/consultingTypes.json'; -import enLanguages from '../i18n/en/languages.json'; - -// File from main repo -import en from '../../../resources/i18n/en/common.json'; - -// Files which extends the original languages -// import deInformal from '../i18n/overwrites/de@informal/common.json'; -// import enOverwrite from '../i18n/overwrites/en/common.json'; - -import { config as baseConfig, uiUrl } from '../../../resources/scripts/config'; - -export { uiUrl, APP_PATH } from '../../../resources/scripts/config'; - -export const routePathNames = { - root: '/', - login: '/login', - termsAndConditions: '/nutzungsbedingungen', - imprint: '/impressum', - privacy: '/datenschutz' -}; - -export const config: AppConfigInterface = { - ..._.merge(baseConfig, { - urls: { - chatScheduleUrl: uiUrl + '/registration', - finishedAnonymousChatRedirect: 'https://www.diakonie.de', - home: uiUrl + '/registration', - landingpage: '/registration', - toEntry: uiUrl + '/registration', - toRegistration: uiUrl + '/registration' - }, - postcodeFallbackUrl: '{url}{postcode}/', - twofactor: { - startObligatoryHint: new Date('2098-07-31'), - dateTwoFactorObligatory: new Date('2099-02-01') - }, - registration: { - consultingTypeDefaults: { - autoSelectPostcode: false - } - } - }), - legalLinks: [ - { - url: uiUrl + routePathNames.imprint, - label: 'login.legal.infoText.impressum' - }, - { - url: uiUrl + routePathNames.privacy, - label: 'login.legal.infoText.dataprotection', - registration: true - } - // { - // url: routePathNames.termsAndConditions, - // label: 'login.legal.infoText.termsAndConditions', - // registration: true - // } - ], - i18n: { - supportedLngs: ['en', 'de'], - fallbackLng: { - en: ['de'], - en_informal: ['en', 'de_informal', 'de'] - }, - resources: { - de: { - languages: { - ...deLanguages - }, - consultingTypes: { - ...deConsultingTypes - }, - agencies: { - ...deAgency - } - }, - en: { - common: [en], - consultingTypes: { - ...enConsultingTypes - }, - agencies: { - ...enAgency - }, - languages: { - ...enLanguages - } - } - } - } -}; - -export const ALIAS_LAST_MESSAGES = { - E2EE_ACTIVATED: 'aliases.lastMessage.e2ee_activated', - FURTHER_STEPS: 'aliases.lastMessage.further_steps', - REASSIGN_CONSULTANT: 'aliases.lastMessage.reassign_consultant', - REASSIGN_CONSULTANT_RESET_LAST_MESSAGE: - 'aliases.lastMessage.reassign_consultant_reset_last_message' -}; diff --git a/src/resources/i18n/de/consultingTypes.json b/src/resources/i18n/de/consultingTypes.json index bb8144ee4..4971dfd86 100644 --- a/src/resources/i18n/de/consultingTypes.json +++ b/src/resources/i18n/de/consultingTypes.json @@ -1,3 +1,410 @@ { - "consultingType": {} + "consultingType": { + "0": {}, + "1": { + "description": "Sie möchten ein Kind adoptieren oder ein Pflegekind in Ihrem Zuhause aufnehmen? Sie sind unsicher, ob Sie ihr Kind gut versorgen können? Sie sind selbst adoptiert und möchten Einblick in Ihre Akte nehmen? Wir beraten Sie vertraulich und kostenfrei hier in der Online-Beratung.", + "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\"]", + "titles": { + "default": "Adoption und Pflegekind", + "short": "Adoption und Pflegekind", + "long": "Adoptions- und Pflegekindberatung", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Adoptions- und Pflegekindberatung" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "2": { + "description": "Sie haben ein persönliches Problem, sind in einer schwierigen finanziellen Lage oder haben Schwierigkeiten mit einer Behörde? Egal welches Problem Sie plagt, wir beraten Sie kostenfrei und vertraulich hier in der Online-Beratung.", + "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\", \"Existenzsicherung\"]", + "titles": { + "default": "Allgemeine Sozialberatung", + "short": "Allgemeine Sozialberatung", + "long": "Allgemeine Sozialberatung", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Allgemeine Sozialberatung" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "3": { + "description": "Sie haben Ihren Job verloren? Sie haben Fragen zum Arbeitslosengeld I und II? Sie brauchen Hilfe bei der Arbeitsplatzsuche oder arbeiten prekär? Wir helfen Ihnen vertraulich und kostenfrei hier in der Online-Beratung.", + "groups": "[\"Existenzsicherung\"]", + "titles": { + "default": "Arbeitslos, erwerbslos", + "short": "Arbeitslos, erwerbslos", + "long": "Arbeitslosenberatung/Erwerbslosenberatung", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Arbeitslosenberatung/Erwerbslosenberatung" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "4": { + "description": "Sie müssen oder wollen Deutschland verlassen? Sie überlegen, ob Sie in Deutschland oder in Ihrem Herkunftsland leben möchten? Wir beraten Sie unabhängig von Ihrem Aufenthaltsstatus vertraulich und kostenfrei hier in der Online-Beratung.", + "groups": "[\"Migration, Flucht, Asyl\"]", + "titles": { + "default": "Ausreise und Perspektive", + "short": "Ausreise und Perspektive", + "long": "Ausreise- und Perspektivberatung - Rückkehrberatung", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Ausreise- und Perspektivberatung - Rückkehrberatung" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "5": { + "description": "Sie haben keine Wohnung oder Angst Ihr Zuhause zu verlieren? Sie leben in unzumutbaren Wohnverhältnissen? Sie sind in einer Notlage? Wir helfen Ihnen vertraulich und kostenfrei hier in der Online-Beratung.", + "groups": "[\"Existenzsicherung\", \"Besondere Lebenssituationen und Krisen\"]", + "titles": { + "default": "Wohnungsnotfall", + "short": "Wohnungsnotfall", + "long": "Beratung bei Wohnungsnotfällen", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Beratung bei Wohnungsnotfällen" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "6": { + "description": "Sie sind Sexarbeiter:in und erleben häufig Stigmatisierung, Diskriminierung und Abwertung? Sie wollen nicht mehr als Sexarbeiter:in arbeiten? Wir unterstützen sie darin, Ihre Rechte durchzusetzen, organisieren notwendige Hilfen und helfen beim Ausstieg.", + "groups": "[\"Besondere Lebenssituationen und Krisen\"]", + "titles": { + "default": "Prostitution", + "short": "Prostitution", + "long": "Beratung für Menschen in Prostitution und Menschenhandel", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Beratung für Menschen in Prostitution und Menschenhandel" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "7": { + "description": "Sie waren in Haft und haben Fragen zu Ansprüchen auf Sozialleistungen? Sie brauchen Unterstützung bei der Wohnungs- und Arbeitssuche? Sie haben persönliche Probleme? Rund um die Haft gibt es Situationen, die man nicht alleine stemmen kann. Wir helfen Ihnen vertraulich und kostenfrei.", + "groups": "[\"Existenzsicherung\", \"Besondere Lebenssituationen und Krisen\"]", + "titles": { + "default": "Straffälligkeit", + "short": "Straffälligkeit", + "long": "Beratung für straffällig gewordene Menschen und ihre Angehörigen", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Beratung für straffällig gewordene Menschen und ihre Angehörigen" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "8": { + "description": "Ihre Familie braucht eine Auszeit, die bezahlbar ist? Wir beraten Sie gerne zu Ihrer individuellen Auszeit und Fördermöglichkeiten für Familien mit geringem Einkommen. Alle Familien sind in den Ferienstätten willkommen. Konfession und Familienkonstellation spielen keine Rolle.", + "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\"]", + "titles": { + "default": "Familienerholung", + "short": "Familienerholung", + "long": "Beratung zu Fragen der Familienerholung", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Beratung zu Fragen der Familienerholung" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "9": { + "description": "Sie haben einen zermürbenden Konflikt oder Sorgen lassen Sie nicht zur Ruhe kommen? Sie haben Probleme in der Partnerschaft, die Sie nicht lösen können? Wir helfen Ihnen, wenn Ängste Ihren Alltag bestimmen, wenn die Trauer über den Verlust eines Menschen oder Einsamkeit Ihnen die Lebensfreude nehmen.", + "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\"]", + "titles": { + "default": "Ehe, Paar und Leben", + "short": "Ehe, Paar und Leben", + "long": "Ehe-, Paar- und Lebensberatung", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Ehe-, Paar- und Lebensberatung" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "10": { + "description": "Hat Ihr Kind Schwierigkeiten im Kindergarten oder in der Schule? Fühlen Sie sich im Familienalltag überfordert? Stehen Sie vor einer Trennung oder brauchen Sie wegen einer Trennung Unterstützung für sich und Ihre Kinder? Wir helfen Ihnen vertraulich und kostenfrei hier in der Online-Beratung.", + "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\"]", + "titles": { + "default": "Erziehung und Familie", + "short": "Erziehung und Familie", + "long": "Erziehungs- und Familienberatung", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Erziehungs- und Familienberatung" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "11": { + "description": "Sie sind geflüchtet und haben Fragen zum Asylverfahren? Sie brauchen Hilfe bei der Vorbereitung zur Anhörung im Asylverfahren? Das Asylverfahren ist abgeschlossen und Sie brauchen Unterstützung in Deutschland? Wir beraten Menschen jeder Herkunft und unabhängig von der Konfession.", + "groups": "[\"Migration, Flucht, Asyl\"]", + "titles": { + "default": "Flucht und Asyl", + "short": "Flucht und Asyl", + "long": "Flüchtlings- & Asylverfahrensberatung", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Flüchtlings- & Asylverfahrensberatung" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "12": { + "description": "Sie haben ein positives Testergebnis erhalten und fragen sich, wie es weitergeht? Sie sind Angehörige:r einer HIV-positiven Person und haben offene Fragen? Sie möchten wissen, wie Sie sich vor HIV oder anderen sexuell übertragbaren Infektionen schützen können? Wir helfen Ihnen vertraulich und kostenfrei.", + "groups": "[\"Gesundheitliche Beeinträchtigung\"]", + "titles": { + "default": "HIV und Aids", + "short": "HIV und Aids", + "long": "HIV und Aids", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "HIV und Aids" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "13": { + "description": "Sie sind schwerkrank, haben nicht mehr lange zu leben oder sind Angehörige:r und brauchen Unterstützung? Sie möchten in dieser Situation die bestmögliche Lebensqualität erreichen? Sie haben Fragen zur Vorsorgeplanung? Wir beraten Sie vertraulich und kostenfrei hier in der Online-Beratung.", + "groups": "[\"Gesundheitliche Beeinträchtigung\", \"Kinder, Jugendliche, Erwachsene und Familie\", \"Alter\"]", + "titles": { + "default": "Hospiz und Palliativ", + "short": "Hospiz und Palliativ", + "long": "Hospiz- und Palliativberatung", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Hospiz- und Palliativberatung" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "14": { + "description": "Sind Sie von sexualisierter Gewalt betroffen? Wurden Sie von einer anderen Person durch physische Gewalt verletzt? Droht Ihnen jemand, beleidigt Sie oder schreit Sie an? Kennen Sie eine Person, die unter häuslicher oder sexualisierter Gewalt leidet? Wir helfen Ihnen vertraulich und kostenfrei.", + "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\"]", + "titles": { + "default": "Gewalt", + "short": "Gewalt", + "long": "Beratung bei häuslicher und sexualisierter Gewalt", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Beratung bei häuslicher und sexualisierter Gewalt" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "15": { + "description": "Du bist zwischen 12 und 27 Jahren alt, hast Migrationshintergrund und Fragen zu schulischen Abschlüssen, Ausbildung oder Sprachkursen? Wir beraten dich zu Bildungs- und Freizeitangeboten kostenfrei und vertraulich hier in der Online-Beratung.", + "groups": "[\"Migration, Flucht, Asyl\"]", + "titles": { + "default": "Jugendmigrationsdienste", + "short": "Jugendmigrationsdienste", + "long": "Jugendmigrationsdienste (JMD)", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Jugendmigrationsdienste (JMD)" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "16": { + "description": "Weißt Du einfach nicht mehr weiter? Fühlst Du Dich nicht verstanden? Machst Du Dir Sorgen um eine Freundin oder einen Freund? Hast Du Schwierigkeiten mit deinen Eltern? Wirst Du geschlagen? Hast Du Stress in der Schule, mit Freunden oder wegen Geld? Wir beraten Dich vertraulich und kostenfrei.", + "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\"]", + "titles": { + "default": "Kinder und Jugend", + "short": "Kinder und Jugend", + "long": "Kinder- und Jugendberatung", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Kinder- und Jugendberatung" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "17": { + "description": "Sie fühlen sich von Ihren Aufgaben durch Job, Familie oder die Pflege von Angehörigen ausgelaugt? Sie sind krank und brauchen eine Auszeit vom Alltag? Eine Kur kann helfen, wieder Kräfte zu sammeln. Wir beraten Mütter, Väter und pflegende Angehörige vertraulich und kostenfrei hier in der Online-Beratung.", + "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\", \"Gesundheitliche Beeinträchtigung\"]", + "titles": { + "default": "Kurberatung", + "short": "Kurberatung", + "long": "Kurberatung für Mütter und Väter", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Kurberatung für Mütter und Väter" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "18": { + "description": "Sie brauchen Beratung zum Thema Wohnen im Alter? Sie haben Fragen zu Hilfen im Haushalt? Sie wollen Ihre Freizeit oder die Freizeit eines älteren Familienangehörigen abwechslungsreicher gestalten? Sie suchen Information zu Themen wie Demenz? Wir beraten Sie vertraulich und kostenfrei hier in der Online-Beratung.", + "groups": "[\"Gesundheitliche Beeinträchtigung\", \"Alter\"]", + "titles": { + "default": "Alter und Pflegeberatung", + "short": "Alter und Pflegeberatung", + "long": "Leben im Alter und Pflegeberatung", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Leben im Alter und Pflegeberatung" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "19": { + "description": "Sie sind über 26 Jahre alt und brauchen Hilfe sich in Deutschland zurecht zu finden? Sie brauchen Hilfe bei der Suche nach Arbeit oder einem Sprachkurs? Wir beraten Neu-Zugewanderte, aber auch Personen, die schon lange in Deutschland leben, Spätaussiedler:innen sowie Unionsbürger:innen.", + "groups": "[\"Migration, Flucht, Asyl\"]", + "titles": { + "default": "Migrationsberatung", + "short": "Migrationsberatung", + "long": "Migrationsberatung für Erwachsene und Familien", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Migrationsberatung für Erwachsene und Familien" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "20": { + "description": "Sie möchten ein selbstbestimmtes Leben führen und brauchen dabei Hilfe? Sie haben Fragen zu Finanzierung, Hilfsmitteln und Assistenz? Wir beraten Sie vertraulich und kostenfrei zu Ihren Fragen zur Selbsthilfe in den Lebensbereichen Arbeiten, Wohnen, Bildung und Freizeit.", + "groups": "[\"Gesundheitliche Beeinträchtigung\"]", + "titles": { + "default": "Psychische Beeintr.", + "short": "Psychische Beeintr.", + "long": "Psychische Beeinträchtigung", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Psychische Beeinträchtigung" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "21": { + "description": "Sie haben während Ihrer Flucht traumatische Erfahrungen gemacht? Sie haben in Ihrem Herkunftsland unter Folter, Gewalt und Rassismus gelitten? Sie kennen eine geflüchtete Person, die traumatisiert ist? Wir helfen Ihnen mit einer psychologischen und sozalpädagogischen Beratung.", + "groups": "[\"Migration, Flucht, Asyl\"]", + "titles": { + "default": "Psychosoziale Beratung", + "short": "Psychosoziale Beratung", + "long": "Psychosoziale Beratung für Geflüchtete und Migrant:innen", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Psychosoziale Beratung für Geflüchtete und Migrant:innen" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "22": { + "description": "Sie möchten als rechtliche:r Betreuer:in eingesetzt werden und möchten wissen, wie eine Betreuung eingerichtet wird und welche Aufgaben auf Sie zukommen? Sie möchten selbst vorsorgen und eine Patientenverfügung erstellen? Wir beraten Sie vertraulich und kostenfrei hier in der Online-Beratung.", + "groups": "[\"Teilhabe für Menschen mit Beeinträchtigung\"]", + "titles": { + "default": "Rechtliche Betreuung", + "short": "Rechtliche Betreuung", + "long": "Rechtliche Betreuung", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Rechtliche Betreuung" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "23": { + "description": "Sie haben Schulden, die Wohnung wurde gekündigt oder der Gerichtsvollzieher kommt? Wir beraten Sie vertraulich und kostenfrei hier in der Online-Beratung.", + "groups": "[\"Existenzsicherung\"]", + "titles": { + "default": "Schulden und Insolvenz", + "short": "Schulden und Insolvenz", + "long": "Schuldnerberatung und Insolvenzberatung", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Schuldnerberatung und Insolvenzberatung" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "24": { + "description": "Sie sind schwanger und haben Fragen? Sie fürchten um Ihre Partnerschaft? Sie haben Angst vor finanziellen Schwierigkeiten, wenn das Kind kommt. Sie möchten Beratung zu vorgeburtlichen Untersuchungen? Sie überlegen die Schwangerschaft abzubrechen? Wir beraten Sie vertraulich und kostenfrei.", + "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\"]", + "titles": { + "default": "Schwangerschaft", + "short": "Schwangerschaft", + "long": "Schwangeren- und Schwangerschaftskonfliktberatung", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Schwangeren- und Schwangerschaftskonfliktberatung" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "25": { + "description": "Sie haben ein Suchtproblem oder machen sich Sorgen um betroffene Freunde und Verwandte? Sie haben Fragen zu Sucht und Abhängigkeit - Alkohol, Drogen, Medikamente, Glücksspiel, Computer-/Medienkonsum? Wir beraten Sie vertraulich und kostenfrei hier in der Online-Beratung.", + "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\", \"Besondere Lebenssituationen und Krisen\", \"Gesundheitliche Beeinträchtigung\"]", + "titles": { + "default": "Sucht", + "short": "Sucht", + "long": "Suchtberatung und -prävention", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Suchtberatung und -prävention" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "26": { + "description": "Sie möchten ein selbstbestimmtes Leben führen und brauchen dabei Hilfe? Sie haben Fragen zu Finanzierung, Hilfsmitteln und Assistenz? Wir beraten Sie vertraulich und kostenfrei zu Ihren Fragen zur Selbsthilfe in den Lebensbereichen Arbeiten, Wohnen, Bildung und Freizeit.", + "groups": "[\"Teilhabe für Menschen mit Beeinträchtigung\"]", + "titles": { + "default": "Teilhabe", + "short": "Teilhabe", + "long": "Teilhabe von Menschen mit Beeinträchtigungen", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Teilhabe von Menschen mit Beeinträchtigungen" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + }, + "27": { + "description": "Du hast Fragen rund um Schule, Ausbildung und Beruf? Wie stellst Du Dir Deine Zukunft vor? Was brauchst Du dafür? Wir helfen Dir vertraulich und kostenfrei hier in der Online-Beratung.", + "groups": "[\"Kinder, Jugendliche, Erwachsene und Familie\"]", + "titles": { + "default": "von Schule zu Beruf", + "short": "von Schule zu Beruf", + "long": "Übergang von Schule zu Beruf", + "welcome": "Willkommen bei der Online-Beratung", + "registrationDropdown": "Übergang von Schule zu Beruf" + }, + "anonymous": { + "title": "Anonym und kostenfrei", + "text": "Sie bleiben anonym und erhalten kostenfreie Beratung und Hilfe" + } + } + } } diff --git a/src/resources/i18n/de/languages.json b/src/resources/i18n/de/languages.json index a0863255b..524c6949b 100644 --- a/src/resources/i18n/de/languages.json +++ b/src/resources/i18n/de/languages.json @@ -1,3 +1,4 @@ { - "de": "(DE) Deutsch" + "de": "(DE) Deutsch", + "en": "(EN) Englisch" } diff --git a/src/resources/i18n/en/consultingTypes.json b/src/resources/i18n/en/consultingTypes.json index bb8144ee4..3ba7e603f 100644 --- a/src/resources/i18n/en/consultingTypes.json +++ b/src/resources/i18n/en/consultingTypes.json @@ -1,3 +1,438 @@ { - "consultingType": {} + "consultingTypeGroup": { + "Teilhabe für Menschen mit Beeinträchtigung": { + "title": "Participation for people with disabilities" + }, + "Alter": { + "title": "Age" + }, + "Gesundheitliche Beeinträchtigung": { + "title": "Health impairment" + }, + "Besondere Lebenssituationen und Krisen": { + "title": "Special life situations and crises" + }, + "Hilfe in besonderen sozialen Situationen": { + "title": "Help in special social situations" + }, + "Kinder, Jugendliche, Erwachsene und Familie": { + "title": "Children, young people, adults and families" + }, + "Migration, Flucht, Asyl": { + "title": "Migration, flight, asylum" + }, + "Existenzsicherung": { + "title": "Livelihood security" + }, + "Hilfe für Kinder, Erwachsene und Familien": { + "title": "Help for children, adults and families" + } + }, + "consultingType": { + "1": { + "description": "You want to adopt a child or take in a foster child in your home? You are unsure whether you can take good care of your child? You are adopted yourself and would like to take a look at your file? We can advise you confidentially and free of charge here in online consulting.", + "groups": "[\"Children, Adolescents, Adults and Family\"]", + "titles": { + "default": "Adoption and foster child", + "short": "Adoption and foster child", + "long": "adoption and foster child consulting", + "welcome": "Welcome to online consulting", + "registrationDropdown": "Adoption and foster child consulting" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and assistance" + } + }, + "2": { + "description": "You have a personal problem, are in a difficult financial situation or have difficulties with an authority? No matter what problem is plaguing you, we will advise you free of charge and confidentially here in online consulting.", + "groups": "[\"Children, Adolescents, Adults and Family\", \"Livelihood\"]", + "titles": { + "default": "General social counseling", + "short": "General social counseling", + "long": "General social consulting", + "welcome": "Welcome to online consulting", + "registrationDropdown": "General Social Counseling" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and help" + } + }, + "3": { + "description": "You have lost your job? You have questions about unemployment benefits I and II? Do you need help with your job search or are you working precariously? We can help you confidentially and free of charge here in the online consulting service.", + "groups": "[\"Existenzsicherung\"]", + "titles": { + "default": "Unemployed, unemployable", + "short": "Unemployed, unemployable", + "long": "Unemployment consulting/unemployed consulting", + "welcome": "Welcome to online consulting", + "registrationDropdown": "unemployment counseling/unemployment counseling" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and help" + } + }, + "4": { + "description": "You have to or want to leave Germany? You are considering whether you want to live in Germany or in your country of origin? We will advise you confidentially and free of charge here in online consulting, regardless of your residence status.", + "groups": "[\"Migration, Flight, Asylum\"]", + "titles": { + "default": "Departure and perspective", + "short": "Departure and perspective", + "long": "Exit and perspective consulting - return consulting", + "welcome": "Welcome to online consulting", + "registrationDropdown": "Exit and perspective consulting - return consulting" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and help" + } + }, + "5": { + "description": "You don't have a home or you are afraid to lose your home? You live in unacceptable housing conditions? You are in an emergency situation? We can help you confidentially and free of charge here in the online consulting service.", + "groups": "[\"Livelihood security\", \"Special life situations and crises\"]", + "titles": { + "default": "Housing emergency", + "short": "Housing emergency", + "long": "housing emergency consulting", + "welcome": "Welcome to online consulting", + "registrationDropdown": "consulting in housing emergencies" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and assistance" + } + }, + "6": { + "description": "You are a sex worker:in and often experience stigmatization, discrimination and devaluation? You no longer want to work as a sex worker? We support you in asserting your rights, organize necessary assistance and help you to get out.", + "groups": "[\"Special life situations and crises\"]", + "titles": { + "default": "Prostitution", + "short": "Prostitution", + "long": "Consulting for people in prostitution and human trafficking", + "welcome": "Welcome to online consulting", + "registrationDropdown": "Consulting for people in prostitution and human trafficking" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and help" + } + }, + "7": { + "description": "You have been in custody and have questions about claims for social benefits? You need assistance in finding housing and employment? Do you have personal problems? There are situations around detention that you can't handle on your own. We can help you confidentially and free of charge.", + "groups": "[\"Securing livelihood\", \"Special life situations and crises\"]", + "titles": { + "default": "delinquency", + "short": "delinquency", + "long": "Consulting for people who have committed crimes and their relatives", + "welcome": "Welcome to online consulting", + "registrationDropdown": "Consulting for people who have committed crimes and their relatives" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and help" + } + }, + "8": { + "description": "Your family needs time off that is affordable? We'll be happy to advise you on your individual time away and funding options for low-income families. All families are welcome at the resorts. Denomination and family constellation do not matter.", + "groups": "[\"Children, youth, adults and family\"]", + "titles": { + "default": "Family recreation", + "short": "Family recovery", + "long": "consulting on family recovery issues", + "welcome": "Welcome to online consulting", + "registrationDropdown": "consulting on family recovery issues" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and help" + } + }, + "9": { + "description": "You have a grueling conflict or worries won't let you rest? You have problems in your partnership that you can't solve? We help you when fears determine your everyday life, when grief over the loss of a person or loneliness take away your joy of life.", + "groups": "[\"Children, adolescents, adults and family\"]", + "titles": { + "default": "Marriage, couple and life", + "short": "Marriage, couple and life", + "long": "Marriage, couple and life consulting", + "welcome": "Welcome to online consulting", + "registrationDropdown": "marriage, couple and life counseling" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and help" + } + }, + "10": { + "description": "Does your child have difficulties in kindergarten or school? Do you feel overwhelmed in everyday family life? Are you facing a separation or do you need support for yourself and your children because of a separation? We can help you confidentially and free of charge here in online consulting.", + "groups": "[\"children, adolescents, adults and family\"]", + "titles": { + "default": "Education and family", + "short": "Education and family", + "long": "education and family consulting", + "welcome": "Welcome to online consulting", + "registrationDropdown": "Educational and family consulting" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and help" + } + }, + "11": { + "description": "You are a refugee and have questions about the asylum procedure? You need help with the preparation for the hearing in the asylum procedure? The asylum procedure has been completed and you need support in Germany? We advise people of all origins and regardless of denomination.", + "groups": "[\"Migration, flight, asylum\"]", + "titles": { + "default": "Flight and asylum", + "short": "Flight and Asylum", + "long": "Refugee & asylum process consulting", + "welcome": "Welcome to online consulting", + "registrationDropdown": "Refugee & asylum procedure consulting" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and assistance" + } + }, + "12": { + "description": "You have received a positive test result and are wondering what to do next? You are a family member of a HIV-positive person and have unanswered questions? Would you like to know how you can protect yourself from HIV or other sexually transmitted infections? We will help you confidentially and free of charge.", + "groups": "[\"Health impairment\"]", + "titles": { + "default": "HIV and AIDS", + "short": "HIV and Aids", + "long": "HIV and Aids", + "welcome": "Welcome to online consulting", + "registrationDropdown": "HIV and Aids" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and help" + } + }, + "13": { + "description": "You are seriously ill, do not have long to live or are a relative:r and need support? You would like to achieve the best possible quality of life in this situation? Do you have questions about advance care planning? We will advise you confidentially and free of charge here in the online consultation.", + "groups": "[\"Health Impairment\", \"Children, Adolescents, Adults and Family\", \"Age\"]", + "titles": { + "default": "Hospice and palliative", + "short": "Hospice and Palliative", + "long": "Hospice and palliative consulting", + "welcome": "Welcome to online consulting", + "registrationDropdown": "Hospice and palliative consulting" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and assistance" + } + }, + "14": { + "description": "Have you been affected by sexual violence? Have you been hurt by physical violence by another person? Does someone threaten you, insult you, or yell at you? Do you know a person who suffers from domestic or sexualized violence? We can help you confidentially and free of charge.", + "groups": "[\"Children, youth, adults and family\"]", + "titles": { + "default": "violence", + "short": "Violence", + "long": "Domestic and sexual violence consulting", + "welcome": "Welcome to online consulting", + "registrationDropdown": "Domestic and sexual violence consulting" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and help" + } + }, + "15": { + "description": "You are between 12 and 27 years old, have a migration background and questions about school qualifications, training or language courses? We advise you on educational and leisure opportunities free of charge and confidentially here in the online consulting.", + "groups": "[\"Migration, flight, asylum\"]", + "titles": { + "default": "Youth migration services", + "short": "Youth migration services", + "long": "Youth Migration Services (JMD)", + "welcome": "Welcome to online consulting", + "registrationDropdown": "Youth Migration Services (JMD)" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and help" + } + }, + "16": { + "description": "Do you just not know what to do? Do you feel not understood? Are you worried about a friend? Are you having trouble with your parents? Are you being beaten? Do you have stress at school, with friends or because of money? We advise you confidentially and free of charge.", + "groups": "[\"Children, youth, adults and family\"]", + "titles": { + "default": "Children and youth", + "short": "children and youth", + "long": "Children and youth consulting", + "welcome": "Welcome to online consulting", + "registrationDropdown": "child and youth consulting" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and help" + } + }, + "17": { + "description": "You feel drained by your tasks due to job, family or caring for relatives? You are ill and need a break from everyday life? A cure can help you regain your strength. We advise mothers, fathers and caring relatives confidentially and free of charge here in the online consulting service.", + "groups": "[\"Children, Adolescents, Adults and Family\", \"Health Impairment\"]", + "titles": { + "default": "Cure counseling", + "short": "spa counseling", + "long": "Cure consulting for mothers and fathers", + "welcome": "Welcome to online consulting", + "registrationDropdown": "Cure consulting for mothers and fathers" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and help" + } + }, + "18": { + "description": "You need advice about living in old age? Do you have questions about help in the household? Do you want to diversify your leisure time or the leisure time of an elderly family member? Are you looking for information on topics such as dementia? We will advise you confidentially and free of charge here in the online consulting service.", + "groups": "[\"Health impairment\", \"age\"]", + "titles": { + "default": "Age and care consulting", + "short": "Age and care consulting", + "long": "Living in old age and care consulting", + "welcome": "Welcome to online consulting", + "registrationDropdown": "Life in old age and care consulting" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and assistance" + } + }, + "19": { + "description": "You are over 26 years old and need help to find your way in Germany? Do you need help finding a job or a language course? We advise new immigrants, but also people who have been living in Germany for a long time, late repatriates and citizens of the EU", + "groups": "[\"Migration, Flight, Asylum\"]", + "titles": { + "default": "Migration consulting", + "short": "Migration consulting", + "long": "Migration counseling for adults and families", + "welcome": "Welcome to online consulting", + "registrationDropdown": "Migration consulting for adults and families" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and assistance" + } + }, + "20": { + "description": "You want to lead a self-determined life and need help? Do you have questions about financing, aids and assistance? We advise you confidentially and free of charge on your questions about self-help in the areas of work, housing, education and leisure.", + "groups": "[\"Health impairment\"]", + "titles": { + "default": "Mental impairment", + "short": "Mental impairment", + "long": "Mental impairment", + "welcome": "Welcome to online consulting", + "registrationDropdown": "mental impairment" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and help" + } + }, + "21": { + "description": "You have had traumatic experiences during your flight? You have suffered from torture, violence and racism in your country of origin? You know a refugee who is traumatized? We can help you with psychological and socio-educational counseling.", + "groups": "[\"Migration, flight, asylum\"]", + "titles": { + "default": "Psychosocial counseling", + "short": "Psychosocial counseling", + "long": "Psychosocial counseling for refugees and migrants", + "welcome": "Welcome to online consulting", + "registrationDropdown": "Psychosocial counseling for refugees and migrants" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and help" + } + }, + "22": { + "description": "You would like to be appointed as a legal guardian and would like to know how a guardianship is set up and what tasks await you? Would you like to make your own provisions and draw up a living will? We will advise you confidentially and free of charge here in the online consultation.", + "groups": "[\"Participation for people with impairments\"]", + "titles": { + "default": "Legal care", + "short": "Legal care", + "long": "Legal support", + "welcome": "Welcome to online consulting", + "registrationDropdown": "Legal support" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and help" + } + }, + "23": { + "description": "You have debts, the apartment was canceled or the bailiff comes? We advise you confidentially and free of charge here in the online consulting.", + "groups": "[\"Existenzsicherung\"]", + "titles": { + "default": "Debt and insolvency", + "short": "Debt and insolvency", + "long": "Debt and insolvency consulting", + "welcome": "Welcome to online consulting", + "registrationDropdown": "debtor and insolvency consulting" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and help" + } + }, + "24": { + "description": "You are pregnant and have questions? You fear for your partnership? You are afraid of financial difficulties when the child comes? You want advice on prenatal examinations? Are you considering terminating the pregnancy? We will advise you confidentially and free of charge.", + "groups": "[\"Children, adolescents, adults and family\"]", + "titles": { + "default": "Pregnancy", + "short": "Pregnancy", + "long": "Pregnancy and pregnancy conflict consulting", + "welcome": "Welcome to online consulting", + "registrationDropdown": "Pregnancy and pregnancy conflict consulting" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and help" + } + }, + "25": { + "description": "Do you have an addiction problem or are you worried about friends and relatives who are affected? You have questions about addiction and dependence - alcohol, drugs, medication, gambling, computer/media use? We can advise you confidentially and free of charge here in the online consulting service.", + "groups": "[\"Children, adolescents, adults and family\", \"Special life situations and crises\", \"Health impairment\"]", + "titles": { + "default": "Addiction", + "short": "Addiction", + "long": "Addiction consulting and prevention", + "welcome": "Welcome to online consulting", + "registrationDropdown": "Addiction counseling and prevention" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and help" + } + }, + "26": { + "description": "You want to lead a self-determined life and need help? Do you have questions about financing, aids and assistance? We advise you confidentially and free of charge on your questions about self-help in the areas of work, housing, education and leisure.", + "groups": "[\"Participation for people with impairments\"]", + "titles": { + "default": "participation", + "short": "participation", + "long": "Participation of people with impairments", + "welcome": "Welcome to online consulting", + "registrationDropdown": "Participation of people with impairments" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and assistance" + } + }, + "27": { + "description": "You have questions about school, training and career? How do you imagine your future? What do you need for it? We will help you confidentially and free of charge here in the online consulting.", + "groups": "[\"Children, youth, adults and family\"]", + "titles": { + "default": "from school to work", + "short": "from school to work", + "long": "school-to-work transition", + "welcome": "Welcome to online consulting", + "registrationDropdown": "transition from school to work" + }, + "anonymous": { + "title": "Anonymous and free of charge", + "text": "You remain anonymous and receive free advice and assistance" + } + } + } } diff --git a/src/resources/scripts/config.ts b/src/resources/scripts/config.ts index 71e1ac3c9..e45cd4e69 100644 --- a/src/resources/scripts/config.ts +++ b/src/resources/scripts/config.ts @@ -1,5 +1,10 @@ import deAgency from '../i18n/de/agency.json'; import deConsultingTypes from '../i18n/de/consultingTypes.json'; +import deLanguages from '../i18n/de/languages.json'; +import en from '../i18n/en/common.json'; +import enAgency from '../i18n/en/agency.json'; +import enConsultingTypes from '../i18n/en/consultingTypes.json'; +import enLanguages from '../i18n/en/languages.json'; import { AppConfigInterface } from '../../globalState/interfaces'; import { OVERLAY_RELEASE_NOTE, @@ -10,6 +15,14 @@ export const uiUrl = window.location.origin; export const APP_PATH = 'app'; +export const routePathNames = { + root: '/', + login: '/login', + termsAndConditions: '/nutzungsbedingungen', + imprint: '/impressum', + privacy: '/datenschutz' +}; + export const config: AppConfigInterface = { budibaseUrl: '', budibaseSSO: false, // Feature flag to enable SSO on budibase @@ -32,7 +45,7 @@ export const config: AppConfigInterface = { } }, urls: { - chatScheduleUrl: 'https://www.caritas.de/onlineberatung', + chatScheduleUrl: uiUrl + '/registration', consultantVideoConference: '/consultant/videoberatung/:type/:appointmentId', error401: uiUrl + '/error.401.html', @@ -40,14 +53,14 @@ export const config: AppConfigInterface = { error500: uiUrl + '/error.500.html', finishedAnonymousChatRedirect: 'https://www.caritas.de/hilfeundberatung/hilfeundberatung', - home: 'https://www.caritas.de', - landingpage: '/login', + home: uiUrl + '/registration', + landingpage: '/registration', releases: uiUrl + '/releases', redirectToApp: uiUrl + '/' + APP_PATH, registration: uiUrl + '/registration', - toEntry: uiUrl + '/', + toEntry: uiUrl + '/registration', toLogin: uiUrl + '/login', - toRegistration: 'https://www.caritas.de/onlineberatung', + toRegistration: uiUrl + '/registration', videoCall: '/videoanruf/:domain/:jwt/:video?/:username?/:e2e?', videoConference: '/videoberatung/:type/:appointmentId' }, @@ -57,7 +70,7 @@ export const config: AppConfigInterface = { showCreationDate: false } }, - postcodeFallbackUrl: '{url}', + postcodeFallbackUrl: '{url}{postcode}/', jitsi: { /** * Enable WebRTC Encoded Transform as an alternative to insertable streams. @@ -75,14 +88,19 @@ export const config: AppConfigInterface = { }, legalLinks: [ { - url: 'https://www.caritas.de/impressum', + url: uiUrl + routePathNames.imprint, label: 'login.legal.infoText.impressum' }, { - url: 'https://www.caritas.de/hilfeundberatung/onlineberatung/datenschutz', + url: uiUrl + routePathNames.privacy, label: 'login.legal.infoText.dataprotection', registration: true } + // { + // url: routePathNames.termsAndConditions, + // label: 'login.legal.infoText.termsAndConditions', + // registration: true + // } ], welcomeScreen: { consultingType: { @@ -91,7 +109,7 @@ export const config: AppConfigInterface = { }, registration: { consultingTypeDefaults: { - autoSelectPostcode: true, + autoSelectPostcode: false, autoSelectAgency: false } }, @@ -312,16 +330,34 @@ export const config: AppConfigInterface = { 'zu' ], i18n: { - supportedLngs: ['de', 'de@informal'], - preload: ['de', 'de@informal'], + supportedLngs: ['en', 'de'], + fallbackLng: { + en: ['de'], + en_informal: ['en', 'de_informal', 'de'] + }, resources: { de: { + languages: { + ...deLanguages + }, consultingTypes: { ...deConsultingTypes }, agencies: { ...deAgency } + }, + en: { + common: [en], + consultingTypes: { + ...enConsultingTypes + }, + agencies: { + ...enAgency + }, + languages: { + ...enLanguages + } } } }, diff --git a/src/resources/styles/_layout.scss b/src/resources/styles/_layout.scss index 55ccdcafa..6aa85d7ab 100644 --- a/src/resources/styles/_layout.scss +++ b/src/resources/styles/_layout.scss @@ -56,9 +56,6 @@ hr { &:hover { color: var(--skin-color-primary-contrast-safe, $hover-primary); - .formAccordionItem__index { - border: 1px solid $hover-primary; - } } } @@ -76,6 +73,7 @@ hr { content: ' '; display: table; } + &:after { clear: both; } From 2cc1b09f84409a1c750e44ffafb4712f65f08f6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Tue, 17 Sep 2024 15:30:34 +0200 Subject: [PATCH 44/49] feat(caritas-theme): move new registration to core, cleanup styles & extensions --- .../generateQrCode/generateQrCode.styles.scss | 2 +- src/components/registration/Registration.tsx | 538 +++++++++++++----- .../registration/accountData/AccountData.tsx | 12 +- .../accountData/accountData.stories.ts | 0 .../agencySelection/AgencyLanguages.tsx | 4 +- .../agencySelection/AgencySelection.tsx | 8 +- .../AgencySelectionResults.tsx | 10 +- .../agencySelection.stories.ts | 0 .../registration/infoDrawer/InfoDrawer.tsx | 4 +- .../registration/metaInfo/MetaInfo.tsx | 0 .../preselectionBox/PreselectedAgency.tsx | 2 +- .../preselectionBox/PreselectedConsultant.tsx | 0 .../preselectionBox/PreselectedTopic.tsx | 2 +- .../preselectionBox/PreselectionBox.tsx | 6 +- .../preselectionDrawer/loader.svg | 0 .../registration/preselectionDrawer/logo.svg | 0 .../preselectionDrawer/preselectionDrawer.tsx | 4 +- .../preselectionError/PreselectionError.tsx | 0 .../registrationDataValidation.ts | 0 .../registration/stepBar/StepBar.stories.ts | 0 .../registration/stepBar/StepBar.tsx | 0 .../topicSelection/TopicSelection.tsx | 12 +- .../topicSelection/topicSelection.stories.ts | 0 .../welcomeScreen/WelcomeScreen.tsx | 1 + .../welcomeScreen/welcomeScreen.stories.ts | 0 .../welcomeScreen/welcomeScreen.styles.scss | 79 +++ .../zipcodeInput/ZipcodeInput.tsx | 4 +- .../zipcodeInput/zipcodeInput.stories.ts | 0 .../releaseNote/releaseNote.styles.scss | 4 + src/components/stage/stage.styles.scss | 194 +++++-- src/components/stage/stage.tsx | 131 +++-- src/components/stageLayout/StageLayout.tsx | 2 +- .../twoFactorAuth/twoFactorAuth.styles.scss | 5 + .../ProposedAgencies/ProposedAgencies.tsx | 18 +- .../components/registration/Registration.tsx | 414 -------------- .../components/stage/StageLayout.styles.scss | 20 - src/extensions/components/stage/loader.svg | 35 -- src/extensions/components/stage/logo.svg | 1 - .../components/stage/stage.styles.scss | 221 ------- src/extensions/components/stage/stage.tsx | 144 ----- src/extensions/initApp.tsx | 66 --- .../resources/styles/generateQrCode.scss | 3 - .../resources/styles/releaseNote.styles.scss | 3 - src/extensions/resources/styles/settings.scss | 150 ----- .../resources/styles/twoFactorAuth.scss | 4 - .../provider/RegistrationProvider.tsx | 8 +- src/initApp.tsx | 60 +- .../styles/mui-variables-mapping.scss | 2 +- 48 files changed, 822 insertions(+), 1351 deletions(-) rename src/{extensions => }/components/registration/accountData/AccountData.tsx (94%) rename src/{extensions => }/components/registration/accountData/accountData.stories.ts (100%) rename src/{extensions => }/components/registration/agencySelection/AgencyLanguages.tsx (88%) rename src/{extensions => }/components/registration/agencySelection/AgencySelection.tsx (86%) rename src/{extensions => }/components/registration/agencySelection/AgencySelectionResults.tsx (96%) rename src/{extensions => }/components/registration/agencySelection/agencySelection.stories.ts (100%) rename src/{extensions => }/components/registration/infoDrawer/InfoDrawer.tsx (96%) rename src/{extensions => }/components/registration/metaInfo/MetaInfo.tsx (100%) rename src/{extensions => }/components/registration/preselectionBox/PreselectedAgency.tsx (92%) rename src/{extensions => }/components/registration/preselectionBox/PreselectedConsultant.tsx (100%) rename src/{extensions => }/components/registration/preselectionBox/PreselectedTopic.tsx (93%) rename src/{extensions => }/components/registration/preselectionBox/PreselectionBox.tsx (89%) rename src/{extensions => }/components/registration/preselectionDrawer/loader.svg (100%) rename src/{extensions => }/components/registration/preselectionDrawer/logo.svg (100%) rename src/{extensions => }/components/registration/preselectionDrawer/preselectionDrawer.tsx (96%) rename src/{extensions => }/components/registration/preselectionError/PreselectionError.tsx (100%) rename src/{extensions => }/components/registration/registrationDataValidation.ts (100%) rename src/{extensions => }/components/registration/stepBar/StepBar.stories.ts (100%) rename src/{extensions => }/components/registration/stepBar/StepBar.tsx (100%) rename src/{extensions => }/components/registration/topicSelection/TopicSelection.tsx (96%) rename src/{extensions => }/components/registration/topicSelection/topicSelection.stories.ts (100%) rename src/{extensions => }/components/registration/welcomeScreen/WelcomeScreen.tsx (99%) rename src/{extensions => }/components/registration/welcomeScreen/welcomeScreen.stories.ts (100%) create mode 100644 src/components/registration/welcomeScreen/welcomeScreen.styles.scss rename src/{extensions => }/components/registration/zipcodeInput/ZipcodeInput.tsx (96%) rename src/{extensions => }/components/registration/zipcodeInput/zipcodeInput.stories.ts (100%) delete mode 100644 src/extensions/components/registration/Registration.tsx delete mode 100644 src/extensions/components/stage/StageLayout.styles.scss delete mode 100644 src/extensions/components/stage/loader.svg delete mode 100644 src/extensions/components/stage/logo.svg delete mode 100644 src/extensions/components/stage/stage.styles.scss delete mode 100644 src/extensions/components/stage/stage.tsx delete mode 100644 src/extensions/initApp.tsx delete mode 100644 src/extensions/resources/styles/generateQrCode.scss delete mode 100644 src/extensions/resources/styles/releaseNote.styles.scss delete mode 100644 src/extensions/resources/styles/settings.scss delete mode 100644 src/extensions/resources/styles/twoFactorAuth.scss diff --git a/src/components/generateQrCode/generateQrCode.styles.scss b/src/components/generateQrCode/generateQrCode.styles.scss index dab0536f5..122674ac1 100644 --- a/src/components/generateQrCode/generateQrCode.styles.scss +++ b/src/components/generateQrCode/generateQrCode.styles.scss @@ -40,7 +40,7 @@ .text { max-width: 500px; - margin-left: auto; + margin-left: 0; margin-right: auto; } diff --git a/src/components/registration/Registration.tsx b/src/components/registration/Registration.tsx index a46585997..188f1f1af 100644 --- a/src/components/registration/Registration.tsx +++ b/src/components/registration/Registration.tsx @@ -1,183 +1,413 @@ -import '../../polyfill'; +import { Typography, Link, Button, Box } from '@mui/material'; import * as React from 'react'; -import unionBy from 'lodash/unionBy'; -import { useParams } from 'react-router-dom'; -import { useContext, useEffect, useState } from 'react'; -import { getUrlParameter } from '../../utils/getUrlParameter'; -import { WelcomeScreen } from './WelcomeScreen'; -import { InformalContext } from '../../globalState'; -import { RegistrationForm } from './RegistrationForm'; -import '../../resources/styles/styles'; -import { StageLayout } from '../stageLayout/StageLayout'; -import useIsFirstVisit from '../../utils/useIsFirstVisit'; +import { + useState, + useEffect, + useContext, + useCallback, + useMemo, + FormEvent +} from 'react'; +import { + Route, + Switch, + useHistory, + useLocation, + useParams, + useRouteMatch, + generatePath, + Link as RouterLink +} from 'react-router-dom'; import { useTranslation } from 'react-i18next'; +import { Helmet } from 'react-helmet'; +import { StageLayout } from '../../components/stageLayout/StageLayout'; +import useIsFirstVisit from '../../utils/useIsFirstVisit'; +import { ReactComponent as HelloBannerIcon } from '../../resources/img/illustrations/hello-banner.svg'; +import { StepBar } from './stepBar/StepBar'; +import { WelcomeScreen } from './welcomeScreen/WelcomeScreen'; +import { + RegistrationContext, + TenantContext, + registrationSessionStorageKey, + RegistrationData, + NotificationsContext, + NOTIFICATION_TYPE_ERROR, + LocaleContext +} from '../../globalState'; import { GlobalComponentContext } from '../../globalState/provider/GlobalComponentContext'; -import { UrlParamsContext } from '../../globalState/provider/UrlParamsProvider'; +import { + OVERLAY_FUNCTIONS, + Overlay, + OverlayItem +} from '../../components/overlay/Overlay'; +import { redirectToApp } from '../../components/registration/autoLogin'; +import { BUTTON_TYPES } from '../../components/button/Button'; +import { PreselectionBox } from './preselectionBox/PreselectionBox'; +import { endpoints } from '../../resources/scripts/endpoints'; +import { apiPostRegistration } from '../../api'; import { useAppConfig } from '../../hooks/useAppConfig'; +import { REGISTRATION_DATA_VALIDATION } from './registrationDataValidation'; +import { UrlParamsContext } from '../../globalState/provider/UrlParamsProvider'; -export const Registration = () => { - const { t: translate } = useTranslation([ - 'common', - 'consultingTypes', - 'agencies' - ]); - - const { consultingTypeSlug } = useParams<{ consultingTypeSlug: string }>(); +/** + * This type of registration is currently not supporting: + * - autoSelectPostcode because its loaded over the consultingType and + * + * MultiTenancy: + * Each consultingType in mongodb has stored the tenant id (One to One Relation) -> Tenant URL could load by consultingType by tenant alternative only one consultingType exits + * MultiTenancyWithSingleDomain: + * Each consultintType in mongodb has stored the tenant id but this relation could not be loaded because no idea which consultingType settings to load before agency is selected + * For Caritas there is no consultingType tenant relation and every tenant could have different consultingType depending on agency. So before agency is selected no idea which consultingType settings to load before agency is selected + * @constructor + */ - const agencyId = getUrlParameter('aid'); - const consultantId = getUrlParameter('cid'); - const postcodeParameter = getUrlParameter('postcode'); +export const Registration = () => { + const { t } = useTranslation(['common', 'consultingTypes', 'agencies']); const settings = useAppConfig(); + const isFirstVisit = useIsFirstVisit(); + const location = useLocation(); + const history = useHistory(); + const { path } = useRouteMatch(); + const { step, topicSlug } = useParams<{ + step: string; + topicSlug: string; + }>(); - const { setInformal } = useContext(InformalContext); const { Stage } = useContext(GlobalComponentContext); + const { addNotification } = useContext(NotificationsContext); + const { + disabledNextButton, + updateRegistrationData, + registrationData, + availableSteps + } = useContext(RegistrationContext); + const { consultant: preselectedConsultant } = useContext(UrlParamsContext); + const { tenant } = useContext(TenantContext); + const { locale } = useContext(LocaleContext); + + const [stepData, setStepData] = useState>({}); + const [redirectOverlayActive, setRedirectOverlayActive] = + useState(false); + + const handleOverlayAction = (buttonFunction: string) => { + if (buttonFunction === OVERLAY_FUNCTIONS.REDIRECT_WITH_BLUR) { + redirectToApp(); + } + }; + const overlayItemRegistrationSuccess: OverlayItem = { + illustrationStyle: 'large', + svg: HelloBannerIcon, + headline: t('registration.overlay.success.headline'), + copy: t('registration.overlay.success.copy'), + buttonSet: [ + { + label: t('registration.overlay.success.button'), + function: OVERLAY_FUNCTIONS.REDIRECT_WITH_BLUR, + type: BUTTON_TYPES.AUTO_CLOSE + } + ] + }; - const loginParams = Object.entries({ - cid: consultantId, - aid: agencyId - }) - .filter(([, value]) => value) - .map(([key, value]) => `${key}=${value}`) - .join('&'); + const checkForStepsWithMissingMandatoryFields = + useCallback((): number[] => { + return availableSteps.reduce( + (missingSteps, step, currentIndex) => { + if ( + step?.mandatoryFields?.some( + (mandatoryField) => + registrationData?.[mandatoryField] === undefined + ) + ) { + return [...missingSteps, currentIndex]; + } + return missingSteps; + }, + [] + ); + }, [availableSteps, registrationData]); - const [showWelcomeScreen, setShowWelcomeScreen] = useState( - postcodeParameter === null + const currStepIndex = useMemo( + () => availableSteps.findIndex(({ name }) => name === step), + [availableSteps, step] ); - const [isReady, setIsReady] = useState(false); + const [prevStepUrl, nextStepUrl] = useMemo( + () => [ + `${generatePath(path, { topicSlug, step: availableSteps[currStepIndex - 1]?.name || 'welcome' })}${location.search}`, + availableSteps[currStepIndex + 1] + ? `${generatePath(path, { topicSlug, step: availableSteps[currStepIndex + 1]?.name || 'welcome' })}${location.search}` + : null + ], + [availableSteps, currStepIndex, path, topicSlug, location.search] + ); - const handleForwardToRegistration = () => { - setShowWelcomeScreen(false); - window.scrollTo({ top: 0 }); - }; + const onNextClick = useCallback(() => { + updateRegistrationData(stepData); + setStepData({}); + history.push(nextStepUrl); + }, [updateRegistrationData, stepData, history, nextStepUrl]); + + const onPrevClick = useCallback(() => { + if (stepData.zipcode) { + registrationData.zipcode = ''; + } + setStepData({}); + history.push(prevStepUrl); + }, [registrationData, stepData, history, prevStepUrl]); - const { agency, consultingType, consultant, topic, loaded } = - useContext(UrlParamsContext); + const handleSubmit = useCallback( + (e: FormEvent) => { + e.preventDefault(); + if (disabledNextButton) return; + onNextClick(); + }, + [disabledNextButton, onNextClick] + ); useEffect(() => { - if (!loaded) { - return; - } + // Check if mandatory fields from previous steps are missing + const missingPreviousSteps = checkForStepsWithMissingMandatoryFields() + .sort() + .filter((missingStep) => missingStep < currStepIndex); - if (!consultingType && !agency && !consultant && !topic) { - console.error( - 'No `consultingType`, `consultant`, `agency` or `topic` found in URL.' + if (missingPreviousSteps.length > 0) { + history.push( + `${generatePath(path, { topicSlug, step: availableSteps[missingPreviousSteps[0]]?.name })}${location.search}` ); - window.location.href = settings.urls.toRegistration; - return; } + }, [ + availableSteps, + checkForStepsWithMissingMandatoryFields, + history, + location.search, + currStepIndex, + path, + topicSlug + ]); - try { - if (consultant) { - // If all consultant agencies are informal then use informal - const isInformal = consultant.agencies.every( - (agency) => !agency.consultingTypeRel.languageFormal - ); - setInformal(isInformal); - - // If consultant has only one consulting type set document title - const hasUniqueConsultingType = - unionBy(consultant.agencies, 'consultingType').length > 1; - - if (hasUniqueConsultingType) { - document.title = `${translate( - 'registration.title.start' - )} ${translate( - [ - `consultingType.${consultant.agencies[0].consultingTypeRel.id}.titles.long`, - `consultingType.fallback.titles.long`, - consultant.agencies[0].consultingTypeRel.titles.long - ], - { ns: 'consultingTypes' } - )}`; - } - } else { - if ( - consultingType.urls?.requiredAidMissingRedirectUrl && - !agency - ) { - window.location.href = - consultingType.urls?.requiredAidMissingRedirectUrl; - throw new Error(`Consulting type requires matching aid`); - } - - // SET FORMAL/INFORMAL - setInformal(!consultingType.languageFormal); - - document.title = `${translate( - 'registration.title.start' - )} ${translate( - [ - `consultingType.${consultingType.id}.titles.long`, - `consultingType.fallback.titles.long`, - consultingType.titles.long - ], - { ns: 'consultingTypes' } - )}`; - } - setIsReady(true); - } catch (error) { - console.log(error); - return; + const onRegisterClick = useCallback(() => { + const data = { + ...registrationData, + ...stepData, + mainTopicId: registrationData.mainTopic.id.toString(), + topicId: registrationData.topic?.id?.toString(), + agencyId: registrationData.agency.id.toString(), + postcode: registrationData.zipcode, + termsAccepted: 'true', + preferredLanguage: locale || 'de', + consultingType: registrationData.agency.consultingType, + ...(preselectedConsultant + ? { consultantId: preselectedConsultant?.consultantId } + : {}) + }; + + if ( + Object.keys(REGISTRATION_DATA_VALIDATION).every((item) => + REGISTRATION_DATA_VALIDATION[item].validation(data[item]) + ) + ) { + apiPostRegistration( + endpoints.registerAsker, + data, + settings.multitenancyWithSingleDomainEnabled, + tenant + ).then(() => { + sessionStorage.removeItem(registrationSessionStorageKey); + setRedirectOverlayActive(true); + }); + } else { + addNotification({ + notificationType: NOTIFICATION_TYPE_ERROR, + title: t('registration.errors.ups.title'), + text: t('registration.errors.ups.text'), + closeable: true, + timeout: 3000 + }); } }, [ - consultingType, - agency, - consultant, - loaded, - consultingTypeSlug, - translate, - setInformal, - settings.urls.toRegistration, - topic + registrationData, + stepData, + preselectedConsultant, + settings.multitenancyWithSingleDomainEnabled, + tenant, + addNotification, + t, + locale ]); - const isFirstVisit = useIsFirstVisit(); + const stepPaths = useMemo( + () => + availableSteps.reduce( + (acc, { name }) => + acc.concat(generatePath(path, { topicSlug, step: name })), + [] + ), + [availableSteps, path, topicSlug] + ); return ( - } - loginParams={loginParams} - > - {isReady && - (showWelcomeScreen ? ( - - ) : ( - - ))} - + <> + } + showRegistrationInfoDrawer={true} + > + + + + + + +
    name) + .join(',')} + > + + + {t('registration.headline')} + + + + + + + {availableSteps.map( + ({ + name, + component: Component + }) => ( + + + + ) + )} + + + + + + {t('registration.back')} + + + {!nextStepUrl ? ( + + ) : ( + + )} + + +
    +
    + + + +
    +
    +
    + {redirectOverlayActive && ( + + )} + ); }; diff --git a/src/extensions/components/registration/accountData/AccountData.tsx b/src/components/registration/accountData/AccountData.tsx similarity index 94% rename from src/extensions/components/registration/accountData/AccountData.tsx rename to src/components/registration/accountData/AccountData.tsx index 170b8a542..5c3f2c7ab 100644 --- a/src/extensions/components/registration/accountData/AccountData.tsx +++ b/src/components/registration/accountData/AccountData.tsx @@ -18,18 +18,18 @@ import { import { useTranslation } from 'react-i18next'; import PersonIcon from '@mui/icons-material/Person'; import LockIcon from '@mui/icons-material/Lock'; -import { Input } from '../../../../components/input/input'; +import { Input } from '../../../components/input/input'; import VisibilityIcon from '@mui/icons-material/Visibility'; import { hasMixedLetters, hasNumber, hasSpecialChar -} from '../../../../utils/validateInputValue'; -import { LegalLinksContext } from '../../../../globalState/provider/LegalLinksProvider'; -import { RegistrationContext, RegistrationData } from '../../../../globalState'; -import { apiGetIsUsernameAvailable } from '../../../../api/apiGetIsUsernameAvailable'; +} from '../../../utils/validateInputValue'; +import { LegalLinksContext } from '../../../globalState/provider/LegalLinksProvider'; +import { RegistrationContext, RegistrationData } from '../../../globalState'; +import { apiGetIsUsernameAvailable } from '../../../api/apiGetIsUsernameAvailable'; import { REGISTRATION_DATA_VALIDATION } from '../registrationDataValidation'; -import LegalLinks from '../../../../components/legalLinks/LegalLinks'; +import LegalLinks from '../../../components/legalLinks/LegalLinks'; export const passwordCriteria = [ { diff --git a/src/extensions/components/registration/accountData/accountData.stories.ts b/src/components/registration/accountData/accountData.stories.ts similarity index 100% rename from src/extensions/components/registration/accountData/accountData.stories.ts rename to src/components/registration/accountData/accountData.stories.ts diff --git a/src/extensions/components/registration/agencySelection/AgencyLanguages.tsx b/src/components/registration/agencySelection/AgencyLanguages.tsx similarity index 88% rename from src/extensions/components/registration/agencySelection/AgencyLanguages.tsx rename to src/components/registration/agencySelection/AgencyLanguages.tsx index de71fa48e..3e1598451 100644 --- a/src/extensions/components/registration/agencySelection/AgencyLanguages.tsx +++ b/src/components/registration/agencySelection/AgencyLanguages.tsx @@ -2,8 +2,8 @@ import { Typography } from '@mui/material'; import * as React from 'react'; import { useContext, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { apiAgencyLanguages } from '../../../../api/apiAgencyLanguages'; -import { LanguagesContext } from '../../../../globalState/provider/LanguagesProvider'; +import { apiAgencyLanguages } from '../../../api/apiAgencyLanguages'; +import { LanguagesContext } from '../../../globalState/provider/LanguagesProvider'; interface AgencyLanguagesProps { agencyId?: number; diff --git a/src/extensions/components/registration/agencySelection/AgencySelection.tsx b/src/components/registration/agencySelection/AgencySelection.tsx similarity index 86% rename from src/extensions/components/registration/agencySelection/AgencySelection.tsx rename to src/components/registration/agencySelection/AgencySelection.tsx index 1a375e5b4..ed35df11b 100644 --- a/src/extensions/components/registration/agencySelection/AgencySelection.tsx +++ b/src/components/registration/agencySelection/AgencySelection.tsx @@ -8,12 +8,12 @@ import { SetStateAction } from 'react'; import { AgencySelectionResults } from './AgencySelectionResults'; -import { RegistrationContext, RegistrationData } from '../../../../globalState'; +import { RegistrationContext, RegistrationData } from '../../../globalState'; import { Box, Typography } from '@mui/material'; import { useTranslation } from 'react-i18next'; -import { UrlParamsContext } from '../../../../globalState/provider/UrlParamsProvider'; -import { useAgenciesForRegistration } from '../../../../containers/registration/hooks/useAgenciesForRegistration'; -import { Loading } from '../../../../components/app/Loading'; +import { UrlParamsContext } from '../../../globalState/provider/UrlParamsProvider'; +import { useAgenciesForRegistration } from '../../../containers/registration/hooks/useAgenciesForRegistration'; +import { Loading } from '../../../components/app/Loading'; export const AgencySelection: VFC<{ onChange: Dispatch>>; diff --git a/src/extensions/components/registration/agencySelection/AgencySelectionResults.tsx b/src/components/registration/agencySelection/AgencySelectionResults.tsx similarity index 96% rename from src/extensions/components/registration/agencySelection/AgencySelectionResults.tsx rename to src/components/registration/agencySelection/AgencySelectionResults.tsx index 65f1603ee..d725d9f98 100644 --- a/src/extensions/components/registration/agencySelection/AgencySelectionResults.tsx +++ b/src/components/registration/agencySelection/AgencySelectionResults.tsx @@ -17,16 +17,16 @@ import { useState } from 'react'; import TaskAltIcon from '@mui/icons-material/TaskAlt'; -import NoResultsIllustration from '../../../../resources/img/illustrations/no-results.svg'; -import ConsultantIllustration from '../../../../resources/img/illustrations/consultant-found.svg'; +import NoResultsIllustration from '../../../resources/img/illustrations/no-results.svg'; +import ConsultantIllustration from '../../../resources/img/illustrations/consultant-found.svg'; import OpenInNewIcon from '@mui/icons-material/OpenInNew'; import { useTranslation } from 'react-i18next'; -import { RegistrationContext, RegistrationData } from '../../../../globalState'; -import { AgencyDataInterface } from '../../../../globalState/interfaces'; +import { RegistrationContext, RegistrationData } from '../../../globalState'; +import { AgencyDataInterface } from '../../../globalState/interfaces'; import { AgencyLanguages } from './AgencyLanguages'; import { MetaInfo } from '../metaInfo/MetaInfo'; import { REGISTRATION_DATA_VALIDATION } from '../registrationDataValidation'; -import { UrlParamsContext } from '../../../../globalState/provider/UrlParamsProvider'; +import { UrlParamsContext } from '../../../globalState/provider/UrlParamsProvider'; interface AgencySelectionResultsProps { onChange: Dispatch>>; diff --git a/src/extensions/components/registration/agencySelection/agencySelection.stories.ts b/src/components/registration/agencySelection/agencySelection.stories.ts similarity index 100% rename from src/extensions/components/registration/agencySelection/agencySelection.stories.ts rename to src/components/registration/agencySelection/agencySelection.stories.ts diff --git a/src/extensions/components/registration/infoDrawer/InfoDrawer.tsx b/src/components/registration/infoDrawer/InfoDrawer.tsx similarity index 96% rename from src/extensions/components/registration/infoDrawer/InfoDrawer.tsx rename to src/components/registration/infoDrawer/InfoDrawer.tsx index 6e349e8fe..831232383 100644 --- a/src/extensions/components/registration/infoDrawer/InfoDrawer.tsx +++ b/src/components/registration/infoDrawer/InfoDrawer.tsx @@ -4,9 +4,9 @@ import { useTranslation } from 'react-i18next'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp'; import { Box, SwipeableDrawer, Typography } from '@mui/material'; -import { RegistrationContext } from '../../../../globalState'; +import { RegistrationContext } from '../../../globalState'; import { PreselectionError } from '../preselectionError/PreselectionError'; -import { UrlParamsContext } from '../../../../globalState/provider/UrlParamsProvider'; +import { UrlParamsContext } from '../../../globalState/provider/UrlParamsProvider'; interface InfoDrawerProps { trigger?: boolean; diff --git a/src/extensions/components/registration/metaInfo/MetaInfo.tsx b/src/components/registration/metaInfo/MetaInfo.tsx similarity index 100% rename from src/extensions/components/registration/metaInfo/MetaInfo.tsx rename to src/components/registration/metaInfo/MetaInfo.tsx diff --git a/src/extensions/components/registration/preselectionBox/PreselectedAgency.tsx b/src/components/registration/preselectionBox/PreselectedAgency.tsx similarity index 92% rename from src/extensions/components/registration/preselectionBox/PreselectedAgency.tsx rename to src/components/registration/preselectionBox/PreselectedAgency.tsx index 4aa804209..999143f91 100644 --- a/src/extensions/components/registration/preselectionBox/PreselectedAgency.tsx +++ b/src/components/registration/preselectionBox/PreselectedAgency.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { useTranslation } from 'react-i18next'; import { Typography } from '@mui/material'; import ReportProblemIcon from '@mui/icons-material/ReportProblem'; -import { AgencyDataInterface } from '../../../../globalState/interfaces'; +import { AgencyDataInterface } from '../../../globalState/interfaces'; const PreselectedAgency = ({ hasError, diff --git a/src/extensions/components/registration/preselectionBox/PreselectedConsultant.tsx b/src/components/registration/preselectionBox/PreselectedConsultant.tsx similarity index 100% rename from src/extensions/components/registration/preselectionBox/PreselectedConsultant.tsx rename to src/components/registration/preselectionBox/PreselectedConsultant.tsx diff --git a/src/extensions/components/registration/preselectionBox/PreselectedTopic.tsx b/src/components/registration/preselectionBox/PreselectedTopic.tsx similarity index 93% rename from src/extensions/components/registration/preselectionBox/PreselectedTopic.tsx rename to src/components/registration/preselectionBox/PreselectedTopic.tsx index dd8631e9d..7f498c7b7 100644 --- a/src/extensions/components/registration/preselectionBox/PreselectedTopic.tsx +++ b/src/components/registration/preselectionBox/PreselectedTopic.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { useTranslation } from 'react-i18next'; import { SxProps, Theme, Typography } from '@mui/material'; import ReportProblemIcon from '@mui/icons-material/ReportProblem'; -import { TopicsDataInterface } from '../../../../globalState/interfaces'; +import { TopicsDataInterface } from '../../../globalState/interfaces'; const PreselectedTopic = ({ hasError, diff --git a/src/extensions/components/registration/preselectionBox/PreselectionBox.tsx b/src/components/registration/preselectionBox/PreselectionBox.tsx similarity index 89% rename from src/extensions/components/registration/preselectionBox/PreselectionBox.tsx rename to src/components/registration/preselectionBox/PreselectionBox.tsx index 75663bc83..350233ab4 100644 --- a/src/extensions/components/registration/preselectionBox/PreselectionBox.tsx +++ b/src/components/registration/preselectionBox/PreselectionBox.tsx @@ -1,10 +1,10 @@ import * as React from 'react'; import { useContext } from 'react'; import { Box } from '@mui/material'; -import { RegistrationContext } from '../../../../globalState'; +import { RegistrationContext } from '../../../globalState'; import { PreselectionDrawer } from '../preselectionDrawer/preselectionDrawer'; -import { useResponsive } from '../../../../hooks/useResponsive'; -import { UrlParamsContext } from '../../../../globalState/provider/UrlParamsProvider'; +import { useResponsive } from '../../../hooks/useResponsive'; +import { UrlParamsContext } from '../../../globalState/provider/UrlParamsProvider'; import PreselectedConsultant from './PreselectedConsultant'; import PreselectedTopic from './PreselectedTopic'; import PreselectedAgency from './PreselectedAgency'; diff --git a/src/extensions/components/registration/preselectionDrawer/loader.svg b/src/components/registration/preselectionDrawer/loader.svg similarity index 100% rename from src/extensions/components/registration/preselectionDrawer/loader.svg rename to src/components/registration/preselectionDrawer/loader.svg diff --git a/src/extensions/components/registration/preselectionDrawer/logo.svg b/src/components/registration/preselectionDrawer/logo.svg similarity index 100% rename from src/extensions/components/registration/preselectionDrawer/logo.svg rename to src/components/registration/preselectionDrawer/logo.svg diff --git a/src/extensions/components/registration/preselectionDrawer/preselectionDrawer.tsx b/src/components/registration/preselectionDrawer/preselectionDrawer.tsx similarity index 96% rename from src/extensions/components/registration/preselectionDrawer/preselectionDrawer.tsx rename to src/components/registration/preselectionDrawer/preselectionDrawer.tsx index dc88c4b6a..4fcd5d158 100644 --- a/src/extensions/components/registration/preselectionDrawer/preselectionDrawer.tsx +++ b/src/components/registration/preselectionDrawer/preselectionDrawer.tsx @@ -5,8 +5,8 @@ import { ReactComponent as Loader } from './loader.svg'; import { ReactComponent as Logo } from './logo.svg'; import { useTranslation } from 'react-i18next'; import { PreselectionError } from '../preselectionError/PreselectionError'; -import { RegistrationContext } from '../../../../globalState'; -import { UrlParamsContext } from '../../../../globalState/provider/UrlParamsProvider'; +import { RegistrationContext } from '../../../globalState'; +import { UrlParamsContext } from '../../../globalState/provider/UrlParamsProvider'; const ConsultantPreslection = ({ hasError }) => { const { t } = useTranslation(); diff --git a/src/extensions/components/registration/preselectionError/PreselectionError.tsx b/src/components/registration/preselectionError/PreselectionError.tsx similarity index 100% rename from src/extensions/components/registration/preselectionError/PreselectionError.tsx rename to src/components/registration/preselectionError/PreselectionError.tsx diff --git a/src/extensions/components/registration/registrationDataValidation.ts b/src/components/registration/registrationDataValidation.ts similarity index 100% rename from src/extensions/components/registration/registrationDataValidation.ts rename to src/components/registration/registrationDataValidation.ts diff --git a/src/extensions/components/registration/stepBar/StepBar.stories.ts b/src/components/registration/stepBar/StepBar.stories.ts similarity index 100% rename from src/extensions/components/registration/stepBar/StepBar.stories.ts rename to src/components/registration/stepBar/StepBar.stories.ts diff --git a/src/extensions/components/registration/stepBar/StepBar.tsx b/src/components/registration/stepBar/StepBar.tsx similarity index 100% rename from src/extensions/components/registration/stepBar/StepBar.tsx rename to src/components/registration/stepBar/StepBar.tsx diff --git a/src/extensions/components/registration/topicSelection/TopicSelection.tsx b/src/components/registration/topicSelection/TopicSelection.tsx similarity index 96% rename from src/extensions/components/registration/topicSelection/TopicSelection.tsx rename to src/components/registration/topicSelection/TopicSelection.tsx index f40221e5c..554f09628 100644 --- a/src/extensions/components/registration/topicSelection/TopicSelection.tsx +++ b/src/components/registration/topicSelection/TopicSelection.tsx @@ -25,18 +25,18 @@ import { LocaleContext, RegistrationContext, RegistrationData -} from '../../../../globalState'; -import { apiGetTopicGroups } from '../../../../api/apiGetTopicGroups'; -import { apiGetTopicsData } from '../../../../api/apiGetTopicsData'; +} from '../../../globalState'; +import { apiGetTopicGroups } from '../../../api/apiGetTopicGroups'; +import { apiGetTopicsData } from '../../../api/apiGetTopicsData'; import { TopicsDataInterface, TopicGroup -} from '../../../../globalState/interfaces'; +} from '../../../globalState/interfaces'; import { MetaInfo } from '../metaInfo/MetaInfo'; -import { Loading } from '../../../../components/app/Loading'; +import { Loading } from '../../../components/app/Loading'; import TaskAltIcon from '@mui/icons-material/TaskAlt'; import { REGISTRATION_DATA_VALIDATION } from '../registrationDataValidation'; -import { UrlParamsContext } from '../../../../globalState/provider/UrlParamsProvider'; +import { UrlParamsContext } from '../../../globalState/provider/UrlParamsProvider'; export const TopicSelection: VFC<{ onChange: Dispatch>>; diff --git a/src/extensions/components/registration/topicSelection/topicSelection.stories.ts b/src/components/registration/topicSelection/topicSelection.stories.ts similarity index 100% rename from src/extensions/components/registration/topicSelection/topicSelection.stories.ts rename to src/components/registration/topicSelection/topicSelection.stories.ts diff --git a/src/extensions/components/registration/welcomeScreen/WelcomeScreen.tsx b/src/components/registration/welcomeScreen/WelcomeScreen.tsx similarity index 99% rename from src/extensions/components/registration/welcomeScreen/WelcomeScreen.tsx rename to src/components/registration/welcomeScreen/WelcomeScreen.tsx index da74de364..04d03e8a6 100644 --- a/src/extensions/components/registration/welcomeScreen/WelcomeScreen.tsx +++ b/src/components/registration/welcomeScreen/WelcomeScreen.tsx @@ -8,6 +8,7 @@ import LockIcon from '@mui/icons-material/Lock'; import { Link as RouterLink } from 'react-router-dom'; import { useMemo } from 'react'; import { PreselectionBox } from '../preselectionBox/PreselectionBox'; +import './welcomeScreen.styles'; interface WelcomeScreenProps { nextStepUrl: string; diff --git a/src/extensions/components/registration/welcomeScreen/welcomeScreen.stories.ts b/src/components/registration/welcomeScreen/welcomeScreen.stories.ts similarity index 100% rename from src/extensions/components/registration/welcomeScreen/welcomeScreen.stories.ts rename to src/components/registration/welcomeScreen/welcomeScreen.stories.ts diff --git a/src/components/registration/welcomeScreen/welcomeScreen.styles.scss b/src/components/registration/welcomeScreen/welcomeScreen.styles.scss new file mode 100644 index 000000000..d39ad31c3 --- /dev/null +++ b/src/components/registration/welcomeScreen/welcomeScreen.styles.scss @@ -0,0 +1,79 @@ +$welcome-screen-button-text-align: center !default; + +.registrationWelcome { + margin: 0; + + h2 { + margin-bottom: $grid-base-two; + } + + h4 { + line-height: 28px; + font-weight: 400; + } + + & > * { + max-width: 500px; + margin: auto; + } + + &__explanation, + &__buttonsWrapper { + margin: $grid-base-five auto 0; + max-width: 500px; + display: grid; + grid-template-columns: auto; + column-gap: $grid-base-three; + row-gap: $grid-base-three; + + @include breakpoint($fromMedium) { + margin: $grid-base-six auto 0; + grid-template-columns: auto auto; + row-gap: $grid-base-four; + width: 100%; + } + } + + &__buttonsWrapper { + border: 1px solid $border-default; + border-radius: $input-field-border-radius; + padding: $grid-base-four; + + .text { + text-align: $welcome-screen-button-text-align; + margin-bottom: 14px; + color: $text-high-emphasis; + font-weight: 600; + } + + .buttonWrapper { + text-align: center; + } + + button { + min-width: auto; + width: 100%; + } + + .button__wrapper { + &:focus { + outline: $focus-outline; + outline-offset: 4px; + } + } + + &:focus:not(:focus-visible) { + outline: none; + } + } + + &__consultingType { + font-size: $font-size-secondary; + font-weight: $font-weight-medium; + line-height: 14px; + letter-spacing: 1.5px; + text-transform: uppercase; + padding-bottom: $grid-base; + color: $text-low-emphasis; + } +} diff --git a/src/extensions/components/registration/zipcodeInput/ZipcodeInput.tsx b/src/components/registration/zipcodeInput/ZipcodeInput.tsx similarity index 96% rename from src/extensions/components/registration/zipcodeInput/ZipcodeInput.tsx rename to src/components/registration/zipcodeInput/ZipcodeInput.tsx index 5a31e1c81..42d51d628 100644 --- a/src/extensions/components/registration/zipcodeInput/ZipcodeInput.tsx +++ b/src/components/registration/zipcodeInput/ZipcodeInput.tsx @@ -10,8 +10,8 @@ import { SetStateAction } from 'react'; import { useTranslation } from 'react-i18next'; -import { Input } from '../../../../components/input/input'; -import { RegistrationContext, RegistrationData } from '../../../../globalState'; +import { Input } from '../../../components/input/input'; +import { RegistrationContext, RegistrationData } from '../../../globalState'; import { REGISTRATION_DATA_VALIDATION } from '../registrationDataValidation'; export const ZipcodeInput: VFC<{ diff --git a/src/extensions/components/registration/zipcodeInput/zipcodeInput.stories.ts b/src/components/registration/zipcodeInput/zipcodeInput.stories.ts similarity index 100% rename from src/extensions/components/registration/zipcodeInput/zipcodeInput.stories.ts rename to src/components/registration/zipcodeInput/zipcodeInput.stories.ts diff --git a/src/components/releaseNote/releaseNote.styles.scss b/src/components/releaseNote/releaseNote.styles.scss index b250379d3..d136332ff 100644 --- a/src/components/releaseNote/releaseNote.styles.scss +++ b/src/components/releaseNote/releaseNote.styles.scss @@ -1,4 +1,8 @@ .releaseNote { + .overay { + z-index: 9999; + } + .overlay__content { text-align: left; diff --git a/src/components/stage/stage.styles.scss b/src/components/stage/stage.styles.scss index f3c764615..010b94c4a 100644 --- a/src/components/stage/stage.styles.scss +++ b/src/components/stage/stage.styles.scss @@ -1,9 +1,43 @@ -$loginOverlayDelayDesktop: 1s; -$loginOverlayDelayMobile: 2.5s; +$animation-duration: 2.5s; +$animation-duration-loader: $animation-duration * 0.25 * 3; +$animation-duration-width: $animation-duration * 0.25; +$animation-duration-title: calc($animation-duration / 7); + +$animation-easing-width: cubic-bezier(0, 0, 0.1, 1); +$animation-easing-title: cubic-bezier(0, 0, 0.5, 1); + $iconSize: 55px; $gridSpacing: $grid-base-four; +.stageLayout { + @media (min-width: $fromXLarge) { + &__legalLinks { + display: none; + } + } + + &__legalLinks { + justify-content: center; + } + + &__legalLinksItem { + color: $tertiary; + text-transform: none; + font-weight: normal; + + &:hover { + color: var(--skin-color-primary-hover, $hover-primary); + } + } +} + .stage { + width: 100vw; + overflow: hidden; + transition: width $animation-duration-width $animation-easing-width; + transition-delay: $animation-duration - $animation-duration-width; + text-align: center; + background-color: var(--skin-color-primary, $primary); color: var(--text-color-contrast-switch, $text-invert); flex-direction: column; @@ -15,27 +49,73 @@ $gridSpacing: $grid-base-four; display: flex; } + &--no-animation { + transition: none; + + .stage__title { + transition: none; + } + } + + &--open { + left: -100%; + + @include breakpoint($fromXLarge) { + left: 0; + width: 40vw; + } + + .stage__title { + transform: none; + } + } + + &--ready { + transition-delay: unset; + } + + &__content, + &__loader { + flex-shrink: 0; + flex-grow: 0; + } + + &__content { + display: flex; + flex-direction: column; + height: 100%; + align-self: center; + } + &__headline { display: flex; flex: 1 1 0; flex-direction: column; flex-wrap: wrap; justify-content: flex-end; - margin-bottom: 140px; word-break: normal; - h1 { - margin-bottom: $grid-base; + @include breakpoint($fromLarge) { + padding: $grid-base-six $grid-base-six 120px; } + } - h4 { - margin: 0; - text-align: center; - font-size: $font-size-primary; - font-weight: $font-weight-regular; + &__title { + margin-bottom: $grid-base-four; + + @include breakpoint($fromLarge) { + transform: scale(1.75); + transform-origin: bottom left; + transition: transform $animation-duration-title + $animation-easing-title; + transition-delay: #{$animation-duration - $animation-duration-title}; } } + &__claim { + font-weight: $font-weight-regular; + } + &__logos { display: flex; flex-wrap: wrap; @@ -46,7 +126,7 @@ $gridSpacing: $grid-base-four; margin-bottom: $grid-base-five; transform: scale(0.9); - @media (width >= calc(#{$xsmall} + #{$grid-base-three})) { + @media (width >=calc(#{$xsmall} + #{$grid-base-three})) { transform: scale(1); margin-bottom: $grid-base-ten; } @@ -84,68 +164,70 @@ $gridSpacing: $grid-base-four; } } - &--animated { - display: flex; - width: 100vw; - - &.stage--animation-done { - display: none; - - @include breakpoint($fromXLarge) { - display: flex; - } - } - - &.stage--ready { - animation: overlayAnimation 1.4s ease forwards; - animation-delay: $loginOverlayDelayMobile; - } + &__spinner { + animation-delay: 2s; + animation: hideSpinner 4s ease forwards; + margin: 80px auto 0; - .stage__headline { - margin-bottom: 80px; + @include breakpoint($fromXLarge) { + animation-duration: 2s; } - @keyframes overlayAnimation { + @keyframes hideSpinner { from { - left: 0; + opacity: 1; } + to { - left: -100vw; + opacity: 0; } } + } - @include breakpoint($fromXLarge) { - &.stage--ready { - animation: overlayAnimation 1s ease forwards; - animation-delay: $loginOverlayDelayDesktop; + &__legalLinks { + display: flex; + align-items: center; + align-self: center; + margin: 40px 0; + + .button-as-link { + background: none; + border: none; + cursor: pointer; + padding: 0; + white-space: nowrap; + color: $tertiary; + + &:focus { + outline: $focus-outline; + border-radius: 4px; } - @keyframes overlayAnimation { - from { - width: 100vw; - } - to { - width: 40vw; - } + &:focus:not(:focus-visible) { + outline: none; + } + + &:hover { + color: var(--skin-color-primary-hover, $hover-primary); } } + + .text { + font-size: $font-size-tertiary; + } } - &__spinner { - animation-delay: 2s; - animation: hideSpinner 4s ease forwards; + &__legalLinksItem { + color: $dark-grey; - @include breakpoint($fromXLarge) { - animation-duration: 2s; + &:hover { + color: $white; } + } - @keyframes hideSpinner { - from { - opacity: 1; - } - to { - opacity: 0; - } - } + &__legalLinksSeparator { + display: inline-block; + color: $white; + margin: 0 $grid-base; } } diff --git a/src/components/stage/stage.tsx b/src/components/stage/stage.tsx index 50fdb6449..338cb7eb0 100644 --- a/src/components/stage/stage.tsx +++ b/src/components/stage/stage.tsx @@ -1,8 +1,20 @@ -import * as React from 'react'; -import { useCallback, useRef, useState, MouseEvent } from 'react'; import clsx from 'clsx'; -import { Spinner } from '../spinner/Spinner'; -import { useTenant } from '../../globalState'; +import * as React from 'react'; +import { useTranslation, Trans } from 'react-i18next'; +import { + useState, + useEffect, + useRef, + useCallback, + MouseEvent, + useContext +} from 'react'; +import { Text } from '../text/Text'; +import { LegalLinksContext } from '../../globalState/provider/LegalLinksProvider'; +import './stage.styles'; +import { Banner } from '../banner/Banner'; +import { Headline } from '../headline/Headline'; +import LegalLinks from '../legalLinks/LegalLinks'; import { ReactComponent as SkfLogo } from '../../resources/img/logos/01_skf.svg'; import { ReactComponent as CaritasLogo } from '../../resources/img/logos/02_caritas.svg'; import { ReactComponent as SkmLogo } from '../../resources/img/logos/03_skm.svg'; @@ -10,9 +22,7 @@ import { ReactComponent as InViaLogo } from '../../resources/img/logos/04_via.sv import { ReactComponent as KreuzbundLogo } from '../../resources/img/logos/05_kreuzbund.svg'; import { ReactComponent as RaphaelswerkLogo } from '../../resources/img/logos/06_raphael.svg'; import { ReactComponent as MalteserLogo } from '../../resources/img/logos/07_malteser.svg'; -import './stage.styles'; -import { Trans, useTranslation } from 'react-i18next'; -import { Banner } from '../banner/Banner'; +import { Spinner } from '../spinner/Spinner'; export interface StageProps { className?: string; @@ -26,16 +36,29 @@ export const Stage = ({ isReady = true }: StageProps) => { const { t: translate } = useTranslation(); - const tenant = useTenant(); - const rootNodeRef = useRef(); - const [isAnimationDone, setIsAnimationDone] = useState(false); - function onAnimationEnd(event) { - // Ignore animations of children - if (event.target === rootNodeRef.current) { - setIsAnimationDone(true); + const legalLinks = useContext(LegalLinksContext); + + const rootNodeRef = useRef(null); + + const [isOpen, setIsOpen] = useState(!hasAnimation); + const [hasAnimationFinished, setHasAnimationFinished] = useState(false); + + useEffect(() => { + if (hasAnimation && isReady) { + setIsOpen(true); } - } + + const onTransitionEnd = () => { + setHasAnimationFinished(true); + }; + + const rootNode = rootNodeRef.current; + rootNode.addEventListener('transitionend', onTransitionEnd); + return () => { + rootNode.removeEventListener('transitionend', onTransitionEnd); + }; + }, [hasAnimation, isReady]); const [ieBanner, setIeBanner] = useState(true); const closeIeBanner = useCallback((e: MouseEvent) => { @@ -46,19 +69,18 @@ export const Stage = ({ return (
    {ieBanner && ( )} -
    -

    {tenant?.name || translate('app.stage.title')}

    -

    {tenant?.content?.claim || translate('app.claim')}

    -
    - - {hasAnimation ? : null} -
    - - - - - - - +
    +
    + + + {hasAnimation ? ( + + ) : null} +
    +
    + + + + + + + +
    +
    + + } + > + {(label, url) => ( + + )} + +
    ); diff --git a/src/components/stageLayout/StageLayout.tsx b/src/components/stageLayout/StageLayout.tsx index f04db4ff1..60079c793 100644 --- a/src/components/stageLayout/StageLayout.tsx +++ b/src/components/stageLayout/StageLayout.tsx @@ -22,7 +22,7 @@ import { useScrollTrigger } from '@mui/material'; import LoginIcon from '@mui/icons-material/Login'; -import { InfoDrawer } from '../../extensions/components/registration/infoDrawer/InfoDrawer'; +import { InfoDrawer } from '../registration/infoDrawer/InfoDrawer'; interface StageLayoutProps { className?: string; diff --git a/src/components/twoFactorAuth/twoFactorAuth.styles.scss b/src/components/twoFactorAuth/twoFactorAuth.styles.scss index 03141b118..48b2d7b60 100644 --- a/src/components/twoFactorAuth/twoFactorAuth.styles.scss +++ b/src/components/twoFactorAuth/twoFactorAuth.styles.scss @@ -43,6 +43,7 @@ $two-factor-auth-overlay-buttons-margin-right: auto !default; margin-left: auto; margin-right: $two-factor-auth-overlay-buttons-margin-right; } + .button__wrapper + .button__wrapper { @include breakpoint($fromSmall) { margin-left: $grid-base-two; @@ -193,9 +194,12 @@ $two-factor-auth-overlay-buttons-margin-right: auto !default; &__appConfirmation, &__emailConfirmation { + text-align: center; + svg { max-width: 240px; } + .headline { text-align: center; } @@ -208,6 +212,7 @@ $two-factor-auth-overlay-buttons-margin-right: auto !default; .button__link { color: $tertiary; + svg { margin: 0; } diff --git a/src/containers/registration/components/ProposedAgencies/ProposedAgencies.tsx b/src/containers/registration/components/ProposedAgencies/ProposedAgencies.tsx index 89c89a395..15024f4ac 100644 --- a/src/containers/registration/components/ProposedAgencies/ProposedAgencies.tsx +++ b/src/containers/registration/components/ProposedAgencies/ProposedAgencies.tsx @@ -11,10 +11,13 @@ import { VALIDITY_VALID, VALIDITY_INVALID } from '../../../../components/registration/registrationHelpers'; -import { AgencyDataInterface } from '../../../../globalState/interfaces'; +import { + AgencyDataInterface, + ConsultingTypeInterface, + TopicsDataInterface +} from '../../../../globalState/interfaces'; import { LABEL_TYPES, Text } from '../../../../components/text/Text'; import { useTranslation } from 'react-i18next'; -import { FormAccordionData } from '../../../../components/registration/RegistrationForm'; import { UrlParamsContext } from '../../../../globalState/provider/UrlParamsProvider'; import clsx from 'clsx'; import { AgencyRadioSelect } from '../../../../components/agencyRadioSelect/AgencyRadioSelect'; @@ -22,6 +25,17 @@ import { AgencyRadioSelect } from '../../../../components/agencyRadioSelect/Agen import './proposedAgencies.styles.scss'; import { useAppConfig } from '../../../../hooks/useAppConfig'; +interface FormAccordionData { + username?: string; + password?: string; + agency?: AgencyDataInterface; + consultingType?: ConsultingTypeInterface; + mainTopic?: TopicsDataInterface; + postcode?: string; + state?: string; + age?: string; +} + interface ProposedAgenciesProps { formAccordionData: FormAccordionData; agencySelectionNote?: string; diff --git a/src/extensions/components/registration/Registration.tsx b/src/extensions/components/registration/Registration.tsx deleted file mode 100644 index 7c97b8f80..000000000 --- a/src/extensions/components/registration/Registration.tsx +++ /dev/null @@ -1,414 +0,0 @@ -import { Typography, Link, Button, Box } from '@mui/material'; -import * as React from 'react'; -import { - useState, - useEffect, - useContext, - useCallback, - useMemo, - FormEvent -} from 'react'; -import { - Route, - Switch, - useHistory, - useLocation, - useParams, - useRouteMatch, - generatePath, - Link as RouterLink -} from 'react-router-dom'; -import { useTranslation } from 'react-i18next'; -import { Helmet } from 'react-helmet'; - -import { StageLayout } from '../../../components/stageLayout/StageLayout'; -import useIsFirstVisit from '../../../utils/useIsFirstVisit'; -import { ReactComponent as HelloBannerIcon } from '../../../resources/img/illustrations/hello-banner.svg'; -import { StepBar } from './stepBar/StepBar'; -import { WelcomeScreen } from './welcomeScreen/WelcomeScreen'; -import { - RegistrationContext, - TenantContext, - registrationSessionStorageKey, - RegistrationData, - NotificationsContext, - NOTIFICATION_TYPE_ERROR, - LocaleContext -} from '../../../globalState'; -import { GlobalComponentContext } from '../../../globalState/provider/GlobalComponentContext'; -import { - OVERLAY_FUNCTIONS, - Overlay, - OverlayItem -} from '../../../components/overlay/Overlay'; -import { redirectToApp } from '../../../components/registration/autoLogin'; -import { BUTTON_TYPES } from '../../../components/button/Button'; -import { PreselectionBox } from './preselectionBox/PreselectionBox'; -import { endpoints } from '../../../resources/scripts/endpoints'; -import { apiPostRegistration } from '../../../api'; -import { useAppConfig } from '../../../hooks/useAppConfig'; -import { REGISTRATION_DATA_VALIDATION } from './registrationDataValidation'; -import { UrlParamsContext } from '../../../globalState/provider/UrlParamsProvider'; - -/** - * This type of registration is currently not supporting: - * - autoSelectPostcode because its loaded over the consultingType and - * - * MultiTenancy: - * Each consultingType in mongodb has stored the tenant id (One to One Relation) -> Tenant URL could load by consultingType by tenant alternative only one consultingType exits - * MultiTenancyWithSingleDomain: - * Each consultintType in mongodb has stored the tenant id but this relation could not be loaded because no idea which consultingType settings to load before agency is selected - * For Caritas there is no consultingType tenant relation and every tenant could have different consultingType depending on agency. So before agency is selected no idea which consultingType settings to load before agency is selected - * @constructor - */ - -export const Registration = () => { - const { t } = useTranslation(['common', 'consultingTypes', 'agencies']); - const settings = useAppConfig(); - const isFirstVisit = useIsFirstVisit(); - const location = useLocation(); - const history = useHistory(); - const { path } = useRouteMatch(); - const { step, topicSlug } = useParams<{ - step: string; - topicSlug: string; - }>(); - - const { Stage } = useContext(GlobalComponentContext); - const { addNotification } = useContext(NotificationsContext); - const { - disabledNextButton, - updateRegistrationData, - registrationData, - availableSteps - } = useContext(RegistrationContext); - const { consultant: preselectedConsultant } = useContext(UrlParamsContext); - const { tenant } = useContext(TenantContext); - const { locale } = useContext(LocaleContext); - - const [stepData, setStepData] = useState>({}); - const [redirectOverlayActive, setRedirectOverlayActive] = - useState(false); - - const handleOverlayAction = (buttonFunction: string) => { - if (buttonFunction === OVERLAY_FUNCTIONS.REDIRECT_WITH_BLUR) { - redirectToApp(); - } - }; - const overlayItemRegistrationSuccess: OverlayItem = { - illustrationStyle: 'large', - svg: HelloBannerIcon, - headline: t('registration.overlay.success.headline'), - copy: t('registration.overlay.success.copy'), - buttonSet: [ - { - label: t('registration.overlay.success.button'), - function: OVERLAY_FUNCTIONS.REDIRECT_WITH_BLUR, - type: BUTTON_TYPES.AUTO_CLOSE - } - ] - }; - - const checkForStepsWithMissingMandatoryFields = - useCallback((): number[] => { - return availableSteps.reduce( - (missingSteps, step, currentIndex) => { - if ( - step?.mandatoryFields?.some( - (mandatoryField) => - registrationData?.[mandatoryField] === undefined - ) - ) { - return [...missingSteps, currentIndex]; - } - return missingSteps; - }, - [] - ); - }, [availableSteps, registrationData]); - - const currStepIndex = useMemo( - () => availableSteps.findIndex(({ name }) => name === step), - [availableSteps, step] - ); - - const [prevStepUrl, nextStepUrl] = useMemo( - () => [ - `${generatePath(path, { topicSlug, step: availableSteps[currStepIndex - 1]?.name || 'welcome' })}${location.search}`, - availableSteps[currStepIndex + 1] - ? `${generatePath(path, { topicSlug, step: availableSteps[currStepIndex + 1]?.name || 'welcome' })}${location.search}` - : null - ], - [availableSteps, currStepIndex, path, topicSlug, location.search] - ); - - const onNextClick = useCallback(() => { - updateRegistrationData(stepData); - setStepData({}); - history.push(nextStepUrl); - }, [updateRegistrationData, stepData, history, nextStepUrl]); - - const onPrevClick = useCallback(() => { - if (stepData.zipcode) { - registrationData.zipcode = ''; - } - setStepData({}); - history.push(prevStepUrl); - }, [registrationData, stepData, history, prevStepUrl]); - - const handleSubmit = useCallback( - (e: FormEvent) => { - e.preventDefault(); - if (disabledNextButton) return; - onNextClick(); - }, - [disabledNextButton, onNextClick] - ); - - useEffect(() => { - // Check if mandatory fields from previous steps are missing - const missingPreviousSteps = checkForStepsWithMissingMandatoryFields() - .sort() - .filter((missingStep) => missingStep < currStepIndex); - - if (missingPreviousSteps.length > 0) { - history.push( - `${generatePath(path, { topicSlug, step: availableSteps[missingPreviousSteps[0]]?.name })}${location.search}` - ); - } - }, [ - availableSteps, - checkForStepsWithMissingMandatoryFields, - history, - location.search, - currStepIndex, - path, - topicSlug - ]); - - const onRegisterClick = useCallback(() => { - const data = { - ...registrationData, - ...stepData, - mainTopicId: registrationData.mainTopic.id.toString(), - topicId: registrationData.topic?.id?.toString(), - agencyId: registrationData.agency.id.toString(), - postcode: registrationData.zipcode, - termsAccepted: 'true', - preferredLanguage: locale || 'de', - consultingType: registrationData.agency.consultingType, - ...(preselectedConsultant - ? { consultantId: preselectedConsultant?.consultantId } - : {}) - }; - - if ( - Object.keys(REGISTRATION_DATA_VALIDATION).every((item) => - REGISTRATION_DATA_VALIDATION[item].validation(data[item]) - ) - ) { - apiPostRegistration( - endpoints.registerAsker, - data, - settings.multitenancyWithSingleDomainEnabled, - tenant - ).then(() => { - sessionStorage.removeItem(registrationSessionStorageKey); - setRedirectOverlayActive(true); - }); - } else { - addNotification({ - notificationType: NOTIFICATION_TYPE_ERROR, - title: t('registration.errors.ups.title'), - text: t('registration.errors.ups.text'), - closeable: true, - timeout: 3000 - }); - } - }, [ - registrationData, - stepData, - preselectedConsultant, - settings.multitenancyWithSingleDomainEnabled, - tenant, - addNotification, - t, - locale - ]); - - const stepPaths = useMemo( - () => - availableSteps.reduce( - (acc, { name }) => - acc.concat(generatePath(path, { topicSlug, step: name })), - [] - ), - [availableSteps, path, topicSlug] - ); - - return ( - <> - } - showRegistrationInfoDrawer={true} - > - - - - - - -
    name) - .join(',')} - > - - - {t('registration.headline')} - - - - - - - {availableSteps.map( - ({ - name, - component: Component - }) => ( - - - - ) - )} - - - - - - {t('registration.back')} - - - {!nextStepUrl ? ( - - ) : ( - - )} - - -
    -
    - - - -
    -
    -
    - {redirectOverlayActive && ( - - )} - - ); -}; diff --git a/src/extensions/components/stage/StageLayout.styles.scss b/src/extensions/components/stage/StageLayout.styles.scss deleted file mode 100644 index 2f5ff7982..000000000 --- a/src/extensions/components/stage/StageLayout.styles.scss +++ /dev/null @@ -1,20 +0,0 @@ -.stageLayout { - @media (min-width: $fromXLarge) { - &__legalLinks { - display: none; - } - } - - &__legalLinks { - justify-content: center; - } - - &__legalLinksItem { - color: $tertiary; - text-transform: none; - font-weight: normal; - &:hover { - color: var(--skin-color-primary-hover, $hover-primary); - } - } -} diff --git a/src/extensions/components/stage/loader.svg b/src/extensions/components/stage/loader.svg deleted file mode 100644 index 26bcbb8e0..000000000 --- a/src/extensions/components/stage/loader.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - B5ABEB99-26F0-4259-A9A3-296829836161 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/extensions/components/stage/logo.svg b/src/extensions/components/stage/logo.svg deleted file mode 100644 index 659229425..000000000 --- a/src/extensions/components/stage/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/extensions/components/stage/stage.styles.scss b/src/extensions/components/stage/stage.styles.scss deleted file mode 100644 index 17fb80a35..000000000 --- a/src/extensions/components/stage/stage.styles.scss +++ /dev/null @@ -1,221 +0,0 @@ -$animation-duration: 2.5s; -$animation-duration-loader: $animation-duration * 0.25 * 3; -$animation-duration-width: $animation-duration * 0.25; -$animation-duration-title: calc($animation-duration / 7); - -$animation-easing-width: cubic-bezier(0, 0, 0.1, 1); -$animation-easing-title: cubic-bezier(0, 0, 0.5, 1); - -@import 'StageLayout.styles'; - -.stage { - width: 100vw; - background-color: $primary-2; - color: $white; - overflow: hidden; - transition: width $animation-duration-width $animation-easing-width; - transition-delay: $animation-duration - $animation-duration-width; - text-align: left; - display: none; - - @include breakpoint($fromXLarge) { - display: flex; - } - - &--no-animation { - transition: none; - - .stage__title { - transition: none; - } - } - - &--open { - left: -100%; - - @include breakpoint($fromXLarge) { - left: 0; - width: 40vw; - } - - .stage__title { - transform: none; - } - - .stage__loader { - @keyframes loader { - 0% { - transform: none; - } - 35% { - transform: scale(1.05); - } - 70% { - transform: none; - } - } - - animation: loader #{calc($animation-duration-loader / 3 * 2)} forwards - linear; - animation-delay: calc($animation-duration-loader / 3); - - @include breakpoint($fromLarge) { - @keyframes loaderLarge { - 0% { - transform: none; - opacity: 1; - } - 40% { - transform: scale(1.05); - opacity: 1; - } - 80% { - transform: none; - opacity: 1; - } - 100% { - transform: none; - opacity: 0; - } - } - animation-name: loaderLarge; - } - } - } - - &--ready { - transition-delay: unset; - } - - &__content, - &__loader { - flex-shrink: 0; - flex-grow: 0; - } - - &__content { - display: flex; - flex-direction: column; - height: 100%; - - @include breakpoint($fromLarge) { - width: 60vw; - } - } - - &__logo-wrapper { - padding: $grid-base-five $grid-base-five $grid-base-ten; - background-color: $primary; - - @include breakpoint($fromLarge) { - padding: $grid-base-six $grid-base-six 240px; - } - } - - &__logo { - width: 140px; - - @include breakpoint($fromLarge) { - width: 180px; - } - } - - &__headline { - display: flex; - flex-direction: column; - flex: 1; - justify-content: flex-end; - padding: $grid-base-five; - background-color: $primary-3; - - @include breakpoint($fromLarge) { - padding: $grid-base-six $grid-base-six 120px; - } - } - - &__title { - margin-bottom: $grid-base-four; - - @include breakpoint($fromLarge) { - transform: scale(1.75); - transform-origin: bottom left; - transition: transform $animation-duration-title - $animation-easing-title; - transition-delay: #{$animation-duration - $animation-duration-title}; - } - } - - &__claim { - font-weight: $font-weight-regular; - } - - &__loader { - position: absolute; - top: $grid-base-five; - left: 0; - width: 100%; - display: flex; - align-items: center; - justify-content: center; - padding: $grid-base-ten; - - @include breakpoint($fromMedium) { - top: 240px; - } - - @include breakpoint($fromLarge) { - position: static; - width: 40vw; - padding: 0; - } - } - - &__legalLinks { - display: flex; - align-items: center; - margin: 30px 0; - - @include breakpoint($fromXLarge) { - justify-content: flex-start; - } - - .button-as-link { - background: none; - border: none; - cursor: pointer; - padding: 0; - white-space: nowrap; - color: $tertiary; - - &:focus { - outline: $focus-outline; - border-radius: 4px; - } - - &:focus:not(:focus-visible) { - outline: none; - } - - &:hover { - color: var(--skin-color-primary-hover, $hover-primary); - } - } - - .text { - font-size: $font-size-tertiary; - } - } - - &__legalLinksItem { - color: $dark-grey; - &:hover { - color: $white; - } - } - - &__legalLinksSeparator { - display: inline-block; - color: $white; - margin: 0 $grid-base; - } -} diff --git a/src/extensions/components/stage/stage.tsx b/src/extensions/components/stage/stage.tsx deleted file mode 100644 index 474a8106c..000000000 --- a/src/extensions/components/stage/stage.tsx +++ /dev/null @@ -1,144 +0,0 @@ -import clsx from 'clsx'; -import * as React from 'react'; -import { useTranslation, Trans } from 'react-i18next'; -import { - useState, - useEffect, - useRef, - useCallback, - MouseEvent, - useContext -} from 'react'; -import { ReactComponent as Logo } from './logo.svg'; -import { ReactComponent as Loader } from './loader.svg'; -import { Text } from '../../../components/text/Text'; -import { LegalLinksContext } from '../../../globalState/provider/LegalLinksProvider'; -import './stage.styles'; -import { Banner } from '../../../components/banner/Banner'; -import { Headline } from '../../../components/headline/Headline'; -import LegalLinks from '../../../components/legalLinks/LegalLinks'; - -export interface StageProps { - className?: string; - hasAnimation?: boolean; - isReady?: boolean; -} - -export const Stage = ({ - className, - hasAnimation, - isReady = true -}: StageProps) => { - const { t: translate } = useTranslation(); - - const legalLinks = useContext(LegalLinksContext); - - const rootNodeRef = useRef(null); - - const [isOpen, setIsOpen] = useState(!hasAnimation); - const [hasAnimationFinished, setHasAnimationFinished] = useState(false); - - useEffect(() => { - if (hasAnimation && isReady) { - setIsOpen(true); - } - - const onTransitionEnd = () => { - setHasAnimationFinished(true); - }; - - const rootNode = rootNodeRef.current; - rootNode.addEventListener('transitionend', onTransitionEnd); - return () => { - rootNode.removeEventListener('transitionend', onTransitionEnd); - }; - }, [hasAnimation, isReady]); - - const [ieBanner, setIeBanner] = useState(true); - const closeIeBanner = useCallback((e: MouseEvent) => { - e.preventDefault(); - setIeBanner(false); - }, []); - - return ( -
    - {ieBanner && ( - - - - - - - )} - -
    -
    - -
    -
    - - -
    - - } - > - {(label, url) => ( - - )} - -
    -
    -
    -
    - -
    -
    - ); -}; diff --git a/src/extensions/initApp.tsx b/src/extensions/initApp.tsx deleted file mode 100644 index 5a54f4c03..000000000 --- a/src/extensions/initApp.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import * as React from 'react'; -import * as ReactDOM from 'react-dom'; -import { ThemeProvider } from '@mui/material'; -import { App } from '../components/app/app'; -import { Stage } from './components/stage/stage'; -import { config, routePathNames } from './resources/scripts/config'; -import { UrlParamsProvider } from '../globalState/provider/UrlParamsProvider'; -import { RegistrationProvider } from '../globalState'; -import { lazy } from 'react'; -import '../resources/styles/mui-variables-mapping.scss'; -import theme from './theme'; -import { Redirect } from 'react-router-dom'; -import { Privacy } from './components/legalInformationLinks/Privacy'; -import { Imprint } from './components/legalInformationLinks/Imprint'; - -const Registration = lazy(() => - import('./components/registration/Registration').then((m) => ({ - default: m.Registration - })) -); - -const NewRegistration = () => ( - - - - - -); - -ReactDOM.render( - - ( - - ) - }, - // { - // route: { path: routePathNames.termsAndConditions }, - // component: TermsAndConditions - // }, - { route: { path: routePathNames.imprint }, component: Imprint }, - { route: { path: routePathNames.privacy }, component: Privacy } - ]} - stageComponent={Stage} - /> - , - document.getElementById('appRoot') -); diff --git a/src/extensions/resources/styles/generateQrCode.scss b/src/extensions/resources/styles/generateQrCode.scss deleted file mode 100644 index 0d6ed6176..000000000 --- a/src/extensions/resources/styles/generateQrCode.scss +++ /dev/null @@ -1,3 +0,0 @@ -.generateQrCode__overlayContent .text { - margin-left: 0; -} diff --git a/src/extensions/resources/styles/releaseNote.styles.scss b/src/extensions/resources/styles/releaseNote.styles.scss deleted file mode 100644 index 11160418c..000000000 --- a/src/extensions/resources/styles/releaseNote.styles.scss +++ /dev/null @@ -1,3 +0,0 @@ -.releaseNote.overlay { - z-index: 9999; -} diff --git a/src/extensions/resources/styles/settings.scss b/src/extensions/resources/styles/settings.scss deleted file mode 100644 index 8af8e4a44..000000000 --- a/src/extensions/resources/styles/settings.scss +++ /dev/null @@ -1,150 +0,0 @@ -// FONTS -$font-family-sans-serif: Arial, sans-serif; -$font-family-divider: $font-family-sans-serif; -$body-font-family: $font-family-sans-serif; - -$font-weight-light: normal; -$font-weight-regular: normal; -$font-weight-medium: bold; -$font-weight-bold: bold; - -// COLORS -$primary: #5a2572; -$primary-2: #462672; -$primary-3: #6e2272; -$primary-4: #3a2673; - -$blue: #009bdc; -$grey-light: #d9d7ed; -$background-light: #e4e3f3; -$background-lighter: #f2f0f9; -$background-grey: #677391; -$background-accent: #e4e3f3; - -$message-name-self: $tertiary; -$message-name-system: $primary; -$message-name-consultant: $primary; -$message-name-user: $primary; - -$hover-primary: $primary-4; -$hover-select: $background-accent; - -$text-high-emphasis: rgba(0, 0, 0, 0.9); -$text-low-emphasis: rgba(0, 0, 0, 0.6); -$text-disabled: rgba(0, 0, 0, 0.4); -$text-invert: rgba(255, 255, 255, 1); - -$border-default: rgba(0, 0, 0, 0.2); -$border-hover: rgba(0, 0, 0, 0.9); -$border-active: rgba(0, 0, 0, 0.9); - -// Components -$button-auto-close-color: #835b95; -$button-border-radius: 0px; -$button-box-shadow-default: none; -$button-box-shadow-grey: none; -$button-small-icon-background-color-default: $blue; -$button-small-icon-border-radius: 0; -$button-small-icon-alternate-background-color: $blue; -$checkbox-border-radius: 0; -$datepicker-hover-color: $background-accent; -$enquiry-background: $background-lighter; -$enquiry-circle-background: $background-lighter; -$enquiry-input-border-radius: $grid-base-three; -$form-accordion-index-background-active: $primary; -$form-accordion-index-border: 1px solid $primary; -$form-accordion-index-color-active: $white; -$form-accordion-index-color: $primary; -$form-input-border: #dcd9dc; -$further-steps-step-info-text-align: left; -$headline-1-font-weight: $font-weight-medium; -$headline-2-font-weight: $font-weight-medium; -$illustration-background-error: rgba(255, 0, 0, 0.08); -$illustration-background-info: rgba($black, 0.05); -$illustration-background-neutral: rgba(53, 58, 74, 0.1); -$input-field-border-radius: 0; -$input-field-box-shadow: none; -$input-field-height: 50px; -$legal-information-links-left-default: $grid-base-two; -$legal-information-links-left-large: $grid-base-five; -$legal-information-links-left-medium: $grid-base-five; -$link-color: $primary; -$link-color-hover: $hover-primary; -$link-text-decoration: underline; -$link-text-decoration-hover: $link-text-decoration !default; -$link-font-weight: inherit; -$login-align-items: flex-start; -$login-button-focus-border-radius: 0px; -$login-icon-transform: none; -$login-button-width: 320px; -$login-button-width-large: $login-button-width; -$login-text-align: left; -$link-hover-color-default: $hover-primary; -$max-input-width: 320px; -$message-background-primary: $primary; -$message-background-secondary: black; -$message-background-rate: 0%; -$message-background: mix( - $message-background-secondary, - $primary, - $message-background-rate -); -$message-submit-interface-textarea-background-color: $grey-light; -$message-submit-interface-textarea-background-color-yellow: $yellow-3; -$message-submit-interface-textarea-placeholder-color: $light-grey; -$overlay-text-align: left; -$overlay-list-align: left; -$overlay-input-field-margin: $grid-base-three 0; -$overlay-button-margin: $grid-base-two 0 0 auto; -$overlay-stepped-text-align: left; -$overlay-stepped-input-field-margin: $grid-base-three 0; -$two-factor-qr-code-width: 100px; -$profile-divider-text-align: left; -$profile-imprint-background-color: $grey-light; -$registration-form-max-width: auto; -$registration-form-margin-left: 0 !default; -$registration-text-align: left; -$select-dropdown-border-radius: 0; -$select-focus-background-color: $primary-4; -$selection-focus-color: $text-invert; -$sendInputHeight: 48px; -$session-background-color: $background-lighter; -$session-content-background-color: $background-lighter; -$session-header-background-color: $background-light; -$session-header-background-color-large: $background-lighter; -$session-list-item-background-active: $background-lighter; -$session-list-item-border-radius: 0px; -$sessions-list-background-color-primary: $background-lighter; -$sessions-list-background-color-secondary: $background-light; -$session-menu-legal-links-color: $text-invert; -$statistics-highlight-color: $primary; -$text-color-standard: $secondary; -$text-color-info-large-standard: $secondary; -$text-divider-color: $primary; -$text-divider-letter-spacing: 1px; -$text-divider-font-weight: $font-weight-bold; -$text-divider-text-transform: uppercase; -$upload-progress: #80dd92; -$welcome-screen-icon-background: $primary; -$notice-background: transparent; -$notice-border: 1px solid rgba(0, 0, 0, 0.2); -$notice-padding: $grid-base-three; -$tab-border-radius: 25px; -$tab-background-color: rgba(0, 0, 0, 0.05); -$tab-background-color-hover: rgba(0, 0, 0, 0.2); -$tab-background-color-selected: rgba($primary, 0.2); -$tab-background-color-selected-hover: rgba($hover-primary, 0.2); -$tab-background-border-color-selected: $primary; -$tab-color: $tertiary; -$tab-color-hover: rgba(0, 0, 0, 0.8); -$tab-color-selected: $primary; -$overlay-radio-outline: 1px solid rgba(0, 0, 0, 0.2); -$overlay-radio-radius: 25px; -$header-height: $grid-base-twelve; -$message-wrapper-height: 109px; -$box-border-radius: 0px; -$link-menu-item-border-radius: 0px; - -@import './twoFactorAuth.scss'; -@import './releaseNote.styles'; -@import './generateQrCode.scss'; diff --git a/src/extensions/resources/styles/twoFactorAuth.scss b/src/extensions/resources/styles/twoFactorAuth.scss deleted file mode 100644 index 4e3038f4a..000000000 --- a/src/extensions/resources/styles/twoFactorAuth.scss +++ /dev/null @@ -1,4 +0,0 @@ -.twoFactorAuth__emailConfirmation, -.twoFactorAuth__appConfirmation { - text-align: center; -} diff --git a/src/globalState/provider/RegistrationProvider.tsx b/src/globalState/provider/RegistrationProvider.tsx index b54b67e57..6a5202a2b 100644 --- a/src/globalState/provider/RegistrationProvider.tsx +++ b/src/globalState/provider/RegistrationProvider.tsx @@ -15,11 +15,11 @@ import { UrlParamsContext } from './UrlParamsProvider'; import { getUrlParameter } from '../../utils/getUrlParameter'; import { apiGetTopicById } from '../../api/apiGetTopicId'; import { apiGetAgencyById } from '../../api'; -import { TopicSelection } from '../../extensions/components/registration/topicSelection/TopicSelection'; -import { ZipcodeInput } from '../../extensions/components/registration/zipcodeInput/ZipcodeInput'; -import { AgencySelection } from '../../extensions/components/registration/agencySelection/AgencySelection'; -import { AccountData } from '../../extensions/components/registration/accountData/AccountData'; import { RouteProps, useRouteMatch } from 'react-router-dom'; +import { TopicSelection } from '../../components/registration/topicSelection/TopicSelection'; +import { ZipcodeInput } from '../../components/registration/zipcodeInput/ZipcodeInput'; +import { AgencySelection } from '../../components/registration/agencySelection/AgencySelection'; +import { AccountData } from '../../components/registration/accountData/AccountData'; export const RegistrationContext = createContext( {} diff --git a/src/initApp.tsx b/src/initApp.tsx index c2cf4e39e..c8cb7803b 100644 --- a/src/initApp.tsx +++ b/src/initApp.tsx @@ -2,9 +2,65 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom'; import { App } from './components/app/app'; import { Stage } from './components/stage/stage'; -import { config } from './resources/scripts/config'; +import { config, routePathNames } from './resources/scripts/config'; +import { ThemeProvider } from '@mui/material'; +import { UrlParamsProvider } from './globalState/provider/UrlParamsProvider'; +import { RegistrationProvider } from './globalState'; +import { lazy } from 'react'; +import './resources/styles/mui-variables-mapping.scss'; +import theme from './resources/scripts/theme'; +import { Redirect } from 'react-router-dom'; +import { Privacy } from './components/legalInformationLinks/Privacy'; +import { Imprint } from './components/legalInformationLinks/Imprint'; + +const Registration = lazy(() => + import('./components/registration/Registration').then((m) => ({ + default: m.Registration + })) +); + +const NewRegistration = () => ( + + + + + +); ReactDOM.render( - , + + ( + + ) + }, + // { + // route: { path: routePathNames.termsAndConditions }, + // component: TermsAndConditions + // }, + { route: { path: routePathNames.imprint }, component: Imprint }, + { route: { path: routePathNames.privacy }, component: Privacy } + ]} + stageComponent={Stage} + /> + , document.getElementById('appRoot') ); diff --git a/src/resources/styles/mui-variables-mapping.scss b/src/resources/styles/mui-variables-mapping.scss index 0c339ea95..135f5c46b 100644 --- a/src/resources/styles/mui-variables-mapping.scss +++ b/src/resources/styles/mui-variables-mapping.scss @@ -14,7 +14,7 @@ --button-border-radius: #{$button-border-radius}; --hover-primary: #{$hover-primary}; --secondary: #{$secondary}; - --primary-3: #{$primary-3}; + --primary-3: #{$hover-primary}; --tertiary: #{$tertiary}; --black: #{$black}; --form-error: #{$form-error}; From 83fb4ace8c7ec802c57edb399321e4a7dc0f21b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Tue, 17 Sep 2024 16:27:39 +0200 Subject: [PATCH 45/49] feat(caritas-theme): cypress registration tests exclusion --- {cypress => src/extensions/cypress}/cypress.json | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {cypress => src/extensions/cypress}/cypress.json (100%) diff --git a/cypress/cypress.json b/src/extensions/cypress/cypress.json similarity index 100% rename from cypress/cypress.json rename to src/extensions/cypress/cypress.json From c9eaca28eb410925850ccec86eca31b852be16eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Tue, 17 Sep 2024 16:53:58 +0200 Subject: [PATCH 46/49] ci(github-workflows): update artifact action versions --- .github/workflows/build.yml | 2 +- .github/workflows/dockerImage.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 597a496d7..e9d296e38 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -70,7 +70,7 @@ jobs: branch: ${{env.BRANCH}} force: true tags: true - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 if: failure() with: name: cypress-videos diff --git a/.github/workflows/dockerImage.yml b/.github/workflows/dockerImage.yml index 04c8a38ec..46ae1adbf 100644 --- a/.github/workflows/dockerImage.yml +++ b/.github/workflows/dockerImage.yml @@ -58,7 +58,7 @@ jobs: echo "127.0.0.1 localhost" | sudo tee -a /etc/hosts echo "fs.inotify.max_user_watches=524288" | sudo tee -a /etc/sysctl.conf npm run test:build - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: buildfiles path: build/**/* @@ -86,7 +86,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Download buildfiles artifact - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: name: buildfiles path: build From 5c3295ca7d8895ecbaaa6878117276d3f0b3bd42 Mon Sep 17 00:00:00 2001 From: Leandro13Silva13 <115784444+Leandro13Silva13@users.noreply.github.com> Date: Wed, 18 Sep 2024 10:58:05 +0200 Subject: [PATCH 47/49] Update dockerImage.yml --- .github/workflows/dockerImage.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dockerImage.yml b/.github/workflows/dockerImage.yml index 04c8a38ec..46ae1adbf 100644 --- a/.github/workflows/dockerImage.yml +++ b/.github/workflows/dockerImage.yml @@ -58,7 +58,7 @@ jobs: echo "127.0.0.1 localhost" | sudo tee -a /etc/hosts echo "fs.inotify.max_user_watches=524288" | sudo tee -a /etc/sysctl.conf npm run test:build - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: buildfiles path: build/**/* @@ -86,7 +86,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Download buildfiles artifact - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: name: buildfiles path: build From 2669a66f7de34d9b71f0e1f0d9189d8996fe38cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deborah=20K=C3=B6pfer?= Date: Thu, 19 Sep 2024 15:56:26 +0200 Subject: [PATCH 48/49] feat(caritas-theme): pr review styling changes --- src/components/stage/stage.styles.scss | 27 ++++++++------------------ src/components/stage/stage.tsx | 4 +--- 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/src/components/stage/stage.styles.scss b/src/components/stage/stage.styles.scss index 010b94c4a..5954159d3 100644 --- a/src/components/stage/stage.styles.scss +++ b/src/components/stage/stage.styles.scss @@ -37,7 +37,6 @@ $gridSpacing: $grid-base-four; transition: width $animation-duration-width $animation-easing-width; transition-delay: $animation-duration - $animation-duration-width; text-align: center; - background-color: var(--skin-color-primary, $primary); color: var(--text-color-contrast-switch, $text-invert); flex-direction: column; @@ -52,8 +51,8 @@ $gridSpacing: $grid-base-four; &--no-animation { transition: none; - .stage__title { - transition: none; + .stage__headline { + margin-bottom: $grid-base-five; } } @@ -64,10 +63,6 @@ $gridSpacing: $grid-base-four; left: 0; width: 40vw; } - - .stage__title { - transform: none; - } } &--ready { @@ -94,6 +89,7 @@ $gridSpacing: $grid-base-four; flex-wrap: wrap; justify-content: flex-end; word-break: normal; + font-weight: $font-weight-medium; @include breakpoint($fromLarge) { padding: $grid-base-six $grid-base-six 120px; @@ -101,15 +97,7 @@ $gridSpacing: $grid-base-four; } &__title { - margin-bottom: $grid-base-four; - - @include breakpoint($fromLarge) { - transform: scale(1.75); - transform-origin: bottom left; - transition: transform $animation-duration-title - $animation-easing-title; - transition-delay: #{$animation-duration - $animation-duration-title}; - } + margin-bottom: $grid-base; } &__claim { @@ -122,13 +110,14 @@ $gridSpacing: $grid-base-four; flex: 1 1 0; align-items: flex-end; align-content: flex-end; + justify-content: center; width: 335px; - margin-bottom: $grid-base-five; + margin: 0 auto $grid-base-five; transform: scale(0.9); @media (width >=calc(#{$xsmall} + #{$grid-base-three})) { transform: scale(1); - margin-bottom: $grid-base-ten; + margin: 0 auto $grid-base-ten; } svg { @@ -167,7 +156,7 @@ $gridSpacing: $grid-base-four; &__spinner { animation-delay: 2s; animation: hideSpinner 4s ease forwards; - margin: 80px auto 0; + margin: 0 auto; @include breakpoint($fromXLarge) { animation-duration: 2s; diff --git a/src/components/stage/stage.tsx b/src/components/stage/stage.tsx index 338cb7eb0..e1b81cc8f 100644 --- a/src/components/stage/stage.tsx +++ b/src/components/stage/stage.tsx @@ -106,10 +106,8 @@ export const Stage = ({ semanticLevel="4" text={translate('app.claim')} /> - {hasAnimation ? ( - - ) : null}
    + {hasAnimation ? : null}
    From 6ad21cc2e5e842364f5c0931470f2419384829f6 Mon Sep 17 00:00:00 2001 From: Sergio Florez Date: Mon, 18 Nov 2024 14:05:33 +0100 Subject: [PATCH 49/49] feat: playwright setup first step --- .github/workflows/playwright.yml | 30 +++++++ .gitignore | 5 ++ package-lock.json | 64 +++++++++++++++ package.json | 1 + playwright.config.ts | 80 +++++++++++++++++++ tests/config.ts | 8 ++ tests/login/login.spec.ts | 16 ++++ tests/registration/registration.spec.ts | 56 +++++++++++++ .../registrationAgencyLink.spec.ts | 5 ++ .../registrationConsultantLink.spec.ts | 5 ++ tests/utils.ts | 25 ++++++ 11 files changed, 295 insertions(+) create mode 100644 .github/workflows/playwright.yml create mode 100644 playwright.config.ts create mode 100644 tests/config.ts create mode 100644 tests/login/login.spec.ts create mode 100644 tests/registration/registration.spec.ts create mode 100644 tests/registration/registrationAgencyLink.spec.ts create mode 100644 tests/registration/registrationConsultantLink.spec.ts create mode 100644 tests/utils.ts diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 000000000..7ddab15c4 --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,30 @@ +name: Playwright Tests +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] +jobs: + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: Install dependencies + run: npm ci + - name: Install Playwright Browsers + run: npx playwright install --with-deps + - name: Run Playwright tests + env: + USER_NAME: ${{ secrets.USERNAME }} + PASSWORD: ${{ secrets.PASSWORD }} + run: npx playwright test + - uses: actions/upload-artifact@v4 + if: ${{ !cancelled() }} + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 diff --git a/.gitignore b/.gitignore index da1e5896e..60269a615 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,8 @@ npm-debug.log* yarn-debug.log* yarn-error.log* /.idea/ +node_modules/ +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/package-lock.json b/package-lock.json index 1b30bc015..48cb694c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -101,6 +101,7 @@ "@cypress/webpack-dev-server": "^3.5.1", "@cypress/webpack-preprocessor": "^6.0.1", "@dtsgenerator/replace-namespace": "^1.6.0", + "@playwright/test": "^1.48.2", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.11", "@storybook/addon-essentials": "^7.0.18", "@storybook/addon-interactions": "^7.0.18", @@ -4971,6 +4972,22 @@ "node": ">=14" } }, + "node_modules/@playwright/test": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.2.tgz", + "integrity": "sha512-54w1xCWfXuax7dz4W2M9uw0gDyh+ti/0K/MxcCUxChFh37kkdxPdfZDw5QBbuPUJHr1CiHJ1hXgSs+GgeQc5Zw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.48.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@pmmmwh/react-refresh-webpack-plugin": { "version": "0.5.11", "dev": true, @@ -24196,6 +24213,53 @@ "node": ">=4" } }, + "node_modules/playwright": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz", + "integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.48.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz", + "integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/pngjs": { "version": "5.0.0", "license": "MIT", diff --git a/package.json b/package.json index 9dae06380..52cbd2061 100644 --- a/package.json +++ b/package.json @@ -102,6 +102,7 @@ "@cypress/webpack-dev-server": "^3.5.1", "@cypress/webpack-preprocessor": "^6.0.1", "@dtsgenerator/replace-namespace": "^1.6.0", + "@playwright/test": "^1.48.2", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.11", "@storybook/addon-essentials": "^7.0.18", "@storybook/addon-interactions": "^7.0.18", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 000000000..cedc520a7 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,80 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +import dotenv from 'dotenv'; +import path from 'path'; +dotenv.config({ path: path.resolve(__dirname, '.env') }); + +/** + * See https://playwright.dev/docs/test-configuration. + */ + +export default defineConfig({ + testDir: './tests', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + // baseURL: 'http://127.0.0.1:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry' + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] } + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] } + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ] + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // url: 'http://127.0.0.1:3000', + // reuseExistingServer: !process.env.CI, + // }, +}); diff --git a/tests/config.ts b/tests/config.ts new file mode 100644 index 000000000..fd3e2b3c5 --- /dev/null +++ b/tests/config.ts @@ -0,0 +1,8 @@ +export const caritasRework = { + dev: 'https://dev.caritas-rework.dev.virtual-identity.net/', + stage: 'https://beratung-rework-staging.caritas.de/', + prod: 'https://beratung.caritas.de/' +}; + +// write util functions here in config or in another file? +// util functions being general checks in all registration pages and so on diff --git a/tests/login/login.spec.ts b/tests/login/login.spec.ts new file mode 100644 index 000000000..6b4835798 --- /dev/null +++ b/tests/login/login.spec.ts @@ -0,0 +1,16 @@ +import { test } from '@playwright/test'; +import { caritasRework } from '../config'; +import { ensureLanguage } from '../utils'; + +test('Login as an advice seeker', async ({ page }) => { + const username = process.env.TEST_USERNAME; + const password = process.env.TEST_PASSWORD; + ensureLanguage(page); + await page.goto(`${caritasRework.dev}`); + await page.getByLabel(/(user\s?name|benutzername)/i).fill(username!); + await page + .getByLabel(/pass\s?(word|wort)/i) + .first() + .fill(password!); + await page.getByRole('button', { name: /(einloggen|login)/i }).click(); +}); diff --git a/tests/registration/registration.spec.ts b/tests/registration/registration.spec.ts new file mode 100644 index 000000000..a8fc9af3f --- /dev/null +++ b/tests/registration/registration.spec.ts @@ -0,0 +1,56 @@ +import { test, expect } from '@playwright/test'; +import { caritasRework } from '../config'; +import { ensureLanguage, generateRandomAlphanumeric } from '../utils'; + +test('Check registration page elements', async ({ page }) => { + ensureLanguage(page); + await page.goto(`${caritasRework.dev}registration`); + await expect(page.locator('h1.headline--1')).toHaveText( + /Beratung & Hilfe|Consulting & Help/ + ); + await expect(page.locator('h4.headline--4')).toHaveText( + /Online. Anonym. Sicher.|Online. Anonymous. Secure./ + ); +}); + +// registration test is skipped until a delete user account feature is implemented +test.skip('Complete registration process', async ({ page }) => { + const password = process.env.TEST_PASSWORD; + ensureLanguage(page); + await page.goto(`${caritasRework.dev}registration`); + await page.click('a[data-cy="button-register"]'); + + // registration steps + const kidsTopic = page.locator('h4', { + hasText: /Kinder, Jugendliche|Children, teenagers/ + }); + await expect(kidsTopic).toBeVisible(); + await kidsTopic.click(); + await page.getByLabel(/Adoptions- und|Adoption and foster child/).check(); + await page.click('button[data-cy="button-next"]'); + await page.fill('input[data-cy="input-postal-code"]', '99999'); + await page.click('button[data-cy="button-next"]'); + await page + .locator('input[name="agency-selection-radio-group"]') + .first() + .click(); + await page.click('button[data-cy="button-next"]'); + + // usermame & password + const randomUsername = `testuser_${generateRandomAlphanumeric(3)}`; + await page.getByLabel(/(user\s?name|benutzername)/i).fill(randomUsername); + await page + .getByLabel(/pass\s?(word|wort)/i, { exact: true }) + .first() + .fill(password!); + await page + .getByLabel(/(passwort\s?wiederholen|repeat\s?password)/i) + .fill(password!); + await page + .getByLabel(/Ich habe die Datenschutzerklä|I have the Privacy policy/) + .check(); + await page.click('button[data-cy="button-register"]'); + await page + .getByRole('button', { name: /Nachricht verfassen|Compose message/ }) + .click(); +}); diff --git a/tests/registration/registrationAgencyLink.spec.ts b/tests/registration/registrationAgencyLink.spec.ts new file mode 100644 index 000000000..8f3fc8385 --- /dev/null +++ b/tests/registration/registrationAgencyLink.spec.ts @@ -0,0 +1,5 @@ +import { test } from '@playwright/test'; + +test.skip('registration via agency link', async ({ page }) => { + // +}); diff --git a/tests/registration/registrationConsultantLink.spec.ts b/tests/registration/registrationConsultantLink.spec.ts new file mode 100644 index 000000000..0577d2c83 --- /dev/null +++ b/tests/registration/registrationConsultantLink.spec.ts @@ -0,0 +1,5 @@ +import { test } from '@playwright/test'; + +test.skip('registration via consultant link', async ({ page }) => { + // +}); diff --git a/tests/utils.ts b/tests/utils.ts new file mode 100644 index 000000000..75235b1fa --- /dev/null +++ b/tests/utils.ts @@ -0,0 +1,25 @@ +import { expect, Page } from '@playwright/test'; + +export function generateRandomAlphanumeric(length: number): string { + const chars = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + let result = ''; + for (let i = 0; i < length; i++) { + const randomIndex = Math.floor(Math.random() * chars.length); + result += chars[randomIndex]; + } + return result; +} + +export async function ensureLanguage(page: Page) { + let pageLang = (await page.getAttribute('html', 'lang')) || ''; + + if (!['en', 'de'].includes(pageLang)) { + await page.evaluate(() => { + document.documentElement.lang = 'en'; + }); + pageLang = 'en'; + } + + expect(['en', 'de']).toContain(pageLang); +}