2523 lines
84 KiB
JavaScript
2523 lines
84 KiB
JavaScript
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
|
import {
|
|
Form,
|
|
Input,
|
|
InputNumber,
|
|
Button,
|
|
TimePicker,
|
|
Space,
|
|
Checkbox,
|
|
Collapse,
|
|
Tooltip,
|
|
Modal,
|
|
Table,
|
|
Tag,
|
|
Switch,
|
|
Select,
|
|
message,
|
|
} from 'antd';
|
|
import {
|
|
PlusOutlined,
|
|
MinusOutlined,
|
|
DeleteOutlined,
|
|
InfoCircleOutlined,
|
|
ArrowRightOutlined,
|
|
PlusCircleOutlined,
|
|
} from '@ant-design/icons';
|
|
|
|
// Import your custom components (adjust paths as needed)
|
|
import CropUpload from '../../Components/Forms/CropUpload.jsx';
|
|
import { DefaultModal } from '../../Components/Modal/DefaultModal.jsx';
|
|
import { DropDowns } from '../../Components/Forms/DropDown.jsx';
|
|
import {
|
|
getAllsubcatdata,
|
|
getProdCatData,
|
|
getProdSubCatData,
|
|
getUomData,
|
|
postProductData,
|
|
prodCatDataSelector,
|
|
prodSubCatDataSelector,
|
|
putProductData,
|
|
ServiceType,
|
|
uomDataSelector,
|
|
} from '../../Features/ProductPage/ProductPage.js';
|
|
import { useSelector } from 'react-redux';
|
|
import { useDispatch } from 'react-redux';
|
|
import { getSession } from '../../Services/Others.js';
|
|
import {
|
|
ApplicationPreferences,
|
|
getCommonAppPreference,
|
|
} from '../../Features/BrachLogin/BranchLogin.js';
|
|
import { getAdmin, taxSelector } from '../../Features/Tax/Tax.js';
|
|
import { changeBreadCrumb } from '../../Features/AppPage/CenterPage.js';
|
|
import { useLocation, useNavigate } from 'react-router-dom';
|
|
import './SportsMaster.scss';
|
|
import {
|
|
EmpDepartMentDropDown,
|
|
EmpDesgDropDown,
|
|
EmpTypeDropDown,
|
|
getEmpBasedOnCmpIdBrId,
|
|
GettingShiftData,
|
|
postEmp,
|
|
UserDataBasedOnBranchId,
|
|
} from '../../Features/EmpMaster/EmpMaster.js';
|
|
import { DatePic } from '../../Components/Forms/DatePickerEmpMaster.jsx';
|
|
import moment from 'moment';
|
|
import { InputField } from '../../Components/Forms/InputField.jsx';
|
|
import Cancellation from '../CancelReschedule/Cancellation.jsx';
|
|
import EmployeeMasterForm from '../EmpMaster/EmpMasterForm.jsx';
|
|
const { Panel } = Collapse;
|
|
const { TextArea } = Input;
|
|
|
|
const subDirectory = import.meta.env.ENV_BASE_URL;
|
|
|
|
const { RangePicker } = TimePicker;
|
|
|
|
export function SafeRangeTimePicker(props) {
|
|
const popupClass = 'no-hover-autoscroll-timepicker';
|
|
const userScrollTimeout = 150; // ms - time window to consider a scroll as user-initiated
|
|
|
|
// Attach handlers whenever the panel opens; we use a ref to store cleanup
|
|
const cleanupRef = useRef(() => {});
|
|
|
|
const onOpenChange = useCallback((open) => {
|
|
// when closed cleanup immediately
|
|
if (!open) {
|
|
cleanupRef.current();
|
|
cleanupRef.current = () => {};
|
|
return;
|
|
}
|
|
|
|
// Wait for panel to render in DOM
|
|
requestAnimationFrame(() => {
|
|
const columns = document.querySelectorAll(
|
|
`.${popupClass} .ant-picker-time-panel-column`
|
|
);
|
|
const disposers = [];
|
|
|
|
columns.forEach((column) => {
|
|
let rememberedScroll = column.scrollTop;
|
|
let lastUserScroll = 0;
|
|
let disableHoverAuto = false;
|
|
|
|
// Mark last user scroll on wheel / touchstart
|
|
const onUserScrollAttempt = (e) => {
|
|
lastUserScroll = Date.now();
|
|
};
|
|
|
|
// On mouse enter remember current scroll and enable 'guard' for auto-scrolling
|
|
const onMouseEnter = () => {
|
|
rememberedScroll = column.scrollTop;
|
|
disableHoverAuto = true;
|
|
};
|
|
|
|
// On mouse leave, disable the guard so normal behavior resumes
|
|
const onMouseLeave = () => {
|
|
disableHoverAuto = false;
|
|
};
|
|
|
|
// On scroll: if guard is on and there hasn't been a recent user wheel/touch,
|
|
// assume this scroll is the unwanted auto-scroll and revert to rememberedScroll.
|
|
const onScroll = () => {
|
|
const now = Date.now();
|
|
const recentUser = now - lastUserScroll <= userScrollTimeout;
|
|
|
|
if (disableHoverAuto && !recentUser) {
|
|
// cancel the auto scroll by snapping back
|
|
// use requestAnimationFrame to avoid layout thrash
|
|
requestAnimationFrame(() => {
|
|
column.scrollTop = rememberedScroll;
|
|
});
|
|
} else {
|
|
// user scrolled — update remembered position
|
|
rememberedScroll = column.scrollTop;
|
|
}
|
|
};
|
|
|
|
column.addEventListener('wheel', onUserScrollAttempt, {
|
|
passive: true,
|
|
});
|
|
column.addEventListener('touchstart', onUserScrollAttempt, {
|
|
passive: true,
|
|
});
|
|
column.addEventListener('mouseenter', onMouseEnter);
|
|
column.addEventListener('mouseleave', onMouseLeave);
|
|
column.addEventListener('scroll', onScroll);
|
|
|
|
disposers.push(() => {
|
|
column.removeEventListener('wheel', onUserScrollAttempt);
|
|
column.removeEventListener('touchstart', onUserScrollAttempt);
|
|
column.removeEventListener('mouseenter', onMouseEnter);
|
|
column.removeEventListener('mouseleave', onMouseLeave);
|
|
column.removeEventListener('scroll', onScroll);
|
|
});
|
|
});
|
|
|
|
// Save cleanup
|
|
cleanupRef.current = () => disposers.forEach((d) => d());
|
|
});
|
|
}, []);
|
|
|
|
// cleanup on unmount
|
|
useEffect(() => {
|
|
return () => cleanupRef.current();
|
|
}, []);
|
|
|
|
return (
|
|
<RangePicker
|
|
{...props}
|
|
popupClassName={popupClass}
|
|
onOpenChange={onOpenChange}
|
|
/>
|
|
);
|
|
}
|
|
|
|
const SportSlotCreation = ({ formType }) => {
|
|
const [form] = Form.useForm();
|
|
const navigate = useNavigate();
|
|
const dispatch = useDispatch();
|
|
const location = useLocation();
|
|
const state = location?.state;
|
|
const editstate = state?.editstate;
|
|
console.log(editstate, 'editstate');
|
|
const UomData = useSelector(uomDataSelector);
|
|
const ApplicationPreferenceData = useSelector(ApplicationPreferences);
|
|
const TaxData = useSelector(taxSelector);
|
|
const UomTypePreference = ApplicationPreferenceData?.find(
|
|
(preference) => preference?.PreferredCatName === 'Product Uom'
|
|
)?.PreferenceCatDetails;
|
|
const UomPreference = UomData?.filter((item) =>
|
|
UomTypePreference?.some?.(
|
|
(e) =>
|
|
e?.PreferredSubCatName?.toLowerCase() ==
|
|
item?.ConfigName?.toLowerCase() && e?.PreferredStatus == 'Y'
|
|
)
|
|
);
|
|
const ProdCatData = useSelector(prodCatDataSelector);
|
|
const ProdSubCatData = useSelector(prodSubCatDataSelector);
|
|
const [selectedType, setSelectedType] = useState(null);
|
|
const [selectedTypeName, setselectedTypeName] = useState(null);
|
|
const [selectedCategory, setSelectedCategory] = useState(null);
|
|
const [selectedSubCategory, setSelectedSubCategory] = useState(null);
|
|
const [selectedCoach, setSelectedCoach] = useState(null);
|
|
const [selectedCoachName, setSelectedCoachName] = useState(null);
|
|
console.log(selectedType, 'selectedType');
|
|
const [slotDuration, setSlotDuration] = useState(1);
|
|
const [generatedSlots, setGeneratedSlots] = useState([]);
|
|
const [startTime, setStartTime] = useState(null);
|
|
const [endTime, setEndTime] = useState(null);
|
|
const [defaultPrice, setDefaultPrice] = useState(null);
|
|
const [SelectedTaxId, setSelectedTaxId] = useState(null);
|
|
const [individualPricing, setIndividualPricing] = useState(false);
|
|
const [OnlineBooking, setOnlineBooking] = useState(false);
|
|
const [individualDefaultPrice, setIndividualDefaultPrice] = useState(null);
|
|
console.log(defaultPrice, 'defaultPricedefaultPrice');
|
|
// const [fullSlotDefaultPrice, setFullSlotDefaultPrice] = useState(0);
|
|
// const [openCategoryModal, setOpenCategoryModal] = useState(false);
|
|
// const [openSubCategoryModal, setOpenSubCategoryModal] = useState(false);
|
|
// const [openCoachModal, setOpenCoachModal] = useState(false);
|
|
const [ServicesDatas, setServicesDatas] = useState([]);
|
|
// const [EmpTypeDropDownData, setEmpTypeDropDownData] = useState([]);
|
|
// const [seletedEmpTypeDrop, setseletedEmpTypeDrop] = useState(null);
|
|
// const [EmpDesgDropDownData, setEmpDesgDropDownData] = useState([]);
|
|
// const [seletedEmpDesigDrop, setseletedEmpDesigDrop] = useState(null);
|
|
// const [EmpDeptDropDownData, setEmpDeptDropDownData] = useState([]);
|
|
// const [seletedEmpDeptDrop, setseletedEmpDeptDrop] = useState(null);
|
|
// const [ShiftDownData, setShiftDownData] = useState([]);
|
|
// const [seletedShiftDrop, setseletedShiftDrop] = useState(null);
|
|
// const [AppPreference, setAppPreference] = useState([]);
|
|
// const [SelectedDate, setSelectedDate] = useState(null);
|
|
// const [showPassword, setShowPassword] = useState(false);
|
|
const [userDropDown, setuserDropDown] = useState([]);
|
|
const [EmployeesDatas, setEmployeesDatas] = useState([]);
|
|
const [selectedUserData, setSelectedUserData] = useState(null);
|
|
// const [zipCodeData, setZipCodeData] = useState(false);
|
|
// state for multiple images
|
|
const [imageUrls, setImageUrls] = useState([]);
|
|
|
|
// Image states
|
|
const [imageUrl, setImageUrl] = useState('');
|
|
// const [imageopen, setimageOpen] = useState(false);
|
|
// const [imagedata, setimagedata] = useState([]);
|
|
// const [selectedImage, setSelectedImage] = useState(null);
|
|
// const [onlineImage, setOnlineImage] = useState(null);
|
|
|
|
const CompId = getSession('CompId');
|
|
const BranchId = getSession('BranchId');
|
|
const AppId = getSession('AppId');
|
|
const UserId = getSession('UserId');
|
|
|
|
// Day selection states
|
|
const [selectedDays, setSelectedDays] = useState({
|
|
monday: false,
|
|
tuesday: false,
|
|
wednesday: false,
|
|
thursday: false,
|
|
friday: false,
|
|
saturday: false,
|
|
sunday: false,
|
|
});
|
|
const [selectAllDays, setSelectAllDays] = useState(false);
|
|
|
|
// const departmentTypePreference = AppPreference?.[0]?.PreferenceDetails?.find(
|
|
// (preference) => preference?.PreferredCatName === 'Department'
|
|
// );
|
|
|
|
// const activeDeptTypes = departmentTypePreference?.PreferenceCatDetails?.filter(
|
|
// (payment) => payment.PreferredStatus !== 'Y')
|
|
const items = [
|
|
{
|
|
name: 'Home',
|
|
link: `${subDirectory}app-page/home`,
|
|
},
|
|
|
|
{
|
|
name: 'Slot',
|
|
link: `${subDirectory}setting/product-master/`,
|
|
},
|
|
{
|
|
name: editstate ? 'Edit' : 'New',
|
|
link: null,
|
|
},
|
|
];
|
|
|
|
useEffect(() => {
|
|
const allSelected = Object.values(selectedDays).every((day) => day);
|
|
setSelectAllDays(allSelected);
|
|
}, [selectedDays]);
|
|
|
|
useEffect(() => {
|
|
dispatch(changeBreadCrumb({ items: items }));
|
|
|
|
dispatch(getUomData());
|
|
dispatch(getProdCatData({ AppId: AppId }));
|
|
|
|
// dispatch(getProdTaxData({ AppId: AppId }));
|
|
dispatch(getAdmin({ CompId: CompId, AppId: AppId }));
|
|
ServiceTypeFn();
|
|
getEmployees();
|
|
|
|
if (formType == 'edit') {
|
|
const daysOfWeek = editstate?.SlotDetails?.[0]?.DayOfWeek?.map((e) =>
|
|
e.trim()?.toLowerCase()
|
|
);
|
|
dispatch(getProdSubCatData({ ConfigId: editstate?.ProdCat }));
|
|
setselectedTypeName(editstate?.ProdTypeName);
|
|
setSelectedType(editstate?.ProdType);
|
|
setSelectedCategory(editstate?.ProdCat);
|
|
setSelectedTaxId(editstate?.TaxId);
|
|
setSelectedSubCategory(editstate?.ProdSubCat);
|
|
setSelectedDays({
|
|
monday: daysOfWeek?.includes('monday'),
|
|
tuesday: daysOfWeek?.includes('tuesday'),
|
|
wednesday: daysOfWeek?.includes('wednesday'),
|
|
thursday: daysOfWeek?.includes('thursday'),
|
|
friday: daysOfWeek?.includes('friday'),
|
|
saturday: daysOfWeek?.includes('saturday'),
|
|
sunday: daysOfWeek?.includes('sunday'),
|
|
});
|
|
setIndividualPricing(
|
|
editstate?.SlotDetails?.some((e) => e?.SinglePrice != e?.MRP)
|
|
);
|
|
setOnlineBooking(
|
|
editstate?.SlotDetails?.some((e) => e?.OnlineApplicable == 'Y')
|
|
);
|
|
setDefaultPrice(editstate?.SlotDetails?.[0]?.SellPrice);
|
|
setIndividualDefaultPrice(editstate?.SlotDetails?.[0]?.SinglePrice);
|
|
form.setFieldsValue({
|
|
defaultPrice: editstate?.SlotDetails?.[0]?.SellPrice,
|
|
});
|
|
form.setFieldsValue({
|
|
individualDefaultPrice: editstate?.SlotDetails?.[0]?.SinglePrice,
|
|
});
|
|
setStartTime(editstate?.SlotDetails?.[0]?.AvailableFrom);
|
|
setEndTime(
|
|
editstate?.SlotDetails?.[editstate?.SlotDetails?.length - 1]
|
|
?.AvailableTo
|
|
);
|
|
setGeneratedSlots(
|
|
editstate?.SlotDetails?.map((e) => {
|
|
return {
|
|
SlotName: e?.SlotName,
|
|
AvailableFrom: e?.AvailableFrom,
|
|
AvailableTo: e?.AvailableTo,
|
|
OnlineApplicable: e?.OnlineApplicable == 'Y' ? true : false,
|
|
individualPurchase: e?.SinglePrice != e?.MRP ? true : false,
|
|
individualPrice: e?.SinglePrice,
|
|
MRP: e?.MRP,
|
|
SellPrice: e?.SellPrice,
|
|
ExceptionFrom: '',
|
|
ExceptionTo: '',
|
|
IsHoliday: 'N',
|
|
DayOfWeek: e?.DayOfWeek,
|
|
active: true,
|
|
Remarks: 'string',
|
|
};
|
|
})
|
|
);
|
|
// se
|
|
|
|
setSelectedCoach(Number(editstate?.TrainerId));
|
|
setSelectedCoachName(editstate?.ProdName);
|
|
form.setFieldsValue({ coach: Number(editstate?.TrainerId) });
|
|
setOnlineBooking(
|
|
editstate?.SlotDetails?.some((e) => e?.OnlineApplicable == 'Y')
|
|
);
|
|
setIndividualPricing(
|
|
editstate?.SlotDetails?.some((e) => e?.SinglePrice != e?.MRP)
|
|
);
|
|
setSlotDuration(editstate?.SlotHours);
|
|
|
|
setDefaultPrice(editstate?.SlotDetails?.[0]?.SellPrice);
|
|
setImageUrl(editstate?.ProdLogo);
|
|
|
|
form.setFieldsValue({ 'Sport-subCategory': editstate?.ProdSubCat });
|
|
form.setFieldsValue({ TaxId: editstate?.TaxId });
|
|
form.setFieldsValue({ 'Sport-category': editstate?.ProdCat });
|
|
form.setFieldsValue({ type: editstate?.ProdType });
|
|
form.setFieldsValue({ maxCapacity: editstate?.Size });
|
|
form.setFieldsValue({ groundName: editstate?.ProdName });
|
|
form.setFieldsValue({
|
|
defaultPrice: editstate?.SlotDetails?.[0]?.SellPrice,
|
|
});
|
|
form.setFieldsValue({
|
|
description: editstate?.SportDec?.[0]?.description,
|
|
});
|
|
form.setFieldsValue({ facilities: editstate?.SportDec?.[0]?.Facilities });
|
|
form.setFieldsValue({ terms: editstate?.SportDec?.[0]?.Terms });
|
|
form.setFieldsValue({
|
|
cancellationPolicy: editstate?.SportDec?.[0]?.CancellationPolicy,
|
|
});
|
|
}
|
|
}, []);
|
|
|
|
// useEffect(() => {
|
|
// getApplicationPreference()
|
|
// BranchDropDownChange()
|
|
// }, [])
|
|
|
|
// const getApplicationPreference = async () => {
|
|
// const response = await dispatch(getCommonAppPreference(AppId)).unwrap();
|
|
// if (response?.data?.statusCode === 1) {
|
|
// setAppPreference(response?.data?.data)
|
|
// }
|
|
// }
|
|
// const BranchDropDownChange = async (e = BranchId) => {
|
|
// // formRef.current?.setFieldsValue({ BranchId: e });
|
|
// let gettinguserDropDown = [];
|
|
|
|
// gettinguserDropDown = await dispatch(
|
|
// UserDataBasedOnBranchId({
|
|
// BranchId: e,
|
|
// Type: 'E',
|
|
// })
|
|
// ).unwrap();
|
|
// if (gettinguserDropDown?.data?.statusCode === 1) {
|
|
// let finaluserDropDown = gettinguserDropDown?.data?.data?.filter(
|
|
// (value) => value.ActiveStatus === 'A'
|
|
// );
|
|
// if (gettinguserDropDown?.data?.data?.length === 1) {
|
|
// setSelectedUserData(
|
|
// gettinguserDropDown?.data?.data?.length === 1
|
|
// ? gettinguserDropDown?.data?.data[0]?.UserId
|
|
// : null
|
|
// );
|
|
// form?.setFieldsValue({
|
|
// UserId:
|
|
// gettinguserDropDown?.data?.data?.length === 1
|
|
// ? gettinguserDropDown?.data?.data[0]?.UserId
|
|
// : null,
|
|
// });
|
|
// await UserDropDownChangeMobile(
|
|
// gettinguserDropDown?.data?.data[0]?.UserId,
|
|
// finaluserDropDown
|
|
// );
|
|
// }
|
|
|
|
// setuserDropDown(finaluserDropDown);
|
|
// }
|
|
// };
|
|
|
|
// const UserDropDownChangeMobile = async (e, Mobile) => {
|
|
// // MobileNo
|
|
// let mob = Mobile.filter((item) => item?.UserId === e);
|
|
// console.log(mob, 'ddddddddd');
|
|
// const data = mob?.length > 0 ? mob[0] : {};
|
|
|
|
// form?.setFieldsValue({
|
|
// UserId: e,
|
|
// MobileNo: data.MobileNo,
|
|
// Address1: data.Address1,
|
|
// Address2: data.Address2,
|
|
// Latitude: data.Latitude,
|
|
// Longitude: data.Longitude,
|
|
// Zip: data.Zip,
|
|
// MailId: data.MailId,
|
|
// State: data.State,
|
|
// UserImage: data.UserImage,
|
|
// });
|
|
// // await getPincodeValues(mob?.[0]?.Zip);
|
|
// setSelectedUserData(e);
|
|
|
|
// const gettingEmpTypeDropDown = await dispatch(EmpTypeDropDown()).unwrap();
|
|
// if (gettingEmpTypeDropDown?.data?.statusCode === 1) {
|
|
// let finalEmpTypeDropDown = gettingEmpTypeDropDown?.data?.data?.filter(
|
|
// (value) => value.ActiveStatus === 'A'
|
|
// );
|
|
|
|
// if (gettingEmpTypeDropDown?.data?.data?.length === 1) {
|
|
// setseletedEmpTypeDrop(
|
|
// gettingEmpTypeDropDown?.data?.data?.length === 1
|
|
// ? gettingEmpTypeDropDown?.data?.data[0]?.ConfigId
|
|
// : null
|
|
// );
|
|
// form.setFieldsValue({
|
|
// EmpType:
|
|
// gettingEmpTypeDropDown?.data?.data?.length === 1
|
|
// ? gettingEmpTypeDropDown?.data?.data[0]?.ConfigId
|
|
// : null,
|
|
// });
|
|
// await EmpTypeDropDownChange(
|
|
// gettingEmpTypeDropDown?.data?.data[0]?.ConfigId
|
|
// );
|
|
// }
|
|
// //
|
|
// setEmpTypeDropDownData(finalEmpTypeDropDown);
|
|
// }
|
|
// };
|
|
|
|
// const onChange = async (date, dateString) => {
|
|
// if (!dateString) {
|
|
// setSelectedDate();
|
|
// } else {
|
|
// // Convert and format the date properly
|
|
// const Date1 = moment(dateString, 'DD-MM-YYYY').format('YYYY-MM-DDTHH:mm:ss');
|
|
|
|
// form?.setFieldsValue({ EmpDOJ: Date1 });
|
|
// await setSelectedDate(Date1);
|
|
// }
|
|
// };
|
|
|
|
const handleDayChange = (day) => {
|
|
setSelectedDays((prev) => ({
|
|
...prev,
|
|
[day]: !prev[day],
|
|
}));
|
|
};
|
|
|
|
const handleSelectAllDays = (checked) => {
|
|
setSelectAllDays(checked);
|
|
if (checked) {
|
|
setSelectedDays({
|
|
monday: true,
|
|
tuesday: true,
|
|
wednesday: true,
|
|
thursday: true,
|
|
friday: true,
|
|
saturday: true,
|
|
sunday: true,
|
|
});
|
|
} else {
|
|
setSelectedDays({
|
|
monday: false,
|
|
tuesday: false,
|
|
wednesday: false,
|
|
thursday: false,
|
|
friday: false,
|
|
saturday: false,
|
|
sunday: false,
|
|
});
|
|
}
|
|
};
|
|
|
|
const getEmployees = async () => {
|
|
const gettingTableData = await dispatch(
|
|
getEmpBasedOnCmpIdBrId({ cmpId: CompId, BranchId: BranchId })
|
|
).unwrap();
|
|
if (gettingTableData?.data?.statusCode === 1) {
|
|
setEmployeesDatas(gettingTableData?.data?.data);
|
|
}
|
|
};
|
|
|
|
const ServiceTypeFn = async () => {
|
|
let Response = await dispatch(ServiceType()).unwrap();
|
|
if (Response?.data?.statusCode == 1) {
|
|
setServicesDatas(Response?.data?.data);
|
|
} else {
|
|
setServicesDatas([]);
|
|
}
|
|
};
|
|
|
|
// const HandleEmpTypeDropDownData = async () => {
|
|
// const gettingEmpTypeDropDown = await dispatch(EmpTypeDropDown()).unwrap();
|
|
// if (gettingEmpTypeDropDown?.data?.statusCode === 1) {
|
|
// let finalEmpTypeDropDown = gettingEmpTypeDropDown?.data?.data?.filter(
|
|
// (value) => value.ActiveStatus === 'A'
|
|
// );
|
|
|
|
// if (gettingEmpTypeDropDown?.data?.data?.length === 1) {
|
|
// setseletedEmpTypeDrop(
|
|
// gettingEmpTypeDropDown?.data?.data?.length === 1
|
|
// ? gettingEmpTypeDropDown?.data?.data[0]?.ConfigId
|
|
// : null
|
|
// );
|
|
// form.current?.setFieldsValue({
|
|
// EmpType:
|
|
// gettingEmpTypeDropDown?.data?.data?.length === 1
|
|
// ? gettingEmpTypeDropDown?.data?.data[0]?.ConfigId
|
|
// : null,
|
|
// });
|
|
// await EmpTypeDropDownChange(
|
|
// gettingEmpTypeDropDown?.data?.data[0]?.ConfigId
|
|
// );
|
|
// }
|
|
// //
|
|
// setEmpTypeDropDownData(finalEmpTypeDropDown);
|
|
// }
|
|
// };
|
|
|
|
// const getPincodeValues = async (pinCode) => {
|
|
// let response = '';
|
|
// await fetch(`https://api.postalpincode.in/pincode/${pinCode}`)
|
|
// .then((res) => res.text())
|
|
// .then((text) => (response = JSON.parse(text)));
|
|
|
|
// if (response[0]['Status'] === 'Success') {
|
|
// setZipCodeData(true);
|
|
// form?.setFieldsValue({
|
|
// City: response[0]['PostOffice'][0]['Block'],
|
|
// Dist: response[0]['PostOffice'][0]['District'],
|
|
// State: response[0]['PostOffice'][0]['State'],
|
|
// });
|
|
// } else {
|
|
// setZipCodeData(false);
|
|
// }
|
|
// };
|
|
|
|
// const UserDropDownChange = async (e) => {
|
|
|
|
// let mob = userDropDown.filter((item) => item?.UserId === e);
|
|
|
|
// await getPincodeValues(mob?.[0]?.Zip);
|
|
// setSelectedUserData(e);
|
|
|
|
// const gettingEmpTypeDropDown = await dispatch(EmpTypeDropDown()).unwrap();
|
|
// if (gettingEmpTypeDropDown?.data?.statusCode === 1) {
|
|
// let finalEmpTypeDropDown = gettingEmpTypeDropDown?.data?.data?.filter(
|
|
// (value) => value.ActiveStatus === 'A'
|
|
// );
|
|
|
|
// if (gettingEmpTypeDropDown?.data?.data?.length === 1) {
|
|
// setseletedEmpTypeDrop(
|
|
// gettingEmpTypeDropDown?.data?.data?.length === 1
|
|
// ? gettingEmpTypeDropDown?.data?.data[0]?.ConfigId
|
|
// : null
|
|
// );
|
|
// form?.setFieldsValue({
|
|
// EmpType:
|
|
// gettingEmpTypeDropDown?.data?.data?.length === 1
|
|
// ? gettingEmpTypeDropDown?.data?.data[0]?.ConfigId
|
|
// : null,
|
|
// });
|
|
// await EmpTypeDropDownChange(
|
|
// gettingEmpTypeDropDown?.data?.data[0]?.ConfigId
|
|
// );
|
|
// }
|
|
// //
|
|
// setEmpTypeDropDownData(finalEmpTypeDropDown);
|
|
// }
|
|
// };
|
|
// const EmpTypeDropDownChange = async (e) => {
|
|
// form.setFieldsValue({ EmpType: e });
|
|
// setseletedEmpTypeDrop(e);
|
|
// const gettingEmpDesgDropDown = await dispatch(
|
|
// EmpDesgDropDown({ AppId: AppId })
|
|
// ).unwrap();
|
|
// if (gettingEmpDesgDropDown.data?.statusCode === 1) {
|
|
// let finalEmpDesgDropDown = gettingEmpDesgDropDown.data?.data?.filter(
|
|
// (value) => value.ActiveStatus === 'A'
|
|
// );
|
|
// if (gettingEmpDesgDropDown?.data?.data?.length === 1) {
|
|
// setseletedEmpDesigDrop(
|
|
// gettingEmpDesgDropDown?.data?.data?.length === 1
|
|
// ? gettingEmpDesgDropDown?.data?.data[0]?.ConfigId
|
|
// : null
|
|
// );
|
|
// form.setFieldsValue({
|
|
// EmpDesig:
|
|
// gettingEmpDesgDropDown?.data?.data?.length === 1
|
|
// ? gettingEmpDesgDropDown?.data?.data[0]?.ConfigId
|
|
// : null,
|
|
// });
|
|
// await EmpDesigDropDownChange(
|
|
// gettingEmpDesgDropDown?.data?.data[0]?.ConfigId
|
|
// );
|
|
// }
|
|
// setEmpDesgDropDownData(finalEmpDesgDropDown);
|
|
// }
|
|
// };
|
|
// const EmpDesigDropDownChange = async (e) => {
|
|
// form.setFieldsValue({ EmpDesig: e });
|
|
// setseletedEmpDesigDrop(e);
|
|
// const gettingEmpDeptDropDown = await dispatch(
|
|
// EmpDepartMentDropDown()
|
|
// ).unwrap();
|
|
// if (gettingEmpDeptDropDown.data?.statusCode === 1) {
|
|
// let finalEmpDeptDropDown = gettingEmpDeptDropDown.data?.data?.filter(
|
|
// (value) => value.ActiveStatus === 'A'
|
|
// );
|
|
// if (gettingEmpDeptDropDown?.data?.data?.length === 1) {
|
|
// setseletedEmpDeptDrop(
|
|
// gettingEmpDeptDropDown?.data?.data?.length === 1
|
|
// ? gettingEmpDeptDropDown?.data?.data[0]?.ConfigId
|
|
// : null
|
|
// );
|
|
// formsetFieldsValue({
|
|
// EmpDept:
|
|
// gettingEmpDeptDropDown?.data?.data?.length === 1
|
|
// ? gettingEmpDeptDropDown?.data?.data[0]?.ConfigId
|
|
// : null,
|
|
// });
|
|
// await EmpDeptDropDownChange(
|
|
// gettingEmpDeptDropDown?.data?.data[0]?.ConfigId
|
|
// );
|
|
// }
|
|
// setEmpDeptDropDownData(finalEmpDeptDropDown);
|
|
// }
|
|
// };
|
|
// const EmpDeptDropDownChange = async (e) => {
|
|
|
|
// form.setFieldsValue({ EmpDept: e });
|
|
// setseletedEmpDeptDrop(e);
|
|
// const gettingShiftDropDown = await dispatch(
|
|
// GettingShiftData(CompId)
|
|
// ).unwrap();
|
|
// if (gettingShiftDropDown.data?.statusCode === 1) {
|
|
// let finalShiftDropDown = gettingShiftDropDown.data?.data?.filter(
|
|
// (value) => value.ActiveStatus === 'A'
|
|
// );
|
|
// if (gettingShiftDropDown?.data?.data?.length === 1) {
|
|
// setseletedShiftDrop(
|
|
// gettingShiftDropDown?.data?.data?.length === 1
|
|
// ? gettingShiftDropDown?.data?.data[0]?.ShiftId
|
|
// : null
|
|
// );
|
|
// form?.setFieldsValue({
|
|
// EmpShiftId:
|
|
// gettingShiftDropDown?.data?.data?.length === 1
|
|
// ? gettingShiftDropDown?.data?.data[0]?.ShiftId
|
|
// : null,
|
|
// });
|
|
// await ShiftDropDownChange(gettingShiftDropDown?.data?.data[0]?.ShiftId);
|
|
// }
|
|
// setShiftDownData(finalShiftDropDown);
|
|
// }
|
|
// };
|
|
// const ShiftDropDownChange = async (e) => {
|
|
// form?.setFieldsValue({ EmpShiftId: e });
|
|
// setseletedShiftDrop(e);
|
|
// };
|
|
|
|
const handleTypeChange = (value) => {
|
|
setSelectedType(value);
|
|
setselectedTypeName(
|
|
ServicesDatas?.find((e) => e?.ConfigId == value)?.ConfigName
|
|
);
|
|
setSelectedCategory(null);
|
|
setSelectedSubCategory(null);
|
|
setSelectedCoach(null);
|
|
form.setFieldsValue({ type: value });
|
|
};
|
|
const handleTaxDropDownChange = async (TaxId) => {
|
|
form.setFieldsValue({ TaxId: TaxId });
|
|
await setSelectedTaxId(TaxId);
|
|
};
|
|
// Handle category change
|
|
const handleCategoryChange = (value) => {
|
|
dispatch(getProdSubCatData({ ConfigId: value }));
|
|
setSelectedCategory(value);
|
|
setSelectedSubCategory(null);
|
|
form.setFieldsValue({ 'Sport-category': value });
|
|
};
|
|
|
|
// Handle sub category change
|
|
const handleSubCategoryChange = (value) => {
|
|
form.setFieldsValue({ 'Sport-subCategory': value });
|
|
setSelectedSubCategory(value);
|
|
};
|
|
|
|
// Handle coach change
|
|
const handleCoachChange = (value) => {
|
|
setSelectedCoach(value);
|
|
setSelectedCoachName(
|
|
EmployeesDatas?.find((e) => e?.UserId == value)?.EmpFirstName
|
|
);
|
|
form.setFieldsValue({ coach: value });
|
|
};
|
|
|
|
// Duration controls
|
|
const increaseDuration = () => {
|
|
setSlotDuration((prev) => Math.min(prev + 1, 24));
|
|
};
|
|
|
|
const decreaseDuration = () => {
|
|
setSlotDuration((prev) => Math.max(prev - 1, 1));
|
|
};
|
|
|
|
const handleDurationInput = (value) => {
|
|
if (value >= 1 && value <= 24) {
|
|
setSlotDuration(value);
|
|
}
|
|
};
|
|
|
|
// Get field name based on category
|
|
// const getFieldName = () => {
|
|
// if (!selectedCategory) return 'Facility Name';
|
|
|
|
// const category = sportCategories.find(cat => cat.ConfigId === selectedCategory);
|
|
// if (!category) return 'Facility Name';
|
|
|
|
// switch (category.ConfigName.toLowerCase()) {
|
|
// case 'tennis':
|
|
// case 'badminton':
|
|
// case 'basketball':
|
|
// return 'Court Name';
|
|
// case 'swimming':
|
|
// return 'Swimming Pool Name';
|
|
// case 'cricket':
|
|
// case 'football':
|
|
// case 'volleyball':
|
|
// default:
|
|
// return 'Ground Name';
|
|
// }
|
|
// };
|
|
|
|
// Generate slots based on time range and duration
|
|
const generateSlots = () => {
|
|
if (!startTime || !endTime) {
|
|
message.error('Please select start and end time');
|
|
return;
|
|
}
|
|
|
|
const start = moment(startTime, 'HH:mm');
|
|
const end = moment(endTime, 'HH:mm');
|
|
if (end <= start) {
|
|
message.error('End time must be after start time');
|
|
return;
|
|
}
|
|
|
|
// Check if at least one day is selected
|
|
const hasSelectedDays = Object.values(selectedDays).some((day) => day);
|
|
if (!hasSelectedDays) {
|
|
message.error('Please select at least one day for slot availability');
|
|
return;
|
|
}
|
|
|
|
// Validate prices
|
|
if (!defaultPrice || defaultPrice < 1) {
|
|
message.error('Price Per Slot must be at least ₹1');
|
|
return;
|
|
}
|
|
|
|
if (
|
|
individualPricing &&
|
|
(!individualDefaultPrice || individualDefaultPrice < 1)
|
|
) {
|
|
message.error('Individual Price must be at least ₹1');
|
|
return;
|
|
}
|
|
|
|
const durationMinutes = slotDuration * 60;
|
|
const slots = [];
|
|
let currentTime = start;
|
|
let slotNumber = 1;
|
|
|
|
while (currentTime < end) {
|
|
const slotEnd = moment(currentTime).add(durationMinutes, 'minutes');
|
|
if (slotEnd > end) break;
|
|
|
|
// Set both individual and full slot prices
|
|
const individualPrice = individualPricing
|
|
? individualDefaultPrice
|
|
: defaultPrice;
|
|
const fullSlotPrice = defaultPrice;
|
|
|
|
slots.push({
|
|
id: `slot-${slotNumber}`,
|
|
SlotName: `Slot ${slotNumber}`,
|
|
// startTime: currentTime.format('HH:mm'),
|
|
AvailableFrom: currentTime.format('HH:mm'),
|
|
AvailableTo: slotEnd.format('HH:mm'),
|
|
// endTime: slotEnd.format('HH:mm'),
|
|
individualPrice: individualPrice,
|
|
MRP: fullSlotPrice,
|
|
SellPrice: fullSlotPrice,
|
|
// fullSlotPrice: fullSlotPrice,
|
|
editable: true,
|
|
individualPurchase: individualPricing,
|
|
OnlineApplicable: OnlineBooking,
|
|
active: true,
|
|
IsHoliday: null,
|
|
DayOfWeek: Object.keys(selectedDays)?.filter(
|
|
(day) => selectedDays[day]
|
|
),
|
|
});
|
|
|
|
currentTime = slotEnd;
|
|
slotNumber++;
|
|
}
|
|
|
|
if (slots.length === 0) {
|
|
Modal.warning({
|
|
title: 'No Slots Generated',
|
|
content:
|
|
'No slots can be generated with the current time range and duration.',
|
|
});
|
|
return;
|
|
}
|
|
|
|
setGeneratedSlots(slots);
|
|
};
|
|
|
|
// Slot management functions
|
|
const updateSlotName = (index, newName) => {
|
|
const updatedSlots = [...generatedSlots];
|
|
updatedSlots[index].SlotName = newName;
|
|
setGeneratedSlots(updatedSlots);
|
|
};
|
|
|
|
const updateIndividualPrice = (index, price) => {
|
|
const updatedSlots = [...generatedSlots];
|
|
updatedSlots[index].individualPrice = price || 0;
|
|
setGeneratedSlots(updatedSlots);
|
|
};
|
|
|
|
// const updateFullSlotPrice = (index, price) => {
|
|
// const updatedSlots = [...generatedSlots];
|
|
// updatedSlots[index].fullSlotPrice = price || 0;
|
|
// setGeneratedSlots(updatedSlots);
|
|
// };
|
|
|
|
const toggleIndividualPurchase = (index) => {
|
|
const updatedSlots = [...generatedSlots];
|
|
updatedSlots[index].individualPurchase =
|
|
!updatedSlots[index].individualPurchase;
|
|
setGeneratedSlots(updatedSlots);
|
|
};
|
|
|
|
const toggleOnlineApplicable = (index) => {
|
|
const updatedSlots = [...generatedSlots];
|
|
updatedSlots[index].OnlineApplicable =
|
|
!updatedSlots[index].OnlineApplicable;
|
|
setGeneratedSlots(updatedSlots);
|
|
};
|
|
|
|
const removeSlot = (index) => {
|
|
Modal.confirm({
|
|
title: 'Confirm Delete',
|
|
content: 'Are you sure you want to delete this slot?',
|
|
okText: 'Yes',
|
|
cancelText: 'No',
|
|
onOk() {
|
|
const updatedSlots = generatedSlots?.filter((_, i) => i !== index);
|
|
setGeneratedSlots(updatedSlots);
|
|
},
|
|
});
|
|
};
|
|
|
|
// const toggleSlotActive = (index) => {
|
|
// const updatedSlots = [...generatedSlots];
|
|
// updatedSlots[index].active = !updatedSlots[index].active;
|
|
// setGeneratedSlots(updatedSlots);
|
|
// };
|
|
const updateImageUrl = (url, index = 0) => {
|
|
// keep legacy single imageUrl for backward compatibility
|
|
setImageUrl(url);
|
|
setImageUrls((prev) => {
|
|
const copy = Array.isArray(prev) ? [...prev] : [];
|
|
copy[index] = {
|
|
...(copy[index] || {}),
|
|
image: url,
|
|
};
|
|
return copy;
|
|
});
|
|
};
|
|
// Image handling functions
|
|
// const updateImageUrls = (url, index = 0) => {
|
|
// // support updating a specific index in the images array
|
|
// setImageUrls(prev => {
|
|
// const copy = Array.isArray(prev) ? [...prev] : [];
|
|
// copy[index] = {
|
|
// ...(copy[index] || {}),
|
|
// image: url,
|
|
// };
|
|
// return copy;
|
|
// });
|
|
// // also update main image for legacy places
|
|
// setImageUrl(url);
|
|
// };
|
|
|
|
// const updateImageName = (name, index = 0) => {
|
|
// setImageUrls(prev => {
|
|
// const copy = Array.isArray(prev) ? [...prev] : [];
|
|
// copy[index] = {
|
|
// ...(copy[index] || {}),
|
|
// name: name,
|
|
// };
|
|
// return copy;
|
|
// });
|
|
// };
|
|
|
|
// const addimages = () => {
|
|
// setimageOpen(true);
|
|
|
|
// };
|
|
|
|
// const handleimage = () => {
|
|
// setimageOpen(false);
|
|
// setSelectedImage(null);
|
|
// };
|
|
|
|
// const submitimage = async () => {
|
|
// if (selectedImage) {
|
|
// setImageUrl(selectedImage.image);
|
|
// setOnlineImage(selectedImage.image);
|
|
// }
|
|
// setimageOpen(false);
|
|
// };
|
|
|
|
const getSelectedDaysText = () => {
|
|
const daysMap = {
|
|
monday: 'Mon',
|
|
tuesday: 'Tue',
|
|
wednesday: 'Wed',
|
|
thursday: 'Thu',
|
|
friday: 'Fri',
|
|
saturday: 'Sat',
|
|
sunday: 'Sun',
|
|
};
|
|
|
|
const selected = Object.entries(selectedDays)
|
|
?.filter(([_, isSelected]) => isSelected)
|
|
.map(([day]) => daysMap[day]);
|
|
|
|
return selected.length > 0 ? selected.join(', ') : 'No days selected';
|
|
};
|
|
|
|
const slotColumns = [
|
|
{
|
|
title: 'Sl.No',
|
|
key: 'sno',
|
|
align: 'center',
|
|
width: '60px',
|
|
render: (text, record, index) => index + 1,
|
|
},
|
|
{
|
|
title: 'Slot Name',
|
|
dataIndex: 'SlotName',
|
|
key: 'SlotName',
|
|
align: 'center',
|
|
render: (text, record, index) => (
|
|
<Input
|
|
value={text}
|
|
maxLength={30}
|
|
onChange={(e) => updateSlotName(index, e.target.value)}
|
|
className="sports-master__slot-input"
|
|
placeholder="Enter slot name"
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
title: 'Time Slot',
|
|
key: 'time',
|
|
align: 'center',
|
|
width: '120px',
|
|
render: (record) => (
|
|
<div className="sports-master__time-slot">
|
|
<div className="sports-master__time-value">
|
|
{record.AvailableFrom}
|
|
</div>
|
|
<div className="sports-master__time-separator">to</div>
|
|
<div className="sports-master__time-value">{record.AvailableTo}</div>
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
title: 'Days',
|
|
key: 'DayOfWeek',
|
|
align: 'center',
|
|
width: '150px',
|
|
render: (record) => {
|
|
const daysArray = Array.isArray(record?.DayOfWeek)
|
|
? record.DayOfWeek.map((day) => day.trim())
|
|
: [];
|
|
console.log(daysArray, 'daysArray11111111');
|
|
|
|
return (
|
|
<div className="sports-master__days-container">
|
|
{daysArray?.map((day, index) => (
|
|
<Tag key={index} color="blue" className="sports-master__day-tag">
|
|
{day?.[0]?.toUpperCase()}
|
|
</Tag>
|
|
))}
|
|
</div>
|
|
);
|
|
},
|
|
},
|
|
|
|
{
|
|
title: 'Individual Price (₹)',
|
|
dataIndex: 'individualPrice',
|
|
key: 'individualPrice',
|
|
align: 'center',
|
|
width: '140px',
|
|
render: (text, record, index) =>
|
|
record?.individualPurchase ? (
|
|
<InputNumber
|
|
value={text}
|
|
onChange={(value) => updateIndividualPrice(index, value)}
|
|
min={0}
|
|
max={99999}
|
|
className="sports-master__input-number"
|
|
formatter={(value) =>
|
|
`₹ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
|
}
|
|
parser={(value) => value.replace(/₹\s?|(,*)/g, '')}
|
|
size="small"
|
|
/>
|
|
) : (
|
|
<span>-</span>
|
|
),
|
|
},
|
|
// {
|
|
// title: 'Full Slot Price (₹)',
|
|
// dataIndex: 'fullSlotPrice',
|
|
// key: 'fullSlotPrice',
|
|
// align: 'center',
|
|
// width: '140px',
|
|
// render: (text, record, index) => (
|
|
// <InputNumber
|
|
// value={text}
|
|
// onChange={(value) => updateFullSlotPrice(index, value)}
|
|
// min={0}
|
|
// className="sports-master__input-number"
|
|
// formatter={value => `₹ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
|
|
// parser={value => value.replace(/₹\s?|(,*)/g, '')}
|
|
// size="small"
|
|
// />
|
|
// ),
|
|
// },
|
|
{
|
|
title: 'Individual Purchase',
|
|
dataIndex: 'individualPurchase',
|
|
key: 'individualPurchase',
|
|
align: 'center',
|
|
width: '120px',
|
|
render: (text, record, index) => (
|
|
<Checkbox
|
|
checked={text}
|
|
onChange={() => toggleIndividualPurchase(index)}
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
title: 'Online Booking',
|
|
dataIndex: 'OnlineApplicable',
|
|
key: 'OnlineApplicable',
|
|
align: 'center',
|
|
width: '120px',
|
|
render: (text, record, index) => (
|
|
<Checkbox
|
|
checked={text}
|
|
onChange={() => toggleOnlineApplicable(index)}
|
|
/>
|
|
),
|
|
},
|
|
// {
|
|
// title: 'Status',
|
|
// key: 'status',
|
|
// align: 'center',
|
|
// width: '100px',
|
|
// render: (record, _, index) => (
|
|
// <Switch
|
|
// checked={record.active}
|
|
// onChange={() => toggleSlotActive(index)}
|
|
// size="small"
|
|
// checkedChildren="A"
|
|
// unCheckedChildren="I"
|
|
// />
|
|
// ),
|
|
// },
|
|
{
|
|
title: 'Action',
|
|
key: 'action',
|
|
align: 'center',
|
|
width: '80px',
|
|
render: (text, record, index) => (
|
|
<Button
|
|
type="text"
|
|
danger
|
|
icon={<DeleteOutlined />}
|
|
onClick={() => removeSlot(index)}
|
|
size="small"
|
|
/>
|
|
),
|
|
},
|
|
];
|
|
|
|
const handleSubmit = async (values) => {
|
|
let UomId = UomPreference?.filter(
|
|
(item) =>
|
|
item.ConfigName?.toLowerCase() ===
|
|
(values?.maxCapacity > 1 ? 'members' : 'member')
|
|
)?.[0]?.['ConfigId'];
|
|
|
|
const today = new Date();
|
|
const formattedDate = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`;
|
|
let postData = {
|
|
ProdName:
|
|
selectedTypeName.toLowerCase() == 'coach'
|
|
? selectedCoachName
|
|
: values?.groundName,
|
|
...(selectedTypeName.toLowerCase() == 'coach' && {
|
|
TrainerId: selectedCoach,
|
|
}),
|
|
Size: values?.maxCapacity,
|
|
UOM: UomId,
|
|
MRP: '0',
|
|
SellPrice: '0',
|
|
ProdCat: selectedCategory,
|
|
ProdSubCat: selectedSubCategory,
|
|
Brand: null,
|
|
ProdCount: null,
|
|
ProdType: selectedType,
|
|
TaxId: SelectedTaxId,
|
|
Cess: 0,
|
|
CompId: CompId,
|
|
BranchId: BranchId,
|
|
AppId: AppId,
|
|
SuppId: '',
|
|
ProdLogo: imageUrl,
|
|
QtyBasedPrice: 'N',
|
|
ProdQtywisePriceDetails: [],
|
|
StockAvailable: 'N',
|
|
TokenAvailable: 'N',
|
|
OnePcsAvailable: individualPricing ? 'Y' : 'N',
|
|
IsEmiAllowed: 'N',
|
|
InwardDate: formattedDate,
|
|
AutoGenerateQr: 'N',
|
|
AutoGenerateSingleQr: 'N',
|
|
CreatedBy: UserId,
|
|
Rack: 0,
|
|
ProdVariantDetails: [],
|
|
ProdVariantName: '',
|
|
DiscountLimit: 0,
|
|
DiscountLimitType: 'F',
|
|
SlotHours: slotDuration,
|
|
SlotDetails: generatedSlots?.map((e) => {
|
|
return {
|
|
SlotName: e?.SlotName,
|
|
AvailableFrom: e?.AvailableFrom,
|
|
AvailableTo: e?.AvailableTo,
|
|
OnlineApplicable: e?.OnlineApplicable ? 'Y' : 'N',
|
|
MRP: e?.MRP,
|
|
SellPrice: e?.SellPrice,
|
|
SinglePrice: e?.individualPurchase ? e?.individualPrice : 0,
|
|
ExceptionFrom: '',
|
|
ExceptionTo: '',
|
|
IsHoliday: 'N',
|
|
DayOfWeek:
|
|
typeof e?.DayOfWeek === 'object' && e?.DayOfWeek !== null
|
|
? Object.keys(selectedDays)?.filter((day) => selectedDays[day])
|
|
: e?.DayOfWeek,
|
|
Remarks: 'string',
|
|
};
|
|
}),
|
|
SportDec: [
|
|
{
|
|
description: values?.description || '',
|
|
Facilities: values?.facilities || '',
|
|
Terms: values?.terms || '',
|
|
CancellationPolicy: values?.cancellationPolicy || '',
|
|
},
|
|
],
|
|
};
|
|
|
|
if (formType == 'add') {
|
|
try {
|
|
let response = await dispatch(postProductData(postData)).unwrap();
|
|
|
|
if (response?.data?.statusCode == 1) {
|
|
navigate(`${subDirectory}setting/product-master/`, {
|
|
state: {
|
|
Notiffy: {
|
|
messageType: 'success',
|
|
messageData: response?.data?.response,
|
|
},
|
|
},
|
|
});
|
|
}
|
|
} catch (err) {}
|
|
} else {
|
|
try {
|
|
delete postData?.CreatedBy;
|
|
postData = {
|
|
...postData,
|
|
ProdId: editstate?.ProdId,
|
|
UniqueId: editstate?.UniqueId,
|
|
UpdatedBy: UserId,
|
|
};
|
|
console.log(postData, 'postData');
|
|
let response = await dispatch(putProductData(postData)).unwrap();
|
|
|
|
if (response?.data?.statusCode == 1) {
|
|
navigate(`${subDirectory}setting/product-master/`, {
|
|
state: {
|
|
Notiffy: {
|
|
messageType: 'success',
|
|
messageData: response?.data?.response,
|
|
},
|
|
},
|
|
});
|
|
}
|
|
} catch (err) {}
|
|
}
|
|
};
|
|
|
|
// const addCategory = () => {
|
|
// setOpenCategoryModal(true);
|
|
// };
|
|
|
|
// const addSubCategory = () => {
|
|
// if (!selectedCategory) {
|
|
// Modal.warning({
|
|
// title: 'Warning',
|
|
// content: 'Please select a category first',
|
|
// });
|
|
// return;
|
|
// }
|
|
// setOpenSubCategoryModal(true);
|
|
// };
|
|
|
|
const addCoach = () => {
|
|
// setOpenCoachModal(true);
|
|
navigate(`${subDirectory}setting/employee-master/new`);
|
|
};
|
|
|
|
// const handleCategoryModalClose = () => {
|
|
// setOpenCategoryModal(false);
|
|
// };
|
|
|
|
// const handleSubCategoryModalClose = () => {
|
|
// setOpenSubCategoryModal(false);
|
|
// };
|
|
|
|
// const handleCoachModalClose = () => {
|
|
// setOpenCoachModal(false);
|
|
// };
|
|
|
|
// const submitCategory = () => {
|
|
// Modal.success({
|
|
// title: 'Success',
|
|
// content: 'Category added successfully!',
|
|
// });
|
|
// setOpenCategoryModal(false);
|
|
// };
|
|
|
|
// const submitSubCategory = () => {
|
|
// Modal.success({
|
|
// title: 'Success',
|
|
// content: 'Sub-category added successfully!',
|
|
// });
|
|
// setOpenSubCategoryModal(false);
|
|
// };
|
|
|
|
// const submitCoach = async () => {
|
|
|
|
// let postData = {
|
|
// "UserId": selectedUserData,
|
|
// "CompId": CompId,
|
|
// "BranchId": BranchId,
|
|
// "EmpFirstName": userDropDown?.find((e) => e?.UserId == selectedUserData)?.UserName,
|
|
// // "EmpLastName": "string",
|
|
// "EmpType": seletedEmpTypeDrop,
|
|
// "EmpDesig": seletedEmpDesigDrop,
|
|
// "EmpDept": seletedEmpDeptDrop,
|
|
// "EmpDOJ": "2025-10-14T12:28:22.596Z",
|
|
// "EmpPhotoLink": "",
|
|
// "RoleId": 0,
|
|
// "EmpShiftId": seletedShiftDrop,
|
|
// // "MobileAppAccess": "string",
|
|
// // "Address1": "string",
|
|
// // "Address2": "string",
|
|
// // "Zip": 0,
|
|
// // "City": "string",
|
|
// // "Dist": "string",
|
|
// // "State": "string",
|
|
// // "Latitude": 0,
|
|
// // "Longitude": 0,
|
|
// // "Password": "string",
|
|
// // "Pin": "string",
|
|
// "MobileNo": form?.getFieldValue("MobileNo"),
|
|
// // "MailId": "string",
|
|
// "Description": form?.getFieldValue("coachQualifications"),
|
|
// "Certification": "string",
|
|
// "Experience": form?.getFieldValue("coachExperience"),
|
|
// // "ImageDetails": [
|
|
// // {
|
|
// // "ImageUrl": "string",
|
|
// // "ImageType": "string",
|
|
// // "DisplayOrder": "string"
|
|
// // }
|
|
// // ],
|
|
// ImageDetails: (imageUrls || []).filter(item => item && (item.image || item.name)).map((item, index) => ({
|
|
// ImageUrl: item.image || '',
|
|
// ImageName: item.name || '',
|
|
// ImageType: "Coach",
|
|
// DisplayOrder: index + 1
|
|
|
|
// })) || [],
|
|
// "CreatedBy": UserId
|
|
// }
|
|
|
|
// let response = await dispatch(postEmp(postData)).unwrap();
|
|
// if (response?.data?.statusCode == 1) {
|
|
// Modal.success({
|
|
// title: 'Success',
|
|
// content: 'Coach added successfully!',
|
|
// });
|
|
// setOpenCoachModal(false);
|
|
// }
|
|
|
|
// };
|
|
|
|
// Update all slot prices when pricing settings change
|
|
// useEffect(() => {
|
|
// if (generatedSlots.length > 0) {
|
|
// const updatedSlots = generatedSlots.map(slot => ({
|
|
// ...slot,
|
|
// individualPrice: individualPricing ? individualDefaultPrice : defaultPrice,
|
|
// fullSlotPrice: fullSlotDefaultPrice || defaultPrice,
|
|
// // DayOfWeek: { ...selectedDays }
|
|
// // Update days for all slots when days change
|
|
// }));
|
|
// setGeneratedSlots(updatedSlots);
|
|
// }
|
|
// }, [individualPricing, individualDefaultPrice, defaultPrice, fullSlotDefaultPrice, selectedDays]);
|
|
|
|
// Load images when modal opens
|
|
// useEffect(() => {
|
|
// if (imageopen) {
|
|
// imagecall();
|
|
// }
|
|
// }, [imageopen]);
|
|
|
|
// Calculate totals for summary
|
|
const getOptionLabel = (option, selected) => {
|
|
return selected
|
|
? option.TaxPercentage + ' %'
|
|
: option.TaxIdName + ' - ' + option.TaxPercentage + ' % ';
|
|
};
|
|
const calculateTotals = () => {
|
|
const activeSlots = generatedSlots?.filter((slot) => slot.active);
|
|
const totalIndividualRevenue = activeSlots?.reduce(
|
|
(sum, slot) => sum + (slot.individualPrice || 0),
|
|
0
|
|
);
|
|
const totalFullSlotRevenue = activeSlots?.reduce(
|
|
(sum, slot) => sum + (slot.fullSlotPrice || 0),
|
|
0
|
|
);
|
|
|
|
return {
|
|
totalSlots: generatedSlots.length,
|
|
activeSlots: activeSlots.length,
|
|
totalIndividualRevenue,
|
|
totalFullSlotRevenue,
|
|
totalRevenue: totalIndividualRevenue + totalFullSlotRevenue,
|
|
};
|
|
};
|
|
|
|
const totals = calculateTotals();
|
|
|
|
return (
|
|
<div className="sports-master">
|
|
<div className="sports-master__header">
|
|
<h1 className="sports-master__title">Add Slot</h1>
|
|
{/* <p className="sports-master__subtitle">
|
|
Create and manage time slots for sports grounds and coaching sessions
|
|
</p> */}
|
|
</div>
|
|
|
|
<Form
|
|
form={form}
|
|
layout="vertical"
|
|
onFinish={handleSubmit}
|
|
initialValues={{
|
|
maxPlayers: 1,
|
|
slotDuration: 0.5,
|
|
defaultPrice: 0,
|
|
individualDefaultPrice: 0,
|
|
// fullSlotDefaultPrice: 0
|
|
}}
|
|
>
|
|
<div className="sports-master__basic-info">
|
|
<div className="sports-master__form-row">
|
|
<div className="sports-master__form-container">
|
|
<div className="sports-master__form-group">
|
|
<div className="sports-master__form-field">
|
|
<Form.Item
|
|
name="type"
|
|
rules={[{ required: true, message: 'Please select type' }]}
|
|
>
|
|
<DropDowns
|
|
options={ServicesDatas?.map((e) => ({
|
|
value: e.ConfigId,
|
|
label: e.ConfigName,
|
|
}))}
|
|
// label="Select Type"
|
|
label={<label class="required">Select Type</label>}
|
|
className="field-DropDown"
|
|
onChangeFunction={handleTypeChange}
|
|
valueData={selectedType}
|
|
isOnchanges={selectedType ? true : false}
|
|
disabled={formType === 'edit' ? true : false}
|
|
/>
|
|
</Form.Item>
|
|
</div>
|
|
|
|
{selectedTypeName?.toLowerCase() === 'ground' && (
|
|
<>
|
|
<div className="sports-master__form-field">
|
|
<Form.Item
|
|
name="groundName"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: `Please enter Ground Name `,
|
|
},
|
|
]}
|
|
>
|
|
<InputField
|
|
label={
|
|
<label class="required">Enter Ground Name</label>
|
|
}
|
|
isOnChange={form.getFieldValue('groundName')}
|
|
/>
|
|
</Form.Item>
|
|
</div>
|
|
|
|
<div className="sports-master__form-field">
|
|
<Form.Item
|
|
name="Sport-category"
|
|
// label="Sport Category"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: 'Please select sport category',
|
|
},
|
|
]}
|
|
>
|
|
<div style={{ display: 'flex' }}>
|
|
<DropDowns
|
|
options={ProdCatData.map((cat) => ({
|
|
value: cat.ConfigId,
|
|
label: cat.ConfigName,
|
|
}))}
|
|
label={
|
|
<label class="required">Sport Category</label>
|
|
}
|
|
className="field-DropDown"
|
|
onChangeFunction={handleCategoryChange}
|
|
valueData={selectedCategory}
|
|
isOnchanges={selectedCategory ? true : false}
|
|
disabled={formType === 'edit' ? true : false}
|
|
/>
|
|
{/* <Tooltip title="Add New Category">
|
|
<PlusCircleOutlined
|
|
onClick={addCategory}
|
|
className="sports-master__plus-icon"
|
|
/>
|
|
</Tooltip> */}
|
|
</div>
|
|
</Form.Item>
|
|
</div>
|
|
|
|
{selectedCategory && (
|
|
<div className="sports-master__form-field">
|
|
<Form.Item
|
|
name="Sport-subCategory"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: 'Please select sport sub category',
|
|
},
|
|
]}
|
|
>
|
|
<DropDowns
|
|
options={ProdSubCatData.map((subCat) => ({
|
|
value: subCat.ConfigId,
|
|
label: subCat.ConfigName,
|
|
}))}
|
|
label="Sport Sub Category"
|
|
className="field-DropDown"
|
|
onChangeFunction={handleSubCategoryChange}
|
|
valueData={selectedSubCategory}
|
|
isOnchanges={selectedSubCategory ? true : false}
|
|
disabled={formType === 'edit' ? true : false}
|
|
/>
|
|
</Form.Item>
|
|
{/* <Tooltip title="Add New Sub Category">
|
|
<PlusCircleOutlined
|
|
onClick={addSubCategory}
|
|
className="sports-master__plus-icon"
|
|
/>
|
|
</Tooltip> */}
|
|
</div>
|
|
)}
|
|
</>
|
|
)}
|
|
|
|
{selectedTypeName?.toLowerCase() === 'coach' && (
|
|
<>
|
|
<div className="sports-master__form-field">
|
|
<Form.Item
|
|
name="coach"
|
|
rules={[
|
|
{ required: true, message: 'Please select coach' },
|
|
]}
|
|
>
|
|
<div style={{ display: 'flex' }}>
|
|
<DropDowns
|
|
options={EmployeesDatas?.map((coach) => ({
|
|
value: coach.UserId,
|
|
label: `${coach.EmpFirstName}`,
|
|
}))}
|
|
label="Select Coach"
|
|
className="field-DropDown"
|
|
onChangeFunction={handleCoachChange}
|
|
valueData={selectedCoach}
|
|
isOnchanges={selectedCoach ? true : false}
|
|
/>
|
|
<Tooltip title="Add New Coach">
|
|
<PlusCircleOutlined
|
|
onClick={addCoach}
|
|
className="sports-master__plus-icon"
|
|
/>
|
|
</Tooltip>
|
|
</div>
|
|
</Form.Item>
|
|
</div>
|
|
|
|
<div className="sports-master__form-field">
|
|
<Form.Item name="category">
|
|
<DropDowns
|
|
options={ProdCatData.map((cat) => ({
|
|
value: cat.ConfigId,
|
|
label: cat.ConfigName,
|
|
}))}
|
|
label="Sport Category"
|
|
className="field-DropDown"
|
|
onChangeFunction={handleCategoryChange}
|
|
valueData={selectedCategory}
|
|
isOnchanges={false}
|
|
// disabled={!!selectedCoach}
|
|
/>
|
|
</Form.Item>
|
|
</div>
|
|
|
|
{selectedCategory && (
|
|
<div className="sports-master__form-field">
|
|
<Form.Item name="subCategory">
|
|
<DropDowns
|
|
options={ProdSubCatData.map((subCat) => ({
|
|
value: subCat.ConfigId,
|
|
label: subCat.ConfigName,
|
|
}))}
|
|
label="Sport Sub Category"
|
|
className="field-DropDown"
|
|
onChangeFunction={handleSubCategoryChange}
|
|
valueData={selectedSubCategory}
|
|
isOnchanges={false}
|
|
// disabled={!!selectedCoach}
|
|
/>
|
|
</Form.Item>
|
|
</div>
|
|
)}
|
|
</>
|
|
)}
|
|
|
|
<div className="sports-master__tax-field">
|
|
<Form.Item
|
|
name="TaxId"
|
|
rules={[{ required: true, message: 'Please select Tax' }]}
|
|
>
|
|
<DropDowns
|
|
options={TaxData?.map((option) => ({
|
|
value: option.TaxId,
|
|
label: getOptionLabel(
|
|
option,
|
|
SelectedTaxId === option.TaxId
|
|
),
|
|
}))}
|
|
label="Tax"
|
|
className="field-DropDown"
|
|
isOnchanges={SelectedTaxId ? true : false}
|
|
onChangeFunction={handleTaxDropDownChange}
|
|
valueData={SelectedTaxId}
|
|
/>
|
|
</Form.Item>
|
|
</div>
|
|
|
|
<div className="sports-master__form-field">
|
|
<Form.Item
|
|
name="maxCapacity"
|
|
//label={selectedTypeName?.toLowerCase() === 'coach' ? "Maximum Trainees" : "Maximum Players"}
|
|
rules={[
|
|
{ required: true, message: 'Please enter number' },
|
|
{ pattern: /^[0-9]+$/, message: 'Only numbers allowed' },
|
|
]}
|
|
>
|
|
<InputField
|
|
autoComplete="off"
|
|
label={
|
|
<label class="required">
|
|
{selectedTypeName?.toLowerCase() === 'coach'
|
|
? 'Maximum Trainees'
|
|
: 'Maximum Players'}
|
|
</label>
|
|
}
|
|
isOnChange={form.getFieldValue('maxCapacity')}
|
|
|
|
/>
|
|
</Form.Item>
|
|
</div>
|
|
|
|
{/* {selectedType === 'coach' && selectedCoach && (
|
|
<div className="sports-master__form-field">
|
|
<div className="sports-master__coach-details">
|
|
<div>
|
|
<strong>Coach Details:</strong>
|
|
</div>
|
|
<div>
|
|
{coaches.find(c => c.CoachId === selectedCoach)?.CoachName} -
|
|
{coaches.find(c => c.CoachId === selectedCoach)?.Sport} (
|
|
{coaches.find(c => c.CoachId === selectedCoach)?.Specialization})
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)} */}
|
|
|
|
{selectedTypeName && (
|
|
<div className="sports-master__image-container">
|
|
<div className="sports-master__image-upload">
|
|
<div style={{ marginBottom: '2px' }}>
|
|
<label className="sports-master__image-label">
|
|
{selectedTypeName?.toLowerCase() === 'coach'
|
|
? 'Coach Image'
|
|
: 'Facility Image'}
|
|
</label>
|
|
</div>
|
|
|
|
<div className="sports-master__image-actions">
|
|
<CropUpload
|
|
onlineImage={''}
|
|
ImageLink={imageUrl}
|
|
updateImageUrl={updateImageUrl}
|
|
/>
|
|
|
|
{/* <div>
|
|
<Button
|
|
type="default"
|
|
onClick={addimages}
|
|
style={{ width: '100%' }}
|
|
>
|
|
Browse Online Images
|
|
</Button>
|
|
</div> */}
|
|
</div>
|
|
|
|
{/* {imageUrl && (
|
|
<div style={{ marginTop: '12px' }}>
|
|
<div style={{
|
|
width: '100px',
|
|
height: '100px',
|
|
margin: '0 auto',
|
|
border: '1px solid #d9d9d9',
|
|
borderRadius: '4px',
|
|
overflow: 'hidden'
|
|
}}>
|
|
<img
|
|
src={imageUrl}
|
|
alt={selectedType === 'coach' ? 'Coach' : 'Facility'}
|
|
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
|
|
/>
|
|
</div>
|
|
</div>
|
|
)} */}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<Collapse defaultActiveKey={['1']} className="sports-master__collapse">
|
|
<Panel header="Slot Configuration" key="1">
|
|
{/* Day Selection */}
|
|
<div className="sports-master__days-section">
|
|
<Form.Item label="Available Days" required>
|
|
<div className="sports-master__days-wrapper">
|
|
<div className="sports-master__select-all">
|
|
<Checkbox
|
|
checked={selectAllDays}
|
|
onChange={(e) => handleSelectAllDays(e.target.checked)}
|
|
>
|
|
<strong>Select All Days</strong>
|
|
</Checkbox>
|
|
</div>
|
|
|
|
<div className="sports-master__days-grid">
|
|
<div className="sports-master__day-item">
|
|
<Checkbox
|
|
checked={selectedDays.monday}
|
|
onChange={() => handleDayChange('monday')}
|
|
>
|
|
Monday
|
|
</Checkbox>
|
|
</div>
|
|
<div className="sports-master__day-item">
|
|
<Checkbox
|
|
checked={selectedDays.tuesday}
|
|
onChange={() => handleDayChange('tuesday')}
|
|
>
|
|
Tuesday
|
|
</Checkbox>
|
|
</div>
|
|
<div className="sports-master__day-item">
|
|
<Checkbox
|
|
checked={selectedDays.wednesday}
|
|
onChange={() => handleDayChange('wednesday')}
|
|
>
|
|
Wednesday
|
|
</Checkbox>
|
|
</div>
|
|
<div className="sports-master__day-item">
|
|
<Checkbox
|
|
checked={selectedDays.thursday}
|
|
onChange={() => handleDayChange('thursday')}
|
|
>
|
|
Thursday
|
|
</Checkbox>
|
|
</div>
|
|
<div className="sports-master__day-item">
|
|
<Checkbox
|
|
checked={selectedDays.friday}
|
|
onChange={() => handleDayChange('friday')}
|
|
>
|
|
Friday
|
|
</Checkbox>
|
|
</div>
|
|
<div className="sports-master__day-item">
|
|
<Checkbox
|
|
checked={selectedDays.saturday}
|
|
onChange={() => handleDayChange('saturday')}
|
|
>
|
|
Saturday
|
|
</Checkbox>
|
|
</div>
|
|
<div className="sports-master__day-item">
|
|
<Checkbox
|
|
checked={selectedDays.sunday}
|
|
onChange={() => handleDayChange('sunday')}
|
|
>
|
|
Sunday
|
|
</Checkbox>
|
|
</div>
|
|
</div>
|
|
|
|
{/* <div className="sports-master__selected-days">
|
|
<strong>Selected Days:</strong> {getSelectedDaysText()}
|
|
</div> */}
|
|
</div>
|
|
</Form.Item>
|
|
</div>
|
|
|
|
<div
|
|
style={{ display: 'flex', flexWrap: 'wrap', gap: '16px' }}
|
|
className="slotDurationSprt"
|
|
>
|
|
<div
|
|
style={{
|
|
boxSizing: 'border-box',
|
|
// padding: '8px',
|
|
}}
|
|
>
|
|
<Form.Item label="Slot Duration (hours)">
|
|
<div className="sports-master__duration-controls">
|
|
<Button
|
|
onClick={decreaseDuration}
|
|
disabled={slotDuration <= 1}
|
|
type="primary"
|
|
className="sports-master__duration-button"
|
|
icon={<MinusOutlined />}
|
|
/>
|
|
<InputNumber
|
|
value={slotDuration}
|
|
onChange={handleDurationInput}
|
|
min={1}
|
|
max={24}
|
|
step={1}
|
|
className="sports-master__duration-input"
|
|
formatter={(value) => `${value} hrs`}
|
|
parser={(value) => value.replace(' hrs', '')}
|
|
/>
|
|
<Button
|
|
onClick={increaseDuration}
|
|
disabled={slotDuration >= 24}
|
|
type="primary"
|
|
className="sports-master__duration-button"
|
|
icon={<PlusOutlined />}
|
|
/>
|
|
</div>
|
|
</Form.Item>
|
|
</div>
|
|
|
|
<div
|
|
style={{
|
|
boxSizing: 'border-box',
|
|
// padding: '8px',
|
|
// width: '11%',
|
|
}}
|
|
>
|
|
<Form.Item
|
|
label="Start Time - End Time"
|
|
rules={[
|
|
{ required: true, message: 'Please select time range' },
|
|
]}
|
|
>
|
|
<SafeRangeTimePicker
|
|
format="HH:mm"
|
|
className="sports-master__input-number"
|
|
value={
|
|
startTime && endTime
|
|
? [moment(startTime, 'HH:mm'), moment(endTime, 'HH:mm')]
|
|
: null
|
|
}
|
|
onChange={(times, timeStrings) => {
|
|
if (times && timeStrings) {
|
|
setStartTime(timeStrings[0]);
|
|
setEndTime(timeStrings[1]);
|
|
} else {
|
|
setStartTime(null);
|
|
setEndTime(null);
|
|
}
|
|
}}
|
|
popupClassName="no-scroll-timepicker"
|
|
placeholder={['Start time', 'End time']}
|
|
/>
|
|
</Form.Item>
|
|
</div>
|
|
{/* </div> */}
|
|
|
|
{/* <div style={{ display: 'flex', flexWrap: 'wrap', gap: '16px' }}> */}
|
|
<div
|
|
style={{
|
|
boxSizing: 'border-box',
|
|
// padding: '4px',
|
|
// width: '11%',
|
|
}}
|
|
>
|
|
<Form.Item name="defaultPrice" label="Price Per Slot">
|
|
<InputNumber
|
|
min={0}
|
|
max={99999}
|
|
className="sports-master__input-number"
|
|
formatter={(value) =>
|
|
`₹ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
|
}
|
|
parser={(value) => value.replace(/₹\s?|(,*)/g, '')}
|
|
onChange={setDefaultPrice}
|
|
value={defaultPrice}
|
|
/>
|
|
</Form.Item>
|
|
</div>
|
|
|
|
<div
|
|
style={{
|
|
boxSizing: 'border-box',
|
|
// padding: '4px',
|
|
// width: '14%',
|
|
}}
|
|
>
|
|
<Form.Item>
|
|
<Checkbox
|
|
checked={individualPricing}
|
|
onChange={(e) => setIndividualPricing(e.target.checked)}
|
|
>
|
|
Individual Pricing
|
|
</Checkbox>
|
|
</Form.Item>
|
|
</div>
|
|
<div
|
|
style={{
|
|
boxSizing: 'border-box',
|
|
// padding: '4px',
|
|
// width: '15%',
|
|
}}
|
|
>
|
|
<Form.Item>
|
|
<Checkbox
|
|
checked={OnlineBooking}
|
|
onChange={(e) => setOnlineBooking(e.target.checked)}
|
|
>
|
|
Online Booking
|
|
</Checkbox>
|
|
</Form.Item>
|
|
</div>
|
|
|
|
{individualPricing && (
|
|
<div
|
|
style={{
|
|
boxSizing: 'border-box',
|
|
// padding: '8px',
|
|
// width: '13%',
|
|
}}
|
|
>
|
|
<Form.Item
|
|
name="individualDefaultPrice"
|
|
label="Individual Price"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: 'Please enter individual price',
|
|
},
|
|
]}
|
|
>
|
|
<InputNumber
|
|
className="sports-master__input-number"
|
|
max={99999}
|
|
formatter={(value) =>
|
|
`₹ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
|
}
|
|
parser={(value) => value.replace(/₹\s?|(,*)/g, '')}
|
|
onChange={setIndividualDefaultPrice}
|
|
value={individualDefaultPrice}
|
|
/>
|
|
</Form.Item>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="sports-master__config-summary">
|
|
<Space
|
|
direction="vertical"
|
|
className="sports-master__summary-content"
|
|
>
|
|
<div className="sports-master__summary-title">
|
|
<InfoCircleOutlined style={{ marginRight: '8px' }} />
|
|
Configuration Summary
|
|
</div>
|
|
<div>
|
|
{selectedTypeName && (
|
|
<>
|
|
<strong>Type:</strong>{' '}
|
|
{selectedTypeName === 'Ground' ? 'Ground' : 'Coach'} |
|
|
</>
|
|
)}
|
|
<strong> Days:</strong> {getSelectedDaysText()}
|
|
</div>
|
|
{/* <div>
|
|
<strong>Pricing Mode:</strong> {individualPricing ? 'Individual ' : 'Standard Pricing'}
|
|
</div> */}
|
|
{individualPricing && (
|
|
<div>
|
|
<strong>Default Individual Price:</strong> ₹
|
|
{individualDefaultPrice || ' 0'}
|
|
</div>
|
|
)}
|
|
</Space>
|
|
</div>
|
|
|
|
<Button
|
|
type="primary"
|
|
onClick={generateSlots}
|
|
disabled={!startTime || !endTime}
|
|
icon={<PlusOutlined />}
|
|
size="medium"
|
|
>
|
|
Generate Slots
|
|
</Button>
|
|
</Panel>
|
|
</Collapse>
|
|
|
|
{/* Generated Slots Section */}
|
|
{generatedSlots.length > 0 && (
|
|
<Collapse
|
|
defaultActiveKey={['1']}
|
|
className="sports-master__collapse"
|
|
>
|
|
<Panel
|
|
header={
|
|
<Space>
|
|
<span>Generated Slots ({generatedSlots.length} slots)</span>
|
|
{individualPricing && (
|
|
<Tag color="blue">Dual Pricing Mode</Tag>
|
|
)}
|
|
<Tag color={totals.activeSlots > 0 ? 'green' : 'red'}>
|
|
{totals.activeSlots} Active
|
|
</Tag>
|
|
<Tag color="purple">{getSelectedDaysText()}</Tag>
|
|
</Space>
|
|
}
|
|
key="1"
|
|
>
|
|
<Table
|
|
columns={slotColumns}
|
|
dataSource={generatedSlots}
|
|
pagination={false}
|
|
rowKey="id"
|
|
// scroll={{ x: 1100 }}
|
|
size="small"
|
|
className="sports-master__collapse"
|
|
/>
|
|
|
|
<div className="sports-master__stats-container">
|
|
<div className="sports-master__stats-grid">
|
|
<div className="sports-master__stat-item">
|
|
<div className="sports-master__stat-content">
|
|
<div className="sports-master__stat-label">
|
|
Total Slots
|
|
</div>
|
|
<div className="sports-master__stat-value sports-master__stat-value--primary">
|
|
{totals.totalSlots}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="sports-master__stat-item">
|
|
<div className="sports-master__stat-content">
|
|
<div className="sports-master__stat-label">
|
|
Active Slots
|
|
</div>
|
|
<div className="sports-master__stat-value sports-master__stat-value--success">
|
|
{totals.activeSlots}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="sports-master__stat-item">
|
|
<div className="sports-master__stat-content">
|
|
<div className="sports-master__stat-label">
|
|
Individual Revenue
|
|
</div>
|
|
<div className="sports-master__stat-value sports-master__stat-value--warning">
|
|
₹{totals.totalIndividualRevenue}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{/* <div style={{ flex: '1 1 25%', minWidth: 160 }}>
|
|
<div style={{ textAlign: 'center' }}>
|
|
<div style={{ fontSize: '12px', color: '#666' }}>Full Slot Revenue</div>
|
|
<div style={{ fontSize: '18px', fontWeight: 'bold', color: '#eb2f96' }}>
|
|
₹{totals.totalFullSlotRevenue}
|
|
</div>
|
|
</div>
|
|
</div> */}
|
|
</div>
|
|
<div className="sports-master__stats-footer">
|
|
<div className="sports-master__stats-footer-text">
|
|
Available on: <strong>{getSelectedDaysText()}</strong>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Panel>
|
|
</Collapse>
|
|
)}
|
|
|
|
{/* Additional Information */}
|
|
{/* <Collapse className="sports-master__collapse">
|
|
<Panel header="Additional Information" key="1">
|
|
<div className="sports-master__additional-info">
|
|
<div className="sports-master__info-field">
|
|
<Form.Item name="description" label="Description">
|
|
<TextArea
|
|
rows={4}
|
|
placeholder="Enter additional description about the slots, facilities, rules, etc..."
|
|
/>
|
|
</Form.Item>
|
|
</div>
|
|
<div className="sports-master__info-field">
|
|
<Form.Item name="facilities" label="Facilities & Amenities">
|
|
<TextArea
|
|
rows={4}
|
|
placeholder="List available facilities, equipment, amenities..."
|
|
/>
|
|
</Form.Item>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="sports-master__additional-info">
|
|
<div className="sports-master__info-field">
|
|
<Form.Item name="terms" label="Terms & Conditions">
|
|
<TextArea
|
|
rows={3}
|
|
placeholder="Enter booking terms and conditions..."
|
|
/>
|
|
</Form.Item>
|
|
</div>
|
|
<div className="sports-master__info-field">
|
|
<Form.Item name="cancellationPolicy" label="Cancellation Policy">
|
|
<TextArea
|
|
rows={3}
|
|
placeholder="Enter cancellation policy..."
|
|
/>
|
|
</Form.Item>
|
|
</div>
|
|
</div>
|
|
</Panel>
|
|
</Collapse> */}
|
|
|
|
{/* Submit Button */}
|
|
<Form.Item>
|
|
<Button
|
|
type="primary"
|
|
htmlType="submit"
|
|
size="large"
|
|
icon={<ArrowRightOutlined />}
|
|
disabled={generatedSlots.length === 0}
|
|
className="sports-master__submit-button"
|
|
>
|
|
Submit
|
|
</Button>
|
|
</Form.Item>
|
|
</Form>
|
|
|
|
{/* <DefaultModal
|
|
title="Browse Online Images"
|
|
width={800}
|
|
open={imageopen}
|
|
footer={true}
|
|
buttonText="Select Image"
|
|
children={
|
|
<div>
|
|
<div style={{ marginBottom: '16px' }}>
|
|
<p>Select an image for your {selectedType === 'coach' ? 'coach' : 'facility'}:</p>
|
|
</div>
|
|
<div className="sports-master__image-grid">
|
|
{imagedata?.map((item, index) => (
|
|
<div
|
|
key={index}
|
|
className={`sports-master__image-item ${selectedImage === item ? 'sports-master__image-item--selected' : 'sports-master__image-item--default'}`}
|
|
onClick={() => setSelectedImage(item)}
|
|
>
|
|
<img
|
|
src={item.image}
|
|
alt={`Sports ${selectedType === 'coach' ? 'coach' : 'facility'} ${index + 1}`}
|
|
className="sports-master__image-preview"
|
|
/>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
}
|
|
handleSubmit={submitimage}
|
|
handleCancel={handleimage}
|
|
/> */}
|
|
|
|
{/* <Modal
|
|
title="Add New Category"
|
|
open={openCategoryModal}
|
|
onOk={submitCategory}
|
|
onCancel={handleCategoryModalClose}
|
|
okText="Submit"
|
|
cancelText="Cancel"
|
|
>
|
|
<Form layout="vertical">
|
|
<Form.Item
|
|
label="Category Name"
|
|
name="categoryName"
|
|
rules={[{ required: true, message: 'Please enter category name' }]}
|
|
>
|
|
<Input placeholder="Enter category name" />
|
|
</Form.Item>
|
|
<Form.Item
|
|
label="Description"
|
|
name="categoryDescription"
|
|
>
|
|
<TextArea rows={3} placeholder="Enter category description" />
|
|
</Form.Item>
|
|
</Form>
|
|
</Modal> */}
|
|
|
|
{/* <Modal
|
|
title="Add New Sub Category"
|
|
open={openSubCategoryModal}
|
|
onOk={submitSubCategory}
|
|
onCancel={handleSubCategoryModalClose}
|
|
okText="Submit"
|
|
cancelText="Cancel"
|
|
>
|
|
<Form layout="vertical">
|
|
<Form.Item
|
|
label="Category"
|
|
name="parentCategory"
|
|
>
|
|
<DropDowns
|
|
options={sportCategories.map(cat => ({ value: cat.ConfigId, label: cat.ConfigName }))}
|
|
label="Category"
|
|
className="field-DropDown"
|
|
valueData={selectedCategory}
|
|
isOnchanges={false}
|
|
disabled
|
|
/>
|
|
</Form.Item>
|
|
<Form.Item
|
|
label="Sub Category Name"
|
|
name="subCategoryName"
|
|
rules={[{ required: true, message: 'Please enter sub category name' }]}
|
|
>
|
|
<Input placeholder="Enter sub category name" />
|
|
</Form.Item>
|
|
<Form.Item
|
|
label="Description"
|
|
name="subCategoryDescription"
|
|
>
|
|
<TextArea rows={3} placeholder="Enter sub category description" />
|
|
</Form.Item>
|
|
</Form>
|
|
</Modal> */}
|
|
|
|
{/* <DefaultModal
|
|
title="Add New Coach"
|
|
open={openCoachModal}
|
|
handleSubmit={submitCoach}
|
|
handleCancel={handleCoachModalClose}
|
|
|
|
footer={true}
|
|
width={800}
|
|
>
|
|
<Form layout="vertical" className='addnewcoatcgForm'>
|
|
|
|
<Form.Item
|
|
name="coachSport"
|
|
rules={[{ required: true, message: 'Please select sport' }]}
|
|
>
|
|
<DropDowns
|
|
options={userDropDown?.map((option) => ({
|
|
value: option.UserId,
|
|
label:
|
|
option.UserName != ''
|
|
? option.UserName
|
|
: option.MobileNo,
|
|
}))}
|
|
label={<label class="required">User Name</label>}
|
|
id="UserId"
|
|
field="UserId"
|
|
fieldState={true}
|
|
fieldApi={true}
|
|
className="field-DropDown-Emp"
|
|
onChangeFunction={(e) => UserDropDownChange(e)}
|
|
isOnchanges={formType == 'edit' ? true : false}
|
|
valueData={selectedUserData}
|
|
disabled={formType == 'edit' ? true : false}
|
|
/>
|
|
</Form.Item>
|
|
<Form.Item
|
|
name="EmpType"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: 'Please Select Employee Type',
|
|
},
|
|
]}
|
|
>
|
|
<DropDowns
|
|
options={EmpTypeDropDownData?.map((option) => ({
|
|
value: option.ConfigId,
|
|
label: option.ConfigName,
|
|
}))}
|
|
label={<label class="required">Employee Type</label>}
|
|
id="EmpType"
|
|
field="EmpType"
|
|
fieldState={true}
|
|
fieldApi={true}
|
|
className="field-DropDown-Emp"
|
|
onChangeFunction={(e) => EmpTypeDropDownChange(e)}
|
|
isOnchanges={formType == 'edit' ? true : false}
|
|
valueData={seletedEmpTypeDrop}
|
|
/>
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
name="EmpDesig"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: 'Please Select Designation',
|
|
},
|
|
]}
|
|
>
|
|
<DropDowns
|
|
options={EmpDesgDropDownData?.map((option) => ({
|
|
value: option.ConfigId,
|
|
label: option.ConfigName,
|
|
}))}
|
|
label={<label class="required">Designation</label>}
|
|
id="EmpDesig"
|
|
field="EmpDesig"
|
|
fieldState={true}
|
|
fieldApi={true}
|
|
className="field-DropDown-Emp"
|
|
onChangeFunction={(e) => EmpDesigDropDownChange(e)}
|
|
isOnchanges={formType == 'edit' ? true : false}
|
|
valueData={seletedEmpDesigDrop}
|
|
/>
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
name="EmpDept"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: 'Please Select Department',
|
|
},
|
|
]}
|
|
>
|
|
<DropDowns
|
|
options={activeDeptTypes?.map((option) => ({
|
|
value: option.PreferredSubCatId,
|
|
label: option.PreferredSubCatName,
|
|
}))}
|
|
label={<label class="required">Department</label>}
|
|
id="EmpDept"
|
|
field="EmpDept"
|
|
fieldState={true}
|
|
fieldApi={true}
|
|
className="field-DropDown-Emp"
|
|
onChangeFunction={(e) => EmpDeptDropDownChange(e)}
|
|
isOnchanges={formType == 'edit' ? true : false}
|
|
valueData={seletedEmpDeptDrop}
|
|
/>
|
|
</Form.Item>
|
|
|
|
|
|
<Form.Item
|
|
name="EmpShiftId"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: 'Please Select Shift Name',
|
|
},
|
|
]}
|
|
>
|
|
<DropDowns
|
|
options={ShiftDownData?.map((option) => ({
|
|
value: option.ShiftId,
|
|
label: option.ShiftName,
|
|
}))}
|
|
label={<label class="required">Shift Name</label>}
|
|
id="ShiftId"
|
|
field="ShiftId"
|
|
fieldState={true}
|
|
fieldApi={true}
|
|
className="field-DropDown-Emp"
|
|
onChangeFunction={(e) => ShiftDropDownChange(e)}
|
|
isOnchanges={formType == 'edit' ? true : false}
|
|
valueData={seletedShiftDrop}
|
|
/>
|
|
</Form.Item>
|
|
|
|
|
|
<Form.Item
|
|
name="EmpDOJ"
|
|
// hasFeedback
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: 'Please Select Date of Join',
|
|
},
|
|
]}
|
|
>
|
|
|
|
<DatePic
|
|
canSelectPast={true}
|
|
onChange={onChange}
|
|
valueData={SelectedDate}
|
|
label={<label class="required">Date of Join</label>}
|
|
isOnChange={true}
|
|
/>
|
|
</Form.Item>
|
|
<Form.Item
|
|
name="MobileNo"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
pattern: /^\d{10}$/,
|
|
message: 'Please Enter a Valid Mobile Number',
|
|
},
|
|
|
|
]}
|
|
>
|
|
<InputField
|
|
field="MobileNo"
|
|
label={<label class="required">Mobile Number</label>}
|
|
fieldState={true}
|
|
maxLength="10"
|
|
fieldApi={true}
|
|
autocomplete="off"
|
|
isOnChange={formType == 'edit' ? true : false}
|
|
/>
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
label="Experience (Years)"
|
|
name="coachExperience"
|
|
>
|
|
<InputNumber
|
|
min={0}
|
|
max={50}
|
|
style={{ width: '100%' }}
|
|
placeholder="Enter years of experience"
|
|
/>
|
|
</Form.Item>
|
|
<Form.Item
|
|
label="Qualifications"
|
|
name="coachQualifications"
|
|
>
|
|
<TextArea rows={3} placeholder="Enter coach qualifications" />
|
|
</Form.Item>
|
|
<div className="sports-master__image-actions">
|
|
{Array.from({ length: Math.max(1, imageUrls.length) }).map((_, idx) => (
|
|
<div key={idx} style={{ marginBottom: 12 }}>
|
|
<CropUpload
|
|
onlineImage={onlineImage}
|
|
ImageLink={imageUrls[idx]?.image}
|
|
updateImageUrl={(url) => updateImageUrls(url, idx)}
|
|
/>
|
|
|
|
<Input
|
|
placeholder={`Image name (optional)`}
|
|
value={imageUrls[idx]?.name || ''}
|
|
onChange={(e) => updateImageName(e.target.value, idx)}
|
|
style={{ marginTop: 8 }}
|
|
/>
|
|
|
|
<div style={{ display: 'flex', gap: 8, marginTop: 8 }}>
|
|
<Button size="small" onClick={() => setImageUrls(prev => {
|
|
const copy = Array.isArray(prev) ? [...prev] : [];
|
|
copy.splice(idx + 1, 0, { image: '', name: '' });
|
|
return copy;
|
|
})}>Add</Button>
|
|
<Button size="small" danger onClick={() => setImageUrls(prev => (prev || []).filter((__, i) => i !== idx))}>Remove</Button>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</Form>
|
|
</DefaultModal> */}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default SportSlotCreation;
|