Home > Software engineering >  React native loop remove times based on length between last time end and next time start
React native loop remove times based on length between last time end and next time start

Time:01-09

Sorry in advance, possibly been looking at it for t long. I have a test application which shows a horizontal list of dates and times for a selected date for booking appointment slots but can't seem to exclude the times that would overlap into other appointment times.

const updateAvailableTimes = (
            bookings: Array<{stDate: string; enDate: string}>,
            availables: Array<string>,
            currDate: string,
        ) => {
            const newAvailables = [];
            const serviceLengthInMinutes = 90; // 1hr and 30 minutes // Get the actual service length from state or passed param
            for (const ava of availables) {
                const curr = moment(`${currDate} ${ava}`, 'YYYY-MM-DD HH:mm');
                let isBooked = false;
                for (const booking of bookings) {
                    const st = moment(booking.stDate, 'YYYY-MM-DD HH:mm');
                    const en = moment(booking.enDate, 'YYYY-MM-DD HH:mm');

                    if (!curr.isSameOrAfter(st) || !curr.isSameOrAfter(en) && !curr.isBetween(st, en) || curr.isBefore(en)) {
                        if(!curr.isBefore(st) && !curr.isAfter(en)){
                            console.log('Booked Slot: '   moment(en, 'HH:mm').format('HH:mm'));
                            newAvailables.push('');
                            isBooked = true;
                            break;
                        }
                    }
                }
                if (!isBooked) {
                    console.log('Available Slot: '   moment(ava, 'HH:mm').format('HH:mm'))
                    newAvailables.push(ava);
                }
            }
            return newAvailables;
        };

Example or what should happen

A typical appointment length for this selected service is 1hr and 30mins, I have 4 appointments already booked so my app should show the following available appointment times to select from
[12:00, 16:30, 16:45, 17:00]

What is being displayed which is wrong

[12:00, 12:15, 12:30, 12:45, 13:00, 13:15, 13:30, 16:30, 16:45, 17:00]

In this case, if the user was able to select 12:30 then it would overlap into another appointment time so I would need to exclude [12:15, 12:30 etc...]

Data

availableTimes:
['09:00', 09:15 ... 16:45, 17:00] - So opening and closing from 09:00 until 17:00

existingBooks for the selected day (2022-01-07):

[stDateTime: '2023-01-07 09:00', enDateTime: '2023-01-07 10:30']
[stDateTime: '2023-01-07 10:30', enDateTime: '2023-01-07 12:00']
[stDateTime: '2023-01-07 13:30', enDateTime: '2023-01-07 15:00']
[stDateTime: '2023-01-07 15:00', enDateTime: '2023-01-07 16:30']

I actually think it's a problem somewhere in the loop but not sure how to alter the arrays or data.

CodePudding user response:

My bad. The solution was to add an additional condition to compare the service length to the time in between the last appointment end and next start or vs versa. Working solution would look something like the below;

const updateAvailableTimes = (
            bookings: Array<{stDate: string; enDate: string}>,
            availables: Array<string>,
            currDate: string,
        ) => {
            const newAvailables = [];
            const serviceLengthInMinutesPositive = 90; // FOR TESTING 1hr and 30 minutes // Get the actual service length from state or passed param
            const serviceLengthInMinutesNegative = -90; // FOR TESTING
            for (const ava of availables) {
                const curr = moment(`${currDate} ${ava}`, 'YYYY-MM-DD HH:mm');
                let isBooked = false;
                for (const booking of bookings) {
                    const st = moment(booking.stDate, 'YYYY-MM-DD HH:mm');
                    const en = moment(booking.enDate, 'YYYY-MM-DD HH:mm');
                    let checkForOverlaps = moment.duration(curr.diff(st)).asMinutes();

                    let overlapCondition = Math.abs(checkForOverlaps) <= 89 && Math.abs(checkForOverlaps) >= -89;


                    if (!curr.isSameOrAfter(st) || !curr.isSameOrAfter(en) && !curr.isBetween(st, en) || curr.isBefore(en)) {
                         if(!curr.isBefore(st) && !curr.isAfter(en) || overlapCondition){
                            newAvailables.push('');
                            isBooked = true;
                            break;
                        }
                    }
                }

                if (!isBooked) {
                    newAvailables.push(ava);
                }
            }
            return newAvailables;
        };

So the output would look like the below if the business starting time was 07:00 and the specific service length the user is trying to book is 1hr 30min (90 mins)
[07:00, 07:15, 07:30, 12:00, 16:30...]

But why would it look like this?
If a business has a booking scheduled for 09:00 that lasts for 90 mins and a new customer was able to book a time between 07:45 - 08:45 then it would clash with the appointment booked for 09:00. So if the available hours are set to [07:00, 07:15, 07:30], these times would not clash with the appointment booked at 09:00

  • Related