1078 lines
35 KiB
JavaScript
1078 lines
35 KiB
JavaScript
import { CaretRightOutlined, PlusOutlined } from "@ant-design/icons";
|
|
import {
|
|
Avatar,
|
|
Button,
|
|
Card,
|
|
Collapse,
|
|
Flex,
|
|
Form,
|
|
Grid,
|
|
Skeleton,
|
|
Space,
|
|
Spin,
|
|
Tooltip,
|
|
Typography,
|
|
notification,
|
|
} from "antd";
|
|
import { useTranslation } from "react-i18next";
|
|
import { useEffect, useState } from "react";
|
|
import {
|
|
AppStyle,
|
|
Constants,
|
|
myFetch,
|
|
showInputsInvalidNotification,
|
|
} from "../../../utils";
|
|
import { useParams } from "react-router-dom";
|
|
import MyModal, {
|
|
MyModalCloseCreateButtonFooter,
|
|
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";
|
|
import CountUp from "react-countup";
|
|
|
|
const { useBreakpoint } = Grid;
|
|
|
|
export default function StoreServices() {
|
|
const { t } = useTranslation();
|
|
const [notificationApi, notificationContextHolder] =
|
|
notification.useNotification();
|
|
const screenBreakpoint = useBreakpoint();
|
|
const { storeId } = useParams();
|
|
|
|
const [isRequestingServices, setIsRequestingServices] = useState(false);
|
|
const [addEditServiceModalOptions, setAddEditServiceModalOptions] = useState({
|
|
mode: "add", // add | edit
|
|
isOpen: false,
|
|
service: null,
|
|
});
|
|
const [
|
|
addEditServiceActivityModalOptions,
|
|
setAddEditServiceActivityModalOptions,
|
|
] = useState({
|
|
mode: "add", // add | edit
|
|
isOpen: false,
|
|
activity: null,
|
|
});
|
|
const [servicesData, setServicesData] = useState({
|
|
services: [],
|
|
users: [],
|
|
});
|
|
|
|
const fetchServices = () => {
|
|
setIsRequestingServices(true);
|
|
|
|
myFetch({
|
|
url: `/store/services/${storeId}`,
|
|
method: "GET",
|
|
notificationApi: notificationApi,
|
|
t: t,
|
|
})
|
|
.then((data) => {
|
|
setIsRequestingServices(false);
|
|
setServicesData(data);
|
|
})
|
|
.catch(() => {});
|
|
};
|
|
|
|
useEffect(() => fetchServices(), []);
|
|
|
|
return (
|
|
<>
|
|
{notificationContextHolder}
|
|
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
justifyContent: "space-between",
|
|
flexDirection: screenBreakpoint.xs ? "column" : "row",
|
|
paddingBottom: screenBreakpoint.xs ? 16 : 0,
|
|
}}
|
|
>
|
|
<h1>
|
|
{t("storeServices.pageTitle")} {" ("}
|
|
<CountUp end={servicesData.services.length} />
|
|
{")"}
|
|
</h1>
|
|
|
|
<ModalAddEditService
|
|
storeId={storeId}
|
|
fetchServices={fetchServices}
|
|
addEditServiceModalOptions={addEditServiceModalOptions}
|
|
setAddEditServiceModalOptions={setAddEditServiceModalOptions}
|
|
/>
|
|
</div>
|
|
<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" /> */}
|
|
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
justifyContent: "center",
|
|
paddingTop: 70,
|
|
}}
|
|
>
|
|
<Spin />
|
|
</div>
|
|
</>
|
|
) : servicesData.services.length > 0 ? (
|
|
<>
|
|
{servicesData.services.map((service) => (
|
|
<Service
|
|
key={service.service_id}
|
|
service={service}
|
|
users={servicesData.users}
|
|
storeId={storeId}
|
|
setAddEditServiceActivityModalOptions={
|
|
setAddEditServiceActivityModalOptions
|
|
}
|
|
setAddEditServiceModalOptions={setAddEditServiceModalOptions}
|
|
fetchServices={fetchServices}
|
|
/>
|
|
))}
|
|
</>
|
|
) : (
|
|
<MyEmpty />
|
|
)}
|
|
</Space>
|
|
|
|
<ModalAddEditServiceActivity
|
|
fetchServices={fetchServices}
|
|
addEditServiceActivityModalOptions={addEditServiceActivityModalOptions}
|
|
setAddEditServiceActivityModalOptions={
|
|
setAddEditServiceActivityModalOptions
|
|
}
|
|
users={servicesData.users}
|
|
/>
|
|
</>
|
|
);
|
|
}
|
|
|
|
function Service({
|
|
service,
|
|
users,
|
|
storeId,
|
|
setAddEditServiceActivityModalOptions,
|
|
setAddEditServiceModalOptions,
|
|
fetchServices,
|
|
}) {
|
|
const { t } = useTranslation();
|
|
const [notificationApi, notificationContextHolder] =
|
|
notification.useNotification();
|
|
|
|
const [isRequestingActivities, setIsRequestingActivities] = useState(false);
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
|
|
const [serviceActivities, setServiceActivities] = useState([]);
|
|
|
|
const fetchServiceActivities = () => {
|
|
if (!isOpen) return;
|
|
|
|
setIsRequestingActivities(true);
|
|
|
|
myFetch({
|
|
url: `/store/services/activities/${storeId}/${service.service_id}`,
|
|
method: "GET",
|
|
notificationApi: notificationApi,
|
|
t: t,
|
|
})
|
|
.then((data) => {
|
|
setIsRequestingActivities(false);
|
|
setServiceActivities(data.activities);
|
|
})
|
|
.catch((errStatus) => {
|
|
console.log(errStatus);
|
|
});
|
|
};
|
|
|
|
useEffect(() => fetchServiceActivities(), [isOpen]);
|
|
|
|
const expandIcon = ({ isActive }) => {
|
|
if (isRequestingActivities) return <Spin size="small" />;
|
|
|
|
return <CaretRightOutlined rotate={isActive ? 90 : 0} />;
|
|
};
|
|
|
|
return (
|
|
<>
|
|
{notificationContextHolder}
|
|
|
|
<Collapse
|
|
key={service.service_id}
|
|
onChange={(e) => setIsOpen(e.length !== 0)}
|
|
expandIcon={expandIcon}
|
|
items={[
|
|
{
|
|
key: "1",
|
|
label: (
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
justifyContent: "space-between",
|
|
alignItems: "center",
|
|
}}
|
|
>
|
|
<span>{service.name}</span>
|
|
|
|
<Space>
|
|
{/*
|
|
<ArrowUpOutlined
|
|
disabled
|
|
onClick={(e) => e.stopPropagation()}
|
|
/>
|
|
<ArrowDownOutlined
|
|
disabled
|
|
onClick={(e) => e.stopPropagation()}
|
|
/>
|
|
*/}
|
|
<MyPlusIcon
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
|
|
setAddEditServiceActivityModalOptions({
|
|
mode: "add",
|
|
isOpen: true,
|
|
service: service,
|
|
});
|
|
}}
|
|
/>
|
|
|
|
<MyEditIcon
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
|
|
setAddEditServiceModalOptions({
|
|
mode: "edit",
|
|
isOpen: true,
|
|
service: service,
|
|
});
|
|
}}
|
|
/>
|
|
<MyDeleteIcon
|
|
onClick={(e) => e.stopPropagation()}
|
|
propsPopconfirm={{
|
|
placement: "left",
|
|
}}
|
|
onConfirm={() => {
|
|
return myFetch({
|
|
url: `/store/services/${service.service_id}`,
|
|
method: "DELETE",
|
|
notificationApi: notificationApi,
|
|
t: t,
|
|
});
|
|
}}
|
|
onFetchSuccess={fetchServices}
|
|
popConfirmTitle={t(
|
|
"storeServices.popConfirmDeleteService.title"
|
|
)}
|
|
popConfirmDescription={t(
|
|
"storeServices.popConfirmDeleteService.description"
|
|
)}
|
|
/>
|
|
</Space>
|
|
</div>
|
|
),
|
|
children: (
|
|
<Space
|
|
key={`space-${service.service_id}`}
|
|
direction="vertical"
|
|
style={{ width: "100%" }}
|
|
>
|
|
{isRequestingActivities ? (
|
|
<Skeleton active>
|
|
<Card title="loading">
|
|
<p>loading</p>
|
|
<p>loading</p>
|
|
<p>loading</p>
|
|
</Card>
|
|
</Skeleton>
|
|
) : (
|
|
<>
|
|
{serviceActivities.length === 0 ? (
|
|
<MyEmpty />
|
|
) : (
|
|
serviceActivities.map((activity) => {
|
|
let userList = [];
|
|
|
|
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]);
|
|
}
|
|
}
|
|
}
|
|
} 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}
|
|
style={{ backgroundColor: "#fafbfb" }}
|
|
hoverable
|
|
extra={
|
|
<Space>
|
|
<Avatar.Group maxCount={2} size="small">
|
|
{userList.map((user) => (
|
|
<Tooltip
|
|
key={user.user_id}
|
|
title={user.username}
|
|
>
|
|
<Avatar
|
|
size="small"
|
|
style={{
|
|
backgroundColor:
|
|
AppStyle.colors.primary,
|
|
}}
|
|
>
|
|
{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({
|
|
url: `/store/services/activity/${activity.activity_id}`,
|
|
method: "DELETE",
|
|
notificationApi: notificationApi,
|
|
t: t,
|
|
});
|
|
}}
|
|
onFetchSuccess={fetchServiceActivities}
|
|
popConfirmTitle={t(
|
|
"storeServices.popConfirmDeleteServiceActivity.title"
|
|
)}
|
|
popConfirmDescription={t(
|
|
"storeServices.popConfirmDeleteServiceActivity.description"
|
|
)}
|
|
/>
|
|
</Space>
|
|
}
|
|
>
|
|
<Typography.Paragraph type="secondary">
|
|
{activity.description}
|
|
</Typography.Paragraph>
|
|
|
|
<Flex justify="space-around">
|
|
<p>{activity.price} €</p>
|
|
|
|
<Typography.Paragraph>
|
|
{activity.duration}{" "}
|
|
{activity.duration === 1
|
|
? t("common.unit.minute")
|
|
: t("common.unit.minutes")}{" "}
|
|
{/*<Typography.Text type="secondary">
|
|
{durationToHoursAndMinutes(
|
|
t,
|
|
activity.duration
|
|
)}
|
|
</Typography.Text> */}
|
|
</Typography.Paragraph>
|
|
</Flex>
|
|
</Card>
|
|
);
|
|
})
|
|
)}
|
|
</>
|
|
)}
|
|
</Space>
|
|
),
|
|
},
|
|
]}
|
|
/>
|
|
</>
|
|
);
|
|
}
|
|
|
|
function durationToHoursAndMinutes(t, duration) {
|
|
const MINUTES_IN_HOUR = 60;
|
|
const singularHourText = t("common.unit.hour");
|
|
const pluralHourText = t("common.unit.hours");
|
|
const singularMinuteText = t("common.unit.minute");
|
|
const pluralMinuteText = t("common.unit.minutes");
|
|
|
|
const hours = Math.floor(duration / MINUTES_IN_HOUR);
|
|
const minutes = duration % MINUTES_IN_HOUR;
|
|
|
|
if (hours === 0 && minutes < 61) {
|
|
return "";
|
|
}
|
|
|
|
let response = "";
|
|
|
|
if (hours === 0) {
|
|
response = `${minutes} ${
|
|
minutes === 1 ? singularMinuteText : pluralMinuteText
|
|
}`;
|
|
} else if (minutes === 0) {
|
|
response = `${hours} ${hours === 1 ? singularHourText : pluralHourText}`;
|
|
} else {
|
|
response = `${hours} ${hours === 1 ? singularHourText : pluralHourText} ${t(
|
|
"common.unit.separator"
|
|
)} ${minutes} ${minutes === 1 ? singularMinuteText : pluralMinuteText}`;
|
|
}
|
|
|
|
return `(${response})`;
|
|
}
|
|
|
|
// this modal is used to create and edit services
|
|
function ModalAddEditService({
|
|
storeId,
|
|
fetchServices,
|
|
addEditServiceModalOptions,
|
|
setAddEditServiceModalOptions,
|
|
}) {
|
|
const { t } = useTranslation();
|
|
const [notificationApi, notificationContextHolder] =
|
|
notification.useNotification();
|
|
const screenBreakpoint = useBreakpoint();
|
|
const [form] = Form.useForm();
|
|
|
|
const [isRequesting, setIsRequesting] = useState(false);
|
|
|
|
const handleModalClose = () => {
|
|
setAddEditServiceModalOptions({
|
|
...addEditServiceModalOptions,
|
|
isOpen: false,
|
|
mode: "add",
|
|
});
|
|
|
|
form.resetFields();
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (!addEditServiceModalOptions.isOpen) return;
|
|
|
|
if (addEditServiceModalOptions.mode === "edit") {
|
|
form.setFieldsValue({
|
|
serviceName: addEditServiceModalOptions.service.name,
|
|
});
|
|
}
|
|
}, [addEditServiceModalOptions.isOpen]);
|
|
|
|
return (
|
|
<>
|
|
{notificationContextHolder}
|
|
|
|
<Button
|
|
type="primary"
|
|
icon={<PlusOutlined />}
|
|
block={screenBreakpoint.xs}
|
|
onClick={() =>
|
|
setAddEditServiceModalOptions({
|
|
...addEditServiceModalOptions,
|
|
isOpen: true,
|
|
})
|
|
}
|
|
>
|
|
{t("storeServices.buttonAddService")}
|
|
</Button>
|
|
|
|
<MyModal
|
|
title={
|
|
addEditServiceModalOptions.mode === "add"
|
|
? t("storeServices.modalAddService.title")
|
|
: t("storeServices.modalEditService.title")
|
|
}
|
|
isOpen={addEditServiceModalOptions.isOpen}
|
|
onCancel={handleModalClose}
|
|
footer={
|
|
addEditServiceModalOptions.mode === "add" ? (
|
|
<MyModalCloseCreateButtonFooter
|
|
onCancel={handleModalClose}
|
|
isCreateButtonLoading={isRequesting}
|
|
onCreate={() => {
|
|
form
|
|
.validateFields()
|
|
.then((values) => {
|
|
setIsRequesting(true);
|
|
|
|
myFetch({
|
|
url: "/store/services/service",
|
|
method: "POST",
|
|
body: {
|
|
storeId: storeId,
|
|
name: values.serviceName,
|
|
},
|
|
notificationApi: notificationApi,
|
|
t: t,
|
|
})
|
|
.then(() => {
|
|
setIsRequesting(false);
|
|
handleModalClose();
|
|
|
|
fetchServices();
|
|
})
|
|
.catch((errStatus) => {
|
|
setIsRequesting(false);
|
|
|
|
if (errStatus === 400) {
|
|
notificationApi["error"]({
|
|
message: t("common.request.inputsInvalid.title"),
|
|
description: t(
|
|
"common.request.inputsInvalid.description"
|
|
),
|
|
});
|
|
}
|
|
});
|
|
})
|
|
.catch(() =>
|
|
showInputsInvalidNotification(notificationApi, t)
|
|
);
|
|
}}
|
|
/>
|
|
) : (
|
|
<MyModalCloseSaveButtonFooter
|
|
onCancel={handleModalClose}
|
|
isSaveButtonLoading={isRequesting}
|
|
onSave={() => {
|
|
// if the service name didn't change, don't send a request
|
|
let formServiceName = form.getFieldValue("serviceName");
|
|
|
|
if (
|
|
addEditServiceModalOptions.service.name === formServiceName
|
|
) {
|
|
handleModalClose();
|
|
return;
|
|
}
|
|
form
|
|
.validateFields()
|
|
.then(() => {
|
|
setIsRequesting(true);
|
|
|
|
myFetch({
|
|
url: "/store/services/update",
|
|
method: "POST",
|
|
body: {
|
|
serviceId:
|
|
addEditServiceModalOptions.service.service_id,
|
|
name: formServiceName,
|
|
},
|
|
notificationApi: notificationApi,
|
|
t: t,
|
|
})
|
|
.then(() => {
|
|
setIsRequesting(false);
|
|
handleModalClose();
|
|
|
|
fetchServices();
|
|
})
|
|
.catch((errStatus) => {
|
|
setIsRequesting(false);
|
|
|
|
if (errStatus === 400) {
|
|
notificationApi["error"]({
|
|
message: t("common.request.inputsInvalid.title"),
|
|
description: t(
|
|
"common.request.inputsInvalid.description"
|
|
),
|
|
});
|
|
}
|
|
});
|
|
})
|
|
.catch(() =>
|
|
showInputsInvalidNotification(notificationApi, t)
|
|
);
|
|
}}
|
|
/>
|
|
)
|
|
}
|
|
>
|
|
<Form form={form} layout="vertical" requiredMark={false}>
|
|
<ServiceNameFormInput formItemName="serviceName" />
|
|
</Form>
|
|
</MyModal>
|
|
</>
|
|
);
|
|
}
|
|
|
|
function ModalAddEditServiceActivity({
|
|
fetchServices,
|
|
addEditServiceActivityModalOptions,
|
|
setAddEditServiceActivityModalOptions,
|
|
users,
|
|
}) {
|
|
const { t } = useTranslation();
|
|
const [notificationApi, notificationContextHolder] =
|
|
notification.useNotification();
|
|
const [form] = Form.useForm();
|
|
const [isRequesting, setIsRequesting] = useState(false);
|
|
const [selectedEmployeesRowKeys, setSelectedEmployeesRowKeys] = useState([]);
|
|
|
|
const handleModalClose = () => {
|
|
setAddEditServiceActivityModalOptions({
|
|
...addEditServiceActivityModalOptions,
|
|
isOpen: false,
|
|
});
|
|
|
|
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;
|
|
|
|
if (addEditServiceActivityModalOptions.mode === "edit") {
|
|
form.setFieldsValue({
|
|
serviceActivityName: addEditServiceActivityModalOptions.activity.name,
|
|
serviceActivityDescription:
|
|
addEditServiceActivityModalOptions.activity.description,
|
|
serviceActivityPrice: addEditServiceActivityModalOptions.activity.price,
|
|
|
|
serviceActivityDurationMinutes:
|
|
addEditServiceActivityModalOptions.activity.duration,
|
|
});
|
|
|
|
setSelectedEmployeesRowKeys(
|
|
addEditServiceActivityModalOptions.activity.StoreServiceActivityUsers
|
|
.length === 0
|
|
? users.map((user) => user.user_id)
|
|
: addEditServiceActivityModalOptions.activity.StoreServiceActivityUsers.map(
|
|
(user) => user.user_id
|
|
)
|
|
);
|
|
} else {
|
|
setSelectedEmployeesRowKeys(users.map((user) => user.user_id));
|
|
}
|
|
}, [addEditServiceActivityModalOptions.isOpen]);
|
|
|
|
return (
|
|
<>
|
|
{notificationContextHolder}
|
|
|
|
<MyModal
|
|
title={
|
|
addEditServiceActivityModalOptions.mode === "add"
|
|
? t("storeServices.modalAddServiceActivity.title")
|
|
: t("storeServices.modalEditServiceActivity.title")
|
|
}
|
|
isOpen={addEditServiceActivityModalOptions.isOpen}
|
|
onCancel={handleModalClose}
|
|
footer={
|
|
addEditServiceActivityModalOptions.mode === "add" ? (
|
|
<MyModalCloseCreateButtonFooter
|
|
onCancel={handleModalClose}
|
|
isCreateButtonLoading={isRequesting}
|
|
onCreate={() => {
|
|
form
|
|
.validateFields()
|
|
.then((values) => {
|
|
setIsRequesting(true);
|
|
|
|
myFetch({
|
|
url: "/store/services/activity",
|
|
method: "POST",
|
|
body: {
|
|
serviceId:
|
|
addEditServiceActivityModalOptions.service.service_id,
|
|
name: values.serviceActivityName,
|
|
description: values.serviceActivityDescription,
|
|
price: values.serviceActivityPrice,
|
|
duration: values.serviceActivityDurationMinutes,
|
|
userIds:
|
|
selectedEmployeesRowKeys.length === users.length
|
|
? []
|
|
: selectedEmployeesRowKeys,
|
|
},
|
|
notificationApi: notificationApi,
|
|
t: t,
|
|
})
|
|
.then(() => {
|
|
setIsRequesting(false);
|
|
handleModalClose();
|
|
|
|
fetchServices();
|
|
})
|
|
.catch((errStatus) => {
|
|
setIsRequesting(false);
|
|
|
|
if (errStatus === 400) {
|
|
notificationApi["error"]({
|
|
message: t("common.request.inputsInvalid.title"),
|
|
description: t(
|
|
"common.request.inputsInvalid.description"
|
|
),
|
|
});
|
|
}
|
|
});
|
|
})
|
|
.catch(() =>
|
|
showInputsInvalidNotification(notificationApi, t)
|
|
);
|
|
}}
|
|
/>
|
|
) : (
|
|
<MyModalCloseSaveButtonFooter
|
|
onCancel={handleModalClose}
|
|
isSaveButtonLoading={isRequesting}
|
|
onSave={() => {
|
|
const formServiceActivityName = form.getFieldValue(
|
|
"serviceActivityName"
|
|
);
|
|
const formServiceActivityDescription = form.getFieldValue(
|
|
"serviceActivityDescription"
|
|
);
|
|
const formServiceActivityPrice = form.getFieldValue(
|
|
"serviceActivityPrice"
|
|
);
|
|
const formServiceActivityDurationMinutes = form.getFieldValue(
|
|
"serviceActivityDurationMinutes"
|
|
);
|
|
|
|
// if the service didn't change, don't send a request
|
|
if (
|
|
addEditServiceActivityModalOptions.activity.name ===
|
|
formServiceActivityName &&
|
|
addEditServiceActivityModalOptions.activity.description ===
|
|
formServiceActivityDescription &&
|
|
addEditServiceActivityModalOptions.activity.price ===
|
|
formServiceActivityPrice &&
|
|
addEditServiceActivityModalOptions.activity.duration ===
|
|
formServiceActivityDurationMinutes &&
|
|
(selectedEmployeesRowKeys.length === users.length ||
|
|
addEditServiceActivityModalOptions.activity
|
|
.StoreServiceActivityUsers.length ===
|
|
selectedEmployeesRowKeys.length)
|
|
) {
|
|
handleModalClose();
|
|
return;
|
|
}
|
|
|
|
let validateFields = [];
|
|
let body = {
|
|
activityId:
|
|
addEditServiceActivityModalOptions.activity.activity_id,
|
|
};
|
|
|
|
if (
|
|
formServiceActivityName !==
|
|
addEditServiceActivityModalOptions.activity.name
|
|
) {
|
|
validateFields.push("serviceActivityName");
|
|
body.name = formServiceActivityName;
|
|
}
|
|
|
|
// description is not required
|
|
body.description = formServiceActivityDescription;
|
|
|
|
if (
|
|
formServiceActivityPrice !==
|
|
addEditServiceActivityModalOptions.activity.price
|
|
) {
|
|
validateFields.push("serviceActivityPrice");
|
|
body.price = formServiceActivityPrice;
|
|
}
|
|
|
|
let formDuration = formServiceActivityDurationMinutes;
|
|
|
|
if (
|
|
formDuration !==
|
|
addEditServiceActivityModalOptions.activity.duration
|
|
) {
|
|
validateFields.push("serviceActivityDurationMinutes");
|
|
body.duration = formDuration;
|
|
}
|
|
|
|
body.userIds = selectedEmployeesRowKeys;
|
|
|
|
form
|
|
.validateFields()
|
|
.then(() => {
|
|
setIsRequesting(true);
|
|
|
|
myFetch({
|
|
url: "/store/services/activity/update",
|
|
method: "POST",
|
|
body: body,
|
|
notificationApi: notificationApi,
|
|
t: t,
|
|
})
|
|
.then(() => {
|
|
setIsRequesting(false);
|
|
handleModalClose();
|
|
|
|
fetchServices();
|
|
})
|
|
.catch((errStatus) => {
|
|
setIsRequesting(false);
|
|
|
|
if (errStatus === 400) {
|
|
notificationApi["error"]({
|
|
message: t("common.request.inputsInvalid.title"),
|
|
description: t(
|
|
"common.request.inputsInvalid.description"
|
|
),
|
|
});
|
|
}
|
|
});
|
|
})
|
|
.catch(() =>
|
|
showInputsInvalidNotification(notificationApi, t)
|
|
);
|
|
}}
|
|
/>
|
|
)
|
|
}
|
|
>
|
|
<Form form={form} layout="vertical" requiredMark={false}>
|
|
<ServiceActivityNameFormInput formItemName="serviceActivityName" />
|
|
|
|
<ServiceActivityDescriptionFormInput formItemName="serviceActivityDescription" />
|
|
|
|
<ServiceActivityPriceFormInput formItemName="serviceActivityPrice" />
|
|
|
|
<ServiceActivityDurationMinutesFormInput formItemName="serviceActivityDurationMinutes" />
|
|
|
|
<Space direction="vertical" style={{ width: "100%" }}>
|
|
<Typography.Text>
|
|
{t("storeServices.serviceActivityResponsible")}
|
|
</Typography.Text>
|
|
<Typography.Text type="secondary">
|
|
{t("storeServices.serviceActivityResponsibleDescription")}
|
|
</Typography.Text>
|
|
|
|
<MyTable
|
|
props={{
|
|
rowSelection: {
|
|
selectedRowKeys: selectedEmployeesRowKeys,
|
|
onChange: (newSelectedRowKeys) =>
|
|
setSelectedEmployeesRowKeys(newSelectedRowKeys),
|
|
},
|
|
loading: isRequesting,
|
|
columns: getTableColumns(),
|
|
dataSource: getTableItems(),
|
|
size: "small",
|
|
pagination: false,
|
|
}}
|
|
/>
|
|
</Space>
|
|
</Form>
|
|
</MyModal>
|
|
</>
|
|
);
|
|
}
|
|
|
|
function ServiceNameFormInput({ formItemName }) {
|
|
const { t } = useTranslation();
|
|
|
|
return (
|
|
<MyFormInput
|
|
formItemName={formItemName}
|
|
propsInput={{
|
|
showCount: true,
|
|
}}
|
|
minLength={Constants.GLOBALS.MIN_STORE_SERVICE_NAME_LENGTH}
|
|
maxLength={Constants.GLOBALS.MAX_STORE_SERVICE_NAME_LENGTH}
|
|
label={t("storeServices.serviceName")}
|
|
ruleMessageValueRequired={t(
|
|
"storeServices.inputRules.serviceNameRequired"
|
|
)}
|
|
ruleMessageValueMinLengthRequired={t(
|
|
"storeServices.inputRules.serviceNameMinLength",
|
|
{
|
|
minLength: Constants.GLOBALS.MIN_STORE_SERVICE_NAME_LENGTH,
|
|
}
|
|
)}
|
|
inputPlaceholder={t("storeServices.serviceNamePlaceholder")}
|
|
/>
|
|
);
|
|
}
|
|
|
|
function ServiceActivityNameFormInput({ formItemName }) {
|
|
const { t } = useTranslation();
|
|
|
|
return (
|
|
<MyFormInput
|
|
formItemName={formItemName}
|
|
propsInput={{
|
|
showCount: true,
|
|
}}
|
|
minLength={Constants.GLOBALS.MIN_STORE_SERVICE_ACTIVITY_NAME_LENGTH}
|
|
maxLength={Constants.GLOBALS.MAX_STORE_SERVICE_ACTIVITY_NAME_LENGTH}
|
|
label={t("storeServices.serviceActivityName")}
|
|
ruleMessageValueRequired={t(
|
|
"storeServices.inputRules.serviceActivityNameRequired"
|
|
)}
|
|
ruleMessageValueMinLengthRequired={t(
|
|
"storeServices.inputRules.serviceActivityNameMinLength",
|
|
{
|
|
minLength: Constants.GLOBALS.MIN_STORE_SERVICE_ACTIVITY_NAME_LENGTH,
|
|
}
|
|
)}
|
|
inputPlaceholder={t("storeServices.serviceActivityNamePlaceholder")}
|
|
/>
|
|
);
|
|
}
|
|
|
|
function ServiceActivityDescriptionFormInput({
|
|
formItemName,
|
|
setIsInputValid,
|
|
}) {
|
|
const { t } = useTranslation();
|
|
|
|
return (
|
|
<MyFormInput
|
|
propsInput={{
|
|
showCount: true,
|
|
}}
|
|
inputType="textarea"
|
|
inputNotRequired
|
|
formItemName={formItemName}
|
|
setIsInputValid={setIsInputValid}
|
|
maxLength={
|
|
Constants.GLOBALS.MAX_STORE_SERVICE_ACTIVITY_DESCRIPTION_LENGTH
|
|
}
|
|
label={t("storeServices.serviceActivityDescription")}
|
|
ruleMessageValueRequired={t(
|
|
"storeServices.inputRules.serviceActivityDescriptionRequired"
|
|
)}
|
|
ruleMessageValueMinLengthRequired={t(
|
|
"storeServices.inputRules.serviceActivityDescriptionMinLength",
|
|
{
|
|
minLength:
|
|
Constants.GLOBALS.MIN_STORE_SERVICE_ACTIVITY_DESCRIPTION_LENGTH,
|
|
}
|
|
)}
|
|
inputPlaceholder={t(
|
|
"storeServices.serviceActivityDescriptionPlaceholder"
|
|
)}
|
|
/>
|
|
);
|
|
}
|
|
|
|
function ServiceActivityPriceFormInput({ formItemName }) {
|
|
const { t } = useTranslation();
|
|
|
|
return (
|
|
<MyFormInput
|
|
propsInput={{
|
|
addonAfter: t("storeServices.serviceActivityPriceUnit"),
|
|
}}
|
|
inputType="number"
|
|
formItemName={formItemName}
|
|
minLength={Constants.GLOBALS.MIN_STORE_SERVICE_ACTIVITY_PRICE}
|
|
maxLength={Constants.GLOBALS.MAX_STORE_SERVICE_ACTIVITY_PRICE}
|
|
label={t("storeServices.serviceActivityPrice")}
|
|
ruleMessageValueRequired={t(
|
|
"storeServices.inputRules.serviceActivityPriceRequired"
|
|
)}
|
|
inputPlaceholder={t("storeServices.serviceActivityPricePlaceholder")}
|
|
/>
|
|
);
|
|
}
|
|
/*
|
|
function ServiceActivityDurationHoursFormInput({
|
|
formItemName,
|
|
setIsInputValid,
|
|
}) {
|
|
const { t } = useTranslation();
|
|
|
|
return (
|
|
<MyFormInput
|
|
propsInput={{
|
|
addonAfter: t("storeServices.serviceActivityDurationHoursUnit"),
|
|
}}
|
|
inputType="number"
|
|
formItemName={formItemName}
|
|
setIsInputValid={setIsInputValid}
|
|
minLength={Constants.GLOBALS.MIN_STORE_SERVICE_ACTIVITY_DURATION_HOURS}
|
|
maxLength={Constants.GLOBALS.MAX_STORE_SERVICE_ACTIVITY_DURATION_HOURS}
|
|
label={t("storeServices.serviceActivityDurationHours")}
|
|
ruleMessageValueRequired={t(
|
|
"storeServices.inputRules.serviceActivityDurationHoursRequired"
|
|
)}
|
|
inputPlaceholder={t(
|
|
"storeServices.serviceActivityDurationHoursPlaceholder"
|
|
)}
|
|
/>
|
|
);
|
|
}
|
|
*/
|
|
function ServiceActivityDurationMinutesFormInput({
|
|
formItemName,
|
|
setIsInputValid,
|
|
}) {
|
|
const { t } = useTranslation();
|
|
|
|
return (
|
|
<MyFormInput
|
|
propsInput={{
|
|
addonAfter: t("storeServices.serviceActivityDurationMinutesUnit"),
|
|
}}
|
|
inputType="number"
|
|
formItemName={formItemName}
|
|
setIsInputValid={setIsInputValid}
|
|
minLength={Constants.GLOBALS.MIN_STORE_SERVICE_ACTIVITY_DURATION_MINUTES}
|
|
maxLength={Constants.GLOBALS.MAX_STORE_SERVICE_ACTIVITY_DURATION_MINUTES}
|
|
label={t("storeServices.serviceActivityDurationMinutes")}
|
|
ruleMessageValueRequired={t(
|
|
"storeServices.inputRules.serviceActivityDurationMinutesRequired"
|
|
)}
|
|
inputPlaceholder={t(
|
|
"storeServices.serviceActivityDurationMinutesPlaceholder"
|
|
)}
|
|
/>
|
|
);
|
|
}
|