Through an extaordinary turn of events, I was able to absolutely jam through the first part of this app. It’s pretty exciting and I have a few thoughts on how I was able to execute that, but it may have to wait for another post. Here we’ll focus on the technical aspects of what I’ve accomplished so far.

Modal titled 'Gift Exchange Helper'
let's get started

Technical Decisions

In my previous post I listed the following features required for the MVP:

  • Create your party (give it a name)
  • Enter participants
  • Anonymously match participants
  • Create a link for each participant to see their matched person

To include these features, we really need 2 different views: Party Creation View (the bulk of the work, where the party is created and matched together) and Match View (where each individual can view their personal match). In a future iteration of this project there’d probably a “Party Edit View” too, but this isn’t part of this current work.

So far I’ve completed the frontend for the Party Creation View. I did this, also as listed in my previous post, just as I planned:

  • React
  • No TypeScript
  • Tailwind CSS (no component library)

So those initial frontend decisions served me well! It helped me move quickly and use my time effectively.

So what is there to discuss?

Form Handling

Why does form setup always seem like such a headache? I had to remind myself of the difference between controlled and unconrolled forms, then determine which made the most sense (controlled, in my case).

Crusty developer skills, ho!

If anything crushed my development speed, it was definitely my crusty ‘ole developer skills. A few technical bumps that gave me pause:

  • Oh man, remembering how to use flex took me a sec. CSS Tricks cheatsheet to the rescue!
  • Tailwind setup with Vite and PostCSS. Good news, I ran into the same issue I experienced in my Bookmark Decay project setup, so gg me for writing things down.
  • useState basics! Never forget to treat your state as read-only by updating your data to new object. You might accidentally and repeatedly change the original value, wasting a good 20-30 minutes. WHOOPS.

Matching algorithm

A few rules I followed setting up this algorithm:

  • We’re not pairing people off, we’re randomly drawing names “from a hat”
  • You can’t match with yourself (if you were to draw you rown name from a hat, you’d draw again)
    • Note to self: I think I need to update the algorithm in case your name happens to be the final one “in the hat”. 🤔

It’s been awhile since I’ve had to write an algorithm for anything, so I had to do a little puzzling on paper (and in code) to figure out how I wanted to do this. Once I wrapped my head around how I wanted to use Math.random to follow the couple of rules, I was good to go.

Basically, I create 2 arrays: one is the list of all names that does not change, the other is the “hat” from which we remove names. We get a random index from the hat array and match it to the “next” index of all names array. Then, ensuring the names aren’t the same, we add the pair of names to our final matching array of tuples. Pretty easy!

FUN FACT: in the final revision of this blog post I realized I’d way over-complicated my implementation (for some reason I was convinced at the time I needed to use state for this as opposed to a simple for-loop) and was able to remove half of my code. Nice! But also, duh.

🪓🪓🪓ing Scope

Besides it feeling good to shake the dust off of my decaying technical body, a big takeaway I had from this work was how aggressively axing scope was so essential to making time to complete this work. So many little details that I would’ve previously considered “quality of life” features I decided to not work on, and the time I got back from them really started to add up. Some of these small/tiny axed features included:

Over-styling

I didn’t over-think my color scheme, and decided to skip styling any additional form or component states, like errors or disabled states.

Also if I ran into any visual issue that didn’t impede the functionality, I let it go. Buttons differently sized on different slides? SKIP IT. Styling issues can be a black hole.

Quality of life

Functionality I typically would have added to make the app feel more refined and work more smoothly or clearly, I skipped:

  • When adding a name to the list, I didn’t spend the time to return the focus back to the input
  • Decided not to include a “total number of names” - not only did I not have to implement it, but I didn’t have to think about where it should live.
  • Form validation. Ain’t nobody got time for that right now.

Development shame

Quick and dirty, y’all. I didn’t attempt to optimize anything, just went with my gut and probably occasionally naive implementations. Also, I skipped writing tests. NO SHAME!

The 'Game of Thrones' Shame Nun rings her shame bell
NO TIME GO FAST

Next Steps

Next up I’ll start adding in the database so we save the party matches and retrieve them later. Hopefully I can keep up this head of steam to push the project onward!