delete account
parent
e99613e767
commit
451f2297fd
|
@ -67,6 +67,10 @@
|
||||||
"failedInternetProblem": {
|
"failedInternetProblem": {
|
||||||
"title": "Anfrage fehlgeschlagen",
|
"title": "Anfrage fehlgeschlagen",
|
||||||
"description": "Bitte überprüfen Sie Ihre Internetverbindung und versuchen Sie es erneut."
|
"description": "Bitte überprüfen Sie Ihre Internetverbindung und versuchen Sie es erneut."
|
||||||
|
},
|
||||||
|
"passwordIncorrect": {
|
||||||
|
"title": "Passwort falsch",
|
||||||
|
"description": "Bitte überprüfen Sie Ihr Passwort und versuchen Sie es erneut."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -214,13 +218,7 @@
|
||||||
"title": "Google Kalender trennen",
|
"title": "Google Kalender trennen",
|
||||||
"description": "Aus Sicherheitsgründen müssen Sie Ihr Passwort eingeben, um die Verbindung zu Ihrem Google Kalender zu trennen.",
|
"description": "Aus Sicherheitsgründen müssen Sie Ihr Passwort eingeben, um die Verbindung zu Ihrem Google Kalender zu trennen.",
|
||||||
"checkboxDeleteCalendars": "Kalender für Öffnungszeiten und Termine löschen (Alle Termine werden gelöscht und können nicht wiederhergestellt werden)",
|
"checkboxDeleteCalendars": "Kalender für Öffnungszeiten und Termine löschen (Alle Termine werden gelöscht und können nicht wiederhergestellt werden)",
|
||||||
"button": "Google Kalender trennen",
|
"button": "Google Kalender trennen"
|
||||||
"request": {
|
|
||||||
"400": {
|
|
||||||
"title": "Passwort ungültig",
|
|
||||||
"description": "Bitte überprüfen Sie Ihr Passwort und versuchen Sie es erneut."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"calendarFrameCustomerView": "Terminkalenderansicht der Kunden"
|
"calendarFrameCustomerView": "Terminkalenderansicht der Kunden"
|
||||||
},
|
},
|
||||||
|
@ -283,7 +281,30 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deleteAccount": {
|
"deleteAccount": {
|
||||||
"cardTitle": "Konto löschen"
|
"cardTitle": "Konto löschen",
|
||||||
|
"info": "Ihr Konto und alle Ihre Daten endgültig löschen.",
|
||||||
|
"button": "Konto löschen",
|
||||||
|
"modal": {
|
||||||
|
"title": "Konto löschen",
|
||||||
|
"info": "Ihr Konto wird sofort deaktiviert und nach {{days}} Tagen gelöscht. Während dieser Zeit können Sie Ihr Konto wiederherstellen, indem Sie sich erneut anmelden.",
|
||||||
|
"why": "Warum löschen Sie Ihr Konto?",
|
||||||
|
"whyRuleRequired": "Bitte wählen Sie einen Grund",
|
||||||
|
"radioOptions": {
|
||||||
|
"notNeeded": "Ich benötige es nicht mehr",
|
||||||
|
"notUseful": "Ich finde es nicht nützlich",
|
||||||
|
"other": "Sonstiges"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"description": "Bitte überprüfen Sie Ihr Passwort und versuchen Sie es erneut."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,10 @@
|
||||||
"failedInternetProblem": {
|
"failedInternetProblem": {
|
||||||
"title": "Request failed",
|
"title": "Request failed",
|
||||||
"description": "The request failed. Please check your internet connection and try again."
|
"description": "The request failed. Please check your internet connection and try again."
|
||||||
|
},
|
||||||
|
"passwordIncorrect": {
|
||||||
|
"title": "Password incorrect",
|
||||||
|
"description": "Please check your password and try again."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -217,13 +221,7 @@
|
||||||
"title": "Unlink Google Calendar",
|
"title": "Unlink Google Calendar",
|
||||||
"description": "For security reasons, you need to enter your password to unlink your Google Calendar.",
|
"description": "For security reasons, you need to enter your password to unlink your Google Calendar.",
|
||||||
"checkboxDeleteCalendars": "Delete calendar for opening hours and appointments (all appointments are deleted and cannot be restored)",
|
"checkboxDeleteCalendars": "Delete calendar for opening hours and appointments (all appointments are deleted and cannot be restored)",
|
||||||
"button": "Unlink Google Calendar",
|
"button": "Unlink Google Calendar"
|
||||||
"request": {
|
|
||||||
"400": {
|
|
||||||
"title": "Password incorrect",
|
|
||||||
"description": "Please check your password and try again."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"calendarFrameCustomerView": "Appointment diary view of customers"
|
"calendarFrameCustomerView": "Appointment diary view of customers"
|
||||||
},
|
},
|
||||||
|
@ -292,7 +290,30 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deleteAccount": {
|
"deleteAccount": {
|
||||||
"cardTitle": "Delete account"
|
"cardTitle": "Delete account",
|
||||||
|
"info": "Permanently delete your account and all your data.",
|
||||||
|
"button": "Delete account",
|
||||||
|
"modal": {
|
||||||
|
"title": "Delete account",
|
||||||
|
"info": "Your account will be deactivated immediately and deleted after {{days}} days. During this time, you can restore your account by logging in again.",
|
||||||
|
"why": "Why are you deleting your account?",
|
||||||
|
"whyRuleRequired": "Please select a reason",
|
||||||
|
"radioOptions": {
|
||||||
|
"notNeeded": "I don't need it anymore",
|
||||||
|
"notUseful": "I don't find it useful",
|
||||||
|
"other": "Other"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"description": "Please check your password and try again."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,6 +108,7 @@ export function MyModalCloseConfirmButtonFooter({
|
||||||
onCancel,
|
onCancel,
|
||||||
onConfirm,
|
onConfirm,
|
||||||
isConfirmButtonLoading,
|
isConfirmButtonLoading,
|
||||||
|
danger = false,
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
@ -115,6 +116,7 @@ export function MyModalCloseConfirmButtonFooter({
|
||||||
<>
|
<>
|
||||||
<Button onClick={onCancel}>{t("common.button.close")}</Button>
|
<Button onClick={onCancel}>{t("common.button.close")}</Button>
|
||||||
<Button
|
<Button
|
||||||
|
danger={danger}
|
||||||
onClick={onConfirm}
|
onClick={onConfirm}
|
||||||
type="primary"
|
type="primary"
|
||||||
loading={isConfirmButtonLoading}
|
loading={isConfirmButtonLoading}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import {
|
||||||
getUserSessionFromLocalStorage,
|
getUserSessionFromLocalStorage,
|
||||||
myFetch,
|
myFetch,
|
||||||
showInputsInvalidNotification,
|
showInputsInvalidNotification,
|
||||||
|
showPasswordIncorrectNotification,
|
||||||
} from "../../../utils";
|
} from "../../../utils";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import MyCenteredContainer from "../../../Components/MyContainer";
|
import MyCenteredContainer from "../../../Components/MyContainer";
|
||||||
|
@ -406,14 +407,7 @@ function CardPersonalCalendarSettings({ settings }) {
|
||||||
setIsRequesting(false);
|
setIsRequesting(false);
|
||||||
|
|
||||||
if (errStatus === 400) {
|
if (errStatus === 400) {
|
||||||
notificationApi["error"]({
|
showPasswordIncorrectNotification(notificationApi, t);
|
||||||
message: t(
|
|
||||||
"calendar.unlinkGoogleCalendar.request.400.title"
|
|
||||||
),
|
|
||||||
description: t(
|
|
||||||
"calendar.unlinkGoogleCalendar.request.400.description"
|
|
||||||
),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,20 +3,24 @@ import {
|
||||||
Card,
|
Card,
|
||||||
Form,
|
Form,
|
||||||
Popconfirm,
|
Popconfirm,
|
||||||
|
Radio,
|
||||||
Select,
|
Select,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Space,
|
Space,
|
||||||
Switch,
|
Switch,
|
||||||
Tabs,
|
Tabs,
|
||||||
Tag,
|
Tag,
|
||||||
|
Typography,
|
||||||
notification,
|
notification,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import {
|
import {
|
||||||
|
Constants,
|
||||||
EncodeStringToBase64,
|
EncodeStringToBase64,
|
||||||
FormatDatetime,
|
FormatDatetime,
|
||||||
handleLogout,
|
handleLogout,
|
||||||
myFetch,
|
myFetch,
|
||||||
showInputsInvalidNotification,
|
showInputsInvalidNotification,
|
||||||
|
showPasswordIncorrectNotification,
|
||||||
} from "../../utils";
|
} from "../../utils";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
@ -27,12 +31,16 @@ import {
|
||||||
import { LogoutOutlined } from "@ant-design/icons";
|
import { LogoutOutlined } from "@ant-design/icons";
|
||||||
import {
|
import {
|
||||||
MyAccountNameFormInput,
|
MyAccountNameFormInput,
|
||||||
|
MyFormInput,
|
||||||
MyPasswordFormInput,
|
MyPasswordFormInput,
|
||||||
MyUsernameFormInput,
|
MyUsernameFormInput,
|
||||||
} from "../../Components/MyFormInputs";
|
} from "../../Components/MyFormInputs";
|
||||||
import { MySupsenseFallback } from "../../Components/MySupsenseFallback";
|
import { MySupsenseFallback } from "../../Components/MySupsenseFallback";
|
||||||
import { useSideBarContext } from "../../Contexts/SideBarContext";
|
import { useSideBarContext } from "../../Contexts/SideBarContext";
|
||||||
import MyTable from "../../Components/MyTable";
|
import MyTable from "../../Components/MyTable";
|
||||||
|
import MyModal, {
|
||||||
|
MyModalCloseConfirmButtonFooter,
|
||||||
|
} from "../../Components/MyModal";
|
||||||
|
|
||||||
const globalRequestStatePreview = {
|
const globalRequestStatePreview = {
|
||||||
global: RequestState.INIT,
|
global: RequestState.INIT,
|
||||||
|
@ -586,5 +594,134 @@ function YourSessions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function DeleteAccount() {
|
function DeleteAccount() {
|
||||||
return <div>Delete account, Password and feedback</div>;
|
const { t } = useTranslation();
|
||||||
|
const [notificationApi, notificationContextHolder] =
|
||||||
|
notification.useNotification();
|
||||||
|
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 (
|
||||||
|
<>
|
||||||
|
{notificationContextHolder}
|
||||||
|
|
||||||
|
<Space direction="vertical">
|
||||||
|
<Typography.Text>{t("userProfile.deleteAccount.info")}</Typography.Text>
|
||||||
|
|
||||||
|
<Button type="primary" danger onClick={() => setIsModalOpen(true)}>
|
||||||
|
{t("userProfile.deleteAccount.button")}
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
|
||||||
|
<MyModal
|
||||||
|
title={t("userProfile.deleteAccount.modal.title")}
|
||||||
|
isOpen={isModalOpen}
|
||||||
|
onCancel={handleModalClose}
|
||||||
|
footer={
|
||||||
|
<MyModalCloseConfirmButtonFooter
|
||||||
|
danger
|
||||||
|
isConfirmButtonLoading={isRequesting}
|
||||||
|
onConfirm={() => {
|
||||||
|
form
|
||||||
|
.validateFields()
|
||||||
|
.then((values) => {
|
||||||
|
setIsRequesting(true);
|
||||||
|
|
||||||
|
myFetch({
|
||||||
|
url: "/user/profile/delete",
|
||||||
|
method: "DELETE",
|
||||||
|
body: {
|
||||||
|
feedback: values.improve,
|
||||||
|
reason: values["deleteReason"],
|
||||||
|
password: EncodeStringToBase64(values.password),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
setIsRequesting(false);
|
||||||
|
|
||||||
|
window.location.reload();
|
||||||
|
})
|
||||||
|
.catch((errStatus) => {
|
||||||
|
setIsRequesting(false);
|
||||||
|
|
||||||
|
if (errStatus === 400) {
|
||||||
|
showPasswordIncorrectNotification(notificationApi, t);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => setIsRequesting(false));
|
||||||
|
}}
|
||||||
|
onCancel={handleModalClose}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Form form={form} layout="vertical" requiredMark={false}>
|
||||||
|
<Typography.Paragraph type="secondary">
|
||||||
|
{t("userProfile.deleteAccount.modal.info", {
|
||||||
|
days: Constants.ACCOUNT_DELETED_AFTER_DAYS,
|
||||||
|
})}
|
||||||
|
</Typography.Paragraph>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="deleteReason"
|
||||||
|
label={t("userProfile.deleteAccount.modal.why")}
|
||||||
|
required
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: t("userProfile.deleteAccount.modal.whyRuleRequired"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Radio.Group>
|
||||||
|
<Space direction="vertical">
|
||||||
|
<Radio value="notNeeded">
|
||||||
|
{t("userProfile.deleteAccount.modal.radioOptions.notNeeded")}
|
||||||
|
</Radio>
|
||||||
|
<Radio value="notUseful">
|
||||||
|
{t("userProfile.deleteAccount.modal.radioOptions.notUseful")}
|
||||||
|
</Radio>
|
||||||
|
<Radio value="other">
|
||||||
|
{t("userProfile.deleteAccount.modal.radioOptions.other")}
|
||||||
|
</Radio>
|
||||||
|
</Space>
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<MyFormInput
|
||||||
|
formItemName="improve"
|
||||||
|
minLength={Constants.GLOBALS.MIN_FEEDBACK_LENGTH}
|
||||||
|
maxLength={Constants.GLOBALS.MAX_FEEDBACK_LENGTH}
|
||||||
|
inputType="textarea"
|
||||||
|
propsInput={{
|
||||||
|
showCount: true,
|
||||||
|
}}
|
||||||
|
label={t("userProfile.deleteAccount.modal.improveLabel")}
|
||||||
|
ruleMessageValueRequired={t(
|
||||||
|
"userProfile.deleteAccount.modal.improveRequired"
|
||||||
|
)}
|
||||||
|
ruleMessageValueMinLengthRequired={t(
|
||||||
|
"userProfile.deleteAccount.modal.improveMinLengthRequired",
|
||||||
|
{
|
||||||
|
minLength: Constants.GLOBALS.MIN_FEEDBACK_LENGTH,
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MyPasswordFormInput />
|
||||||
|
</Form>
|
||||||
|
</MyModal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
13
src/utils.js
13
src/utils.js
|
@ -68,10 +68,13 @@ export const Constants = {
|
||||||
MAX_CALENDAR_FUTURE_BOOKING_DAYS: 365,
|
MAX_CALENDAR_FUTURE_BOOKING_DAYS: 365,
|
||||||
MIN_CALENDAR_EARLIEST_BOOKING_TIME: 0,
|
MIN_CALENDAR_EARLIEST_BOOKING_TIME: 0,
|
||||||
MAX_CALENDAR_EARLIEST_BOOKING_TIME: 60 * 24, // 24 hours in minutes
|
MAX_CALENDAR_EARLIEST_BOOKING_TIME: 60 * 24, // 24 hours in minutes
|
||||||
|
MIN_FEEDBACK_LENGTH: 10,
|
||||||
|
MAX_FEEDBACK_LENGTH: 1024,
|
||||||
},
|
},
|
||||||
DELAY_ACCOUNT_NAME_CHECK: 250,
|
DELAY_ACCOUNT_NAME_CHECK: 250,
|
||||||
CLARITY_PROJECT_ID: "kr0pale8uy",
|
CLARITY_PROJECT_ID: "kr0pale8uy",
|
||||||
KK_JOBS_URL: "https://kk-innovation.eu/jobs/",
|
KK_JOBS_URL: "https://kk-innovation.eu/jobs/",
|
||||||
|
ACCOUNT_DELETED_AFTER_DAYS: 30,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AppStyle = {
|
export const AppStyle = {
|
||||||
|
@ -247,8 +250,16 @@ export function showInputsInvalidNotification(notificationApi, t) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function showPasswordIncorrectNotification(notificationApi, t) {
|
||||||
|
notificationApi["warning"]({
|
||||||
|
message: t("common.request.passwordIncorrect.title"),
|
||||||
|
description: t("common.request.passwordIncorrect.description"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function handleLogout({ setUserSession }) {
|
export function handleLogout({ setUserSession }) {
|
||||||
setUserSession();
|
if (setUserSession !== undefined) setUserSession();
|
||||||
|
|
||||||
window.location.href = "/";
|
window.location.href = "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue