RSVP – using AJAX for simple reservations

brown paper envelope on table

One of the historical problems facing Third Space Music was collecting reservations for their concerts. There was no admission charge, but the concerts had a limited accommodation.

I became the webmaster for Third Space Music during the 2020 pandemic. After going through a complete rebrand, our group launched a brand new website design. All of the concerts presented this season have been livestreamed to our audience and we will hold our first ever ticketed livestream event in February 2021. A simple woocommerce web store serves as the host for our ticket sales for this event.

The problem remains: how will we administer an RSVP service when our concerts return to a live setting? How can we collect emails and names for our patrons, and limit the number who receive details and access to the concert when we have limited capacity?

I decided to create a solution to this as my frontend project for the Flatiron School.

Stubbing out the Backend

After generating a rails API app structure and creating a separate backend and frontend folder, I set about generating migrations for my backend classes. For my MVP (minimum viable product), I needed Events with a collection of Users, but I also needed Users to be able to belong to many events. I settled on a join table class called Reservations that would belong to one Event and one User. To future-proof my app, I added an Admin class. Each Event must belong to an Admin, if I take this app live or build it up in the future this will be an important system to keep basic users from altering the RSVP information and guest list. For now, a simple representation of the connection between the front and back end of my app should do! I checked my migrations, made sure to employ my ActiveRecord associations in my models, created a few seeds for my database, and checked that everything was working correctly in the console.

Now for the Frontend

I stubbed out a simple HTML page to contain my event information, and set about constructing my first fetch request: populating the DOM with the existing events, and their related users. To save some time later, I also stubbed out a basic CSS stylesheet with some simple background colors for .event, .user, and a few other key items to confirm they were all being appended correctly.

What I WISH I had done at this stage was set up my javascript frontend to take the JSON from the backend and translate it into an instance of a JS object. This created an extra day of refactoring and drying my functions to take JS objects instead of the JSON itself. The code is cleaned up considerably, and I was able to extract a few simple functions into class and instance methods, but starting with an object in the first place would have saved a lot of tedious refactoring.

For the functionality of my application, I needed a simple form for users to submit their name and email. I was able to capture this information using a formData object (appending the event_id to make sure the correct event is updated), and send it to the backend to find_or_create a user. I didn’t want multiple copies of the same user, in the future it may be important to collect all of the Events a User is attending, or create a login scheme for each user that would be based on their unique email. For now, a simple way to take a single spot on the list would do.

I decided to include in the returned JSON the Event to which the User was added. This made it very easy to locate the event by id with a selector, and then find the list of users within. My third fetch request is set up on the delete button for each user. In an active version of this app, this button would only be visible to a logged in Admin that owns that event, and the fetch request to the backend would also check that this event belonged to the Admin before updating the database. For now, with the constraints of a single page to work with, simply being able to access every feature without a login procedure is much simpler.

Instead of deleting the user in the backend, the fetch request updates the user’s event list, and returns the user and event again. On the frontend, we find the user’s div within the event, and remove the user.

Visual Enhancements for Users

To add some visual representations of the event’s capacity, I wanted to use the addition and deletion fetch requests. Since the entire Event object was being returned, I could use the capacity parameter and the collection of users to calculate both remaining seats and the percent of capacity that remained. When the fetch response is returned to the frontend, I added functions to locate and update a capacity counter and a status bar showing the percent of the seats that were taken.

Lastly I turned to the stylesheet to take the application from clown-town to something more acceptable visually. I experimented with transparency and a few color schemes, as well as a few fixed backgrounds that the event div’s could “float” over. I landed on using a stock photo of an open envelope, creating two separate images representing an overlay and a background, and positioned them on the screen so the events “float” out of the open envelope at the bottom of the screen.

Applications for the Application

Collecting user information for organizing an event can take on many particular challenges. I would add features based on the needs of the application user. An admin login process would likely be necessary for most uses, allowing one person to securely update and access the information of users. Being able to send a unique url to a specific event would be helpful for users who want to use the app to plan a party or non-business event. Certain users would need an additional “attending” or “not attending” form field, and the option to submit a message to be sent to the admin of the event could also be useful.

I believe this application could be built out to serve a variety of needs:

  • Wedding Invitations (Extra fields for dining preference)
  • Appointment signups (Music lessons, COVID Testing, office hours)
  • Performance Reservation (Any event with limited available seating)
  • Grassroots Organizing

In any case, the ability to host this application on a website that could create secure instances of an event with a unique URL could be endlessly useful and simple for users to access and submit.

Thanks for reading!