Descriptive . 33.
This commit is contained in:
parent
386241b488
commit
0f7d782cd3
@ -49,7 +49,8 @@ export async function POST(req:Request)
|
|||||||
} | null = payload.bodyState as {
|
} | null = payload.bodyState as {
|
||||||
startBodyForm: String,
|
startBodyForm: String,
|
||||||
startWeight: Number,
|
startWeight: Number,
|
||||||
} | null;
|
} | null,
|
||||||
|
subscriptionDate : string | null = payload.subscriptionDate as string | null;
|
||||||
|
|
||||||
// Validate required fields
|
// Validate required fields
|
||||||
if (!firstName || !lastName || !phone) {
|
if (!firstName || !lastName || !phone) {
|
||||||
@ -111,24 +112,24 @@ export async function POST(req:Request)
|
|||||||
// Calculate total monthly pay
|
// Calculate total monthly pay
|
||||||
const payMonth = servicesDocs.reduce((total, service) => total + service.price, 0)
|
const payMonth = servicesDocs.reduce((total, service) => total + service.price, 0)
|
||||||
|
|
||||||
// Declare needed variables
|
// current time variables - use custom date if provided, otherwise use current date
|
||||||
let current_date = new Date(),
|
const subscription_date = subscriptionDate ? new Date(subscriptionDate) : new Date();
|
||||||
current_date_unix = Math.floor(Date.now() / 1000),
|
const subscription_date_unix = Math.floor(subscription_date.getTime() / 1000);
|
||||||
planDelay_unix = planDelay ? planDelay * 2592000: 0 * 2592000,
|
const planDelay_unix = planDelay * 2592000;
|
||||||
planExpAt = new Date((current_date_unix + planDelay_unix) * 1000);
|
const planExpAt = new Date((subscription_date_unix + planDelay_unix) * 1000);
|
||||||
|
|
||||||
// Create services array with per-service subscription details
|
// Create services array with per-service subscription details
|
||||||
const servicesArray = servicesDocs.map(service => ({
|
const servicesArray = servicesDocs.map(service => ({
|
||||||
serviceID: service._id.toString(),
|
serviceID: service._id.toString(),
|
||||||
serviceName: service.name,
|
serviceName: service.name,
|
||||||
registeredAt: current_date.toUTCString(),
|
registeredAt: subscription_date.toUTCString(),
|
||||||
registeredAt_unix: current_date_unix,
|
registeredAt_unix: subscription_date_unix,
|
||||||
planDelay: planDelay,
|
planDelay: planDelay,
|
||||||
planDelay_unix: planDelay_unix,
|
planDelay_unix: planDelay_unix,
|
||||||
planExpAt: planExpAt.toUTCString(),
|
planExpAt: planExpAt.toUTCString(),
|
||||||
planExpAt_unix: current_date_unix + planDelay_unix,
|
planExpAt_unix: subscription_date_unix + planDelay_unix,
|
||||||
planUpdatedAt: current_date.toUTCString(),
|
planUpdatedAt: subscription_date.toUTCString(),
|
||||||
planUpdatedAt_unix: current_date_unix,
|
planUpdatedAt_unix: subscription_date_unix,
|
||||||
active: true,
|
active: true,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@ -155,15 +156,15 @@ export async function POST(req:Request)
|
|||||||
services: servicesArray,
|
services: servicesArray,
|
||||||
gendre,
|
gendre,
|
||||||
bodyState,
|
bodyState,
|
||||||
registerAt: current_date.toUTCString(),
|
registerAt: subscription_date.toUTCString(),
|
||||||
registerAt_unix: current_date_unix,
|
registerAt_unix: subscription_date_unix,
|
||||||
// Global subscription status (derived from services)
|
// Global subscription status (derived from services)
|
||||||
planUpdatedAt: current_date.toUTCString(),
|
planUpdatedAt: subscription_date.toUTCString(),
|
||||||
planUpdatedAt_unix: current_date_unix,
|
planUpdatedAt_unix: subscription_date_unix,
|
||||||
planDelay,
|
planDelay,
|
||||||
planDelay_unix: planDelay_unix,
|
planDelay_unix: planDelay_unix,
|
||||||
planExpAt: planExpAt.toUTCString(),
|
planExpAt: planExpAt.toUTCString(),
|
||||||
planExpAt_unix: current_date_unix + planDelay_unix,
|
planExpAt_unix: subscription_date_unix + planDelay_unix,
|
||||||
active: true,
|
active: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -180,7 +181,7 @@ export async function POST(req:Request)
|
|||||||
name: `New Member Subscription - ${firstName} ${lastName}`,
|
name: `New Member Subscription - ${firstName} ${lastName}`,
|
||||||
description: `New member subscription for services: ${serviceNamesList} (${planDelay} month${planDelay > 1 ? 's' : ''})`,
|
description: `New member subscription for services: ${serviceNamesList} (${planDelay} month${planDelay > 1 ? 's' : ''})`,
|
||||||
amount: totalAmount,
|
amount: totalAmount,
|
||||||
addedAt: current_date_unix
|
addedAt: subscription_date_unix
|
||||||
});
|
});
|
||||||
await incomeEntry.save();
|
await incomeEntry.save();
|
||||||
|
|
||||||
@ -409,6 +410,7 @@ export async function PUT(req:Request)
|
|||||||
return payload.services as string[];
|
return payload.services as string[];
|
||||||
})(),
|
})(),
|
||||||
planDelay : number = payload.planDelay ? payload.planDelay : 1 as number,
|
planDelay : number = payload.planDelay ? payload.planDelay : 1 as number,
|
||||||
|
subscriptionDate : string | null = payload.subscriptionDate as string | null,
|
||||||
bodyState : {
|
bodyState : {
|
||||||
currentBodyForm: String,
|
currentBodyForm: String,
|
||||||
currentWeight: Number,
|
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 newServiceIds = newServices.map(id => new mongoose.Types.ObjectId(id as string));
|
||||||
const newServicesDocs = await serviceModel.find({ _id: { $in: newServiceIds } });
|
const newServicesDocs = await serviceModel.find({ _id: { $in: newServiceIds } });
|
||||||
|
|
||||||
// Current time variables
|
// Current time variables - use custom date if provided, otherwise use current date
|
||||||
const current_date = new Date();
|
const current_date = subscriptionDate ? new Date(subscriptionDate) : new Date();
|
||||||
const current_date_unix = Math.floor(Date.now() / 1000);
|
const current_date_unix = Math.floor(current_date.getTime() / 1000);
|
||||||
const planDelay_unix = planDelay * 2592000;
|
const planDelay_unix = planDelay * 2592000;
|
||||||
|
|
||||||
// Process current services and new services
|
// Process current services and new services
|
||||||
@ -476,13 +478,13 @@ export async function PUT(req:Request)
|
|||||||
totalIncome += newServiceDoc.price * planDelay;
|
totalIncome += newServiceDoc.price * planDelay;
|
||||||
incomeServiceNames.push(`${newServiceDoc.name} (extended)`);
|
incomeServiceNames.push(`${newServiceDoc.name} (extended)`);
|
||||||
} else {
|
} else {
|
||||||
// Replace expired service
|
// Replace expired service - keep original registration date
|
||||||
const newExpiration = current_date_unix + planDelay_unix;
|
const newExpiration = current_date_unix + planDelay_unix;
|
||||||
updatedServices[existingServiceIndex] = {
|
updatedServices[existingServiceIndex] = {
|
||||||
serviceID: existingService.serviceID,
|
serviceID: existingService.serviceID,
|
||||||
serviceName: existingService.serviceName,
|
serviceName: existingService.serviceName,
|
||||||
registeredAt: current_date.toUTCString(),
|
registeredAt: existingService.registeredAt,
|
||||||
registeredAt_unix: current_date_unix,
|
registeredAt_unix: existingService.registeredAt_unix,
|
||||||
planDelay: planDelay,
|
planDelay: planDelay,
|
||||||
planDelay_unix: planDelay_unix,
|
planDelay_unix: planDelay_unix,
|
||||||
planExpAt: new Date(newExpiration * 1000).toUTCString(),
|
planExpAt: new Date(newExpiration * 1000).toUTCString(),
|
||||||
|
|||||||
@ -51,6 +51,7 @@ export default function AddPopUp()
|
|||||||
address: string | null,
|
address: string | null,
|
||||||
services: string[],
|
services: string[],
|
||||||
planDelay: string | null,
|
planDelay: string | null,
|
||||||
|
subscriptionDate: string | null,
|
||||||
gendre: string | null, // m or w
|
gendre: string | null, // m or w
|
||||||
startBodyForm: string | null,
|
startBodyForm: string | null,
|
||||||
startWeight: string | null,
|
startWeight: string | null,
|
||||||
@ -62,6 +63,7 @@ export default function AddPopUp()
|
|||||||
address: '',
|
address: '',
|
||||||
services: [],
|
services: [],
|
||||||
planDelay: '',
|
planDelay: '',
|
||||||
|
subscriptionDate: new Date().toISOString().split('T')[0], // Default to current date
|
||||||
gendre: 'm',
|
gendre: 'm',
|
||||||
startBodyForm: '',
|
startBodyForm: '',
|
||||||
startWeight: '',
|
startWeight: '',
|
||||||
@ -336,6 +338,22 @@ export default function AddPopUp()
|
|||||||
<div className="w-full flex lg:flex-row flex-col lg:gap-12 gap-7">
|
<div className="w-full flex lg:flex-row flex-col lg:gap-12 gap-7">
|
||||||
<div className="lg:w-1/2 w-full flex flex-col gap-5">
|
<div className="lg:w-1/2 w-full flex flex-col gap-5">
|
||||||
<h3 className="font-bold">{t('subscriptionInformations')}</h3>
|
<h3 className="font-bold">{t('subscriptionInformations')}</h3>
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<input
|
||||||
|
type="date"
|
||||||
|
id="subscriptionDate"
|
||||||
|
className="
|
||||||
|
disabled:bg-primary-dark/10
|
||||||
|
input lg:w-[350px] w-full border-2 border-primary-dark p-[11px]
|
||||||
|
rounded-md bg-primary dark:bg-primary-dark focus:outline-none
|
||||||
|
"
|
||||||
|
onChange={handleChange}
|
||||||
|
onBlur={handleBlur}
|
||||||
|
value={values?.subscriptionDate}
|
||||||
|
placeholder={t('subscriptionDate')}
|
||||||
|
/>
|
||||||
|
<p className="!text-error text-sm">{errors.subscriptionDate && touched.subscriptionDate && t(errors.subscriptionDate)}</p>
|
||||||
|
</div>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
@ -465,6 +483,7 @@ export default function AddPopUp()
|
|||||||
// this is the paper validation schema ( can`t go to next paper or submit if last paper if the validation schema return a false result )
|
// this is the paper validation schema ( can`t go to next paper or submit if last paper if the validation schema return a false result )
|
||||||
validationSchema: Yup.object().shape({
|
validationSchema: Yup.object().shape({
|
||||||
planDelay: Yup.number().typeError('mustBeANumber').required('thisFieldIsRequired'),
|
planDelay: Yup.number().typeError('mustBeANumber').required('thisFieldIsRequired'),
|
||||||
|
subscriptionDate: Yup.date().required('thisFieldIsRequired'),
|
||||||
services: Yup.array().min(1 , "selectAtLeastOneService"),
|
services: Yup.array().min(1 , "selectAtLeastOneService"),
|
||||||
startBodyForm: Yup.string().required('thisFieldIsRequired'),
|
startBodyForm: Yup.string().required('thisFieldIsRequired'),
|
||||||
startWeight: Yup.number().typeError('mustBeANumber').required('thisFieldIsRequired'),
|
startWeight: Yup.number().typeError('mustBeANumber').required('thisFieldIsRequired'),
|
||||||
|
|||||||
@ -268,7 +268,7 @@ export default function ServiceDetailsPopUp()
|
|||||||
<p>
|
<p>
|
||||||
{t('registerAt') + ' ' + '[ ' +
|
{t('registerAt') + ' ' + '[ ' +
|
||||||
new Date(detailsPopUpData?.registerAt || '').toLocaleDateString(
|
new Date(detailsPopUpData?.registerAt || '').toLocaleDateString(
|
||||||
t('locale') === 'ar' ? 'ar-EG' : 'en-US',
|
t('locale') === 'ar' ? 'ar-EG' : 'en-GB',
|
||||||
{
|
{
|
||||||
weekday: 'long',
|
weekday: 'long',
|
||||||
day: 'numeric',
|
day: 'numeric',
|
||||||
@ -330,7 +330,7 @@ export default function ServiceDetailsPopUp()
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span className="text-gray-600 dark:text-gray-400">{t('registeredAt')}:</span>
|
<span className="text-gray-600 dark:text-gray-400">{t('registeredAt')}:</span>
|
||||||
<span>{new Date(service.registeredAt).toLocaleDateString()}</span>
|
<span>{new Date(service.registeredAt).toLocaleDateString("en-GB")}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span className="text-gray-600 dark:text-gray-400">{t('planDelay')}:</span>
|
<span className="text-gray-600 dark:text-gray-400">{t('planDelay')}:</span>
|
||||||
@ -338,11 +338,11 @@ export default function ServiceDetailsPopUp()
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span className="text-gray-600 dark:text-gray-400">{t('planExpAt')}:</span>
|
<span className="text-gray-600 dark:text-gray-400">{t('planExpAt')}:</span>
|
||||||
<span>{new Date(service.planExpAt).toLocaleDateString()}</span>
|
<span>{new Date(service.planExpAt).toLocaleDateString("en-GB")}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span className="text-gray-600 dark:text-gray-400">{t('planUpdatedAt')}:</span>
|
<span className="text-gray-600 dark:text-gray-400">{t('planUpdatedAt')}:</span>
|
||||||
<span>{new Date(service.planUpdatedAt).toLocaleDateString()}</span>
|
<span>{new Date(service.planUpdatedAt).toLocaleDateString("en-GB")}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import useMediaQuery from '@mui/material/useMediaQuery';
|
|||||||
import Slide from '@mui/material/Slide';
|
import Slide from '@mui/material/Slide';
|
||||||
import { TransitionProps } from '@mui/material/transitions';
|
import { TransitionProps } from '@mui/material/transitions';
|
||||||
import { Formik } from 'formik';
|
import { Formik } from 'formik';
|
||||||
|
import * as Yup from "yup";
|
||||||
import DialogContent from '@mui/material/DialogContent';
|
import DialogContent from '@mui/material/DialogContent';
|
||||||
import DialogContentText from '@mui/material/DialogContentText';
|
import DialogContentText from '@mui/material/DialogContentText';
|
||||||
import DialogActions from '@mui/material/DialogActions';
|
import DialogActions from '@mui/material/DialogActions';
|
||||||
@ -215,9 +216,18 @@ export default function UpdateSubPopUp()
|
|||||||
//registerAt: updatePopUpData?.registerAt ? updatePopUpData?.registerAt : '',
|
//registerAt: updatePopUpData?.registerAt ? updatePopUpData?.registerAt : '',
|
||||||
//registerAt_unix: updatePopUpData?.registerAt_unix ? updatePopUpData?.registerAt_unix : '',
|
//registerAt_unix: updatePopUpData?.registerAt_unix ? updatePopUpData?.registerAt_unix : '',
|
||||||
planDelay: 0,
|
planDelay: 0,
|
||||||
|
subscriptionDate: new Date().toISOString().split('T')[0], // Default to current date
|
||||||
//planDelay_unix: updatePopUpData?.planDelay_unix ? updatePopUpData?.planDelay_unix : 0,
|
//planDelay_unix: updatePopUpData?.planDelay_unix ? updatePopUpData?.planDelay_unix : 0,
|
||||||
services: [],
|
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
|
// this function handle the submition of the formik form
|
||||||
onSubmit={async (values, { setSubmitting }) => {
|
onSubmit={async (values, { setSubmitting }) => {
|
||||||
// dispatch the update function
|
// dispatch the update function
|
||||||
@ -321,9 +331,23 @@ export default function UpdateSubPopUp()
|
|||||||
">
|
">
|
||||||
<div className="w-full flex lg:flex-row flex-col lg:gap-12 gap-7">
|
<div className="w-full flex lg:flex-row flex-col lg:gap-12 gap-7">
|
||||||
<div className="lg:w-1/2 w-full flex flex-col gap-5">
|
<div className="lg:w-1/2 w-full flex flex-col gap-5">
|
||||||
<h3 className="font-bold">{t('planDetails')}</h3>
|
<h3 className="font-bold">{t('subscriptionInformations')}</h3>
|
||||||
<div className="flex flex-col gap-5">
|
<div className="flex flex-col gap-5">
|
||||||
<input
|
<input
|
||||||
|
type="date"
|
||||||
|
id="subscriptionDate"
|
||||||
|
className="
|
||||||
|
disabled:bg-primary-dark/10
|
||||||
|
input lg:w-[350px] w-full border-2 border-primary-dark p-[11px]
|
||||||
|
rounded-md bg-primary dark:bg-primary-dark focus:outline-none
|
||||||
|
"
|
||||||
|
onChange={handleChange}
|
||||||
|
onBlur={handleBlur}
|
||||||
|
value={values?.subscriptionDate}
|
||||||
|
placeholder={t('subscriptionDate')}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
id="planDelay"
|
id="planDelay"
|
||||||
className="
|
className="
|
||||||
disabled:bg-primary-dark/10
|
disabled:bg-primary-dark/10
|
||||||
|
|||||||
@ -120,6 +120,7 @@
|
|||||||
"memberAddText1": "اضافة عضو جديد للمجمع يمكنك من تتبع حالة العضو التسجيلية و الصحية",
|
"memberAddText1": "اضافة عضو جديد للمجمع يمكنك من تتبع حالة العضو التسجيلية و الصحية",
|
||||||
"subscriptionInformations": "معلومات الاشتراك",
|
"subscriptionInformations": "معلومات الاشتراك",
|
||||||
"planDelay": "مدة الخطة",
|
"planDelay": "مدة الخطة",
|
||||||
|
"subscriptionDate": "تاريخ الاشتراك",
|
||||||
"healthInformations": "المعلومات الصحية",
|
"healthInformations": "المعلومات الصحية",
|
||||||
"startWeight": "الوزن الابتدائي",
|
"startWeight": "الوزن الابتدائي",
|
||||||
"bodyType": "حالة الجسم",
|
"bodyType": "حالة الجسم",
|
||||||
|
|||||||
@ -121,6 +121,7 @@
|
|||||||
"memberAddText1": "Adding a new member to the complex enables you to track the member’s registration and health status",
|
"memberAddText1": "Adding a new member to the complex enables you to track the member’s registration and health status",
|
||||||
"subscriptionInformations": "Subscription informations",
|
"subscriptionInformations": "Subscription informations",
|
||||||
"planDelay": "Plan delay",
|
"planDelay": "Plan delay",
|
||||||
|
"subscriptionDate": "Subscription Date",
|
||||||
"healthInformations": "Health infomrations",
|
"healthInformations": "Health infomrations",
|
||||||
"startWeight": "Start weight",
|
"startWeight": "Start weight",
|
||||||
"bodyType": "Body state",
|
"bodyType": "Body state",
|
||||||
|
|||||||
@ -237,6 +237,7 @@ const add = createAsyncThunk(
|
|||||||
serviceName: string | null,
|
serviceName: string | null,
|
||||||
}[] | null,
|
}[] | null,
|
||||||
planDelay: string | null,
|
planDelay: string | null,
|
||||||
|
subscriptionDate: string | null,
|
||||||
gendre: string | null, // m or w
|
gendre: string | null, // m or w
|
||||||
bodyState: {
|
bodyState: {
|
||||||
startBodyForm: string | null,
|
startBodyForm: string | null,
|
||||||
@ -394,6 +395,7 @@ const updateSub = createAsyncThunk(
|
|||||||
_id: string | null | undefined,
|
_id: string | null | undefined,
|
||||||
services: string[] | undefined,
|
services: string[] | undefined,
|
||||||
planDelay: number | null | undefined,
|
planDelay: number | null | undefined,
|
||||||
|
subscriptionDate: string | null | undefined,
|
||||||
bodyState: {
|
bodyState: {
|
||||||
currentBodyForm: string | null,
|
currentBodyForm: string | null,
|
||||||
currentWeight: string | null
|
currentWeight: string | null
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user