LifeKnifeX - a Collection of Life Management Tools
Tags: react, django, python, heroku
Published: 2021-05-10 03:39:48

Everyone has their own unique set of priorities, goals, and views of the world and themselves. On top of that, you or someone else you know may not be goal-oriented a person in the first place, instead shifting their focus to intuition and practical application to the world around them.

For those of us who are goal-oriented, however, managing those goals at scale (once again refining the audience to those with markedly busy minds) can become cumbersome without help. If it's not forgetting the goals you had in mind during your brainwave in the day before, it's trying to recall the priority structure that you had; furthermore, it becomes useful to have these goals in your life if you can properly understand if you've been **reaching your own standards**.

## Introductions

Given my experience in both setting goals and writing [React](https://reactjs.org) and [Django](https://www.djangoproject.com) applications (notably in Stopclutch)...

{% post phantomraa/stopclutch-a-django-race-manager-aee %}

...I set out to design a front-end and back-end pair called **LifeKnifeX**.

![LifeKnifeX home](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/home.png)

The name was suggested to me after announcing that I was designing this tool which was "cool enough to slice through the cake of life". The _X_ at the end was more so for domain naming and IP reasons.

## The Objective in a Nutshell

LifeKnifeX aims to cover the "slices" of life that pertain to goal-setting, personal performance metrics, continuous improvement of oneself, and discipline in areas one could call "classic offenders", such as diet and habit.

## Walk Through

The above screenshot of the home page is where users land, giving them a high-level overview of what possible areas the site provides assistance with in one's life. As of these screenshots, this includes _Nutrition_ and _Goals_.

The idea between these two modules, designed as equally applicable to the other planned modules on the home page, is about regular check-ins, and being rewarded for consistency of attention paid to these areas. Such reward would take place through the _Score_ function, though _Score_ will not be covered in this post.

### Nutrition

The _Nutrition_ card provides both direct access and shortcuts to deeper functions within the module itself. When a user first decides to _Visit_ nutrition, they're likely meet with a notice that they've yet to log something they consumed.

![LifeKnifeX empty nutrition](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/empty-nutrition.png)

The app is intelligent enough to display a different message if the user hasn't logged any food to begin with. In this situation, the _Food Library_ button disappears, and the message changes to inform them that they must first add a food they wish to log.

Upon navigating to the _Food Library_ itself in this situation, an appropriate and similar message is shown there, too.

![LifeKnifeX food library - empty](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/food-library-empty.png)

The form to add a new food allows a subjective determination of whether it's of good or bad quality along a [Likert scale](https://en.wikipedia.org/wiki/Likert_scale). This food can also have an image assigned to it for quick reference, and to be easy on the eyes.

![LifeKnifeX new food](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/new-food.png)

Once the food is added, a confirmation toast is shown as such:

![LifeKnifeX food saved toast](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/food-saved-toast.png)

It will then appear in the _Food Library_, replacing the previous guidance message.

![LifeKnifeX food library - full](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/food-library-full.png)

Since Django is used for the back end, it makes for easy management of `Food` and any other model in the app:

![LifeKnifeX admin - food list](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/admin-food-list.png)

One can then log a nutrition (or consumption) record against that food. In doing so, one can specify the food they ate , when they consumed it (because ice cream sounds good for lunch), and how much they had.

![LifeKnifeX log consumption](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/log-consumption.png)

The _When_ field is generalised to hour groups of the current day no later than the current hour. This is to dissuade users from allowing a backlog of consumption records to build up either in their head or on paper; by logging it at the source as soon as possible, the app works to encourage a general philosophy of consistency and discipline.

The intrinsic benefit and purpose of the _Quantity_ field is to have a more complex version of `Quantity • Quality` to categorically rate a user's health in each consumption, and then generate statistics across days or any arbitrary time period.

Saving a consumption record shows a similar toast to before:

![LifeKnifeX consumption logged toast](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/consumption-logged-toast.png)

This consumption then appears in the list, once again replacing the previous empty message on the corresponding page:

![LifeKnifeX nutrition list](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/nutrition-list.png)

Similar to before, this can be seen and managed in the admin:

![LifeKnifeX admin - consumption list](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/admin-consumption-list.png)

### Goals

When visiting the _Goals_ section of the site, one is met with a similar guidance screen to before:

![LifeKnifeX goals empty](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/goals-empty.png)

Adding a goal is performed through a similar procedure, clicking on the big pink button to bring up a form:

![LifeKnifeX new goal](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/new-goal.png)

The _Question_, _Style_, and _Start Date_ fields should be familiar and self-explanatory to many, behaving as intuition would have you guess. However, the _Test_ field is slightly nuanced.

The idea, following on from the precedent set by a `Goal`, is to allocate accountability to users to ensure continued contribution; this then helps the app help them. By choosing one of _At least every_ or _No more than every_ options, the user gets to define both the sentiment, and the priority of the goal in question; this effectively says whether the goal is intrinsically _good_ or _bad_.

The final _Test_ option, _Never_ provides no penalty or action taken on the user not contributing answers.

Saving a `Goal` shows a similar toast message, and then redirects to the Goals page to show the newly saved item:

![LifeKnifeX goals full](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/goals-full.png)

This can then be viewed in the admin:

![LifeKnifeX admin - goal list](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/admin-goal-list.png)

The admin can also edit a `Goal`, much like other models:

![LifeKnifeX admin - goal edit](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/admin-goal-edit.png)

When a goal hasn't been answered on the current day, an exclamation mark will appear in its card. A user can then answer that goal by clicking on the pink _Log Answer_ button, bringing up the answer form:

![LifeKnifeX goal answer](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/goal-answer.png)

Considerably simple, this page shows one goal at a time, allowing the user to choose an answer defined by the _Style_ of the goal as seen the previous form.

Once answered, the previous warning message will change to show success against answered goals, depending on the _Test_:

![LifeKnifeX goal item answered](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/goal-item-answered.png)

Following the now-classic admin pattern, an administrator can edit any answer:

![LifeKnifeX admin - answer edit](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/admin-answer-edit.png)

## Project Structure

The application is broken down into a React front-end and a Django back-end. The Django back-end uses the standard [PostgreSQL](https://www.postgresql.org) database without any frills, and exercises [Django REST framework](https://www.django-rest-framework.org) for communication from the front-end.

### Front-end

This was created with (and still technically uses) [create-react-app](https://reactjs.org/docs/create-a-new-react-app.html), but the project was initially created some time ago; as a result, it uses the older method of `npm install` in place of `yarn` and other similar commands.

It uses [Redux Toolkit](https://redux-toolkit.js.org) to make Redux marginally bearable (more on that story later) for state management, and the wonderful and stunning [Semantic UI React](https://react.semantic-ui.com) integration to make things look pretty. Icons are provided via [React Icons](https://github.com/react-icons/react-icons), which we will see in action shortly.

### Back-end

Aside from the aforementioned PostgreSQL and Django REST framework, this Django application doesn't do anything particularly out of the ordinary. Django's incredibly convenient model and migration management (alliteration not intended) make for a humorously fast development experience, especially when there are no views to be configured.

This site could have been made using the standard MERN stack, and while there's nothing wrong with that intrinsically, I was curious (at the time of this application's development) to see what Django was like when communicating with another stack for the front-end.

## CI and Deployment

Similar to the previous Stopclutch app, both the front-end and back-end use GitHub Actions for testing and deployment checks:

![LifeKnifeX CI](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/ci.png)

Once all checks pass on a merged pull request to `main`, Heroku will detect this and automatically the appropriate app to the staging `environment`. After manual inspection to ensure `staging` works as expected, this can be promoted to `production`.

## Criticism and Improvements

### Building at Scale

Contrary to what it may seem, this was a big project, especially to take on alone. I have a fair number of such small app concepts that I like to try out, often in new languages; this gives me a good idea of how much time and effort an idea will usually take, and as a result I tend to have a good idea of project feasibility.

Here, however, I discovered so much about the front-end from the back-end, and vice-versa. The work increased dramatically as a result; it was here that I had newfound respect for full-stack developers out there in industry. Ironically I'm one of them in a professional capacity, and yet still this took me by surprise.

The lesson learned here was to start small; it's easy to know when something is too small, but often times your internal alarm as a developer won't go off when your idea isn't quite bite-sized enough.

### Stick With What You Know

The front-end uses Semantic UI for theming, and more recently I started a branch to see what it would look like if I shifted everything to Bootstrap. The working copy looks like this:

![LifeKnifeX upgrade](https://cdn.jsdelivr.net/gh/dylanjboyd/dylanjboyd.github.io@main/assets/img/lifeknifex/upgrade.png)

I very quickly realised that the app would have been considerably more valuable had I stuck with contributing to the core internals and mechanics of the app, instead of playing around with theming. Being both the developer and the user of the app, I could quickly imagine myself complaining at the developer (if the poor soul weren't me) about not putting effort where they should.

### Don't Trivialise Fast-Paced Stacks

If PHP is a serene lake, JavaScript is white-water rafting. I have many a time assumed that it was safe to ignore the goings-on and just carry about my business. Little did I know that coming back to this app to ensure it was ready for this post, that many depended-upon libraries had since long moved on (`yarn` in `CRA` is a good example here).

After this experience, it has made me think twice before starting up a React app as a knee-jerk reaction, and instead viewing slower-moving (or perhaps more mature) stacks with greater respect and temptation.

## Conclusion

This has been an incredibly educational experience that has given me newfound respect for both developers and stacks. This isn't a project I feel particularly compelled to continue however, for the main reason that I discovered how it adds more work to my day to contribute such diet and goal logs than it does give back.

This is really something I had to implement to truly understand, and so this has by no means been a waste of time. All in all, thank you for reading through to the end!

Until next time, all the best!