diff --git a/public/locales/de/translation.json b/public/locales/de/translation.json
index 6a8d083..ab19a4a 100644
--- a/public/locales/de/translation.json
+++ b/public/locales/de/translation.json
@@ -378,5 +378,22 @@
"improveMinLengthRequired": "Bitte geben Sie mindestens {{minLength}} Zeichen ein"
}
}
+ },
+ "verification": {
+ "error": {
+ "title": "Verifizierung fehlgeschlagen",
+ "description": "Keine ausstehende Überprüfung gefunden"
+ },
+ "content": [
+ {
+ "requesting": {
+ "title": "E-Mail-Verifizierung ausstehend"
+ },
+ "Erfolg": {
+ "title": "E-Mail-Überprüfung erfolgreich",
+ "button": "Jetzt anmelden"
+ }
+ }
+ ]
}
}
diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json
index 762bfda..c4f2eac 100644
--- a/public/locales/en/translation.json
+++ b/public/locales/en/translation.json
@@ -381,5 +381,22 @@
"improveMinLengthRequired": "Please enter at least {{minLength}} characters"
}
}
+ },
+ "verification": {
+ "error": {
+ "title": "Verification failed",
+ "description": "No pending verification found."
+ },
+ "content": [
+ {
+ "requesting": {
+ "title": "Email verification pending"
+ },
+ "success": {
+ "title": "Email verification successful",
+ "button": "Login now"
+ }
+ }
+ ]
}
}
diff --git a/src/App.js b/src/App.js
index f94393f..2b189fa 100644
--- a/src/App.js
+++ b/src/App.js
@@ -19,7 +19,10 @@ import StoresProvider from "./Contexts/StoresContext";
import { clarity } from "react-microsoft-clarity";
import { useTranslation } from "react-i18next";
import MyAppLogo from "./Components/MyAppLogo";
-import { AuthenticationRoutes } from "./Components/AppRoutes";
+import {
+ AuthenticationRoutes,
+ VerificationRoutes,
+} from "./Components/AppRoutes";
export function Loading() {
const { t } = useTranslation();
@@ -65,7 +68,16 @@ export function Loading() {
);
}
-export default function App() {
+export default function PreApp() {
+ // if the users comes from a verification email (e.g. when sign up or delete account)
+ if (window.location.pathname.startsWith("/verify/")) {
+ return ;
+ }
+
+ return ;
+}
+
+export function App() {
const { _, i18n } = useTranslation();
const { userSession, setUserSession } = UseUserSession();
diff --git a/src/Components/AppRoutes/index.js b/src/Components/AppRoutes/index.js
index 4d8c165..3306ab5 100644
--- a/src/Components/AppRoutes/index.js
+++ b/src/Components/AppRoutes/index.js
@@ -3,6 +3,7 @@ import { Constants, isDevelopmentEnv } from "../../utils";
import { lazy } from "react";
import { MySupsenseFallback } from "../MySupsenseFallback";
import { AuthenticationMethod } from "../../Pages/Authentication";
+import Verification from "../../Pages/Verification";
// Lazy-loaded components
const Authentication = lazy(() => import("../../Pages/Authentication"));
@@ -48,6 +49,30 @@ export function AuthenticationRoutes() {
);
}
+export function VerificationRoutes() {
+ return (
+
+
+
+
+ }
+ />
+
+
+
+
+ }
+ />
+
+ );
+}
+
export function AppRoutes({ setUserSession }) {
return (
diff --git a/src/Components/MyModal/index.js b/src/Components/MyModal/index.js
index e1f0343..12fab9a 100644
--- a/src/Components/MyModal/index.js
+++ b/src/Components/MyModal/index.js
@@ -9,6 +9,7 @@ export default function MyModal({
onCancel,
footer = ,
title,
+ closable = true,
}) {
const screenBreakpoint = useBreakpoint();
@@ -21,6 +22,7 @@ export default function MyModal({
footer={footer}
centered={screenBreakpoint.xs}
title={title}
+ closable={closable}
>
{children}
diff --git a/src/Pages/Authentication/index.js b/src/Pages/Authentication/index.js
index 355e455..45e7926 100644
--- a/src/Pages/Authentication/index.js
+++ b/src/Pages/Authentication/index.js
@@ -126,6 +126,7 @@ function Login({ notificationApi }) {
const [step, setStep] = useState(LoginStep.ACCOUNT_NAME);
const [isRequesting, setIsRequesting] = useState(false);
+ const recaptchaRef = useRef(null);
const recaptchaValueRef = useRef(null);
const [form] = Form.useForm();
@@ -253,7 +254,7 @@ function Login({ notificationApi }) {
]}
>
(recaptchaValueRef.current = value)}
/>
@@ -346,7 +347,7 @@ function Login({ notificationApi }) {
.catch((errStatus) => {
showErrorNotification(errStatus);
setIsRequesting(false);
- recaptchaValueRef.current.reset();
+ recaptchaRef.current.reset();
});
})
.catch(() => showInputsInvalidNotification(notificationApi, t));
diff --git a/src/Pages/PageNotFound/index.js b/src/Pages/PageNotFound/index.js
index 285016b..7866ae7 100644
--- a/src/Pages/PageNotFound/index.js
+++ b/src/Pages/PageNotFound/index.js
@@ -3,7 +3,24 @@ import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
import { Constants } from "../../utils";
-export default function PageNotFound() {
+export function ButtonBackHome({ useHref }) {
+ const { t } = useTranslation();
+
+ return (
+
+ );
+}
+
+export default function PageNotFound({ useHref = false }) {
const { t } = useTranslation();
return (
@@ -12,9 +29,13 @@ export default function PageNotFound() {
title={t("pageNotFound.title")}
subTitle={t("pageNotFound.subTitle")}
extra={
-
-
-
+ useHref ? (
+
+ ) : (
+
+ {}
+
+ )
}
/>
);
diff --git a/src/Pages/Verification/index.js b/src/Pages/Verification/index.js
new file mode 100644
index 0000000..95e239d
--- /dev/null
+++ b/src/Pages/Verification/index.js
@@ -0,0 +1,104 @@
+import { useParams } from "react-router-dom";
+import MyModal from "../../Components/MyModal";
+import { Button, Flex, Result, Spin, notification } from "antd";
+import { useEffect, useState } from "react";
+import MyAppLogo from "../../Components/MyAppLogo";
+import PageNotFound, { ButtonBackHome } from "../PageNotFound";
+import { Constants, myFetch } from "../../utils";
+import { useTranslation } from "react-i18next";
+import { RequestState } from "../../Components/MyRequestStateItem";
+
+export default function Verification() {
+ const { state, emailVerificationId } = useParams();
+ const { t } = useTranslation();
+ const [notificationApi, notificationContextHolder] =
+ notification.useNotification();
+
+ const [isRequesting, setIsRequesting] = useState(RequestState.REQUESTING);
+
+ const content = [
+ {
+ requesting: {
+ title: t("verification.content.0.requesting.title"),
+ },
+ sucess: {
+ title: t("verification.content.0.success.title"),
+ extra: (
+
+ ),
+ },
+ },
+ ];
+
+ const parsedState = isNaN(state) ? 0 : parseInt(state);
+
+ let elementContent;
+
+ if (
+ state === undefined ||
+ emailVerificationId === undefined ||
+ state > content.length - 1
+ ) {
+ elementContent = ;
+ } else if (isRequesting === RequestState.REQUESTING) {
+ elementContent = (
+ }
+ />
+ );
+ } else if (isRequesting === RequestState.SUCCESS) {
+ elementContent = (
+
+ );
+ } else if (isRequesting === RequestState.FAILED) {
+ elementContent = (
+ }
+ />
+ );
+ } else {
+ elementContent = ;
+ }
+
+ useEffect(() => {
+ if (emailVerificationId === undefined || state === undefined) {
+ setIsRequesting(false);
+ return;
+ }
+
+ myFetch({
+ url: `/user/verify/${state}/${emailVerificationId}`,
+ notificationApi: notificationApi,
+ t: t,
+ })
+ .then(() => setIsRequesting(RequestState.SUCCESS))
+ .catch(() => setIsRequesting(RequestState.FAILED));
+ }, []);
+
+ return (
+
+ {notificationContextHolder}
+
+
+
+
+
+ {elementContent}
+
+ );
+}
diff --git a/src/utils.js b/src/utils.js
index 2d101dd..0d764ea 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -7,22 +7,26 @@ import { v4 as uuidv4 } from "uuid";
*/
//const wssProtocol = window.location.protocol === "https:" ? "wss://" : "ws://";
+let dashboardAddress = "";
let apiAddress = "";
// let staticContentAddress = "";
// let wsAddress = "";
if (window.location.hostname === "localhost" && window.location.port === "") {
// for docker container testing on localhost
+ dashboardAddress = "http://localhost/";
apiAddress = "http://localhost/api/v1";
// staticContentAddress = "http://localhost/api/";
// wsAddress = "ws://localhost/ws";
} else if (window.location.hostname === "localhost") {
// programming on localhost
+ dashboardAddress = `http://localhost:${window.location.port}/`;
apiAddress = "http://localhost:50128/api/v1";
// staticContentAddress = "http://localhost:50050/";
// wsAddress = "ws://localhost:50050/ws";
} else {
// production
+ dashboardAddress = `${window.location.protocol}//${window.location.hostname}/`;
apiAddress = `${window.location.protocol}//${window.location.hostname}/api/v1`;
//staticContentAddress = `${window.location.protocol}//${window.location.hostname}/api/`;
// wsAddress = `${wssProtocol}${window.location.hostname}/ws`;
@@ -30,6 +34,7 @@ if (window.location.hostname === "localhost" && window.location.port === "") {
export const Constants = {
TEXT_EMPTY_PLACEHOLDER: "-/-",
+ DASHBOARD_ADDRESS: dashboardAddress,
API_ADDRESS: apiAddress,
//STATIC_CONTENT_ADDRESS: staticContentAddress,
// WS_ADDRESS: wsAddress,
@@ -42,6 +47,7 @@ export const Constants = {
LOGIN: "/login",
SIGN_UP: "/signup",
},
+ VERIFY: "/verify",
OVERVIEW: "/",
STORE: {
// schema: /store/:storeId/:subPage