Android_Retail/src/Pages/BookingScreen/Components/UtillComponents/BSMembership.jsx

501 lines
19 KiB
JavaScript

import { useCallback, useEffect, useState } from 'react';
import {
Crown,
X,
Calendar,
Star,
Zap,
ChevronDown,
ChevronUp,
CrownIcon,
} from 'lucide-react';
import './BSMembership.scss';
import {
createMembershipSubscription,
getMembership,
} from '../../../../Features/Membership/Membership';
import { getSession } from '../../../../Services/Others';
import { useDispatch } from 'react-redux';
import SubscribeMembershipModal from './SubscribeMembershipModal';
import { getAllCustomer } from '../../../../Features/BookingScreen/BookingData/BookingData';
import {
getAddCustomerDetails,
GlobalCustomerRefreshTrigger,
triggerCustomerRefresh,
} from '../../../../Features/BookingScreen/Customer/addCustomer';
import { Messages } from '../../../../Components/Notifications/Messages';
import { Tooltip } from 'antd';
import { useSelector } from 'react-redux';
import {
changeMembershipNumber,
changeSelfBookingCustomerDtls,
GlobalMembershipDetail,
GlobalSelfBookingCustomerDtls,
PostSelfBookingCustomer,
} from '../../../../Features/BookingScreen/BookingData/KioskBookingData';
import { DefaultModal } from '../../../../Components/Modal/DefaultModal';
import { ArrowRightOutlined } from '@ant-design/icons';
const BSMembership = ({ modelOpen = false, setMemberShipOpen, drawerOpen = false, setDrawerOpen = () => { } }) => {
const dispatch = useDispatch();
const AppId = getSession('AppId');
const CompId = getSession('CompId');
const BranchId = getSession('BranchId');
const UserId = getSession('UserId');
const AppName = sessionStorage.getItem('AppName');
const MembershipDetail = useSelector(
GlobalMembershipDetail
)?.MembershipDetail;
const customerRefreshTrigger = useSelector(GlobalCustomerRefreshTrigger);
const [showUserModal, setShowUserModal] = useState(false);
const [isOpen, setIsOpen] = useState(modelOpen);
const [expandedMembership, setExpandedMembership] = useState(null);
const [membershipData, setMembershipData] = useState([]);
const [messageType, setMessageType] = useState(null);
const [messageData, setMessageData] = useState(null);
const [subscribeModalVisible, setSubscribeModalVisible] = useState(false);
const [selectedPlan, setSelectedPlan] = useState(null);
const [selectedMembership, setSelectedMembership] = useState(null);
const CustomerDetails = useSelector(GlobalSelfBookingCustomerDtls);
// These should come from your Redux store or API
const [customers, setCustomers] = useState([]);
const [userNumber, setUserNumber] = useState('');
const [paymentModes, setPaymentModes] = useState([]);
useEffect(() => {
fetchMembershipData();
getCustomerData();
}, [customerRefreshTrigger]);
const getCustomerData = async () => {
const res = await dispatch(
getAllCustomer({ CompId: CompId, AppId: AppId, branchId: BranchId })
)?.unwrap();
if (res?.data?.statusCode === 1) {
setCustomers(res?.data?.data);
}
await dispatch(
getAddCustomerDetails({
CompId: CompId,
AppId: AppId,
branchId: BranchId,
})
);
};
const fetchMembershipData = async () => {
const data = {
AppId: AppId,
CompId: CompId,
BranchId: BranchId,
ActiveStatus: 'A',
};
const res = await dispatch(getMembership(data)).unwrap();
if (res?.data?.statusCode === 1) {
setMembershipData(res?.data?.data);
} else {
setMembershipData([]);
}
};
const toggleMembership = (membershipId) => {
setExpandedMembership((prev) =>
prev === membershipId ? null : membershipId
);
};
const calculateFinalPrice = (plan) => {
let price = plan.DisplayPrice || 0;
if (plan.Discount > 0) {
if (plan.DiscountType === 'F') {
price -= plan.Discount;
} else if (plan.DiscountType === 'P') {
price -= (price * plan.Discount) / 100;
}
}
return price + (plan.TaxAmount || 0);
};
const getIcon = (priority) => {
if (priority === 'Y') return Zap;
if (priority === 'N') return Star;
return Calendar;
};
const handleSubscribeClick = (plan, membership) => {
setSelectedPlan(plan);
setSelectedMembership(membership);
setSubscribeModalVisible(true);
};
const handleSubscribe = async (payload) => {
try {
const response = await dispatch(
createMembershipSubscription(payload)
).unwrap();
if (response?.data?.statusCode === 1) {
setSubscribeModalVisible(false);
setMessageType('success');
setMessageData('Membership subscribed successfully!');
dispatch(triggerCustomerRefresh());
} else {
setMessageType('error');
setMessageData('Failed to subscribe membership');
}
console.log('Subscription Payload:', payload);
} catch (error) {
console.error('Subscription error:', error);
}
};
const onComplete = useCallback(() => {
setMessageData(null);
setMessageType(null);
}, []);
const handlePostCustnumber = async () => {
try {
let response = await dispatch(
PostSelfBookingCustomer({
CompId: CompId,
BranchId: BranchId,
AppId: AppId,
CustMobile: userNumber,
})
).unwrap();
if (response?.data?.statusCode == 1 || response?.data?.statusCode == 2) {
dispatch(
changeSelfBookingCustomerDtls(response?.data?.CustomerDetails?.[0])
);
setShowUserModal(false);
setIsOpen(true);
} else {
dispatch(changeSelfBookingCustomerDtls(null));
}
} catch (error) {
console.log(error);
}
};
// if (!CustomerDetails && AppName?.toLowerCase() == "sports") {
// return (
// <div onClick={() => {
// if (!CustomerDetails) setShowUserModal(true)
// else setIsOpen(true)
// }}> <CrownIcon color="#f16d00ff" size={32} />
// <DefaultModal
// open={showUserModal}
// title="Enter Your Number"
// handleCancel={(e) => {
// e?.stopPropagation?.()
// setShowUserModal(false);
// setUserNumber('');
// }}
// footer={false}
// handleSubmit={handlePostCustnumber}
// okText="Save"
// width={400}
// children={
// <div style={{ padding: '20px' }}>
// <input
// type="text"
// value={userNumber}
// onChange={(e) => {
// const value = e.target.value;
// // Allow only numbers and max 10 digits
// if (/^\d{0,10}$/.test(value)) {
// setUserNumber(value);
// dispatch(changeMembershipNumber(value))
// }
// }}
// placeholder="Enter user number"
// style={{
// width: '100%',
// padding: '8px',
// borderRadius: '4px',
// border: '1px solid #d9d9d9'
// }}
// maxLength={10}
// />
// {userNumber.length > 0 && userNumber.length < 10 && (
// <p style={{ color: 'red', marginTop: '8px', fontSize: '12px' }}>
// Number must be 10 digits
// </p>
// )}
// <div style={{ display: 'flex', flexDirection: "row-reverse", paddingTop: "10px" }}>
// <button
// onClick={handlePostCustnumber}
// disabled={userNumber.length !== 10}
// style={{
// backgroundColor: userNumber.length === 10 ? '#901D77' : '#ccc',
// color: 'white',
// border: 'none',
// borderRadius: '6px',
// padding: '10px 16px',
// display: 'flex',
// alignItems: 'center',
// justifyContent: 'center',
// gap: '8px',
// cursor: userNumber.length === 10 ? 'pointer' : 'not-allowed',
// transition: 'all 0.2s ease-in-out',
// textTransform: 'uppercase',
// }}
// >
// Submit <ArrowRightOutlined />
// </button>
// </div>
// </div>
// }
// /></div>
// )
// }
useEffect(() => {
if (drawerOpen?.membership) {
setIsOpen(true);
setDrawerOpen(prev => ({ ...prev, membership: false }));
}
}, [drawerOpen?.membership])
return (
<>
<Messages
messageType={messageType}
messageData={messageData}
onComplete={onComplete}
/>
{/* Membership Icon Button */}
{membershipData?.length > 0 && AppName?.toLowerCase() !== 'sports' && (
<Tooltip
title="Membership"
placement="bottom"
children={
<button
onClick={() => setIsOpen(true)}
className="bs-membership__icon-btn"
aria-label="Buy Membership"
>
<Crown
size={23}
// color="#fbbf24"
style={{
display: 'flex',
cursor: 'pointer',
alignItems: 'center',
justifyContent: 'center',
}}
/>
</button>
}
/>
)}
{/* Overlay */}
{isOpen && (
<div
className="bs-membership__overlay"
onClick={() => setIsOpen(false)}
/>
)}
{/* Drawer */}
<div
className={`bs-membership__drawer ${isOpen ? 'bs-membership__drawer--open' : ''}`}
>
<div className="bs-membership__drawer-content">
{/* Header */}
<div className="bs-membership__header">
<div className="bs-membership__header-title">
<Crown size={32} />
<h2>Memberships</h2>
</div>
<button
onClick={() => {
(setIsOpen(false), setMemberShipOpen(false));
}}
className="bs-membership__close-btn"
aria-label="Close"
>
<X size={24} />
</button>
</div>
{/* Content */}
<div className="bs-membership__content">
<div className="bs-membership__list">
{membershipData.map((membership) => {
const isExpanded =
expandedMembership === membership.MembershipId;
const gradientClass = `bs-membership__membership-header--${membership.MembershipName.toLowerCase()}`;
return (
<div
key={membership.UniqueId}
className="bs-membership__membership"
>
{/* Membership Header */}
<button
onClick={() => toggleMembership(membership.MembershipId)}
className={`bs-membership__membership-header ${gradientClass}`}
>
<div className="bs-membership__membership-header-left">
<Crown size={24} />
<div className="membershiplength">
<h3>{membership.MembershipName}</h3>
<p>
{membership.MembershipPlanDtl.length}{' '}
{membership.MembershipPlanDtl.length === 1
? 'Plan'
: 'Plans'}{' '}
Available
</p>
</div>
</div>
{isExpanded ? (
<ChevronUp size={20} />
) : (
<ChevronDown size={20} />
)}
</button>
{/* Plans (Expandable) */}
{isExpanded && (
<div className="bs-membership__plans">
{membership.MembershipPlanDtl.map((plan, index) => {
const IconComponent = getIcon(plan.Priority);
const planGradientClass = `bs-membership__plan--${plan.Priority === 'Y' ? 'priority' : `color${index % 4}`}`;
const finalPrice = calculateFinalPrice(plan);
return (
<div
key={plan.UniqueId}
className={`bs-membership__plan ${planGradientClass}`}
>
{plan.Priority === 'Y' && (
<span className="bs-membership__plan-priority">
<Zap size={10} />
Priority
</span>
)}
<div className="bs-membership__plan-top">
<div className="bs-membership__plan-top-left">
<div className="bs-membership__plan-icon">
<IconComponent size={16} />
</div>
<div>
<h4>{plan.PlanDuration} Days</h4>
<p>
{plan.Priority === 'Y'
? 'Priority Access'
: 'Standard'}
</p>
</div>
</div>
<div className="bs-membership__plan-top-right">
{plan.Discount > 0 && (
<div className="bs-membership__plan-price-strike">
{plan.Price}
</div>
)}
<span className="bs-membership__plan-price">
{(
plan.DisplayPrice - (plan.TaxAmount || 0)
).toFixed(2)}
</span>
{plan.TaxAmount > 0 && (
<div className="bs-membership__plan-tax">
+{plan.TaxAmount} tax
</div>
)}
</div>
</div>
<ul className="bs-membership__plan-features">
<li>
<span className="bs-membership__plan-feature-check">
</span>
<span>
{plan.FreeSessionHrs} Free Session Hours
</span>
</li>
{plan.Discount > 0 && (
<li>
<span className="bs-membership__plan-feature-check">
</span>
<span>
Save{' '}
{plan.DiscountType === 'F'
? `${plan.Discount}`
: `${plan.Discount}%`}{' '}
after free sessions.
</span>
</li>
)}
{plan.Priority === 'Y' &&
plan.Prioritydays.length > 0 && (
<li>
<span className="bs-membership__plan-feature-check">
</span>
<span>
Priority:{' '}
{plan.Prioritydays?.[0]
?.split?.(',')
.join(', ')}
</span>
</li>
)}
</ul>
{plan.Remarks && plan.Remarks.trim() && (
<div className="bs-membership__plan-remarks">
{plan.Remarks}
</div>
)}
<button
className="bs-membership__plan-btn"
onClick={() =>
handleSubscribeClick(plan, membership)
}
>
Subscribe Now
</button>
</div>
);
})}
</div>
)}
</div>
);
})}
</div>
</div>
{/* Footer */}
<div className="bs-membership__footer">
<p>Cancel anytime. No hidden fees.</p>
</div>
</div>
</div>
<SubscribeMembershipModal
visible={subscribeModalVisible}
onClose={() => setSubscribeModalVisible(false)}
plan={selectedPlan}
membership={selectedMembership}
customers={customers}
paymentModes={paymentModes}
onSubscribe={handleSubscribe}
/>
</>
);
};
export default BSMembership;