Skip to content

Fixing unconfirmed/recurring bookings#4881

Merged
PeerRich merged 6 commits into
mainfrom
fix/bookings-unconfirmed-recurring
Oct 6, 2022
Merged

Fixing unconfirmed/recurring bookings#4881
PeerRich merged 6 commits into
mainfrom
fix/bookings-unconfirmed-recurring

Conversation

@leog
Copy link
Copy Markdown
Contributor

@leog leog commented Oct 6, 2022

What does this PR do?

When looking at "Unconfirmed" tab in Bookings, and you have recurring events to be accepted, they were not grouped correctly. Also, the number of instances in the tooltip info section for recurring events was dependant on loaded bookings, hence infinite scrolling was affecting its content, flickering the number.

See the number flickering:

Screen.Recording.2022-10-06.at.10.42.10.mov

Also as part of the fix, a new little feature is shown, the number of recurring events is adjusted to show actually dates in the future in case any instance already passed, and the tooltip shows passed instances as striked:

And the ungrouped unconfirmed recurring events:

Fixed ungrouped unconfirmed recurring events with better tooltip content:

Environment: Staging(main branch) / Production

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How should this be tested?

Have at least 3 x12 unconfirmed recurring events and go to Unconfirmed tab or Recurring tab in Bookings page.

@leog leog added the 🐛 bug Something isn't working label Oct 6, 2022
@leog leog added this to the v.2.1 milestone Oct 6, 2022
@leog leog requested a review from a team October 6, 2022 14:00
@leog leog self-assigned this Oct 6, 2022
@vercel
Copy link
Copy Markdown

vercel Bot commented Oct 6, 2022

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated
cal ✅ Ready (Inspect) Visit Preview Oct 6, 2022 at 6:53PM (UTC)

type BookingItemProps = BookingItem & {
listingStatus: BookingListingStatus;
recurringBookings?: BookingItem[];
recurringBookings: inferQueryOutput<"viewer.bookings">["recurringInfo"];
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now relying on the returned information from tRPC viewer.bookings

const isPending = booking.status === BookingStatus.PENDING;
const isRecurring = booking.recurringEventId !== null;
const isTabRecurring = booking.listingStatus === "recurring";
const isTabUnconfirmed = booking.listingStatus === "unconfirmed";
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplifying a bunch of conditions throughout this file

<Tooltip
content={recurringStrings.map((aDate, key) => (
<p key={key}>{aDate}</p>
<p key={key} className={classNames(recurringDates[key] < now && "line-through")}>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to show striked instances in the tooltip:
image

recurringCount: booking.recurringBookings.length,
recurringCount: recurringDates.filter((date) => {
return date >= now;
}).length,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to just show the number of "active" instances in the tooltip trigger:
image

Comment thread apps/web/lib/parseDate.ts
}).all();
const dateStrings = allDates.map((r) => {
return processDate(dayjs(r).tz(timeZone), i18n);
});
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation does not require the list of bookings anymore, which was flickering along the infinite scroll loaded more results. It calculates all the instances based on the new introduced recurring information coming from tRPC viewer.bookings which comes with actual count of recurring events selected by user (a.k.a. recurring count) and the date of the first instance of the recurring booking

key={booking.id}
listingStatus={status}
{...defineRecurrentBookings(booking, shownBookings)}
recurringBookings={page.recurringInfo}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repeating last comment: Not relying on a list of bookings anymore, which was flickering along the infinite scroll loaded more results. It calculates all the instances based on the new introduced recurring information coming from tRPC viewer.bookings which comes with actual count of recurring events selected by user (a.k.a. recurring count) and the date of the first instance of the recurring booking

const shownBookings: Record<string, BookingOutput[]> = {};
const filterBookings = (booking: BookingOutput) => {
if (status === "recurring" || status === "cancelled") {
if (status === "recurring" || status == "unconfirmed" || status === "cancelled") {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unconfirmed tab needs to behave the same as recurring and cancelled when it comes to grouping recurring instances

Comment thread packages/prisma/seed.ts
startTime: dayjs().add(1, "day").toDate(),
endTime: dayjs().add(1, "day").add(30, "minutes").toDate(),
status: BookingStatus.PENDING,
status: BookingStatus.ACCEPTED,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yoga class does not require confirmation, so changing its status to ACCEPTED to be aligned to that.

{
status: { equals: BookingStatus.PENDING },
},
],
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Behavior similar to the upcoming status but taking into consideration just PENDING bookings.

notIn: [BookingStatus.CANCELLED],
},
},
});
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new prisma query comes up with the following useful information to populate recurring bookings explained in other related files.

[
  {
    "_min": {
      "startTime": "2022-09-30T18:48:22.495Z"
    },
    "_count": {
      "recurringEventId": 5
    },
    "recurringEventId": "dGVubmlzLWNsYXNz"
  },
  {
    "_min": {
      "startTime": "2022-09-29T18:48:22.491Z"
    },
    "_count": {
      "recurringEventId": 6
    },
    "recurringEventId": "eW9nYS1jbGFzcw=="
  },
  {
    "_min": {
      "startTime": "2022-10-31T13:00:00.000Z"
    },
    "_count": {
      "recurringEventId": 12
    },
    "recurringEventId": "341f50b8-7d71-4817-96b2-fe2144487d25"
  }
]

seenBookings[booking.recurringEventId] = true;
return true;
});
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code was grouping recurring events before grouping them in the UI, which was causing problems showing not-correlated recurring bookings.

});
}

const bookingsFetched = bookings.length;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved from above, not new

@leog leog added the ♻️ autoupdate tells kodiak to keep this branch up-to-date label Oct 6, 2022
@PeerRich PeerRich enabled auto-merge (squash) October 6, 2022 16:33
Comment thread apps/web/components/booking/BookingListItem.tsx
Comment on lines +397 to +399
(booking.listingStatus === "recurring" ||
booking.listingStatus === "unconfirmed" ||
booking.listingStatus === "cancelled") && (
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use the conditions constants here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Different context as you surely noticed, and it was just used once there, so I found no need to create new constants.

Comment thread apps/web/lib/parseDate.ts
): [string[], Date[]] => {
const dateStrings = bookings.map((booking) => processDate(dayjs(booking.startTime).tz(timeZone), i18n));
const allDates = dateStrings.map((dateString) => dayjs(dateString).tz(timeZone).toDate());
const { count = 0, ...rest } =
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is unused variable intentional?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, removing the count as we are not interested in it, I could have left it there and then let the redefinition overwrite it.

@zomars
Copy link
Copy Markdown
Contributor

zomars commented Oct 6, 2022

Suggested edit:

diff --git a/packages/trpc/server/routers/viewer.tsx b/packages/trpc/server/routers/viewer.tsx
index 2eaf991fa..70f0bee39 100644
--- a/packages/trpc/server/routers/viewer.tsx
+++ b/packages/trpc/server/routers/viewer.tsx
@@ -495,12 +495,8 @@ const loggedInViewerRouter = createProtectedRouter()
           endTime: { gte: new Date() },
           OR: [
             {
-              AND: [
-                { NOT: { recurringEventId: { equals: null } } },
-                {
-                  status: { equals: BookingStatus.PENDING },
-                },
-              ],
+              recurringEventId: { not: null },
+              status: { equals: BookingStatus.PENDING },
             },
             {
               status: { equals: BookingStatus.PENDING },

Comment on lines +497 to +504
{
AND: [
{ NOT: { recurringEventId: { equals: null } } },
{
status: { equals: BookingStatus.PENDING },
},
],
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{
AND: [
{ NOT: { recurringEventId: { equals: null } } },
{
status: { equals: BookingStatus.PENDING },
},
],
},
{
recurringEventId: { not: null },
status: { equals: BookingStatus.PENDING },
},

We can simplify this

Copy link
Copy Markdown
Contributor

@zomars zomars left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some nitpicks here and there but overall very nice improvement @leog
Feel free to merge as you see fit

LGTM

@PeerRich PeerRich merged commit 4e49d32 into main Oct 6, 2022
@PeerRich PeerRich deleted the fix/bookings-unconfirmed-recurring branch October 6, 2022 19:23
@leog
Copy link
Copy Markdown
Contributor Author

leog commented Oct 6, 2022

Thanks for the feedback @zomars. Here is the follow-up PR taking into consideration your comments: #4887

@zomars zomars restored the fix/bookings-unconfirmed-recurring branch October 7, 2022 19:46
@keithwillcode keithwillcode deleted the fix/bookings-unconfirmed-recurring branch September 17, 2025 11:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

♻️ autoupdate tells kodiak to keep this branch up-to-date 🐛 bug Something isn't working

Projects

No open projects
Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants