Week 40

Still plugging away…

Still trying to complete the Linden Project website. The bulk of it is done, but I still need to tie up some lose ends.

One of the challenges I encountered was organizing the seasons.

In my Sanity Studio, I set up an Event schema that takes a whole bunch of different information like the title, link to tickets, the venue, the performers etc. It also takes an array of performance dates.

I’m not sure exactly why, but most performing arts companies structure their season of performances the same way that the school year is structured. So their season starts in Aug/September and ends June/July.

That means when I render the events, I’ve got to do a bit of extra work to group them correctly.

I wanted to then display those events in two places: first of all on the home page I wanted to display just the events of the current season. I also wanted to display them on a events archive page, organized by season.

I didn’t want to have to create another field in my schema to manually assign a season or anything like that, but I just wanted it to generate the seasons based on the performance date.

My solution was to first map through the events as they come into Gatsby from the Graphql query as assign them a season property based on the date. If the performance date is August or later, it belongs in the season of that year, plus the next year (i.e. an event with a performance date of September 24, 2020 belongs to the 2020/2021 season). Events before August get the season that corresponds to the year and the previous year.

const getSeason = date => {
  const month = date.getMonth();
  let season = "";
  if (month > 7) {
    season = `${date.getFullYear()}/${date.getFullYear() + 1}`;
  } else {
    season = `${date.getFullYear() - 1}/${date.getFullYear()}`;
  }
  return season;
};

I then create a new array of event objects with an addition property “season” assigned with the correct value based on their performance date.

const assignSeason = event => {
    if (event.performances.length !== 0) {
      const firstPerformance = new Date(event.performances[0].dateTime);
      const newEvent = { ...event };
      newEvent.season = getSeason(firstPerformance);
      return newEvent;
    }
  };

  const eventsWithSeasons = events.map(event => assignSeason(event));

Then I use the reduce method to create an object with properties corresponding to all the seasons with the value of an array of all my events in that season.

const seasons = eventsWithSeasons.reduce((r, a) => {
    r[a.season] = [...(r[a.season] || []), a];
    return r;
  }, {});

  return seasons;

As I’m typing this and thinking through it again, I’m realizing what might have been better would be to create an array of objects instead. Each object in the array would have two properties: season and events. The way I’ve done it works, but it comes with some weirdness, as you’ll see.

The next step is to apply my season building function to the data from my query on the archive page. I also need to get the current season and the names of the seasons that I’m working with. Because of the way I’ve grouped my seasons in an object, I’m pulling the object property keys.

const Archive = ({ data }) => {
  const seasons = buildSeasons(data.events.nodes);

  const today = new Date();
  const currentSeason = getSeason(today);
  const keys = Object.keys(seasons).sort();

On the archive page, I don’t want to display the current season or any future events I have entered in the Sanity studio, so I splice up my keys.

  // Remove current and future season keys from our keys array
  keys.splice(keys.findIndex(key => key === currentSeason));

Then in the return statement of my component, I render out the seasons.

{keys.map(key => {
          const events = seasons[key];
          return (
            <Season key={key}>
              <SeasonHeading>{key}</SeasonHeading>
              {events.map(event => {
                return <ArchiveEvent key={event.id} event={event} />;
              })}
            </Season>
          );
        })}

This all works and gives me the result I’m looking for, but I’m sure there’s a cleaner way of doing this. If I refactor this, I will put up a new post with the new version.

Copyright © 2026, Jeremy Ludwig. All rights reserved and all that.