Home
/ blog

i'm a bad uncle

Look. I know it sounds bad but seriously, I have a hard time remembering all the birthdays of my extended family. I always seem to forget about someone and then feel guilty about not at least calling. For the last few years, I have totally failed in keeping up with family birthdays. This I think makes me a bad uncle...and brother...and friend. 😦

That will all change now or at least I hope. 😂

You see, I need something that will let me know if there is a birthday coming up AND how old the person is turning.

Wait, why not just a calendar?

I have tried gcal and outlook and honestly, they just suck. In part because I just don't ever have to use them for anything so I rarely check. I actually have most of the birthdays on my calendar but never added the birth years to know how old someone is turning!

It just didn't work for me.

What about a reminder app?

I am sure that may work but I hate push notifications and unless you pay, you get ads with almost all of them.

Why not Facebook or social media?

😑 No.

So...

I initially wanted something that would send me email reminders like 2 weeks, 1 week, and 3 days before some event like a birthday. I didn't want to setup some cron job on a server somewhere in the fluffy clouds because that just sounds awful.

Zapier

Ahh yes I heard about such a thing and decided this would work. I signed up for an account and in no time had a zap that would almost do what I wanted. It would hook up to outlook and remind 2 weeks in advance of a birthday via email. It would not tell me how old the person was turning but I figured this was a good start.

However, it was more than...two fing steps. This means if I wanted it...I'd have to pay some stupid monthly fee. Look I get needing to keep lights on etc. But come on. Can't I instead have x time or steps per month instead of just blocking almost all the usefulness from the app? Anything interesting is going to be more than 2 steps. Like, for the cost of this stupid thing I could pay someone to remind me on the first of every month.

This was almost a deal breaker. But, they have code steps which is likely what I'd have to use to get the "how old are they turning" part.

And well...

IFTTT

So, here is an alternative to Zapier. Honestly, this kinda sucked. It was hard to figure out how to do much at first. I also wasn't able to come close to what I wanted without dropping into code which...ready for it...is behind a paywall.

Do I really need email reminders? Do I? Really?

Scratch the auto reminder thing. What if I just put together a little route on this site that shows everything for me.

I know I know this has the same issue of me needing to check this but I am getting better with lists and I want to write some code so we are doing it. Or uhh I am doing it and you are reading about it.

A calendar UI or list?

At first, I wanted something like a calendar and started looking for components in react to use. Many awesome ones out there but when trying the demos....too much. I need simpler

What of a list? I thought about a look in my head and decided on spitting out a list of important dates for each month. Then you can just scroll up or down to see the important dates. It would start at the given month. It would be nice if it would let you scroll into the past and FAR into the feature or dynamic.

A list

I picked a stupid simple model for the data which maybe could later come from airtable or something.

const data = [{
  date: Date
  name: String,
  type: String/enum
}];

Yup, have a type in there for now as maybe I want something like a monthly or weekly or something kind of event. Maybe even let family add one time events.

Stupid simple.

Not as simple

I spent way too much time figuring out how to get that list into a format to render with. It likely would have been better to make it dynamic from the start but I didn't.

I build a map of months and years starting from the current date/month ending at some 100 months into the future. Sure, not the most elegant but uhh...it works.

Here is this monster that does it all. Note, I am using date-fns because that is what the internet tells me to do.

const getMonthDataMap = () => {
  const eventByMonthMap = new Map();
  let startMonth = new Date();
  const endMonth = addMonths(startMonth, 12 * 10);
  while (differenceInMonths(endMonth, startMonth) > 0) {
    eventByMonthMap.set(format(startMonth, "MMMM yyyy"), [
      ...eventDates.filter(
        (event) => getMonth(new Date(event.date)) === getMonth(startMonth)
      ),
    ]);
    startMonth = addMonths(startMonth, 1);
  }

  return eventByMonthMap;
};

Cool. Next, we render it.

Rendering a list

Ok, nothing cool here. I am not the best designer out there...if I'd even be called one, to begin with.

I decided to use my oh-so-favorite color palette package to set a background color for each month.

import niceColors from "nice-color-palettes";

It looked bad

I don't have the version of what it looked like but it felt...wrong. You see the issue was that because there were not that many events per month, you'd have like 12 months on the screen and the ones that were empty felt...off.

I decided with my outrageously amazing design skillz to just make each month 100vh.

It kinda worked

It looked way better but there was another issue. The contrast between the text color and the background. You see I reused something I like which is to add a slight drop shadow to text headers. It makes them pop a little more. Idk, I like it.

The issue is that for some of the colors in the palette package...it was horrible. White text with a little drop shadow on light backgrounds is horrible.

And off on a tangent we go

Ok, to save some time. There is much going on with color spaces and representations. I a familiar with a bit of it from back when I did graphics programming (sRGB, HSL, linear, gamma) etc.

This all means that having a is this too light for light text function, would be complicated. I found some HSP method that uses some 3d distances and arbitrary weights to figure out the "perceived" brightness of a color.

Awesome. Find the source of this function -> here

It gave awful results.

It isn't that it didn't work, but I kept having to fiddle with the threshold as white worked for 80 to 90 percent of the colors.

I ended up just filtering out all of the super bright colors from our palette list.

// niceColors is an array of palettes so we make it a single array first
const ALL_COLOURS = niceColors
  .reduce((acc, colors) => [...acc, ...colors], [])
  .filter((hex) => !isBrightColour(hex));

And left it with always using white.

Some colors still don't look the best but it is good enough.

The result

What did it look like? Amazing! Well, let me dial it back a bit. This isn't really all that impressive. It is just displaying data in a list.

Here it is with 150 random people courtesy of faker

The end

Did you scroll past all that? Nice job. Glad you made it to the end with me and thank you for reading.

There are some other ideas I have such as a little track on the side which shows the years you can skip to and from by tapping. I saw this in some apps and it was cool.

Maybe a fab to scroll back to the top.

Make it a dynamic list so one can scroll infinitely forward and backward in time.

And a "remind me" button which will send an email reminder x number of days before the birthday........

Cheers!