fetch error message handling
parent
260bebf8dc
commit
a8f6f75d28
|
@ -54,6 +54,20 @@
|
||||||
"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",
|
||||||
"calendarMinEarliestBookingTimeRequired": "Minimaler frühester Buchungszeitpunkt ist erforderlich"
|
"calendarMinEarliestBookingTimeRequired": "Minimaler frühester Buchungszeitpunkt ist erforderlich"
|
||||||
|
},
|
||||||
|
"request": {
|
||||||
|
"inputsInvalid": {
|
||||||
|
"title": "Eingaben ungültig",
|
||||||
|
"description": "Bitte überprüfen Sie Ihre Eingaben."
|
||||||
|
},
|
||||||
|
"failed": {
|
||||||
|
"title": "Ein Fehler ist aufgetreten",
|
||||||
|
"description": "Bitte versuchen Sie es erneut."
|
||||||
|
},
|
||||||
|
"failedInternetProblem": {
|
||||||
|
"title": "Anfrage fehlgeschlagen",
|
||||||
|
"description": "Bitte überprüfen Sie Ihre Internetverbindung und versuchen Sie es erneut."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pageNotFound": {
|
"pageNotFound": {
|
||||||
|
@ -98,7 +112,13 @@
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"login": "Anmelden",
|
"login": "Anmelden",
|
||||||
"signUp": "Registrieren"
|
"signUp": "Registrieren",
|
||||||
|
"request": {
|
||||||
|
"400": {
|
||||||
|
"title": "Anmeldung fehlgeschlagen",
|
||||||
|
"description": "Bitte überprüfen Sie Ihre Eingaben."
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"storeServices": {
|
"storeServices": {
|
||||||
"pageTitle": "Dienstleistungen",
|
"pageTitle": "Dienstleistungen",
|
||||||
|
|
|
@ -54,6 +54,20 @@
|
||||||
"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",
|
||||||
"calendarMinEarliestBookingTimeRequired": "Please enter the min. earliest booking time"
|
"calendarMinEarliestBookingTimeRequired": "Please enter the min. earliest booking time"
|
||||||
|
},
|
||||||
|
"request": {
|
||||||
|
"inputsInvalid": {
|
||||||
|
"title": "Invalid inputs",
|
||||||
|
"description": "Please check your inputs and try again."
|
||||||
|
},
|
||||||
|
"failed": {
|
||||||
|
"title": "An error has occurred",
|
||||||
|
"description": "The request failed. Please try again."
|
||||||
|
},
|
||||||
|
"failedInternetProblem": {
|
||||||
|
"title": "Request failed",
|
||||||
|
"description": "The request failed. Please check your internet connection and try again."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pageNotFound": {
|
"pageNotFound": {
|
||||||
|
@ -98,7 +112,13 @@
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"login": "Login",
|
"login": "Login",
|
||||||
"signUp": "Sign up"
|
"signUp": "Sign up",
|
||||||
|
"request": {
|
||||||
|
"400": {
|
||||||
|
"title": "Login failed",
|
||||||
|
"description": "Please check your inputs and try again."
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"services": {
|
"services": {
|
||||||
"pageTitle": "Services"
|
"pageTitle": "Services"
|
||||||
|
|
|
@ -24,7 +24,10 @@ export default function App() {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!userSession) return;
|
if (!userSession) return;
|
||||||
|
|
||||||
myFetch("/user", "GET")
|
myFetch({
|
||||||
|
url: "/user",
|
||||||
|
method: "GET",
|
||||||
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
setAppUserData(data);
|
setAppUserData(data);
|
||||||
})
|
})
|
||||||
|
|
|
@ -17,9 +17,7 @@ const StoreWebsite = lazy(() => import("../../Pages/Store/Website"));
|
||||||
//const Feedback = lazy(() => import("../../Pages/Feedback"));
|
//const Feedback = lazy(() => import("../../Pages/Feedback"));
|
||||||
const UserProfile = lazy(() => import("../../Pages/UserProfile"));
|
const UserProfile = lazy(() => import("../../Pages/UserProfile"));
|
||||||
|
|
||||||
export default function AppRoutes({ userSession, setUserSession }) {
|
export default function AppRoutes({ setUserSession }) {
|
||||||
//const appContext = useAppContext();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route
|
<Route
|
||||||
|
@ -111,10 +109,7 @@ export default function AppRoutes({ userSession, setUserSession }) {
|
||||||
path={Constants.ROUTE_PATHS.USER_PROFILE}
|
path={Constants.ROUTE_PATHS.USER_PROFILE}
|
||||||
element={
|
element={
|
||||||
<MySupsenseFallback>
|
<MySupsenseFallback>
|
||||||
<UserProfile
|
<UserProfile setUserSession={setUserSession} />
|
||||||
userSession={userSession}
|
|
||||||
setUserSession={setUserSession}
|
|
||||||
/>
|
|
||||||
</MySupsenseFallback>
|
</MySupsenseFallback>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,65 +1,11 @@
|
||||||
import {
|
import { MenuFoldOutlined, MenuUnfoldOutlined } from "@ant-design/icons";
|
||||||
BellOutlined,
|
import { Button } from "antd";
|
||||||
CheckCircleOutlined,
|
|
||||||
CloseCircleOutlined,
|
|
||||||
CloseOutlined,
|
|
||||||
DeleteOutlined,
|
|
||||||
ExclamationCircleOutlined,
|
|
||||||
InboxOutlined,
|
|
||||||
InfoCircleOutlined,
|
|
||||||
MenuFoldOutlined,
|
|
||||||
MenuUnfoldOutlined,
|
|
||||||
QuestionCircleOutlined,
|
|
||||||
} from "@ant-design/icons";
|
|
||||||
import { Badge, Button, Drawer, List, Popconfirm, Typography } from "antd";
|
|
||||||
import { Header } from "antd/es/layout/layout";
|
import { Header } from "antd/es/layout/layout";
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import { useHeaderContext } from "../../Contexts/HeaderContext";
|
|
||||||
import { myFetch } from "../../utils";
|
|
||||||
import { useWebSocketContext } from "../../Contexts/WebSocketContext";
|
|
||||||
import { SentMessagesCommands } from "../../Handlers/WebSocketMessageHandler";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import LiveTimeAgo from "../LiveTimeAgo";
|
|
||||||
import MyPagination from "../MyPagination";
|
|
||||||
|
|
||||||
export default function HeaderMenu({
|
export default function HeaderMenu({
|
||||||
isSideMenuCollapsed,
|
isSideMenuCollapsed,
|
||||||
setIsSideMenuCollapsed,
|
setIsSideMenuCollapsed,
|
||||||
}) {
|
}) {
|
||||||
//const webSocketContext = useWebSocketContext();
|
|
||||||
//const headerContext = useHeaderContext();
|
|
||||||
//const { t } = useTranslation();
|
|
||||||
const [isNotificationDrawerOpen, setIsNotificationDrawerOpen] =
|
|
||||||
useState(false);
|
|
||||||
|
|
||||||
/*
|
|
||||||
const fetchNotifications = (page = 1) => {
|
|
||||||
myFetch(`/notifications?page=${page}`, "GET").then((data) =>
|
|
||||||
headerContext.setNotificationResponse(data)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onPaginationChange = (page) => {
|
|
||||||
headerContext.setPaginationPage(page);
|
|
||||||
headerContext.paginationPageRef.current = page;
|
|
||||||
}; */
|
|
||||||
|
|
||||||
/*
|
|
||||||
useEffect(() => {
|
|
||||||
// fetch will only be called if the drawer is open and there are no notifications
|
|
||||||
// further notifications will be fetched by the websocket
|
|
||||||
if (!isNotificationDrawerOpen || headerContext.notficationResponse !== null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
fetchNotifications(1);
|
|
||||||
}, [isNotificationDrawerOpen]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!isNotificationDrawerOpen) return;
|
|
||||||
|
|
||||||
fetchNotifications(headerContext.paginationPage);
|
|
||||||
}, [headerContext.paginationPage]); */
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Header
|
<Header
|
||||||
style={{
|
style={{
|
||||||
|
@ -85,112 +31,3 @@ export default function HeaderMenu({
|
||||||
</Header>
|
</Header>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
<Button
|
|
||||||
type="text"
|
|
||||||
icon={
|
|
||||||
<Badge count={headerContext.totalNotifications} offset={[2, -2]}>
|
|
||||||
<BellOutlined style={{ fontSize: "16px" }} />
|
|
||||||
</Badge>
|
|
||||||
}
|
|
||||||
onClick={() => setIsNotificationDrawerOpen(true)}
|
|
||||||
style={{ fontSize: "16px", width: 64, height: 64 }}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Drawer
|
|
||||||
title={t("header.notificationDrawer.title")}
|
|
||||||
placement="right"
|
|
||||||
open={isNotificationDrawerOpen}
|
|
||||||
onClose={() => setIsNotificationDrawerOpen(false)}
|
|
||||||
extra={
|
|
||||||
headerContext.totalNotifications > 0 && (
|
|
||||||
<Popconfirm
|
|
||||||
title={t("header.notificationDrawer.deleteAllPopconfirm.title")}
|
|
||||||
okText={t("common.button.confirm")}
|
|
||||||
cancelText={t("common.button.cancel")}
|
|
||||||
onConfirm={() => {
|
|
||||||
webSocketContext.SendSocketMessage(
|
|
||||||
SentMessagesCommands.DeleteAllNotifications,
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
|
|
||||||
setIsNotificationDrawerOpen(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Button type="link" icon={<DeleteOutlined />}>
|
|
||||||
{t("header.notificationDrawer.deleteAllButtonText")}
|
|
||||||
</Button>
|
|
||||||
</Popconfirm>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{isNotificationDrawerOpen && (
|
|
||||||
<>
|
|
||||||
{headerContext.totalNotifications === 0 ||
|
|
||||||
headerContext.notficationResponse === null ? (
|
|
||||||
<div style={{ textAlign: "center" }}>
|
|
||||||
<InboxOutlined style={{ fontSize: 32, marginBottom: 10 }} />
|
|
||||||
<Typography.Title level={5}>
|
|
||||||
{t("header.notificationDrawer.noNotifications")}
|
|
||||||
</Typography.Title>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<List
|
|
||||||
dataSource={headerContext.notficationResponse.Notifications.sort(
|
|
||||||
(a, b) => {
|
|
||||||
return new Date(b.CreatedAt) - new Date(a.CreatedAt);
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
footer={
|
|
||||||
<MyPagination
|
|
||||||
paginationPage={headerContext.paginationPage}
|
|
||||||
setPaginationPage={(page) => onPaginationChange(page)}
|
|
||||||
totalPages={headerContext.notficationResponse.TotalPages}
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
renderItem={(item) => (
|
|
||||||
<List.Item>
|
|
||||||
<List.Item.Meta
|
|
||||||
avatar={<NotificationTypeIcon type={item.Type} />}
|
|
||||||
title={item.Title}
|
|
||||||
description={<LiveTimeAgo startTime={item.CreatedAt} />}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<CloseOutlined
|
|
||||||
onClick={() => {
|
|
||||||
/*webSocketContext.SendSocketMessage(
|
|
||||||
SentMessagesCommands.DeleteOneNotification,
|
|
||||||
{
|
|
||||||
notificationId: item.Id,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</List.Item>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Drawer>
|
|
||||||
*/
|
|
||||||
|
|
||||||
function NotificationTypeIcon({ type }) {
|
|
||||||
switch (type) {
|
|
||||||
case 1:
|
|
||||||
return <CheckCircleOutlined color="#33a834" style={{ fontSize: 16 }} />;
|
|
||||||
case 2:
|
|
||||||
return <InfoCircleOutlined color="#0c69d7" style={{ fontSize: 16 }} />;
|
|
||||||
case 3:
|
|
||||||
return (
|
|
||||||
<ExclamationCircleOutlined color="#dd9433" style={{ fontSize: 16 }} />
|
|
||||||
);
|
|
||||||
case 4:
|
|
||||||
return <CloseCircleOutlined color="#e5444b" style={{ fontSize: 16 }} />;
|
|
||||||
default:
|
|
||||||
return <QuestionCircleOutlined color="#fff" style={{ fontSize: 16 }} />;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -187,7 +187,11 @@ export function MyAvailableCheckFormInput({
|
||||||
|
|
||||||
body[fetchParameter] = value; // like accountName: value
|
body[fetchParameter] = value; // like accountName: value
|
||||||
|
|
||||||
myFetch(fetchUrl, "POST", body)
|
myFetch({
|
||||||
|
url: fetchUrl,
|
||||||
|
method: "POST",
|
||||||
|
body: body,
|
||||||
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {
|
||||||
PlusOutlined,
|
PlusOutlined,
|
||||||
QuestionCircleOutlined,
|
QuestionCircleOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import { Popconfirm, Tooltip } from "antd";
|
import { Popconfirm } from "antd";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
@ -79,14 +79,14 @@ export function MyPlusIcon({ onClick }) {
|
||||||
export function MyIcon({
|
export function MyIcon({
|
||||||
popconfirmDisabled,
|
popconfirmDisabled,
|
||||||
propsPopconfirm,
|
propsPopconfirm,
|
||||||
propsTooltip,
|
// propsTooltip,
|
||||||
onConfirm,
|
onConfirm,
|
||||||
onFetchSuccess,
|
onFetchSuccess,
|
||||||
onCancel,
|
onCancel,
|
||||||
popConfirmTitle,
|
popConfirmTitle,
|
||||||
popConfirmDescription,
|
popConfirmDescription,
|
||||||
popConfirmOkText,
|
popConfirmOkText,
|
||||||
tooltipTitle,
|
//tooltipTitle,
|
||||||
icon,
|
icon,
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
|
@ -3,8 +3,8 @@ import { Button, Form, Modal, Tabs, notification } from "antd";
|
||||||
import {
|
import {
|
||||||
EncodeStringToBase64,
|
EncodeStringToBase64,
|
||||||
myFetch,
|
myFetch,
|
||||||
myFetchContentType,
|
|
||||||
setUserSessionToLocalStorage,
|
setUserSessionToLocalStorage,
|
||||||
|
showInputsInvalidNotification,
|
||||||
} from "../../utils";
|
} from "../../utils";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import {
|
import {
|
||||||
|
@ -19,31 +19,27 @@ export default function Login() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
const [api, contextHolder] = notification.useNotification();
|
const [notificationApi, notificationContextHolder] =
|
||||||
|
notification.useNotification();
|
||||||
|
|
||||||
const [selectedMethod, setSelectedMethod] = useState("1");
|
const [selectedMethod, setSelectedMethod] = useState("1");
|
||||||
const [isRequesting, setIsRequesting] = useState(false);
|
const [isRequesting, setIsRequesting] = useState(false);
|
||||||
|
|
||||||
const showErrorNotification = (errStatus) => {
|
const showErrorNotification = (errStatus) => {
|
||||||
if (errStatus === 401) {
|
if (errStatus === 400) {
|
||||||
api["error"]({
|
notificationApi["error"]({
|
||||||
message: "Account deactivated",
|
message: t("login.request.400.title"),
|
||||||
description: "Please contact an administrator",
|
description: t("login.request.400.description"),
|
||||||
});
|
});
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
api["error"]({
|
|
||||||
message: "Login failed",
|
|
||||||
description: "Please check your accountName and password!",
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{contextHolder}
|
{notificationContextHolder}
|
||||||
<Modal
|
<Modal
|
||||||
open={true}
|
open={true}
|
||||||
|
mask={false}
|
||||||
closable={false}
|
closable={false}
|
||||||
centered
|
centered
|
||||||
keyboard={false}
|
keyboard={false}
|
||||||
|
@ -68,18 +64,16 @@ export default function Login() {
|
||||||
body.username = values.username;
|
body.username = values.username;
|
||||||
}
|
}
|
||||||
|
|
||||||
myFetch(
|
myFetch({
|
||||||
`/user/auth/${selectedMethod === "1" ? "login" : "signup"}`,
|
url: `/user/auth/${
|
||||||
"POST",
|
selectedMethod === "1" ? "login" : "signup"
|
||||||
body,
|
}`,
|
||||||
{},
|
method: "POST",
|
||||||
myFetchContentType.JSON,
|
body: body,
|
||||||
"",
|
notificationApi: notificationApi,
|
||||||
true
|
t: t,
|
||||||
)
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
console.log(data.XAuthorization);
|
|
||||||
|
|
||||||
setUserSessionToLocalStorage(data.XAuthorization);
|
setUserSessionToLocalStorage(data.XAuthorization);
|
||||||
window.location.href = "/";
|
window.location.href = "/";
|
||||||
})
|
})
|
||||||
|
@ -88,9 +82,7 @@ export default function Login() {
|
||||||
setIsRequesting(false);
|
setIsRequesting(false);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((info) => {
|
.catch(() => showInputsInvalidNotification(notificationApi, t));
|
||||||
console.log("Validate Failed:", info);
|
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{selectedMethod === "1" ? t("login.login") : t("login.signUp")}
|
{selectedMethod === "1" ? t("login.login") : t("login.signUp")}
|
||||||
|
@ -119,9 +111,7 @@ export default function Login() {
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
centered
|
centered
|
||||||
onChange={(activeKey) => {
|
onChange={(activeKey) => setSelectedMethod(activeKey)}
|
||||||
setSelectedMethod(activeKey);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Form form={form} layout="vertical" requiredMark={false}>
|
<Form form={form} layout="vertical" requiredMark={false}>
|
||||||
|
|
|
@ -1,20 +1,27 @@
|
||||||
import { Button, Result, Spin } from "antd";
|
import { Button, Result, Spin, notification } from "antd";
|
||||||
import { Link, useParams, useNavigate } from "react-router-dom";
|
import { Link, useParams, useNavigate } from "react-router-dom";
|
||||||
import { Constants, myFetch } from "../../../../utils";
|
import { Constants, myFetch } from "../../../../utils";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import MyCenteredContainer from "../../../../Components/MyContainer";
|
import MyCenteredContainer from "../../../../Components/MyContainer";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { MySupsenseFallback } from "../../../../Components/MySupsenseFallback";
|
|
||||||
|
|
||||||
export default function StoreCalendarAuth() {
|
export default function StoreCalendarAuth() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [notificationApi, notificationContextHolder] =
|
||||||
|
notification.useNotification();
|
||||||
|
|
||||||
const { status } = useParams();
|
const { status } = useParams();
|
||||||
|
|
||||||
const [isRequesting, setIsRequesting] = useState(true);
|
const [isRequesting, setIsRequesting] = useState(true);
|
||||||
const [storeId, setStoreId] = useState("");
|
const [storeId, setStoreId] = useState("");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
myFetch("/calendar/store", "GET")
|
myFetch({
|
||||||
|
url: "/calendar/store",
|
||||||
|
method: "GET",
|
||||||
|
notificationApi: notificationApi,
|
||||||
|
t: t,
|
||||||
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setIsRequesting(false);
|
setIsRequesting(false);
|
||||||
setStoreId(res.storeId);
|
setStoreId(res.storeId);
|
||||||
|
@ -33,6 +40,9 @@ export default function StoreCalendarAuth() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
{notificationContextHolder}
|
||||||
|
|
||||||
<Result
|
<Result
|
||||||
status={status === "finish" ? "success" : "error"}
|
status={status === "finish" ? "success" : "error"}
|
||||||
title={
|
title={
|
||||||
|
@ -59,6 +69,7 @@ export default function StoreCalendarAuth() {
|
||||||
</div>,
|
</div>,
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
Spin,
|
Spin,
|
||||||
Switch,
|
Switch,
|
||||||
Typography,
|
Typography,
|
||||||
|
notification,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import {
|
import {
|
||||||
|
@ -38,6 +39,9 @@ const { useBreakpoint } = Grid;
|
||||||
|
|
||||||
export default function StoreCalendar() {
|
export default function StoreCalendar() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [notificationApi, notificationContextHolder] =
|
||||||
|
notification.useNotification();
|
||||||
|
|
||||||
const { storeId } = useParams();
|
const { storeId } = useParams();
|
||||||
|
|
||||||
const [calendarSettings, setCalendarSettings] = useState({});
|
const [calendarSettings, setCalendarSettings] = useState({});
|
||||||
|
@ -47,7 +51,12 @@ export default function StoreCalendar() {
|
||||||
// delete session cookie
|
// delete session cookie
|
||||||
document.cookie = `session=; path=/; expires=Thu, 01 Jan 1970 00:00:01 GMT;`;
|
document.cookie = `session=; path=/; expires=Thu, 01 Jan 1970 00:00:01 GMT;`;
|
||||||
|
|
||||||
myFetch("/calendar/settings", "GET")
|
myFetch({
|
||||||
|
url: "/calendar/settings",
|
||||||
|
method: "GET",
|
||||||
|
notificationApi: notificationApi,
|
||||||
|
t: t,
|
||||||
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setIsRequesting(false);
|
setIsRequesting(false);
|
||||||
setCalendarSettings(res);
|
setCalendarSettings(res);
|
||||||
|
@ -67,6 +76,8 @@ export default function StoreCalendar() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{notificationContextHolder}
|
||||||
|
|
||||||
{calendarSettings.connected === false ? (
|
{calendarSettings.connected === false ? (
|
||||||
<MyCenteredContainer>
|
<MyCenteredContainer>
|
||||||
<Result
|
<Result
|
||||||
|
@ -135,6 +146,7 @@ function CalendarFrame({ storeId }) {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<iframe
|
<iframe
|
||||||
|
title="calendar"
|
||||||
onLoad={() => setIsLoading(false)}
|
onLoad={() => setIsLoading(false)}
|
||||||
style={{ border: 0, borderRadius: 12 }}
|
style={{ border: 0, borderRadius: 12 }}
|
||||||
width="100%"
|
width="100%"
|
||||||
|
@ -147,6 +159,9 @@ function CalendarFrame({ storeId }) {
|
||||||
|
|
||||||
function CardPersonalCalendarSettings({ settings }) {
|
function CardPersonalCalendarSettings({ settings }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [notificationApi, notificationContextHolder] =
|
||||||
|
notification.useNotification();
|
||||||
|
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [formUnlinkCalendar] = Form.useForm();
|
const [formUnlinkCalendar] = Form.useForm();
|
||||||
const screenBreakpoint = useBreakpoint();
|
const screenBreakpoint = useBreakpoint();
|
||||||
|
@ -189,8 +204,14 @@ function CardPersonalCalendarSettings({ settings }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
delayTimeout.current = setTimeout(() => {
|
delayTimeout.current = setTimeout(() => {
|
||||||
myFetch("/calendar/settings/personal", "POST", {
|
myFetch({
|
||||||
|
url: "/calendar/settings/personal",
|
||||||
|
method: "POST",
|
||||||
|
body: {
|
||||||
calendarUsingPrimaryCalendar: usingPrimaryCalendar,
|
calendarUsingPrimaryCalendar: usingPrimaryCalendar,
|
||||||
|
},
|
||||||
|
notificationApi: notificationApi,
|
||||||
|
t: t,
|
||||||
})
|
})
|
||||||
.then(() => setRequestState(RequestState.SUCCESS))
|
.then(() => setRequestState(RequestState.SUCCESS))
|
||||||
.catch((errStatus) => {
|
.catch((errStatus) => {
|
||||||
|
@ -239,6 +260,8 @@ function CardPersonalCalendarSettings({ settings }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{notificationContextHolder}
|
||||||
|
|
||||||
<Card
|
<Card
|
||||||
title={
|
title={
|
||||||
screenBreakpoint.xl ? (
|
screenBreakpoint.xl ? (
|
||||||
|
@ -290,8 +313,14 @@ function CardPersonalCalendarSettings({ settings }) {
|
||||||
formUnlinkCalendar.validateFields().then((values) => {
|
formUnlinkCalendar.validateFields().then((values) => {
|
||||||
setIsRequesting(true);
|
setIsRequesting(true);
|
||||||
|
|
||||||
myFetch("/calendar/settings/personal/unlink", "POST", {
|
myFetch({
|
||||||
|
url: "/calendar/settings/personal/unlink",
|
||||||
|
method: "POST",
|
||||||
|
body: {
|
||||||
password: EncodeStringToBase64(values.password),
|
password: EncodeStringToBase64(values.password),
|
||||||
|
},
|
||||||
|
notificationApi: notificationApi,
|
||||||
|
t: t,
|
||||||
})
|
})
|
||||||
.then(() => window.location.reload())
|
.then(() => window.location.reload())
|
||||||
.catch((errStatus) => {
|
.catch((errStatus) => {
|
||||||
|
@ -321,6 +350,9 @@ function CardPersonalCalendarSettings({ settings }) {
|
||||||
|
|
||||||
function CardStoreCalendarSettings({ settings }) {
|
function CardStoreCalendarSettings({ settings }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [notificationApi, notificationContextHolder] =
|
||||||
|
notification.useNotification();
|
||||||
|
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
const [requestState, setRequestState] = useState(RequestState.INIT);
|
const [requestState, setRequestState] = useState(RequestState.INIT);
|
||||||
|
@ -369,9 +401,15 @@ function CardStoreCalendarSettings({ settings }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
delayTimeout.current = setTimeout(() => {
|
delayTimeout.current = setTimeout(() => {
|
||||||
myFetch("/calendar/settings/store", "POST", {
|
myFetch({
|
||||||
|
url: "/calendar/settings/store",
|
||||||
|
method: "POST",
|
||||||
|
body: {
|
||||||
calendarMaxFutureBookingDays,
|
calendarMaxFutureBookingDays,
|
||||||
calendarMinEarliestBookingTime,
|
calendarMinEarliestBookingTime,
|
||||||
|
},
|
||||||
|
notificationApi: notificationApi,
|
||||||
|
t: t,
|
||||||
})
|
})
|
||||||
.then(() => setRequestState(RequestState.SUCCESS))
|
.then(() => setRequestState(RequestState.SUCCESS))
|
||||||
.catch((errStatus) => {
|
.catch((errStatus) => {
|
||||||
|
@ -382,6 +420,9 @@ function CardStoreCalendarSettings({ settings }) {
|
||||||
}, [calendarMaxFutureBookingDays, calendarMinEarliestBookingTime]);
|
}, [calendarMaxFutureBookingDays, calendarMinEarliestBookingTime]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
{notificationContextHolder}
|
||||||
|
|
||||||
<Card
|
<Card
|
||||||
title={t("calendar.cardStoreCalendarSettings.title")}
|
title={t("calendar.cardStoreCalendarSettings.title")}
|
||||||
extra={
|
extra={
|
||||||
|
@ -399,5 +440,6 @@ function CardStoreCalendarSettings({ settings }) {
|
||||||
</>
|
</>
|
||||||
</Form>
|
</Form>
|
||||||
</Card>
|
</Card>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
import { PlusOutlined } from "@ant-design/icons";
|
import { PlusOutlined } from "@ant-design/icons";
|
||||||
import { Button, Checkbox, Form, Grid, Popconfirm, Space } from "antd";
|
import {
|
||||||
|
Button,
|
||||||
|
Checkbox,
|
||||||
|
Form,
|
||||||
|
Grid,
|
||||||
|
Popconfirm,
|
||||||
|
Space,
|
||||||
|
notification,
|
||||||
|
} from "antd";
|
||||||
import MyModal, {
|
import MyModal, {
|
||||||
MyModalCloseCreateButtonFooter,
|
MyModalCloseCreateButtonFooter,
|
||||||
MyModalCloseSaveButtonFooter,
|
MyModalCloseSaveButtonFooter,
|
||||||
|
@ -21,6 +29,9 @@ const { useBreakpoint } = Grid;
|
||||||
|
|
||||||
export default function StoreEmployees() {
|
export default function StoreEmployees() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [notificationApi, notificationContextHolder] =
|
||||||
|
notification.useNotification();
|
||||||
|
|
||||||
const screenBreakpoint = useBreakpoint();
|
const screenBreakpoint = useBreakpoint();
|
||||||
const { storeId } = useParams();
|
const { storeId } = useParams();
|
||||||
|
|
||||||
|
@ -85,8 +96,12 @@ export default function StoreEmployees() {
|
||||||
onConfirm={() => {
|
onConfirm={() => {
|
||||||
setIsRequesting(true);
|
setIsRequesting(true);
|
||||||
|
|
||||||
myFetch("/users", "DELETE", {
|
myFetch({
|
||||||
userId: record.key,
|
url: "/users",
|
||||||
|
method: "DELETE",
|
||||||
|
body: { userId: record.key },
|
||||||
|
notificationApi: notificationApi,
|
||||||
|
t: t,
|
||||||
})
|
})
|
||||||
.then(() => fetchEmployees())
|
.then(() => fetchEmployees())
|
||||||
.catch((errStatus) => {
|
.catch((errStatus) => {
|
||||||
|
@ -123,7 +138,12 @@ export default function StoreEmployees() {
|
||||||
const fetchEmployees = () => {
|
const fetchEmployees = () => {
|
||||||
setIsRequesting(true);
|
setIsRequesting(true);
|
||||||
|
|
||||||
myFetch(`/users/${storeId}`, "GET")
|
myFetch({
|
||||||
|
url: `/users/${storeId}`,
|
||||||
|
method: "GET",
|
||||||
|
notificationApi: notification,
|
||||||
|
t: t,
|
||||||
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
setIsRequesting(false);
|
setIsRequesting(false);
|
||||||
setRequestData(data);
|
setRequestData(data);
|
||||||
|
@ -137,6 +157,8 @@ export default function StoreEmployees() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{notificationContextHolder}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
|
@ -271,7 +293,13 @@ function ModalAddEditEmployee({
|
||||||
values.calendarMinEarliestBookingTime;
|
values.calendarMinEarliestBookingTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
myFetch("/users", "POST", body)
|
myFetch({
|
||||||
|
url: "/users",
|
||||||
|
method: "POST",
|
||||||
|
body: body,
|
||||||
|
notificationApi: notification,
|
||||||
|
t: t,
|
||||||
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setIsRequesting(false);
|
setIsRequesting(false);
|
||||||
handleModalClose();
|
handleModalClose();
|
||||||
|
@ -357,7 +385,13 @@ function ModalAddEditEmployee({
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setIsRequesting(true);
|
setIsRequesting(true);
|
||||||
|
|
||||||
myFetch("/users/update", "POST", body)
|
myFetch({
|
||||||
|
url: "/users/update",
|
||||||
|
method: "POST",
|
||||||
|
body: body,
|
||||||
|
notificationApi: notification,
|
||||||
|
t: t,
|
||||||
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setIsRequesting(false);
|
setIsRequesting(false);
|
||||||
handleModalClose();
|
handleModalClose();
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {
|
||||||
Spin,
|
Spin,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Typography,
|
Typography,
|
||||||
|
notification,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
@ -33,6 +34,8 @@ const { useBreakpoint } = Grid;
|
||||||
|
|
||||||
export default function StoreServices() {
|
export default function StoreServices() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [notificationApi, notificationContextHolder] =
|
||||||
|
notification.useNotification();
|
||||||
const screenBreakpoint = useBreakpoint();
|
const screenBreakpoint = useBreakpoint();
|
||||||
const { storeId } = useParams();
|
const { storeId } = useParams();
|
||||||
|
|
||||||
|
@ -58,7 +61,12 @@ export default function StoreServices() {
|
||||||
const fetchServices = () => {
|
const fetchServices = () => {
|
||||||
setIsRequestingServices(true);
|
setIsRequestingServices(true);
|
||||||
|
|
||||||
myFetch(`/store/services/${storeId}`, "GET")
|
myFetch({
|
||||||
|
url: `/store/services/${storeId}`,
|
||||||
|
method: "GET",
|
||||||
|
notificationApi: notificationApi,
|
||||||
|
t: t,
|
||||||
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
setIsRequestingServices(false);
|
setIsRequestingServices(false);
|
||||||
setServicesData(data);
|
setServicesData(data);
|
||||||
|
@ -72,6 +80,8 @@ export default function StoreServices() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{notificationContextHolder}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
|
@ -148,6 +158,8 @@ function Service({
|
||||||
fetchServices,
|
fetchServices,
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [notificationApi, notificationContextHolder] =
|
||||||
|
notification.useNotification();
|
||||||
|
|
||||||
const [isRequestingActivities, setIsRequestingActivities] = useState(false);
|
const [isRequestingActivities, setIsRequestingActivities] = useState(false);
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
@ -159,10 +171,12 @@ function Service({
|
||||||
|
|
||||||
setIsRequestingActivities(true);
|
setIsRequestingActivities(true);
|
||||||
|
|
||||||
myFetch(
|
myFetch({
|
||||||
`/store/services/activities/${storeId}/${service.service_id}`,
|
url: `/store/services/activities/${storeId}/${service.service_id}`,
|
||||||
"GET"
|
method: "GET",
|
||||||
)
|
notificationApi: notificationApi,
|
||||||
|
t: t,
|
||||||
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
setIsRequestingActivities(false);
|
setIsRequestingActivities(false);
|
||||||
setServiceActivities(data.activities);
|
setServiceActivities(data.activities);
|
||||||
|
@ -175,6 +189,9 @@ function Service({
|
||||||
useEffect(() => fetchServiceActivities(), [isOpen]);
|
useEffect(() => fetchServiceActivities(), [isOpen]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
{notificationContextHolder}
|
||||||
|
|
||||||
<Collapse
|
<Collapse
|
||||||
key={service.service_id}
|
key={service.service_id}
|
||||||
onChange={(e) => setIsOpen(e.length !== 0)}
|
onChange={(e) => setIsOpen(e.length !== 0)}
|
||||||
|
@ -231,10 +248,12 @@ function Service({
|
||||||
placement: "left",
|
placement: "left",
|
||||||
}}
|
}}
|
||||||
onConfirm={() => {
|
onConfirm={() => {
|
||||||
return myFetch(
|
return myFetch({
|
||||||
`/store/services/${service.service_id}`,
|
url: `/store/services/${service.service_id}`,
|
||||||
"DELETE"
|
method: "DELETE",
|
||||||
);
|
notificationApi: notificationApi,
|
||||||
|
t: t,
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
onFetchSuccess={fetchServices}
|
onFetchSuccess={fetchServices}
|
||||||
popConfirmTitle={t(
|
popConfirmTitle={t(
|
||||||
|
@ -334,10 +353,12 @@ function Service({
|
||||||
placement: "left",
|
placement: "left",
|
||||||
}}
|
}}
|
||||||
onConfirm={() => {
|
onConfirm={() => {
|
||||||
return myFetch(
|
return myFetch({
|
||||||
`/store/services/activity/${activity.activity_id}`,
|
url: `/store/services/activity/${activity.activity_id}`,
|
||||||
"DELETE"
|
method: "DELETE",
|
||||||
);
|
notificationApi: notificationApi,
|
||||||
|
t: t,
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
onFetchSuccess={fetchServiceActivities}
|
onFetchSuccess={fetchServiceActivities}
|
||||||
popConfirmTitle={t(
|
popConfirmTitle={t(
|
||||||
|
@ -365,7 +386,9 @@ function Service({
|
||||||
<p>{activity.price} €</p>
|
<p>{activity.price} €</p>
|
||||||
|
|
||||||
<Typography.Title level={5}>
|
<Typography.Title level={5}>
|
||||||
{t("storeServices.serviceActivityDurationMinutes")}
|
{t(
|
||||||
|
"storeServices.serviceActivityDurationMinutes"
|
||||||
|
)}
|
||||||
</Typography.Title>
|
</Typography.Title>
|
||||||
|
|
||||||
<Typography.Paragraph>
|
<Typography.Paragraph>
|
||||||
|
@ -374,7 +397,10 @@ function Service({
|
||||||
? t("common.unit.minute")
|
? t("common.unit.minute")
|
||||||
: t("common.unit.minutes")}{" "}
|
: t("common.unit.minutes")}{" "}
|
||||||
<Typography.Text type="secondary">
|
<Typography.Text type="secondary">
|
||||||
{durationToHoursAndMinutes(t, activity.duration)}
|
{durationToHoursAndMinutes(
|
||||||
|
t,
|
||||||
|
activity.duration
|
||||||
|
)}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
</Typography.Paragraph>
|
</Typography.Paragraph>
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -388,6 +414,7 @@ function Service({
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,6 +457,8 @@ function ModalAddEditService({
|
||||||
setAddEditServiceModalOptions,
|
setAddEditServiceModalOptions,
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [notificationApi, notificationContextHolder] =
|
||||||
|
notification.useNotification();
|
||||||
const screenBreakpoint = useBreakpoint();
|
const screenBreakpoint = useBreakpoint();
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
|
@ -456,6 +485,8 @@ function ModalAddEditService({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{notificationContextHolder}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
icon={<PlusOutlined />}
|
icon={<PlusOutlined />}
|
||||||
|
@ -489,9 +520,15 @@ function ModalAddEditService({
|
||||||
.then((values) => {
|
.then((values) => {
|
||||||
setIsRequesting(true);
|
setIsRequesting(true);
|
||||||
|
|
||||||
myFetch("/store/services", "POST", {
|
myFetch({
|
||||||
|
url: "/store/services",
|
||||||
|
method: "POST",
|
||||||
|
body: {
|
||||||
storeId: storeId,
|
storeId: storeId,
|
||||||
name: values.serviceName,
|
name: values.serviceName,
|
||||||
|
},
|
||||||
|
notificationApi: notificationApi,
|
||||||
|
t: t,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setIsRequesting(false);
|
setIsRequesting(false);
|
||||||
|
@ -527,9 +564,16 @@ function ModalAddEditService({
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setIsRequesting(true);
|
setIsRequesting(true);
|
||||||
|
|
||||||
myFetch("/store/services/update", "POST", {
|
myFetch({
|
||||||
serviceId: addEditServiceModalOptions.service.service_id,
|
url: "/store/services/update",
|
||||||
|
method: "POST",
|
||||||
|
body: {
|
||||||
|
serviceId:
|
||||||
|
addEditServiceModalOptions.service.service_id,
|
||||||
name: formServiceName,
|
name: formServiceName,
|
||||||
|
},
|
||||||
|
notificationApi: notificationApi,
|
||||||
|
t: t,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setIsRequesting(false);
|
setIsRequesting(false);
|
||||||
|
@ -564,7 +608,8 @@ function ModalAddEditServiceActivity({
|
||||||
users,
|
users,
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [notificationApi, notificationContextHolder] =
|
||||||
|
notification.useNotification();
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [isRequesting, setIsRequesting] = useState(false);
|
const [isRequesting, setIsRequesting] = useState(false);
|
||||||
const [selectedEmployeesRowKeys, setSelectedEmployeesRowKeys] = useState([]);
|
const [selectedEmployeesRowKeys, setSelectedEmployeesRowKeys] = useState([]);
|
||||||
|
@ -629,6 +674,9 @@ function ModalAddEditServiceActivity({
|
||||||
}, [addEditServiceActivityModalOptions.isOpen]);
|
}, [addEditServiceActivityModalOptions.isOpen]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
{notificationContextHolder}
|
||||||
|
|
||||||
<MyModal
|
<MyModal
|
||||||
title={
|
title={
|
||||||
addEditServiceActivityModalOptions.mode === "add"
|
addEditServiceActivityModalOptions.mode === "add"
|
||||||
|
@ -648,7 +696,10 @@ function ModalAddEditServiceActivity({
|
||||||
.then((values) => {
|
.then((values) => {
|
||||||
setIsRequesting(true);
|
setIsRequesting(true);
|
||||||
|
|
||||||
myFetch("/store/services/activity", "POST", {
|
myFetch({
|
||||||
|
url: "/store/services/activity",
|
||||||
|
method: "POST",
|
||||||
|
body: {
|
||||||
serviceId:
|
serviceId:
|
||||||
addEditServiceActivityModalOptions.service.service_id,
|
addEditServiceActivityModalOptions.service.service_id,
|
||||||
name: values.serviceActivityName,
|
name: values.serviceActivityName,
|
||||||
|
@ -659,6 +710,9 @@ function ModalAddEditServiceActivity({
|
||||||
selectedEmployeesRowKeys.length === users.length
|
selectedEmployeesRowKeys.length === users.length
|
||||||
? []
|
? []
|
||||||
: selectedEmployeesRowKeys,
|
: selectedEmployeesRowKeys,
|
||||||
|
},
|
||||||
|
notificationApi: notificationApi,
|
||||||
|
t: t,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setIsRequesting(false);
|
setIsRequesting(false);
|
||||||
|
@ -759,7 +813,13 @@ function ModalAddEditServiceActivity({
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setIsRequesting(true);
|
setIsRequesting(true);
|
||||||
|
|
||||||
myFetch("/store/services/activity/update", "POST", body)
|
myFetch({
|
||||||
|
url: "/store/services/activity/update",
|
||||||
|
method: "POST",
|
||||||
|
body: body,
|
||||||
|
notificationApi: notificationApi,
|
||||||
|
t: t,
|
||||||
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setIsRequesting(false);
|
setIsRequesting(false);
|
||||||
handleModalClose();
|
handleModalClose();
|
||||||
|
@ -809,6 +869,7 @@ function ModalAddEditServiceActivity({
|
||||||
</Space>
|
</Space>
|
||||||
</Form>
|
</Form>
|
||||||
</MyModal>
|
</MyModal>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { myFetch } from "../../../utils";
|
import { myFetch } from "../../../utils";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { Card, Form } from "antd";
|
import { Card, Form, notification } from "antd";
|
||||||
import { MyFormInput } from "../../../Components/MyFormInputs";
|
import { MyFormInput } from "../../../Components/MyFormInputs";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import {
|
import {
|
||||||
|
@ -11,6 +11,8 @@ import {
|
||||||
|
|
||||||
export default function StoreSettings() {
|
export default function StoreSettings() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [notificationApi, notificationContextHolder] =
|
||||||
|
notification.useNotification();
|
||||||
|
|
||||||
const { storeId } = useParams();
|
const { storeId } = useParams();
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
@ -26,7 +28,12 @@ export default function StoreSettings() {
|
||||||
const address = Form.useWatch("address", form);
|
const address = Form.useWatch("address", form);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
myFetch(`/store/${storeId}`, "GET")
|
myFetch({
|
||||||
|
url: `/store/${storeId}`,
|
||||||
|
method: "GET",
|
||||||
|
notificationApi: notificationApi,
|
||||||
|
t: t,
|
||||||
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
setStoreData(data.store);
|
setStoreData(data.store);
|
||||||
|
|
||||||
|
@ -65,11 +72,17 @@ export default function StoreSettings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
delayTimeout.current = setTimeout(() => {
|
delayTimeout.current = setTimeout(() => {
|
||||||
myFetch(`/store/${storeId}`, "POST", {
|
myFetch({
|
||||||
|
url: `/store/${storeId}`,
|
||||||
|
method: "POST",
|
||||||
|
body: {
|
||||||
name: companyName,
|
name: companyName,
|
||||||
phoneNumber,
|
phoneNumber,
|
||||||
email,
|
email,
|
||||||
address,
|
address,
|
||||||
|
},
|
||||||
|
notificationApi: notificationApi,
|
||||||
|
t: t,
|
||||||
})
|
})
|
||||||
.then(() => setRequestState(RequestState.SUCCESS))
|
.then(() => setRequestState(RequestState.SUCCESS))
|
||||||
.catch((errStatus) => {
|
.catch((errStatus) => {
|
||||||
|
@ -81,6 +94,8 @@ export default function StoreSettings() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{notificationContextHolder}
|
||||||
|
|
||||||
<Card
|
<Card
|
||||||
title={t("storeSettings.pageTitle")}
|
title={t("storeSettings.pageTitle")}
|
||||||
loading={isRequesting}
|
loading={isRequesting}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { lazy, useEffect, useState } from "react";
|
||||||
import { isDevelopmentEnv, myFetch } from "../../../utils";
|
import { isDevelopmentEnv, myFetch } from "../../../utils";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import MyCenteredContainer from "../../../Components/MyContainer";
|
import MyCenteredContainer from "../../../Components/MyContainer";
|
||||||
import { Button, Card, Result, Spin, Tabs } from "antd";
|
import { Button, Card, Result, Spin, Tabs, notification } from "antd";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { MySupsenseFallback } from "../../../Components/MySupsenseFallback";
|
import { MySupsenseFallback } from "../../../Components/MySupsenseFallback";
|
||||||
import PageInDevelopment from "../../PageInDevelopment";
|
import PageInDevelopment from "../../PageInDevelopment";
|
||||||
|
@ -20,6 +20,8 @@ function SuspenseFallback({ children }) {
|
||||||
export default function Website() {
|
export default function Website() {
|
||||||
const { storeId } = useParams();
|
const { storeId } = useParams();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [notificationApi, notificationContextHolder] =
|
||||||
|
notification.useNotification();
|
||||||
|
|
||||||
const [isRequesting, setIsRequesting] = useState(true);
|
const [isRequesting, setIsRequesting] = useState(true);
|
||||||
const [website, setWebsite] = useState({});
|
const [website, setWebsite] = useState({});
|
||||||
|
@ -48,10 +50,13 @@ export default function Website() {
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
myFetch(`/website/${storeId}`, "GET")
|
myFetch({
|
||||||
.then((res) => {
|
url: `/website/${storeId}`,
|
||||||
setIsRequesting(false);
|
method: "GET",
|
||||||
|
notificationApi: notificationApi,
|
||||||
|
t: t,
|
||||||
})
|
})
|
||||||
|
.then(() => setIsRequesting(false))
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
setIsRequesting(false);
|
setIsRequesting(false);
|
||||||
|
|
||||||
|
@ -76,7 +81,9 @@ export default function Website() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
|
{notificationContextHolder}
|
||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
<Tabs
|
<Tabs
|
||||||
type="card"
|
type="card"
|
||||||
|
@ -86,12 +93,15 @@ export default function Website() {
|
||||||
onChange={(key) => setActiveTab(key)}
|
onChange={(key) => setActiveTab(key)}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function NoWebsiteCreateOne({ setWebsite }) {
|
function NoWebsiteCreateOne({ setWebsite }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [notificationApi, notificationContextHolder] =
|
||||||
|
notification.useNotification();
|
||||||
|
|
||||||
const { storeId } = useParams();
|
const { storeId } = useParams();
|
||||||
|
|
||||||
const [isRequesting, setIsRequesting] = useState(false);
|
const [isRequesting, setIsRequesting] = useState(false);
|
||||||
|
@ -99,8 +109,14 @@ function NoWebsiteCreateOne({ setWebsite }) {
|
||||||
const handleCreateWebsite = () => {
|
const handleCreateWebsite = () => {
|
||||||
setIsRequesting(true);
|
setIsRequesting(true);
|
||||||
|
|
||||||
myFetch("/website", "POST", {
|
myFetch({
|
||||||
|
url: "/website",
|
||||||
|
method: "POST",
|
||||||
|
body: {
|
||||||
storeId,
|
storeId,
|
||||||
|
},
|
||||||
|
notificationApi: notificationApi,
|
||||||
|
t: t,
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
console.log(res);
|
console.log(res);
|
||||||
|
@ -116,6 +132,8 @@ function NoWebsiteCreateOne({ setWebsite }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MyCenteredContainer>
|
<MyCenteredContainer>
|
||||||
|
{notificationContextHolder}
|
||||||
|
|
||||||
<Result
|
<Result
|
||||||
status="404"
|
status="404"
|
||||||
title={t("storeWebsite.noWebsite.title")}
|
title={t("storeWebsite.noWebsite.title")}
|
||||||
|
|
|
@ -1,28 +1,39 @@
|
||||||
import { Button, Card, Select, Typography } from "antd";
|
import { Button, Card, Select, Typography, notification } from "antd";
|
||||||
import { Constants } from "../../utils";
|
import { myFetch } from "../../utils";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
export default function UserProfile({ userSession, setUserSession }) {
|
export default function UserProfile({ setUserSession }) {
|
||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
|
const [notificationApi, notificationContextHolder] =
|
||||||
|
notification.useNotification();
|
||||||
|
|
||||||
|
const [isRequestingLogout, setIsRequestingLogout] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{notificationContextHolder}
|
||||||
|
|
||||||
<Card
|
<Card
|
||||||
title={t("userProfile.title")}
|
title={t("userProfile.title")}
|
||||||
extra={
|
extra={
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
|
loading={isRequestingLogout}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
setIsRequestingLogout(true);
|
||||||
|
|
||||||
|
myFetch({
|
||||||
|
url: "/user/auth/logout",
|
||||||
|
method: "DELETE",
|
||||||
|
notificationApi: notificationApi,
|
||||||
|
t: t,
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
setUserSession();
|
setUserSession();
|
||||||
window.location.href = "/";
|
window.location.href = "/";
|
||||||
|
})
|
||||||
fetch(`${Constants.API_ADDRESS}/user/auth/logout`, {
|
.catch(() => setIsRequestingLogout(false));
|
||||||
method: "DELETE",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-Authorization": userSession,
|
|
||||||
},
|
|
||||||
}).catch(console.error);
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t("common.button.logout")}
|
{t("common.button.logout")}
|
||||||
|
|
|
@ -6,6 +6,7 @@ body {
|
||||||
|
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
background-color: #f5f5f5;
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
|
|
1149
src/utils.js
1149
src/utils.js
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue