authentication
parent
bfa1a6796c
commit
2456a0ab6d
|
@ -25,7 +25,6 @@
|
|||
},
|
||||
"failed": "Fehlgeschlagen",
|
||||
"action": "Aktion",
|
||||
"contactAdmin": "Bitte kontaktieren Sie einen Administrator",
|
||||
"username": "Anzeigename",
|
||||
"usernamePlaceholder": "Geben Sie Ihren Anzeigename ein",
|
||||
"accountName": "Benutzername",
|
||||
|
@ -71,6 +70,10 @@
|
|||
"passwordIncorrect": {
|
||||
"title": "Passwort falsch",
|
||||
"description": "Bitte überprüfen Sie Ihr Passwort und versuchen Sie es erneut."
|
||||
},
|
||||
"unknownError": {
|
||||
"title": "Ein unbekannter Fehler ist aufgetreten",
|
||||
"description": "Bitte versuchen Sie es erneut."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -110,20 +113,49 @@
|
|||
"addEmployee": "Mitarbeiter anlegen",
|
||||
"editEmployee": "Mitarbeiter bearbeiten",
|
||||
"modalAddEmployee": {
|
||||
"checkboxPasswordChange": "Mitarbeiter auffordern, das Passwort zu ändern (empfohlen)"
|
||||
"checkboxSetPasswordOnLogging": "Mitarbeiter auffordern, beim ersten Anmelden ein eigenes Passwort festzulegen",
|
||||
"checkboxSetPasswordOnLoggingInfo": "Wenn diese Option aktiviert ist, wird der Mitarbeiter beim ersten Anmelden aufgefordert, ein eigenes Passwort festzulegen. Andernfalls können Sie ein Passwort für den Mitarbeiter festlegen."
|
||||
},
|
||||
"popConfirmDeleteEmployee": {
|
||||
"title": "Mitarbeiter löschen",
|
||||
"description": "Möchten Sie den Mitarbeiter wirklich löschen?"
|
||||
}
|
||||
},
|
||||
"login": {
|
||||
"login": "Anmelden",
|
||||
"signUp": "Registrieren",
|
||||
"authentication": {
|
||||
"rememberMe": "Angemeldet bleiben",
|
||||
"loginLink": "Jetzt anmelden",
|
||||
"signUpLink": "Jetzt registrieren",
|
||||
"login": {
|
||||
"button": "Anmelden",
|
||||
"dontHaveAccount": "Sie haben noch kein Konto?",
|
||||
"stateAccountPendingDeletion": {
|
||||
"title": "Anstehende Kontolöschung",
|
||||
"description": "Wenn Sie sich einloggen, wird die Löschung Ihres Kontos rückgängig gemacht und Ihr Konto wieder aktiviert.",
|
||||
"button": "Konto wiederherstellen"
|
||||
},
|
||||
"stateAccountBanned": {
|
||||
"title": "Konto gesperrt",
|
||||
"infoSupport": "Bitte kontaktieren Sie den Support, um Ihr Konto wiederherzustellen.",
|
||||
"backButton": "Zurück zur Anmeldung"
|
||||
},
|
||||
"stateInitLogin": {
|
||||
"info": "Ihr Konto wurde neu erstellt und hat noch kein Passwort. Bitte legen Sie ein Passwort fest, um sich anzumelden."
|
||||
},
|
||||
"request": {
|
||||
"400": {
|
||||
"title": "Anmeldung fehlgeschlagen",
|
||||
"description": "Bitte überprüfen Sie Ihre Eingaben und versuchen Sie es erneut."
|
||||
}
|
||||
}
|
||||
},
|
||||
"signUp": {
|
||||
"button": "Registrieren",
|
||||
"alreadyHaveAccount": "Sie haben bereits ein Konto?"
|
||||
},
|
||||
"request": {
|
||||
"400": {
|
||||
"title": "Anmeldung fehlgeschlagen",
|
||||
"description": "Bitte überprüfen Sie Ihre Eingaben."
|
||||
"title": "Registrierung fehlgeschlagen",
|
||||
"description": "Bitte überprüfen Sie Ihre Eingaben und versuchen Sie es erneut."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
},
|
||||
"failed": "Failed",
|
||||
"action": "Action",
|
||||
"contactAdmin": "Please contact an administrator",
|
||||
"username": "Username",
|
||||
"usernamePlaceholder": "Enter your username",
|
||||
"accountName": "Account name",
|
||||
|
@ -71,6 +70,10 @@
|
|||
"passwordIncorrect": {
|
||||
"title": "Password incorrect",
|
||||
"description": "Please check your password and try again."
|
||||
},
|
||||
"unknownError": {
|
||||
"title": "An unknown error has occurred",
|
||||
"description": "The request failed. Please try again."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -110,20 +113,49 @@
|
|||
"addEmployee": "Add employee",
|
||||
"editEmployee": "Edit employee",
|
||||
"modalAddEmployee": {
|
||||
"checkboxPasswordChange": "Require employee to change password (recommended)"
|
||||
"checkboxSetPasswordOnLogging": "Ask employees to set their own password when logging in for the first time",
|
||||
"checkboxSetPasswordOnLoggingInfo": "If this option is activated, the employee is prompted to set their own password when they log in for the first time. Otherwise, you can set a password for the employee."
|
||||
},
|
||||
"popConfirmDeleteEmployee": {
|
||||
"title": "Delete employee",
|
||||
"description": "Are you sure you want to delete this employee?"
|
||||
}
|
||||
},
|
||||
"login": {
|
||||
"login": "Login",
|
||||
"signUp": "Sign up",
|
||||
"request": {
|
||||
"400": {
|
||||
"title": "Login failed",
|
||||
"description": "Please check your inputs and try again."
|
||||
"authentication": {
|
||||
"rememberMe": "Remember me",
|
||||
"loginLink": "Login",
|
||||
"signUpLink": "Sign up now",
|
||||
"login": {
|
||||
"button": "Login",
|
||||
"dontHaveAccount": "Don't have an account?",
|
||||
"stateAccountPendingDeletion": {
|
||||
"title": "Pending account deletion",
|
||||
"description": "By logging in, the deletion of your account will be cancelled and your account reactivated.",
|
||||
"button": "Reactivate account"
|
||||
},
|
||||
"stateAccountBanned": {
|
||||
"title": "Account banned",
|
||||
"infoSupport": "Please contact support to reactivate your account.",
|
||||
"backButton": "Back to login"
|
||||
},
|
||||
"stateInitLogin": {
|
||||
"info": "Your account has been newly created and does not yet have a password. Please set a password to log in."
|
||||
},
|
||||
"request": {
|
||||
"400": {
|
||||
"title": "Login failed",
|
||||
"description": "Please check your inputs and try again."
|
||||
}
|
||||
}
|
||||
},
|
||||
"signUp": {
|
||||
"button": "Sign up",
|
||||
"alreadyHaveAccount": "Already have an account?",
|
||||
"request": {
|
||||
"400": {
|
||||
"title": "Sign up failed",
|
||||
"description": "Please check your inputs and try again."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import "antd/dist/reset.css";
|
||||
import "./App.css";
|
||||
import Login from "./Pages/Login";
|
||||
import { Layout, Spin, Typography } from "antd";
|
||||
import { Constants, UseUserSession, myFetch } from "./utils";
|
||||
import DashboardLayout from "./Components/DashboardLayout";
|
||||
|
@ -14,6 +13,7 @@ import StoresProvider from "./Contexts/StoresContext";
|
|||
import { clarity } from "react-microsoft-clarity";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import MyAppLogo from "./Components/MyAppLogo";
|
||||
import Authentication from "./Pages/Authentication";
|
||||
|
||||
export function Loading() {
|
||||
const { t } = useTranslation();
|
||||
|
@ -90,7 +90,7 @@ export default function App() {
|
|||
}, []);
|
||||
|
||||
if (!userSession) {
|
||||
return <Login />;
|
||||
return <Authentication />;
|
||||
}
|
||||
|
||||
if (appUserData === null) {
|
||||
|
|
|
@ -60,11 +60,6 @@ export function SideMenuContent({
|
|||
key: `${Constants.ROUTE_PATHS.STORE.OVERVIEW}/${store.store_id}`,
|
||||
};
|
||||
|
||||
console.warn(
|
||||
"here",
|
||||
`${Constants.ROUTE_PATHS.STORE.OVERVIEW}/${store.store_id}`
|
||||
);
|
||||
|
||||
if (sideBarContext.permissions.includes("settings")) {
|
||||
groupStore.children.push({
|
||||
label: t("sideMenu.store.settings"),
|
||||
|
|
|
@ -0,0 +1,482 @@
|
|||
import { LoginOutlined } from "@ant-design/icons";
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
Flex,
|
||||
Form,
|
||||
Modal,
|
||||
Result,
|
||||
Space,
|
||||
Tabs,
|
||||
Typography,
|
||||
notification,
|
||||
} from "antd";
|
||||
import {
|
||||
Constants,
|
||||
EncodeStringToBase64,
|
||||
myFetch,
|
||||
setUserSessionToLocalStorage,
|
||||
showInputsInvalidNotification,
|
||||
showUnkownErrorNotification,
|
||||
} from "../../utils";
|
||||
import { useEffect, useState } from "react";
|
||||
import {
|
||||
MyAccountNameFormInput,
|
||||
MyPasswordFormInput,
|
||||
MyUsernameFormInput,
|
||||
} from "../../Components/MyFormInputs";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import MyAppLogo from "../../Components/MyAppLogo";
|
||||
|
||||
const AuthenticationMethod = {
|
||||
LOGIN: 1,
|
||||
SIGNUP: 2,
|
||||
};
|
||||
|
||||
export default function Authentication() {
|
||||
const { t, i18n } = useTranslation();
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const [notificationApi, notificationContextHolder] =
|
||||
notification.useNotification();
|
||||
|
||||
const [selectedMethod, setSelectedMethod] = useState(
|
||||
AuthenticationMethod.LOGIN
|
||||
);
|
||||
const [isRequesting, setIsRequesting] = useState(false);
|
||||
|
||||
const showErrorNotification = (errStatus) => {
|
||||
if (errStatus === 400) {
|
||||
notificationApi["error"]({
|
||||
message: t("login.request.400.title"),
|
||||
description: t("login.request.400.description"),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{notificationContextHolder}
|
||||
<Modal
|
||||
open={true}
|
||||
mask={false}
|
||||
closable={false}
|
||||
centered
|
||||
keyboard={false}
|
||||
footer={null}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<MyAppLogo height={80} />
|
||||
</div>
|
||||
|
||||
{selectedMethod === AuthenticationMethod.LOGIN ? (
|
||||
<Login
|
||||
switchMethod={() => setSelectedMethod(AuthenticationMethod.SIGNUP)}
|
||||
notificationApi={notificationApi}
|
||||
/>
|
||||
) : (
|
||||
<SignUp
|
||||
switchMethod={() => setSelectedMethod(AuthenticationMethod.LOGIN)}
|
||||
notificationApi={notificationApi}
|
||||
/>
|
||||
)}
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function RememberMeCheckbox() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Form.Item name="rememberMe" valuePropName="checked">
|
||||
<Checkbox>{t("authentication.rememberMe")}</Checkbox>
|
||||
</Form.Item>
|
||||
);
|
||||
}
|
||||
|
||||
const LoginStep = {
|
||||
ACCOUNT_NAME: 1,
|
||||
PASSWORD: 2,
|
||||
PENDING_DELETION: 3,
|
||||
INIT_LOGIN: 4,
|
||||
BANNED: 5,
|
||||
};
|
||||
|
||||
// First step: account name -> get state of account by backend
|
||||
// Second step: if account is active -> password -> login otherwise show the state of the account (e. g. deleted, banned)
|
||||
function Login({ switchMethod, notificationApi }) {
|
||||
const { t } = useTranslation();
|
||||
const [isRequesting, setIsRequesting] = useState(false);
|
||||
const [step, setStep] = useState(LoginStep.ACCOUNT_NAME);
|
||||
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const accountName = Form.useWatch("accountName", form);
|
||||
|
||||
const showErrorNotification = (errStatus) => {
|
||||
if (errStatus === 400) {
|
||||
notificationApi["error"]({
|
||||
message: t("authentication.login.request.400.title"),
|
||||
description: t("authentication.login.request.400.description"),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!accountName) return;
|
||||
|
||||
console.log("accountName here", step);
|
||||
|
||||
// reset step if account name changed for handling the state of the account
|
||||
if (step === LoginStep.PASSWORD || step === LoginStep.INIT_LOGIN) {
|
||||
console.log("reset step", accountName);
|
||||
setStep(LoginStep.ACCOUNT_NAME);
|
||||
}
|
||||
}, [accountName]);
|
||||
|
||||
if (step === LoginStep.PENDING_DELETION) {
|
||||
return (
|
||||
<Result
|
||||
status="warning"
|
||||
title={t("authentication.login.stateAccountPendingDeletion.title")}
|
||||
subTitle={t(
|
||||
"authentication.login.stateAccountPendingDeletion.description"
|
||||
)}
|
||||
extra={[
|
||||
<Button key={0} onClick={() => setStep(LoginStep.ACCOUNT_NAME)}>
|
||||
{t("common.button.cancel")}
|
||||
</Button>,
|
||||
<Button
|
||||
key={1}
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
console.log("reactivate account");
|
||||
setStep(LoginStep.PASSWORD);
|
||||
}}
|
||||
>
|
||||
{t("authentication.login.stateAccountPendingDeletion.button")}
|
||||
</Button>,
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (step === LoginStep.BANNED) {
|
||||
return (
|
||||
<Result
|
||||
status="error"
|
||||
title={t("authentication.login.stateAccountBanned.title")}
|
||||
subTitle={
|
||||
<Space direction="vertical">
|
||||
<Typography.Text type="secondary">
|
||||
{t("authentication.login.stateAccountBanned.infoSupport")}
|
||||
</Typography.Text>
|
||||
|
||||
<Button type="link" href={`mailto:${Constants.SUPPORT_EMAIL}`}>
|
||||
{Constants.SUPPORT_EMAIL}
|
||||
</Button>
|
||||
</Space>
|
||||
}
|
||||
extra={[
|
||||
<Button
|
||||
key={0}
|
||||
onClick={() => {
|
||||
setStep(LoginStep.ACCOUNT_NAME);
|
||||
}}
|
||||
>
|
||||
{t("authentication.login.stateAccountBanned.backButton")}
|
||||
</Button>,
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
requiredMark={false}
|
||||
initialValues={{
|
||||
rememberMe: false,
|
||||
}}
|
||||
>
|
||||
{step === LoginStep.INIT_LOGIN && (
|
||||
<Typography.Paragraph type="secondary">
|
||||
{t("authentication.login.stateInitLogin.info")}
|
||||
</Typography.Paragraph>
|
||||
)}
|
||||
|
||||
<MyAccountNameFormInput
|
||||
disableAccountNameCheck={true}
|
||||
hasFeedback={false}
|
||||
/>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display:
|
||||
step === LoginStep.PASSWORD || step === LoginStep.INIT_LOGIN
|
||||
? "block"
|
||||
: "none",
|
||||
}}
|
||||
>
|
||||
<MyPasswordFormInput />
|
||||
|
||||
<RememberMeCheckbox />
|
||||
</div>
|
||||
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
block
|
||||
loading={isRequesting}
|
||||
onClick={() => {
|
||||
let validateFields = [];
|
||||
|
||||
if (step === LoginStep.ACCOUNT_NAME) {
|
||||
validateFields = ["accountName"];
|
||||
} else {
|
||||
validateFields = ["accountName", "password", "rememberMe"];
|
||||
}
|
||||
|
||||
form
|
||||
.validateFields(validateFields)
|
||||
.then((values) => {
|
||||
setIsRequesting(true);
|
||||
|
||||
let body = {
|
||||
accountName: values.accountName.toLocaleLowerCase(),
|
||||
};
|
||||
|
||||
if (
|
||||
step === LoginStep.PASSWORD ||
|
||||
step === LoginStep.INIT_LOGIN
|
||||
) {
|
||||
body.password = EncodeStringToBase64(values.password);
|
||||
body.rememberMe = values.rememberMe;
|
||||
}
|
||||
|
||||
myFetch({
|
||||
url: `/user/auth/login`,
|
||||
method: "POST",
|
||||
body: body,
|
||||
notificationApi: notificationApi,
|
||||
t: t,
|
||||
})
|
||||
.then((data) => {
|
||||
setIsRequesting(false);
|
||||
|
||||
if (
|
||||
step === LoginStep.PASSWORD ||
|
||||
step === LoginStep.INIT_LOGIN
|
||||
) {
|
||||
setUserSessionToLocalStorage(data.XAuthorization);
|
||||
window.location.href = "/";
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.state === undefined) return;
|
||||
|
||||
switch (data.state) {
|
||||
case Constants.ACCOUNT_STATE.ACTIVE:
|
||||
setStep(LoginStep.PASSWORD);
|
||||
break;
|
||||
case Constants.ACCOUNT_STATE.PENDING_DELETION:
|
||||
setStep(LoginStep.PENDING_DELETION);
|
||||
break;
|
||||
case Constants.ACCOUNT_STATE.BANNED:
|
||||
setStep(LoginStep.BANNED);
|
||||
break;
|
||||
case Constants.ACCOUNT_STATE.INIT_LOGGING:
|
||||
setStep(LoginStep.INIT_LOGIN);
|
||||
break;
|
||||
default:
|
||||
showUnkownErrorNotification(notificationApi, t);
|
||||
break;
|
||||
}
|
||||
})
|
||||
.catch((errStatus) => {
|
||||
showErrorNotification(errStatus);
|
||||
setIsRequesting(false);
|
||||
});
|
||||
})
|
||||
.catch(() => showInputsInvalidNotification(notificationApi, t));
|
||||
}}
|
||||
>
|
||||
{t("authentication.login.button")}
|
||||
</Button>
|
||||
|
||||
<Flex justify="center" style={{ paddingTop: 12 }}>
|
||||
<Typography.Text>
|
||||
{t("authentication.login.dontHaveAccount")}{" "}
|
||||
<Button type="link" style={{ padding: 0 }} onClick={switchMethod}>
|
||||
{t("authentication.signUpLink")}
|
||||
</Button>
|
||||
</Typography.Text>
|
||||
</Flex>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
||||
function SignUp({ switchMethod, notificationApi }) {
|
||||
const { t, i18n } = useTranslation();
|
||||
const [isRequesting, setIsRequesting] = useState(false);
|
||||
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const showErrorNotification = (errStatus) => {
|
||||
if (errStatus === 400) {
|
||||
notificationApi["error"]({
|
||||
message: t("authentication.signUp.request.400.title"),
|
||||
description: t("authentication.signUp.request.400.description"),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmit = () => {
|
||||
form
|
||||
.validateFields()
|
||||
.then((values) => {
|
||||
setIsRequesting(true);
|
||||
|
||||
let body = {
|
||||
accountName: values.accountName.toLocaleLowerCase(),
|
||||
password: EncodeStringToBase64(values.password),
|
||||
username: values.username,
|
||||
language: i18n.language,
|
||||
rememberMe: values.rememberMe,
|
||||
};
|
||||
|
||||
myFetch({
|
||||
url: `/user/auth/signup`,
|
||||
method: "POST",
|
||||
body: body,
|
||||
notificationApi: notificationApi,
|
||||
t: t,
|
||||
})
|
||||
.then((data) => {
|
||||
setUserSessionToLocalStorage(data.XAuthorization);
|
||||
window.location.href = "/";
|
||||
})
|
||||
.catch((errStatus) => {
|
||||
showErrorNotification(errStatus);
|
||||
setIsRequesting(false);
|
||||
});
|
||||
})
|
||||
.catch(() => showInputsInvalidNotification(notificationApi, t));
|
||||
};
|
||||
|
||||
return (
|
||||
<Form form={form} layout="vertical" requiredMark={false}>
|
||||
<MyUsernameFormInput />
|
||||
|
||||
<MyAccountNameFormInput hasFeedback={true} />
|
||||
|
||||
<MyPasswordFormInput />
|
||||
|
||||
<RememberMeCheckbox />
|
||||
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
block
|
||||
onClick={handleSubmit}
|
||||
loading={isRequesting}
|
||||
>
|
||||
{t("authentication.signUp.button")}
|
||||
</Button>
|
||||
|
||||
<Flex justify="center" style={{ paddingTop: 12 }}>
|
||||
<Typography.Text>
|
||||
{t("authentication.signUp.alreadyHaveAccount")}{" "}
|
||||
<Button type="link" style={{ padding: 0 }} onClick={switchMethod}>
|
||||
{t("authentication.loginLink")}
|
||||
</Button>
|
||||
</Typography.Text>
|
||||
</Flex>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
<Button
|
||||
type="primary"
|
||||
block
|
||||
htmlType="submit"
|
||||
loading={isRequesting}
|
||||
onClick={() => {
|
||||
form
|
||||
.validateFields()
|
||||
.then((values) => {
|
||||
setIsRequesting(true);
|
||||
|
||||
let body = {
|
||||
accountName: values.accountName.toLocaleLowerCase(),
|
||||
password: EncodeStringToBase64(values.password),
|
||||
};
|
||||
|
||||
if (selectedMethod === "2") {
|
||||
body.username = values.username;
|
||||
body.language = i18n.language;
|
||||
}
|
||||
|
||||
myFetch({
|
||||
url: `/user/auth/${
|
||||
selectedMethod === "1" ? "login" : "signup"
|
||||
}`,
|
||||
method: "POST",
|
||||
body: body,
|
||||
notificationApi: notificationApi,
|
||||
t: t,
|
||||
})
|
||||
.then((data) => {
|
||||
setUserSessionToLocalStorage(data.XAuthorization);
|
||||
window.location.href = "/";
|
||||
})
|
||||
.catch((errStatus) => {
|
||||
showErrorNotification(errStatus);
|
||||
setIsRequesting(false);
|
||||
});
|
||||
})
|
||||
.catch(() => showInputsInvalidNotification(notificationApi, t));
|
||||
}}
|
||||
>
|
||||
{selectedMethod === AuthenticationMethod.LOGIN
|
||||
? t("authentication.login.button")
|
||||
: t("authentication.signUp.button")}
|
||||
</Button>
|
||||
*/
|
||||
|
||||
/*
|
||||
<Tabs
|
||||
defaultActiveKey="1"
|
||||
items={[
|
||||
{
|
||||
key: "1",
|
||||
label: t("login.login"),
|
||||
},
|
||||
{
|
||||
key: "2",
|
||||
label: t("login.signUp"),
|
||||
},
|
||||
]}
|
||||
centered
|
||||
onChange={(activeKey) => setSelectedMethod(activeKey)}
|
||||
/>
|
||||
|
||||
<Form form={form} layout="vertical" requiredMark={false}>
|
||||
{selectedMethod === "2" && <MyUsernameFormInput />}
|
||||
|
||||
<MyAccountNameFormInput
|
||||
disableAccountNameCheck={selectedMethod === "1"}
|
||||
hasFeedback={selectedMethod === "2"}
|
||||
/>
|
||||
|
||||
<MyPasswordFormInput />
|
||||
</Form>
|
||||
*/
|
|
@ -1,131 +0,0 @@
|
|||
import { LoginOutlined } from "@ant-design/icons";
|
||||
import { Button, Form, Modal, Tabs, notification } from "antd";
|
||||
import {
|
||||
EncodeStringToBase64,
|
||||
myFetch,
|
||||
setUserSessionToLocalStorage,
|
||||
showInputsInvalidNotification,
|
||||
} from "../../utils";
|
||||
import { useState } from "react";
|
||||
import {
|
||||
MyAccountNameFormInput,
|
||||
MyPasswordFormInput,
|
||||
MyUsernameFormInput,
|
||||
} from "../../Components/MyFormInputs";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import MyAppLogo from "../../Components/MyAppLogo";
|
||||
|
||||
export default function Login() {
|
||||
const { t, i18n } = useTranslation();
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const [notificationApi, notificationContextHolder] =
|
||||
notification.useNotification();
|
||||
|
||||
const [selectedMethod, setSelectedMethod] = useState("1");
|
||||
const [isRequesting, setIsRequesting] = useState(false);
|
||||
|
||||
const showErrorNotification = (errStatus) => {
|
||||
if (errStatus === 400) {
|
||||
notificationApi["error"]({
|
||||
message: t("login.request.400.title"),
|
||||
description: t("login.request.400.description"),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{notificationContextHolder}
|
||||
<Modal
|
||||
open={true}
|
||||
mask={false}
|
||||
closable={false}
|
||||
centered
|
||||
keyboard={false}
|
||||
footer={
|
||||
<Button
|
||||
type="primary"
|
||||
htmlType="submit"
|
||||
icon={<LoginOutlined />}
|
||||
loading={isRequesting}
|
||||
onClick={() => {
|
||||
form
|
||||
.validateFields()
|
||||
.then((values) => {
|
||||
setIsRequesting(true);
|
||||
|
||||
let body = {
|
||||
accountName: values.accountName.toLocaleLowerCase(),
|
||||
password: EncodeStringToBase64(values.password),
|
||||
};
|
||||
|
||||
if (selectedMethod === "2") {
|
||||
body.username = values.username;
|
||||
body.language = i18n.language;
|
||||
}
|
||||
|
||||
myFetch({
|
||||
url: `/user/auth/${
|
||||
selectedMethod === "1" ? "login" : "signup"
|
||||
}`,
|
||||
method: "POST",
|
||||
body: body,
|
||||
notificationApi: notificationApi,
|
||||
t: t,
|
||||
})
|
||||
.then((data) => {
|
||||
setUserSessionToLocalStorage(data.XAuthorization);
|
||||
window.location.href = "/";
|
||||
})
|
||||
.catch((errStatus) => {
|
||||
showErrorNotification(errStatus);
|
||||
setIsRequesting(false);
|
||||
});
|
||||
})
|
||||
.catch(() => showInputsInvalidNotification(notificationApi, t));
|
||||
}}
|
||||
>
|
||||
{selectedMethod === "1" ? t("login.login") : t("login.signUp")}
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<MyAppLogo height={80} />
|
||||
</div>
|
||||
|
||||
<Tabs
|
||||
defaultActiveKey="1"
|
||||
items={[
|
||||
{
|
||||
key: "1",
|
||||
label: t("login.login"),
|
||||
},
|
||||
{
|
||||
key: "2",
|
||||
label: t("login.signUp"),
|
||||
},
|
||||
]}
|
||||
centered
|
||||
onChange={(activeKey) => setSelectedMethod(activeKey)}
|
||||
/>
|
||||
|
||||
<Form form={form} layout="vertical" requiredMark={false}>
|
||||
{selectedMethod === "2" && <MyUsernameFormInput />}
|
||||
|
||||
<MyAccountNameFormInput
|
||||
disableAccountNameCheck={selectedMethod === "1"}
|
||||
hasFeedback={selectedMethod === "2"}
|
||||
/>
|
||||
|
||||
<MyPasswordFormInput />
|
||||
</Form>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -202,6 +202,11 @@ function ModalAddEditEmployee({
|
|||
const screenBreakpoint = useBreakpoint();
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const checkboxSetPasswordOnLogging = Form.useWatch(
|
||||
"checkboxSetPasswordOnLogging",
|
||||
form
|
||||
);
|
||||
|
||||
const [isRequesting, setIsRequesting] = useState(false);
|
||||
|
||||
const handleModalClose = () => {
|
||||
|
@ -276,10 +281,18 @@ function ModalAddEditEmployee({
|
|||
storeId: storeId,
|
||||
username: values.username,
|
||||
accountName: values.accountName,
|
||||
password: EncodeStringToBase64(values.password),
|
||||
language: i18n.language,
|
||||
passwordSetOnInitLogging:
|
||||
values.checkboxSetPasswordOnLogging,
|
||||
};
|
||||
|
||||
if (
|
||||
!values.checkboxSetPasswordOnLogging &&
|
||||
values.password
|
||||
) {
|
||||
body.password = EncodeStringToBase64(values.password);
|
||||
}
|
||||
|
||||
if (
|
||||
values.calendarMaxFutureBookingDays !==
|
||||
storeSettings.calendar_max_future_booking_days
|
||||
|
@ -415,20 +428,33 @@ function ModalAddEditEmployee({
|
|||
)
|
||||
}
|
||||
>
|
||||
<Form form={form} layout="vertical" requiredMark={false}>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
requiredMark={false}
|
||||
initialValues={{
|
||||
checkboxSetPasswordOnLogging: true,
|
||||
}}
|
||||
>
|
||||
<MyUsernameFormInput />
|
||||
|
||||
<MyAccountNameFormInput hasFeedback />
|
||||
|
||||
{modalOptions.mode === "add" && (
|
||||
<>
|
||||
<MyPasswordFormInput />
|
||||
|
||||
<Form.Item>
|
||||
<Checkbox defaultChecked disabled>
|
||||
{t("employees.modalAddEmployee.checkboxPasswordChange")}
|
||||
<Form.Item
|
||||
name="checkboxSetPasswordOnLogging"
|
||||
valuePropName="checked"
|
||||
extra={t(
|
||||
"employees.modalAddEmployee.checkboxSetPasswordOnLoggingInfo"
|
||||
)}
|
||||
>
|
||||
<Checkbox>
|
||||
{t("employees.modalAddEmployee.checkboxSetPasswordOnLogging")}
|
||||
</Checkbox>
|
||||
</Form.Item>
|
||||
|
||||
{!checkboxSetPasswordOnLogging && <MyPasswordFormInput />}
|
||||
</>
|
||||
)}
|
||||
|
||||
|
|
14
src/utils.js
14
src/utils.js
|
@ -77,6 +77,13 @@ export const Constants = {
|
|||
CLARITY_PROJECT_ID: "kr0pale8uy",
|
||||
KK_JOBS_URL: "https://kk-innovation.eu/jobs/",
|
||||
ACCOUNT_DELETED_AFTER_DAYS: 30,
|
||||
ACCOUNT_STATE: {
|
||||
ACTIVE: 0,
|
||||
PENDING_DELETION: 1,
|
||||
INIT_LOGGING: 2,
|
||||
BANNED: 3,
|
||||
},
|
||||
SUPPORT_EMAIL: "support@zeitadler.de",
|
||||
};
|
||||
|
||||
export const AppStyle = {
|
||||
|
@ -259,6 +266,13 @@ export function showPasswordIncorrectNotification(notificationApi, t) {
|
|||
});
|
||||
}
|
||||
|
||||
export function showUnkownErrorNotification(notificationApi, t) {
|
||||
notificationApi["error"]({
|
||||
message: t("common.request.unknownError.title"),
|
||||
description: t("common.request.unknownError.description"),
|
||||
});
|
||||
}
|
||||
|
||||
export function handleLogout({ setUserSession }) {
|
||||
if (setUserSession !== undefined) setUserSession();
|
||||
|
||||
|
|
Loading…
Reference in New Issue