export account
parent
5e0af4aa88
commit
eb74f42aa1
|
@ -33,6 +33,8 @@
|
||||||
"accountNamePlaceholder": "Geben Sie Ihren Benutzernamen ein",
|
"accountNamePlaceholder": "Geben Sie Ihren Benutzernamen ein",
|
||||||
"accountNamePlaceholderThirdPerson": "Geben Sie den Benutzernamen ein",
|
"accountNamePlaceholderThirdPerson": "Geben Sie den Benutzernamen ein",
|
||||||
"accountNameInfo": "Der Benutzername wird verwendet, um sich anzumelden.",
|
"accountNameInfo": "Der Benutzername wird verwendet, um sich anzumelden.",
|
||||||
|
"email": "E-Mail",
|
||||||
|
"emailPlaceholder": "Geben Sie Ihre E-Mail ein",
|
||||||
"password": "Passwort",
|
"password": "Passwort",
|
||||||
"passwordPlaceholder": "Geben Sie Ihr Passwort ein",
|
"passwordPlaceholder": "Geben Sie Ihr Passwort ein",
|
||||||
"noDataFound": "Keine Einträge gefunden",
|
"noDataFound": "Keine Einträge gefunden",
|
||||||
|
@ -53,6 +55,8 @@
|
||||||
"accountNameRequired": "Benutzername ist erforderlich",
|
"accountNameRequired": "Benutzername ist erforderlich",
|
||||||
"accountNameMinLength": "Benutzername muss mindestens {{minLength}} Zeichen lang sein",
|
"accountNameMinLength": "Benutzername muss mindestens {{minLength}} Zeichen lang sein",
|
||||||
"accountNameTaken": "Benutzername ist bereits vergeben",
|
"accountNameTaken": "Benutzername ist bereits vergeben",
|
||||||
|
"emailRequired": "E-Mail ist erforderlich",
|
||||||
|
"emailInvalid": "E-Mail ist ungültig",
|
||||||
"passwordRequired": "Passwort ist erforderlich",
|
"passwordRequired": "Passwort ist erforderlich",
|
||||||
"passwordMinLength": "Passwort muss mindestens {{minLength}} Zeichen lang sein",
|
"passwordMinLength": "Passwort muss mindestens {{minLength}} Zeichen lang sein",
|
||||||
"calendarMaxFutureBookingDaysRequired": "Maximaler Buchungszeitraum ist erforderlich",
|
"calendarMaxFutureBookingDaysRequired": "Maximaler Buchungszeitraum ist erforderlich",
|
||||||
|
@ -285,7 +289,7 @@
|
||||||
"yourProfile": "Ihr Profil",
|
"yourProfile": "Ihr Profil",
|
||||||
"changePassword": "Passwort ändern",
|
"changePassword": "Passwort ändern",
|
||||||
"yourSessions": "Ihre Sitzungen",
|
"yourSessions": "Ihre Sitzungen",
|
||||||
"deleteAccount": "Konto löschen"
|
"yourAccount": "Ihr Konto"
|
||||||
},
|
},
|
||||||
"yourProfile": {
|
"yourProfile": {
|
||||||
"cardTitle": "Ihr Profil",
|
"cardTitle": "Ihr Profil",
|
||||||
|
@ -318,6 +322,21 @@
|
||||||
"description": "Möchten Sie diese Sitzung wirklich abmelden?"
|
"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": {
|
"deleteAccount": {
|
||||||
"cardTitle": "Konto löschen",
|
"cardTitle": "Konto löschen",
|
||||||
"info": "Ihr Konto und alle Ihre Daten endgültig 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?",
|
"improveLabel": "Wie können wir das Produkt verbessern?",
|
||||||
"improveRequired": "Bitte geben Sie Ihr Feedback ein",
|
"improveRequired": "Bitte geben Sie Ihr Feedback ein",
|
||||||
"improveMinLengthRequired": "Bitte geben Sie mindestens {{minLength}} Zeichen ein",
|
"improveMinLengthRequired": "Bitte geben Sie mindestens {{minLength}} Zeichen ein",
|
||||||
"button": "Konto löschen",
|
|
||||||
"request": {
|
"request": {
|
||||||
"400": {
|
"400": {
|
||||||
"title": "Passwort falsch",
|
"title": "Passwort falsch",
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
"accountNamePlaceholder": "Enter your account name",
|
"accountNamePlaceholder": "Enter your account name",
|
||||||
"accountNamePlaceholderThirdPerson": "Enter the account name",
|
"accountNamePlaceholderThirdPerson": "Enter the account name",
|
||||||
"accountNameInfo": "The account name is used to log in.",
|
"accountNameInfo": "The account name is used to log in.",
|
||||||
|
"email": "Email",
|
||||||
|
"emailPlaceholder": "Enter your email",
|
||||||
"password": "Password",
|
"password": "Password",
|
||||||
"passwordPlaceholder": "Enter your password",
|
"passwordPlaceholder": "Enter your password",
|
||||||
"noDataFound": "No data found",
|
"noDataFound": "No data found",
|
||||||
|
@ -53,6 +55,8 @@
|
||||||
"accountNameRequired": "Please enter your account name",
|
"accountNameRequired": "Please enter your account name",
|
||||||
"accountNameMinLength": "Account name must be at least {{minLength}} characters",
|
"accountNameMinLength": "Account name must be at least {{minLength}} characters",
|
||||||
"accountNameTaken": "Account name already exists",
|
"accountNameTaken": "Account name already exists",
|
||||||
|
"emailRequired": "Please enter your email",
|
||||||
|
"emailInvalid": "Please enter a valid email",
|
||||||
"passwordRequired": "Please enter your password",
|
"passwordRequired": "Please enter your password",
|
||||||
"passwordMinLength": "Password must be at least {{minLength}} characters",
|
"passwordMinLength": "Password must be at least {{minLength}} characters",
|
||||||
"calendarMaxFutureBookingDaysRequired": "Please enter the max. future booking days",
|
"calendarMaxFutureBookingDaysRequired": "Please enter the max. future booking days",
|
||||||
|
@ -288,7 +292,7 @@
|
||||||
"yourProfile": "Your profile",
|
"yourProfile": "Your profile",
|
||||||
"changePassword": "Change password",
|
"changePassword": "Change password",
|
||||||
"yourSessions": "Your sessions",
|
"yourSessions": "Your sessions",
|
||||||
"deleteAccount": "Delete account"
|
"yourAccount": "Your account"
|
||||||
},
|
},
|
||||||
"yourProfile": {
|
"yourProfile": {
|
||||||
"cardTitle": "Your profile",
|
"cardTitle": "Your profile",
|
||||||
|
@ -327,6 +331,21 @@
|
||||||
"description": "Are you sure you want to delete this session?"
|
"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": {
|
"deleteAccount": {
|
||||||
"cardTitle": "Delete account",
|
"cardTitle": "Delete account",
|
||||||
"info": "Permanently delete your account and all your data.",
|
"info": "Permanently delete your account and all your data.",
|
||||||
|
@ -344,7 +363,6 @@
|
||||||
"improveLabel": "How can we improve the product?",
|
"improveLabel": "How can we improve the product?",
|
||||||
"improveRequired": "Please enter your feedback",
|
"improveRequired": "Please enter your feedback",
|
||||||
"improveMinLengthRequired": "Please enter at least {{minLength}} characters",
|
"improveMinLengthRequired": "Please enter at least {{minLength}} characters",
|
||||||
"button": "Delete account",
|
|
||||||
"request": {
|
"request": {
|
||||||
"400": {
|
"400": {
|
||||||
"title": "Password incorrect",
|
"title": "Password incorrect",
|
||||||
|
|
|
@ -110,6 +110,28 @@ export function MyPasswordFormInput({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function MyEmailFormInput() {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MyFormInput
|
||||||
|
formItemName="email"
|
||||||
|
minLength={0}
|
||||||
|
maxLength={64}
|
||||||
|
label={t("common.email")}
|
||||||
|
ruleMessageValueRequired={t("common.inputRules.emailRequired")}
|
||||||
|
inputPlaceholder={t("common.emailPlaceholder")}
|
||||||
|
inputType="email"
|
||||||
|
formItemRules={[
|
||||||
|
{
|
||||||
|
type: "email",
|
||||||
|
message: t("common.inputRules.emailInvalid"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function MyCalendarMaxFutureBookingDaysFormInput({ formItemName }) {
|
export function MyCalendarMaxFutureBookingDaysFormInput({ formItemName }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
|
Col,
|
||||||
Form,
|
Form,
|
||||||
Popconfirm,
|
Popconfirm,
|
||||||
Radio,
|
Radio,
|
||||||
|
Row,
|
||||||
Select,
|
Select,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Space,
|
Space,
|
||||||
|
@ -31,6 +33,7 @@ import {
|
||||||
import { LogoutOutlined } from "@ant-design/icons";
|
import { LogoutOutlined } from "@ant-design/icons";
|
||||||
import {
|
import {
|
||||||
MyAccountNameFormInput,
|
MyAccountNameFormInput,
|
||||||
|
MyEmailFormInput,
|
||||||
MyFormInput,
|
MyFormInput,
|
||||||
MyPasswordFormInput,
|
MyPasswordFormInput,
|
||||||
MyUsernameFormInput,
|
MyUsernameFormInput,
|
||||||
|
@ -64,7 +67,6 @@ export default function UserProfile({ setUserSession }) {
|
||||||
const tabItems = [
|
const tabItems = [
|
||||||
{
|
{
|
||||||
label: t("userProfile.tabs.yourProfile"),
|
label: t("userProfile.tabs.yourProfile"),
|
||||||
cardTitle: t("userProfile.yourProfile.cardTitle"),
|
|
||||||
children: (
|
children: (
|
||||||
<YourProfile
|
<YourProfile
|
||||||
notificationApi={notificationApi}
|
notificationApi={notificationApi}
|
||||||
|
@ -75,7 +77,6 @@ export default function UserProfile({ setUserSession }) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t("userProfile.tabs.changePassword"),
|
label: t("userProfile.tabs.changePassword"),
|
||||||
cardTitle: t("userProfile.changePassword.cardTitle"),
|
|
||||||
children: (
|
children: (
|
||||||
<ChangePassword
|
<ChangePassword
|
||||||
notificationApi={notificationApi}
|
notificationApi={notificationApi}
|
||||||
|
@ -87,24 +88,20 @@ export default function UserProfile({ setUserSession }) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t("userProfile.tabs.yourSessions"),
|
label: t("userProfile.tabs.yourSessions"),
|
||||||
cardTitle: t("userProfile.yourSessions.cardTitle"),
|
|
||||||
children: <YourSessions />,
|
children: <YourSessions />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t("userProfile.tabs.deleteAccount"),
|
label: t("userProfile.tabs.yourAccount"),
|
||||||
cardTitle: t("userProfile.deleteAccount.cardTitle"),
|
children: <YourAccount />,
|
||||||
children: <DeleteAccount />,
|
|
||||||
},
|
},
|
||||||
].map((item, index) => {
|
].map((item, index) => {
|
||||||
return {
|
return {
|
||||||
key: index,
|
key: index,
|
||||||
...item,
|
...item,
|
||||||
children: (
|
children: (
|
||||||
<Card title={item.cardTitle}>
|
|
||||||
<MySupsenseFallback spinnerCentered={false}>
|
<MySupsenseFallback spinnerCentered={false}>
|
||||||
{item.children}
|
{item.children}
|
||||||
</MySupsenseFallback>
|
</MySupsenseFallback>
|
||||||
</Card>
|
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -305,8 +302,12 @@ function YourProfile({
|
||||||
}, [language, analyticsEnabled, username, accountName]);
|
}, [language, analyticsEnabled, username, accountName]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<Card title={t("userProfile.yourProfile.cardTitle")}>
|
||||||
<Form form={form} layout="vertical" requiredMark={false}>
|
<Form form={form} layout="vertical" requiredMark={false}>
|
||||||
<Form.Item name="language" label={t("userProfile.yourProfile.language")}>
|
<Form.Item
|
||||||
|
name="language"
|
||||||
|
label={t("userProfile.yourProfile.language")}
|
||||||
|
>
|
||||||
{requestState === RequestState.INIT ? (
|
{requestState === RequestState.INIT ? (
|
||||||
<Skeleton.Input active block></Skeleton.Input>
|
<Skeleton.Input active block></Skeleton.Input>
|
||||||
) : (
|
) : (
|
||||||
|
@ -340,7 +341,9 @@ function YourProfile({
|
||||||
)}
|
)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<MyUsernameFormInput showSkeleton={requestState === RequestState.INIT} />
|
<MyUsernameFormInput
|
||||||
|
showSkeleton={requestState === RequestState.INIT}
|
||||||
|
/>
|
||||||
|
|
||||||
<MyAccountNameFormInput
|
<MyAccountNameFormInput
|
||||||
showSkeleton={requestState === RequestState.INIT}
|
showSkeleton={requestState === RequestState.INIT}
|
||||||
|
@ -348,6 +351,7 @@ function YourProfile({
|
||||||
disableAccountNameCheck={requestData.account_name === accountName}
|
disableAccountNameCheck={requestData.account_name === accountName}
|
||||||
/>
|
/>
|
||||||
</Form>
|
</Form>
|
||||||
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,7 +421,13 @@ function ChangePassword({
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form form={form} layout="vertical" autoComplete="off" requiredMark={false}>
|
<Card title={t("userProfile.changePassword.cardTitle")}>
|
||||||
|
<Form
|
||||||
|
form={form}
|
||||||
|
layout="vertical"
|
||||||
|
autoComplete="off"
|
||||||
|
requiredMark={false}
|
||||||
|
>
|
||||||
<MyPasswordFormInput
|
<MyPasswordFormInput
|
||||||
propsInput={{
|
propsInput={{
|
||||||
id: "currentPassword",
|
id: "currentPassword",
|
||||||
|
@ -480,6 +490,7 @@ function ChangePassword({
|
||||||
</Space>
|
</Space>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,6 +594,7 @@ function YourSessions() {
|
||||||
useEffect(() => requestSessions(), []);
|
useEffect(() => requestSessions(), []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<Card title={t("userProfile.yourSessions.cardTitle")}>
|
||||||
<MyTable
|
<MyTable
|
||||||
props={{
|
props={{
|
||||||
loading: isRequesting,
|
loading: isRequesting,
|
||||||
|
@ -590,21 +602,40 @@ function YourSessions() {
|
||||||
dataSource: getTableItems(),
|
dataSource: getTableItems(),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DeleteAccount() {
|
function YourAccount() {
|
||||||
const { t } = useTranslation();
|
|
||||||
const [notificationApi, notificationContextHolder] =
|
const [notificationApi, notificationContextHolder] =
|
||||||
notification.useNotification();
|
notification.useNotification();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{notificationContextHolder}
|
||||||
|
|
||||||
|
<Row gutter={[16, 16]}>
|
||||||
|
<Col span={24}>
|
||||||
|
<YourAccountExportDataCard notificationApi={notificationApi} />
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
<Col span={24}>
|
||||||
|
<YourAccountDeleteAccountCard notificationApi={notificationApi} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function YourAccountExportDataCard({ notificationApi }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
const [isRequesting, setIsRequesting] = useState(false);
|
const [isRequesting, setIsRequesting] = useState(false);
|
||||||
|
|
||||||
const handleModalClose = () => {
|
const handleModalClose = () => setIsModalOpen(false);
|
||||||
setIsModalOpen(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isModalOpen) return;
|
if (!isModalOpen) return;
|
||||||
|
@ -613,9 +644,85 @@ function DeleteAccount() {
|
||||||
}, [isModalOpen]);
|
}, [isModalOpen]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Card title={t("userProfile.accountExport.cardTitle")}>
|
||||||
{notificationContextHolder}
|
<Space direction="vertical">
|
||||||
|
<Typography.Text>{t("userProfile.accountExport.info")}</Typography.Text>
|
||||||
|
|
||||||
|
<Button type="default" onClick={() => setIsModalOpen(true)}>
|
||||||
|
{t("userProfile.accountExport.button")}
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
|
||||||
|
<MyModal
|
||||||
|
title={t("userProfile.accountExport.modal.title")}
|
||||||
|
isOpen={isModalOpen}
|
||||||
|
onCancel={handleModalClose}
|
||||||
|
footer={
|
||||||
|
<MyModalCloseConfirmButtonFooter
|
||||||
|
isConfirmButtonLoading={isRequesting}
|
||||||
|
onConfirm={() => {
|
||||||
|
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}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Form form={form} layout="vertical" requiredMark={false}>
|
||||||
|
<Typography.Paragraph type="secondary">
|
||||||
|
{t("userProfile.accountExport.modal.info")}
|
||||||
|
</Typography.Paragraph>
|
||||||
|
|
||||||
|
<MyEmailFormInput />
|
||||||
|
|
||||||
|
<MyPasswordFormInput />
|
||||||
|
</Form>
|
||||||
|
</MyModal>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<Card title={t("userProfile.deleteAccount.cardTitle")}>
|
||||||
<Space direction="vertical">
|
<Space direction="vertical">
|
||||||
<Typography.Text>{t("userProfile.deleteAccount.info")}</Typography.Text>
|
<Typography.Text>{t("userProfile.deleteAccount.info")}</Typography.Text>
|
||||||
|
|
||||||
|
@ -660,7 +767,7 @@ function DeleteAccount() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(() => setIsRequesting(false));
|
.catch(() => showInputsInvalidNotification(notificationApi, t));
|
||||||
}}
|
}}
|
||||||
onCancel={handleModalClose}
|
onCancel={handleModalClose}
|
||||||
/>
|
/>
|
||||||
|
@ -722,6 +829,6 @@ function DeleteAccount() {
|
||||||
<MyPasswordFormInput />
|
<MyPasswordFormInput />
|
||||||
</Form>
|
</Form>
|
||||||
</MyModal>
|
</MyModal>
|
||||||
</>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue