master
alex 2024-01-13 19:43:02 +01:00
parent a3c979c5b7
commit ec9516e5e4
10 changed files with 586 additions and 264 deletions

View File

@ -7,7 +7,13 @@
"delete": "Löschen",
"confirm": "Bestätigen",
"create": "Erstellen",
"edit": "Bearbeiten"
"edit": "Bearbeiten",
"logout": "Abmelden"
},
"tooltip": {
"edit": "Bearbeiten",
"delete": "Löschen",
"add": "Hinzufügen"
},
"action": "Aktion",
"contactAdmin": "Bitte kontaktieren Sie einen Administrator",
@ -86,6 +92,7 @@
"serviceActivityDurationMinutes": "Dauer der Tätigkeit (Minuten)",
"serviceActivityDurationMinutesPlaceholder": "Geben Sie die Dauer der Tätigkeit in Minuten ein",
"serviceActivityDurationMinutesUnit": "Minuten",
"serviceActivityResponsible": "Verantwortliche Mitarbeiter",
"inputRules": {
"serviceNameRequired": "Name der Dienstleistung ist erforderlich",
"serviceNameMinLength": "Name der Dienstleistung muss mindestens {{minLength}} Zeichen lang sein",
@ -108,6 +115,17 @@
},
"modalEditServiceActivity": {
"title": "Tätigkeit bearbeiten"
},
"popConfirmDeleteService": {
"title": "Dienstleistung löschen",
"description": "Sind Sie sicher, dass Sie diese Dienstleistung löschen möchten?"
},
"popConfirmDeleteServiceActivity": {
"title": "Tätigkeit löschen",
"description": "Sind Sie sicher, dass Sie diese Tätigkeit löschen möchten?"
}
},
"calendar": {
"pageTitle": "Kalender"
}
}

View File

@ -7,7 +7,13 @@
"delete": "Delete",
"confirm": "Confirm",
"create": "Create",
"edit": "Edit"
"edit": "Edit",
"logout": "Logout"
},
"tooltip": {
"edit": "Edit",
"delete": "Delete",
"add": "Add"
},
"action": "Action",
"contactAdmin": "Please contact an administrator",
@ -89,6 +95,7 @@
"serviceActivityDurationMinutes": "Duration of activity (minutes)",
"serviceActivityDurationMinutesPlaceholder": "Enter the duration of the activity in minutes",
"serviceActivityDurationMinutesUnit": "Minutes",
"serviceActivityResponsible": "Responsible employees",
"inputRules": {
"serviceNameRequired": "Service name is required",
"serviceNameMinLength": "Service name must be at least {{minLength}} characters long",
@ -111,6 +118,17 @@
},
"modalEditServiceActivity": {
"title": "Edit activity"
},
"popConfirmDeleteService": {
"title": "Delete service",
"description": "Are you sure you want to delete this service?"
},
"popConfirmDeleteServiceActivity": {
"title": "Delete activity",
"description": "Are you sure you want to delete this activity?"
}
},
"calendar": {
"pageTitle": "Calendar"
}
}

View File

@ -0,0 +1,8 @@
import { Empty } from "antd";
import { useTranslation } from "react-i18next";
export function MyEmpty({ children }) {
const { t } = useTranslation();
return <Empty description={t("common.noDataFound")}>{children}</Empty>;
}

View File

@ -1,12 +1,166 @@
import {
CopyOutlined,
EyeInvisibleOutlined,
EyeOutlined,
ReloadOutlined,
DeleteOutlined,
EditOutlined,
PlusOutlined,
QuestionCircleOutlined,
} from "@ant-design/icons";
import { Tooltip } from "antd";
import { Popconfirm, Tooltip } from "antd";
import { useState } from "react";
import { useTranslation } from "react-i18next";
export function MyDeleteIcon({
propsPopconfirm,
propsTooltip,
onConfirm,
onFetchSuccess,
popConfirmTitle,
popConfirmDescription,
onClick,
}) {
const { t } = useTranslation();
const [open, setOpen] = useState(false);
return (
<MyIcon
propsPopconfirm={{
...propsPopconfirm,
icon: <QuestionCircleOutlined style={{ color: "red" }} />,
open: open,
}}
propsTooltip={propsTooltip}
onConfirm={onConfirm}
onFetchSuccess={() => {
setOpen(false);
onFetchSuccess();
}}
onCancel={() => setOpen(false)}
popConfirmTitle={popConfirmTitle}
popConfirmDescription={popConfirmDescription}
popConfirmOkText={t("common.button.delete")}
tooltipTitle={t("common.tooltip.delete")}
icon={
<DeleteOutlined
onClick={(e) => {
setOpen(true);
if (onClick) onClick(e);
}}
/>
}
/>
);
}
export function MyEditIcon({ onClick }) {
const { t } = useTranslation();
return (
<MyIcon
popconfirmDisabled
tooltipTitle={t("common.tooltip.edit")}
icon={<EditOutlined onClick={onClick} />}
/>
);
}
export function MyPlusIcon({ onClick }) {
const { t } = useTranslation();
return (
<MyIcon
popconfirmDisabled
tooltipTitle={t("common.tooltip.add")}
icon={<PlusOutlined onClick={onClick} />}
/>
);
}
export function MyIcon({
popconfirmDisabled,
propsPopconfirm,
propsTooltip,
onConfirm,
onFetchSuccess,
onCancel,
popConfirmTitle,
popConfirmDescription,
popConfirmOkText,
tooltipTitle,
icon,
}) {
const { t } = useTranslation();
const [isRequesting, setIsRequesting] = useState(false);
const content = (
<Tooltip {...propsTooltip} title={tooltipTitle}>
{icon}
</Tooltip>
);
if (popconfirmDisabled) {
return content;
}
return (
<Popconfirm
{...propsPopconfirm}
title={popConfirmTitle}
description={popConfirmDescription}
okText={popConfirmOkText}
cancelText={t("common.button.cancel")}
okButtonProps={{ loading: isRequesting }}
onCancel={() => {
if (onCancel) onCancel();
}}
onConfirm={() => {
setIsRequesting(true);
onConfirm()
.then(() => {
setIsRequesting(false);
onFetchSuccess();
})
.catch(() => {
setIsRequesting(false);
});
}}
>
{content}
</Popconfirm>
);
}
/*
<Popconfirm
title={t(
"employees.popConfirmDeleteEmployee.title"
)}
description={t(
"employees.popConfirmDeleteEmployee.description"
)}
okText={t("common.button.delete")}
onConfirm={() => {
setIsRequesting(true);
myFetch("/users", "DELETE", {
userId: record.key,
})
.then(() => fetchEmployees())
.catch((errStatus) => {
console.log(errStatus);
setIsRequesting(false);
});
}}
>
<DeleteOutlined />
</Popconfirm>
*/
/*
export function MyCopyIcon({ text, notificationApi }) {
const { t } = useTranslation();
@ -48,3 +202,4 @@ export function MyReloadIcon({ onClick }) {
</Tooltip>
);
}
*/

View File

@ -1,26 +1,13 @@
import { Table } from "antd";
import { useTranslation } from "react-i18next";
import { MyEmpty } from "../MyEmpty";
export default function MyTable({ props }) {
const { t } = useTranslation();
return (
<Table
{...props}
scroll={{ x: "max-content" }}
locale={{
emptyText: (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: 110,
}}
>
{t("common.noDataFound")}
</div>
),
emptyText: <MyEmpty />,
}}
/>
);

View File

@ -46,7 +46,55 @@ export default function Login() {
closable={false}
centered
keyboard={false}
footer={null}
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;
}
myFetch(
`/user/auth/${selectedMethod === "1" ? "login" : "signup"}`,
"POST",
body,
{},
myFetchContentType.JSON,
"",
true
)
.then((data) => {
console.log(data.XAuthorization);
setUserSessionToLocalStorage(data.XAuthorization);
window.location.href = "/";
})
.catch((errStatus) => {
showErrorNotification(errStatus);
setIsRequesting(false);
});
})
.catch((info) => {
console.log("Validate Failed:", info);
});
}}
>
{selectedMethod === "1" ? t("login.login") : t("login.signUp")}
</Button>
}
>
<Tabs
defaultActiveKey="1"
@ -75,58 +123,6 @@ export default function Login() {
/>
<MyPasswordFormInput />
<div style={{ display: "flex", justifyContent: "flex-end" }}>
<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;
}
myFetch(
`/user/auth/${
selectedMethod === "1" ? "login" : "signup"
}`,
"POST",
body,
{},
myFetchContentType.JSON,
"",
true
)
.then((data) => {
console.log(data.XAuthorization);
setUserSessionToLocalStorage(data.XAuthorization);
window.location.href = "/";
})
.catch((errStatus) => {
showErrorNotification(errStatus);
setIsRequesting(false);
});
})
.catch((info) => {
console.log("Validate Failed:", info);
});
}}
>
{selectedMethod === "1" ? t("login.login") : t("login.signUp")}
</Button>
</div>
</Form>
</Modal>
</>

View File

@ -1,7 +1,11 @@
import { useTranslation } from "react-i18next";
export default function StoreCalendar() {
const { t } = useTranslation();
return (
<>
<h1>Calendar</h1>
<h1>{t("calendar.pageTitle")}</h1>
</>
);
}

View File

@ -1,21 +1,16 @@
import {
ArrowDownOutlined,
ArrowUpOutlined,
DeleteOutlined,
EditOutlined,
PlusOutlined,
} from "@ant-design/icons";
import { PlusOutlined } from "@ant-design/icons";
import {
Avatar,
Button,
Card,
Collapse,
Empty,
Form,
Grid,
Skeleton,
Space,
Spin,
Tooltip,
Typography,
} from "antd";
import { useTranslation } from "react-i18next";
import { useEffect, useState } from "react";
@ -26,6 +21,13 @@ import MyModal, {
MyModalCloseSaveButtonFooter,
} from "../../../Components/MyModal";
import { MyFormInput } from "../../../Components/MyFormInputs";
import MyTable from "../../../Components/MyTable";
import {
MyDeleteIcon,
MyEditIcon,
MyPlusIcon,
} from "../../../Components/MyIcon";
import { MyEmpty } from "../../../Components/MyEmpty";
const { useBreakpoint } = Grid;
@ -89,11 +91,21 @@ export default function StoreServices() {
<Space direction="vertical" style={{ width: "100%" }}>
{isRequestingServices ? (
<>
<Skeleton.Input block active size="large" />
<Skeleton.Input block active size="large" />
<Skeleton.Input block active size="large" />
{/* <Skeleton.Input block active size="large" />
<Skeleton.Input block active size="large" />
<Skeleton.Input block active size="large" /> */}
<div
style={{
display: "flex",
justifyContent: "center",
paddingTop: 70,
}}
>
<Spin />
</div>
</>
) : (
) : servicesData.services.length > 0 ? (
<>
{servicesData.services.map((service) => (
<Service
@ -105,9 +117,12 @@ export default function StoreServices() {
setAddEditServiceActivityModalOptions
}
setAddEditServiceModalOptions={setAddEditServiceModalOptions}
fetchServices={fetchServices}
/>
))}
</>
) : (
<MyEmpty />
)}
</Space>
@ -117,6 +132,7 @@ export default function StoreServices() {
setAddEditServiceActivityModalOptions={
setAddEditServiceActivityModalOptions
}
users={servicesData.users}
/>
</>
);
@ -128,7 +144,10 @@ function Service({
storeId,
setAddEditServiceActivityModalOptions,
setAddEditServiceModalOptions,
fetchServices,
}) {
const { t } = useTranslation();
const [isRequestingActivities, setIsRequestingActivities] = useState(false);
const [isOpen, setIsOpen] = useState(false);
@ -172,15 +191,17 @@ function Service({
<span>{service.name}</span>
<Space>
<ArrowUpOutlined
{/*
<ArrowUpOutlined
disabled
onClick={(e) => e.stopPropagation()}
/>
<ArrowDownOutlined
disabled
onClick={(e) => e.stopPropagation()}
/>
<PlusOutlined
/>
*/}
<MyPlusIcon
onClick={(e) => {
e.stopPropagation();
@ -191,7 +212,8 @@ function Service({
});
}}
/>
<EditOutlined
<MyEditIcon
onClick={(e) => {
e.stopPropagation();
@ -202,7 +224,25 @@ function Service({
});
}}
/>
<DeleteOutlined onClick={(e) => e.stopPropagation()} />
<MyDeleteIcon
onClick={(e) => e.stopPropagation()}
propsPopconfirm={{
placement: "left",
}}
onConfirm={() => {
return myFetch(
`/store/services/${service.service_id}`,
"DELETE"
);
}}
onFetchSuccess={fetchServices}
popConfirmTitle={t(
"storeServices.popConfirmDeleteService.title"
)}
popConfirmDescription={t(
"storeServices.popConfirmDeleteService.description"
)}
/>
</Space>
</div>
),
@ -223,50 +263,98 @@ function Service({
) : (
<>
{serviceActivities.length === 0 ? (
<Empty />
<MyEmpty />
) : (
serviceActivities.map((activity) => (
<Card
key={activity.activity_id}
title={activity.name}
extra={
<Space>
<Avatar.Group maxCount={1} size="small">
{users.map((user) => (
<Tooltip
key={user.user_id}
title={user.username}
>
<Avatar
size="small"
style={{ backgroundColor: "#87d068" }}
>
{user.username.charAt(0)}
</Avatar>
</Tooltip>
))}
</Avatar.Group>
serviceActivities.map((activity) => {
let userList = [];
<ArrowUpOutlined disabled />
<ArrowDownOutlined disabled />
<EditOutlined
onClick={() => {
setAddEditServiceActivityModalOptions({
mode: "edit",
isOpen: true,
activity: activity,
});
}}
/>
<DeleteOutlined />
</Space>
if (activity.StoreServiceActivityUsers.length > 0) {
// StoreServiceActivityUsers is only an array of user_ids
// we need to get the user object from the users array
for (let i = 0; i < users.length; i++) {
for (
let j = 0;
j < activity.StoreServiceActivityUsers.length;
j++
) {
if (
users[i].user_id ===
activity.StoreServiceActivityUsers[j].user_id
) {
userList.push(users[i]);
}
}
}
>
<p>{activity.description}</p>
<p>Preis: {activity.price} </p>
<p>Dauer: {activity.duration} Minuten</p>
</Card>
))
} else {
// if there are no users assigned to this activity, we just use the whole users array
userList = users;
}
return (
<Card
key={activity.activity_id}
title={activity.name}
extra={
<Space>
<Avatar.Group maxCount={2} size="small">
{userList.map((user) => (
<Tooltip
key={user.user_id}
title={user.username}
>
<Avatar
size="small"
style={{ backgroundColor: "#87d068" }}
>
{user.username.charAt(0)}
</Avatar>
</Tooltip>
))}
</Avatar.Group>
{/*
<ArrowUpOutlined disabled />
<ArrowDownOutlined disabled />
*/}
<MyEditIcon
onClick={() => {
setAddEditServiceActivityModalOptions({
mode: "edit",
isOpen: true,
activity: activity,
});
}}
/>
<MyDeleteIcon
propsPopconfirm={{
placement: "left",
}}
onConfirm={() => {
return myFetch(
`/store/services/activity/${activity.activity_id}`,
"DELETE"
);
}}
onFetchSuccess={fetchServiceActivities}
popConfirmTitle={t(
"storeServices.popConfirmDeleteServiceActivity.title"
)}
popConfirmDescription={t(
"storeServices.popConfirmDeleteServiceActivity.description"
)}
/>
</Space>
}
>
<p>{activity.description}</p>
<p>Preis: {activity.price} </p>
<p>Dauer: {activity.duration} Minuten</p>
</Card>
);
})
)}
</>
)}
@ -413,26 +501,17 @@ function ModalAddEditService({
);
}
let defaultModalAddServiceFormValidOptions = {
serviceActivityName: false,
serviceActivityDescription: false,
serviceActivityPrice: false,
serviceActivityDurationHours: false,
serviceActivityDurationMinutes: false,
};
function ModalAddEditServiceActivity({
fetchServices,
addEditServiceActivityModalOptions,
setAddEditServiceActivityModalOptions,
users,
}) {
const { t } = useTranslation();
const [isFormValid, setIsFormValid] = useState(
defaultModalAddServiceFormValidOptions
);
const [form] = Form.useForm();
const [isRequesting, setIsRequesting] = useState(false);
const [selectedEmployeesRowKeys, setSelectedEmployeesRowKeys] = useState([]);
const handleModalClose = () => {
setAddEditServiceActivityModalOptions({
@ -443,21 +522,28 @@ function ModalAddEditServiceActivity({
form.resetFields();
};
const getTableColumns = () => {
return [
{
title: t("common.username"),
dataIndex: "username",
key: "username",
},
];
};
const getTableItems = () => {
return users.map((user) => {
return {
key: user.user_id,
username: user.username,
};
});
};
useEffect(() => {
if (!addEditServiceActivityModalOptions.isOpen) return;
setIsFormValid(
addEditServiceActivityModalOptions.mode === "add"
? defaultModalAddServiceFormValidOptions
: {
serviceActivityName: true,
serviceActivityDescription: true,
serviceActivityPrice: true,
serviceActivityDurationHours: true,
serviceActivityDurationMinutes: true,
}
);
if (addEditServiceActivityModalOptions.mode === "edit") {
form.setFieldsValue({
serviceActivityName: addEditServiceActivityModalOptions.activity.name,
@ -470,6 +556,21 @@ function ModalAddEditServiceActivity({
serviceActivityDurationMinutes:
addEditServiceActivityModalOptions.activity.duration % 60,
});
setSelectedEmployeesRowKeys(
addEditServiceActivityModalOptions.activity.StoreServiceActivityUsers
.length === 0
? users.map((user) => user.user_id)
: addEditServiceActivityModalOptions.activity.StoreServiceActivityUsers.map(
(user) => user.user_id
)
);
} else {
form.setFieldsValue({
serviceActivityDurationHours: 0,
});
setSelectedEmployeesRowKeys(users.map((user) => user.user_id));
}
}, [addEditServiceActivityModalOptions.isOpen]);
@ -486,87 +587,146 @@ function ModalAddEditServiceActivity({
addEditServiceActivityModalOptions.mode === "add" ? (
<MyModalCloseCreateButtonFooter
onCancel={handleModalClose}
isCreateButtonDisabled={
!isFormValid.serviceActivityName ||
!isFormValid.serviceActivityDescription ||
!isFormValid.serviceActivityPrice ||
!isFormValid.serviceActivityDurationHours ||
!isFormValid.serviceActivityDurationMinutes
}
isCreateButtonLoading={isRequesting}
onCreate={() => {
setIsRequesting(true);
form
.validateFields()
.then((values) => {
setIsRequesting(true);
myFetch("/store/services/activity", "POST", {
serviceId:
addEditServiceActivityModalOptions.service.service_id,
name: form.getFieldValue("serviceActivityName"),
description: form.getFieldValue("serviceActivityDescription"),
price: form.getFieldValue("serviceActivityPrice"),
duration:
form.getFieldValue("serviceActivityDurationHours") * 60 +
form.getFieldValue("serviceActivityDurationMinutes"),
})
.then(() => {
setIsRequesting(false);
handleModalClose();
myFetch("/store/services/activity", "POST", {
serviceId:
addEditServiceActivityModalOptions.service.service_id,
name: values.serviceActivityName,
description: values.serviceActivityDescription,
price: values.serviceActivityPrice,
duration:
values.serviceActivityDurationHours * 60 +
values.serviceActivityDurationMinutes,
userIds:
selectedEmployeesRowKeys.length === users.length
? []
: selectedEmployeesRowKeys,
})
.then(() => {
setIsRequesting(false);
handleModalClose();
fetchServices();
fetchServices();
})
.catch((errStatus) => {
console.log(errStatus);
});
})
.catch((errStatus) => {
console.log(errStatus);
.catch((info) => {
console.log("Validate Failed:", info);
});
}}
/>
) : (
<MyModalCloseSaveButtonFooter
onCancel={handleModalClose}
isSaveButtonDisabled={
!isFormValid.serviceActivityName ||
!isFormValid.serviceActivityDescription ||
!isFormValid.serviceActivityPrice ||
!isFormValid.serviceActivityDurationHours ||
!isFormValid.serviceActivityDurationMinutes
}
isSaveButtonLoading={isRequesting}
onSave={() => {
const formServiceActivityName = form.getFieldValue(
"serviceActivityName"
);
const formServiceActivityDescription = form.getFieldValue(
"serviceActivityDescription"
);
const formServiceActivityPrice = form.getFieldValue(
"serviceActivityPrice"
);
const formServiceActivityDurationHours = form.getFieldValue(
"serviceActivityDurationHours"
);
const formServiceActivityDurationMinutes = form.getFieldValue(
"serviceActivityDurationMinutes"
);
// if the service name didn't change, don't send a request
if (
addEditServiceActivityModalOptions.activity.name ===
form.getFieldValue("serviceActivityName") &&
formServiceActivityName &&
addEditServiceActivityModalOptions.activity.description ===
form.getFieldValue("serviceActivityDescription") &&
formServiceActivityDescription &&
addEditServiceActivityModalOptions.activity.price ===
form.getFieldValue("serviceActivityPrice") &&
formServiceActivityPrice &&
addEditServiceActivityModalOptions.activity.duration ===
form.getFieldValue("serviceActivityDurationHours") * 60 +
form.getFieldValue("serviceActivityDurationMinutes")
formServiceActivityDurationHours * 60 +
formServiceActivityDurationMinutes &&
(selectedEmployeesRowKeys.length === users.length ||
addEditServiceActivityModalOptions.activity
.StoreServiceActivityUsers.length ===
selectedEmployeesRowKeys.length)
) {
handleModalClose();
console.log("same");
return;
}
setIsRequesting(true);
myFetch("/store/services/activity/update", "POST", {
let validateFields = [];
let body = {
activityId:
addEditServiceActivityModalOptions.activity.activity_id,
name: form.getFieldValue("serviceActivityName"),
description: form.getFieldValue("serviceActivityDescription"),
price: form.getFieldValue("serviceActivityPrice"),
duration:
form.getFieldValue("serviceActivityDurationHours") * 60 +
form.getFieldValue("serviceActivityDurationMinutes"),
})
.then(() => {
setIsRequesting(false);
handleModalClose();
};
fetchServices();
if (
formServiceActivityName !==
addEditServiceActivityModalOptions.activity.name
) {
validateFields.push("serviceActivityName");
body.name = formServiceActivityName;
}
if (
formServiceActivityDescription !==
addEditServiceActivityModalOptions.activity.description
) {
validateFields.push("serviceActivityDescription");
body.description = formServiceActivityDescription;
}
if (
formServiceActivityPrice !==
addEditServiceActivityModalOptions.activity.price
) {
validateFields.push("serviceActivityPrice");
body.price = formServiceActivityPrice;
}
let formDuration =
formServiceActivityDurationHours * 60 +
formServiceActivityDurationMinutes;
if (
formDuration !==
addEditServiceActivityModalOptions.activity.duration
) {
validateFields.push("serviceActivityDurationHours");
validateFields.push("serviceActivityDurationMinutes");
body.duration = formDuration;
}
body.userIds = selectedEmployeesRowKeys;
form
.validateFields()
.then(() => {
setIsRequesting(true);
myFetch("/store/services/activity/update", "POST", body)
.then(() => {
setIsRequesting(false);
handleModalClose();
fetchServices();
})
.catch((errStatus) => {
console.log(errStatus);
});
})
.catch((errStatus) => {
console.log(errStatus);
.catch((info) => {
console.log("Validate Failed:", info);
});
}}
/>
@ -574,55 +734,36 @@ function ModalAddEditServiceActivity({
}
>
<Form form={form} layout="vertical" requiredMark={false}>
<ServiceActivityNameFormInput
formItemName="serviceActivityName"
setIsInputValid={(isValid) =>
setIsFormValid({
...isFormValid,
serviceActivityName: isValid,
})
}
/>
<ServiceActivityNameFormInput formItemName="serviceActivityName" />
<ServiceActivityDescriptionFormInput
formItemName="serviceActivityDescription"
setIsInputValid={(isValid) =>
setIsFormValid({
...isFormValid,
serviceActivityDescription: isValid,
})
}
/>
<ServiceActivityDescriptionFormInput formItemName="serviceActivityDescription" />
<ServiceActivityPriceFormInput
formItemName="serviceActivityPrice"
setIsInputValid={(isValid) =>
setIsFormValid({
...isFormValid,
serviceActivityPrice: isValid,
})
}
/>
<ServiceActivityPriceFormInput formItemName="serviceActivityPrice" />
<ServiceActivityDurationHoursFormInput
formItemName="serviceActivityDurationHours"
setIsInputValid={(isValid) =>
setIsFormValid({
...isFormValid,
serviceActivityDurationHours: isValid,
})
}
/>
<ServiceActivityDurationHoursFormInput formItemName="serviceActivityDurationHours" />
<ServiceActivityDurationMinutesFormInput
formItemName="serviceActivityDurationMinutes"
setIsInputValid={(isValid) =>
setIsFormValid({
...isFormValid,
serviceActivityDurationMinutes: isValid,
})
}
/>
<ServiceActivityDurationMinutesFormInput formItemName="serviceActivityDurationMinutes" />
<Space direction="vertical" style={{ width: "100%" }}>
<Typography.Text>
{t("storeServices.serviceActivityResponsible")}
</Typography.Text>
<MyTable
props={{
rowSelection: {
selectedRowKeys: selectedEmployeesRowKeys,
onChange: (newSelectedRowKeys) =>
setSelectedEmployeesRowKeys(newSelectedRowKeys),
},
loading: isRequesting,
columns: getTableColumns(),
dataSource: getTableItems(),
size: "small",
pagination: false,
}}
/>
</Space>
</Form>
</MyModal>
);
@ -651,13 +792,12 @@ function ServiceNameFormInput({ formItemName }) {
);
}
function ServiceActivityNameFormInput({ formItemName, setIsInputValid }) {
function ServiceActivityNameFormInput({ formItemName }) {
const { t } = useTranslation();
return (
<MyFormInput
formItemName={formItemName}
setIsInputValid={setIsInputValid}
minLength={Constants.GLOBALS.MIN_STORE_SERVICE_ACTIVITY_NAME_LENGTH}
maxLength={Constants.GLOBALS.MAX_STORE_SERVICE_ACTIVITY_NAME_LENGTH}
label={t("storeServices.serviceActivityName")}
@ -710,7 +850,7 @@ function ServiceActivityDescriptionFormInput({
);
}
function ServiceActivityPriceFormInput({ formItemName, setIsInputValid }) {
function ServiceActivityPriceFormInput({ formItemName }) {
const { t } = useTranslation();
return (
@ -720,7 +860,6 @@ function ServiceActivityPriceFormInput({ formItemName, setIsInputValid }) {
}}
inputType="number"
formItemName={formItemName}
setIsInputValid={setIsInputValid}
minLength={Constants.GLOBALS.MIN_STORE_SERVICE_ACTIVITY_PRICE}
maxLength={Constants.GLOBALS.MAX_STORE_SERVICE_ACTIVITY_PRICE}
label={t("storeServices.serviceActivityPrice")}

View File

@ -13,8 +13,6 @@ export default function UserProfile({ userSession, setUserSession }) {
<Button
type="primary"
onClick={() => {
console.log("Logout");
setUserSession();
window.location.href = "/";
@ -27,7 +25,7 @@ export default function UserProfile({ userSession, setUserSession }) {
}).catch(console.error);
}}
>
Logout
{t("common.button.logout")}
</Button>
}
>

View File

@ -54,7 +54,6 @@ export const Constants = {
SUPPORT: "/support",
USER_PROFILE: "/user-profile",
},
GLOBALS: {
MIN_USERNAME_LENGTH: 3,
MAX_USERNAME_LENGTH: 20,
@ -73,7 +72,7 @@ export const Constants = {
MIN_STORE_SERVICE_ACTIVITY_DURATION_HOURS: 0,
MAX_STORE_SERVICE_ACTIVITY_DURATION_HOURS: 23,
MIN_STORE_SERVICE_ACTIVITY_DURATION_MINUTES: 0,
MAX_STORE_SERVICE_ACTIVITY_DURATION_MINUTES: 60,
MAX_STORE_SERVICE_ACTIVITY_DURATION_MINUTES: 59,
},
DELAY_ACCOUNT_NAME_CHECK: 250,
MAX_AVATAR_SIZE: 5 * 1024 * 1024,