diff --git a/webapp/src/app/api/user/actions/members/route.ts b/webapp/src/app/api/user/actions/members/route.ts index cd924d4..6741729 100644 --- a/webapp/src/app/api/user/actions/members/route.ts +++ b/webapp/src/app/api/user/actions/members/route.ts @@ -49,7 +49,8 @@ export async function POST(req:Request) } | null = payload.bodyState as { startBodyForm: String, startWeight: Number, - } | null; + } | null, + subscriptionDate : string | null = payload.subscriptionDate as string | null; // Validate required fields if (!firstName || !lastName || !phone) { @@ -111,24 +112,24 @@ export async function POST(req:Request) // Calculate total monthly pay const payMonth = servicesDocs.reduce((total, service) => total + service.price, 0) - // Declare needed variables - let current_date = new Date(), - current_date_unix = Math.floor(Date.now() / 1000), - planDelay_unix = planDelay ? planDelay * 2592000: 0 * 2592000, - planExpAt = new Date((current_date_unix + planDelay_unix) * 1000); + // current time variables - use custom date if provided, otherwise use current date + const subscription_date = subscriptionDate ? new Date(subscriptionDate) : new Date(); + const subscription_date_unix = Math.floor(subscription_date.getTime() / 1000); + const planDelay_unix = planDelay * 2592000; + const planExpAt = new Date((subscription_date_unix + planDelay_unix) * 1000); // Create services array with per-service subscription details const servicesArray = servicesDocs.map(service => ({ serviceID: service._id.toString(), serviceName: service.name, - registeredAt: current_date.toUTCString(), - registeredAt_unix: current_date_unix, + registeredAt: subscription_date.toUTCString(), + registeredAt_unix: subscription_date_unix, planDelay: planDelay, planDelay_unix: planDelay_unix, planExpAt: planExpAt.toUTCString(), - planExpAt_unix: current_date_unix + planDelay_unix, - planUpdatedAt: current_date.toUTCString(), - planUpdatedAt_unix: current_date_unix, + planExpAt_unix: subscription_date_unix + planDelay_unix, + planUpdatedAt: subscription_date.toUTCString(), + planUpdatedAt_unix: subscription_date_unix, active: true, })) @@ -155,15 +156,15 @@ export async function POST(req:Request) services: servicesArray, gendre, bodyState, - registerAt: current_date.toUTCString(), - registerAt_unix: current_date_unix, + registerAt: subscription_date.toUTCString(), + registerAt_unix: subscription_date_unix, // Global subscription status (derived from services) - planUpdatedAt: current_date.toUTCString(), - planUpdatedAt_unix: current_date_unix, + planUpdatedAt: subscription_date.toUTCString(), + planUpdatedAt_unix: subscription_date_unix, planDelay, planDelay_unix: planDelay_unix, planExpAt: planExpAt.toUTCString(), - planExpAt_unix: current_date_unix + planDelay_unix, + planExpAt_unix: subscription_date_unix + planDelay_unix, active: true, }) @@ -180,7 +181,7 @@ export async function POST(req:Request) name: `New Member Subscription - ${firstName} ${lastName}`, description: `New member subscription for services: ${serviceNamesList} (${planDelay} month${planDelay > 1 ? 's' : ''})`, amount: totalAmount, - addedAt: current_date_unix + addedAt: subscription_date_unix }); await incomeEntry.save(); @@ -409,6 +410,7 @@ export async function PUT(req:Request) return payload.services as string[]; })(), planDelay : number = payload.planDelay ? payload.planDelay : 1 as number, + subscriptionDate : string | null = payload.subscriptionDate as string | null, bodyState : { currentBodyForm: String, currentWeight: Number, @@ -435,9 +437,9 @@ export async function PUT(req:Request) const newServiceIds = newServices.map(id => new mongoose.Types.ObjectId(id as string)); const newServicesDocs = await serviceModel.find({ _id: { $in: newServiceIds } }); - // Current time variables - const current_date = new Date(); - const current_date_unix = Math.floor(Date.now() / 1000); + // Current time variables - use custom date if provided, otherwise use current date + const current_date = subscriptionDate ? new Date(subscriptionDate) : new Date(); + const current_date_unix = Math.floor(current_date.getTime() / 1000); const planDelay_unix = planDelay * 2592000; // Process current services and new services @@ -476,13 +478,13 @@ export async function PUT(req:Request) totalIncome += newServiceDoc.price * planDelay; incomeServiceNames.push(`${newServiceDoc.name} (extended)`); } else { - // Replace expired service + // Replace expired service - keep original registration date const newExpiration = current_date_unix + planDelay_unix; updatedServices[existingServiceIndex] = { serviceID: existingService.serviceID, serviceName: existingService.serviceName, - registeredAt: current_date.toUTCString(), - registeredAt_unix: current_date_unix, + registeredAt: existingService.registeredAt, + registeredAt_unix: existingService.registeredAt_unix, planDelay: planDelay, planDelay_unix: planDelay_unix, planExpAt: new Date(newExpiration * 1000).toUTCString(), diff --git a/webapp/src/components/dashboard/members/parts/addPopUp.tsx b/webapp/src/components/dashboard/members/parts/addPopUp.tsx index 3132616..3f973b1 100644 --- a/webapp/src/components/dashboard/members/parts/addPopUp.tsx +++ b/webapp/src/components/dashboard/members/parts/addPopUp.tsx @@ -51,6 +51,7 @@ export default function AddPopUp() address: string | null, services: string[], planDelay: string | null, + subscriptionDate: string | null, gendre: string | null, // m or w startBodyForm: string | null, startWeight: string | null, @@ -62,6 +63,7 @@ export default function AddPopUp() address: '', services: [], planDelay: '', + subscriptionDate: new Date().toISOString().split('T')[0], // Default to current date gendre: 'm', startBodyForm: '', startWeight: '', @@ -336,6 +338,22 @@ export default function AddPopUp()

{t('subscriptionInformations')}

+
+ +

{errors.subscriptionDate && touched.subscriptionDate && t(errors.subscriptionDate)}

+
{t('registerAt') + ' ' + '[ ' + new Date(detailsPopUpData?.registerAt || '').toLocaleDateString( - t('locale') === 'ar' ? 'ar-EG' : 'en-US', + t('locale') === 'ar' ? 'ar-EG' : 'en-GB', { weekday: 'long', day: 'numeric', @@ -330,7 +330,7 @@ export default function ServiceDetailsPopUp()
{t('registeredAt')}: - {new Date(service.registeredAt).toLocaleDateString()} + {new Date(service.registeredAt).toLocaleDateString("en-GB")}
{t('planDelay')}: @@ -338,11 +338,11 @@ export default function ServiceDetailsPopUp()
{t('planExpAt')}: - {new Date(service.planExpAt).toLocaleDateString()} + {new Date(service.planExpAt).toLocaleDateString("en-GB")}
{t('planUpdatedAt')}: - {new Date(service.planUpdatedAt).toLocaleDateString()} + {new Date(service.planUpdatedAt).toLocaleDateString("en-GB")}
diff --git a/webapp/src/components/dashboard/members/parts/updateSubPopUp.tsx b/webapp/src/components/dashboard/members/parts/updateSubPopUp.tsx index 68eb2d0..a3f9cd6 100644 --- a/webapp/src/components/dashboard/members/parts/updateSubPopUp.tsx +++ b/webapp/src/components/dashboard/members/parts/updateSubPopUp.tsx @@ -10,6 +10,7 @@ import useMediaQuery from '@mui/material/useMediaQuery'; import Slide from '@mui/material/Slide'; import { TransitionProps } from '@mui/material/transitions'; import { Formik } from 'formik'; +import * as Yup from "yup"; import DialogContent from '@mui/material/DialogContent'; import DialogContentText from '@mui/material/DialogContentText'; import DialogActions from '@mui/material/DialogActions'; @@ -215,9 +216,18 @@ export default function UpdateSubPopUp() //registerAt: updatePopUpData?.registerAt ? updatePopUpData?.registerAt : '', //registerAt_unix: updatePopUpData?.registerAt_unix ? updatePopUpData?.registerAt_unix : '', planDelay: 0, + subscriptionDate: new Date().toISOString().split('T')[0], // Default to current date //planDelay_unix: updatePopUpData?.planDelay_unix ? updatePopUpData?.planDelay_unix : 0, services: [], }} + // Validation schema + validationSchema={Yup.object().shape({ + planDelay: Yup.number().typeError('mustBeANumber').required('thisFieldIsRequired'), + subscriptionDate: Yup.date().required('thisFieldIsRequired'), + services: Yup.array().min(1, "selectAtLeastOneService"), + currentBodyForm: Yup.string().required('thisFieldIsRequired'), + currentWeight: Yup.number().typeError('mustBeANumber').required('thisFieldIsRequired'), + })} // this function handle the submition of the formik form onSubmit={async (values, { setSubmitting }) => { // dispatch the update function @@ -321,9 +331,23 @@ export default function UpdateSubPopUp() ">
-

{t('planDetails')}

+

{t('subscriptionInformations')}

+