diff --git a/public/locales/de/translation.json b/public/locales/de/translation.json index 5a7319b..662d050 100644 --- a/public/locales/de/translation.json +++ b/public/locales/de/translation.json @@ -33,6 +33,8 @@ "accountNamePlaceholder": "Geben Sie Ihren Benutzernamen ein", "accountNamePlaceholderThirdPerson": "Geben Sie den Benutzernamen ein", "accountNameInfo": "Der Benutzername wird verwendet, um sich anzumelden.", + "email": "E-Mail", + "emailPlaceholder": "Geben Sie Ihre E-Mail ein", "password": "Passwort", "passwordPlaceholder": "Geben Sie Ihr Passwort ein", "noDataFound": "Keine Einträge gefunden", @@ -53,6 +55,8 @@ "accountNameRequired": "Benutzername ist erforderlich", "accountNameMinLength": "Benutzername muss mindestens {{minLength}} Zeichen lang sein", "accountNameTaken": "Benutzername ist bereits vergeben", + "emailRequired": "E-Mail ist erforderlich", + "emailInvalid": "E-Mail ist ungültig", "passwordRequired": "Passwort ist erforderlich", "passwordMinLength": "Passwort muss mindestens {{minLength}} Zeichen lang sein", "calendarMaxFutureBookingDaysRequired": "Maximaler Buchungszeitraum ist erforderlich", @@ -285,7 +289,7 @@ "yourProfile": "Ihr Profil", "changePassword": "Passwort ändern", "yourSessions": "Ihre Sitzungen", - "deleteAccount": "Konto löschen" + "yourAccount": "Ihr Konto" }, "yourProfile": { "cardTitle": "Ihr Profil", @@ -318,6 +322,21 @@ "description": "Möchten Sie diese Sitzung wirklich abmelden?" } }, + "accountExport": { + "cardTitle": "Konto exportieren", + "info": "Exportieren Sie Ihr Konto und alle Daten, die im Laufe der Nutzung des Dashboards entstanden sind.", + "button": "Konto export anfordern", + "modal": { + "title": "Konto export anfordern", + "info": "Dies kann einige Zeit in Anspruch nehmen. Wir senden Ihnen eine E-Mail mit dem Download-Link, sobald der Export fertig ist.", + "request": { + "400": { + "title": "Passwort falsch", + "description": "Bitte überprüfen Sie Ihr Passwort und versuchen Sie es erneut." + } + } + } + }, "deleteAccount": { "cardTitle": "Konto löschen", "info": "Ihr Konto und alle Ihre Daten endgültig löschen.", @@ -335,7 +354,6 @@ "improveLabel": "Wie können wir das Produkt verbessern?", "improveRequired": "Bitte geben Sie Ihr Feedback ein", "improveMinLengthRequired": "Bitte geben Sie mindestens {{minLength}} Zeichen ein", - "button": "Konto löschen", "request": { "400": { "title": "Passwort falsch", diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index e36f132..6ce468f 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -33,6 +33,8 @@ "accountNamePlaceholder": "Enter your account name", "accountNamePlaceholderThirdPerson": "Enter the account name", "accountNameInfo": "The account name is used to log in.", + "email": "Email", + "emailPlaceholder": "Enter your email", "password": "Password", "passwordPlaceholder": "Enter your password", "noDataFound": "No data found", @@ -53,6 +55,8 @@ "accountNameRequired": "Please enter your account name", "accountNameMinLength": "Account name must be at least {{minLength}} characters", "accountNameTaken": "Account name already exists", + "emailRequired": "Please enter your email", + "emailInvalid": "Please enter a valid email", "passwordRequired": "Please enter your password", "passwordMinLength": "Password must be at least {{minLength}} characters", "calendarMaxFutureBookingDaysRequired": "Please enter the max. future booking days", @@ -288,7 +292,7 @@ "yourProfile": "Your profile", "changePassword": "Change password", "yourSessions": "Your sessions", - "deleteAccount": "Delete account" + "yourAccount": "Your account" }, "yourProfile": { "cardTitle": "Your profile", @@ -327,6 +331,21 @@ "description": "Are you sure you want to delete this session?" } }, + "accountExport": { + "cardTitle": "Account export", + "info": "Export your account and all your data to a ZIP file.", + "button": "Export account", + "modal": { + "title": "Request account export", + "info": "Export your account and all data created during the use of the dashboard.", + "request": { + "400": { + "title": "Password incorrect", + "description": "Please check your password and try again." + } + } + } + }, "deleteAccount": { "cardTitle": "Delete account", "info": "Permanently delete your account and all your data.", @@ -344,7 +363,6 @@ "improveLabel": "How can we improve the product?", "improveRequired": "Please enter your feedback", "improveMinLengthRequired": "Please enter at least {{minLength}} characters", - "button": "Delete account", "request": { "400": { "title": "Password incorrect", diff --git a/src/Components/MyFormInputs/index.js b/src/Components/MyFormInputs/index.js index f76ccbe..bbeb4ae 100644 --- a/src/Components/MyFormInputs/index.js +++ b/src/Components/MyFormInputs/index.js @@ -110,6 +110,28 @@ export function MyPasswordFormInput({ ); } +export function MyEmailFormInput() { + const { t } = useTranslation(); + + return ( + + ); +} + export function MyCalendarMaxFutureBookingDaysFormInput({ formItemName }) { const { t } = useTranslation(); diff --git a/src/Pages/UserProfile/index.js b/src/Pages/UserProfile/index.js index 8336efd..8c57b38 100644 --- a/src/Pages/UserProfile/index.js +++ b/src/Pages/UserProfile/index.js @@ -1,9 +1,11 @@ import { Button, Card, + Col, Form, Popconfirm, Radio, + Row, Select, Skeleton, Space, @@ -31,6 +33,7 @@ import { import { LogoutOutlined } from "@ant-design/icons"; import { MyAccountNameFormInput, + MyEmailFormInput, MyFormInput, MyPasswordFormInput, MyUsernameFormInput, @@ -64,7 +67,6 @@ export default function UserProfile({ setUserSession }) { const tabItems = [ { label: t("userProfile.tabs.yourProfile"), - cardTitle: t("userProfile.yourProfile.cardTitle"), children: ( , }, { - label: t("userProfile.tabs.deleteAccount"), - cardTitle: t("userProfile.deleteAccount.cardTitle"), - children: , + label: t("userProfile.tabs.yourAccount"), + children: , }, ].map((item, index) => { return { key: index, ...item, children: ( - - - {item.children} - - + + {item.children} + ), }; }); @@ -305,49 +302,56 @@ function YourProfile({ }, [language, analyticsEnabled, username, accountName]); return ( -
- - {requestState === RequestState.INIT ? ( - - ) : ( - i18n.changeLanguage(e)} + /> + )} + - - {requestState === RequestState.INIT ? ( - - ) : ( - {t("userProfile.yourProfile.analytics")} - )} - + + {requestState === RequestState.INIT ? ( + + ) : ( + {t("userProfile.yourProfile.analytics")} + )} + - + - - + + + ); } @@ -417,69 +421,76 @@ function ChangePassword({ }; return ( -
- + + + - + - ({ - validator(_, value) { - if (!value || getFieldValue("newPassword") === value) { - return Promise.resolve(); - } - return Promise.reject( - new Error( - t("userProfile.changePassword.confirmNewPasswordMismatch") - ) - ); - }, - })} - /> + ({ + validator(_, value) { + if (!value || getFieldValue("newPassword") === value) { + return Promise.resolve(); + } + return Promise.reject( + new Error( + t("userProfile.changePassword.confirmNewPasswordMismatch") + ) + ); + }, + })} + /> - - - - - - + + + + + + + ); } @@ -583,28 +594,48 @@ function YourSessions() { useEffect(() => requestSessions(), []); return ( - + + + ); } -function DeleteAccount() { - const { t } = useTranslation(); +function YourAccount() { const [notificationApi, notificationContextHolder] = notification.useNotification(); + + return ( + <> + {notificationContextHolder} + + + + + + + + + + + + ); +} + +function YourAccountExportDataCard({ notificationApi }) { + const { t } = useTranslation(); + const [form] = Form.useForm(); const [isModalOpen, setIsModalOpen] = useState(false); const [isRequesting, setIsRequesting] = useState(false); - const handleModalClose = () => { - setIsModalOpen(false); - }; + const handleModalClose = () => setIsModalOpen(false); useEffect(() => { if (!isModalOpen) return; @@ -613,9 +644,85 @@ function DeleteAccount() { }, [isModalOpen]); return ( - <> - {notificationContextHolder} + + + {t("userProfile.accountExport.info")} + + + + { + form + .validateFields() + .then((values) => { + setIsRequesting(true); + + myFetch({ + url: "/user/profile/export", + method: "POST", + body: { + email: values.email, + password: EncodeStringToBase64(values.password), + }, + }) + .then(() => { + setIsRequesting(false); + setIsModalOpen(false); + }) + .catch((errStatus) => { + setIsRequesting(false); + + if (errStatus === 400) { + showPasswordIncorrectNotification(notificationApi, t); + } + }); + }) + .catch(() => showInputsInvalidNotification(notificationApi, t)); + }} + onCancel={handleModalClose} + /> + } + > +
+ + {t("userProfile.accountExport.modal.info")} + + + + + + +
+
+ ); +} + +function YourAccountDeleteAccountCard({ notificationApi }) { + const { t } = useTranslation(); + + const [form] = Form.useForm(); + + const [isModalOpen, setIsModalOpen] = useState(false); + const [isRequesting, setIsRequesting] = useState(false); + + const handleModalClose = () => setIsModalOpen(false); + /*useEffect(() => { + if (!isModalOpen) return; + + form.resetFields(); + }, [isModalOpen]); */ + + return ( + {t("userProfile.deleteAccount.info")} @@ -660,7 +767,7 @@ function DeleteAccount() { } }); }) - .catch(() => setIsRequesting(false)); + .catch(() => showInputsInvalidNotification(notificationApi, t)); }} onCancel={handleModalClose} /> @@ -722,6 +829,6 @@ function DeleteAccount() { - + ); }