Let's Learn: Remix Task Tracker (Part 2)
Tags: remix, webdev, beginners, react
Published: 2022-02-02 13:10:04

Welcome to this week's article 👋, where we would be continuing of from [last week's]() article about my thoughts on Remix whilst creating a Remix task tracker app. Without further ado, let's get started:

## <u>🔧 Rework:</u>

It was time to add the login functions. I decided to mix things up a bit for the authentication, I used `bcryptjs` instead of Supabase like I had planned and instead of a google sign in, stuck with the native email/password authentication method.

Let me draw a rough blueprint for the authentication:

- We would have a login page that allows users to either Sign Up (register) or Log In.
- Validate the users based on their choice, if `register` method:
  - Passwords must be equals to or greater than 8 characters
  - Valid email must be used (it must be unique in the database)
- If the method is `sign-in`:
  - The password must be correct
  - Email entered must be correct
- If validation process is successful, redirect them to the task-tracker page.

Seems good enough to me, let's start the build 👷‍♂️!

```sh
npm install @prisma/client
npm install --save-dev prisma
npm install bcryptjs
npm install --save-dev @types/bcryptjs
```

I created a `prisma` folder in my root directory and in it, created a `schema.prisma` file. This is where our database schema(structure) would go.

Before you are wondering what database, I am using [railway](https://www.railway.app) to host my PostgreSQL database. It is free and great for your little side-projects that require a running database. 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n3wus0eb6p9r1d6einam.png)
I have already provisioned a new PosgreSQL database (call her whatever you want), and now it's time to connect our Prisma to it!

Create a `.env` file in your app root directory and create an environment variable called "DATABASE_URL". It is this url that would allow prisma to connect to our database seamlessly. Head over to your railway dashboard and navigate to the "PostgreSQL" tab, in select the "Connect" tab and copy the Database Connection URL
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rkvy1s3rfnk920i0mcpf.png)
 
Paste the URL in the `.env` file (as your DATABASE_URL) and you can get started with Prisma! 

In the `schema.prisma`, I connected to my railway app and created a model for the database:
```sql
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
    id          String   @id @default(uuid())
    email       String   @unique()
    password    String
    icon        String?
    createdAt   DateTime @default(now())
    tasks       Tasks[]
}

model Tasks {
    id          String   @id @default(uuid())
    title       String
    description String?
    status      String?
    reminder    Boolean  @default(false)
    priority    String?
    deadline    DateTime
    createdAt   DateTime @default(now())
    updatedAt   DateTime @default(now())
    userId      String
    user        User     @relation(fields: [userId], references: [id])
}
```

I created to tables, one for the user and the second one for the tasks, this is a one-to-many relation in the sense that every user would have it's own table of tasks which would contain a lot of tasks (*One user -> Several Tasks*).

In the `User` table, we have an id (IDs are a must for every record in a table) that's a unique user id (uuid), and an email that must be unique. Also have a password field, an icon field that is optional (*indicated by the `?` icon after the type*). A `created-at` field and a Task field (that's more or less, a table).

In the `Tasks` table, the important fields are the id, the task's title, an optional description and deadline (which is our expiry time) and the most iportant, linking our `User` table to the Task table (Prisma has an [explanatory guide](https://www.prisma.io/docs/concepts/components/prisma-schema/relations/one-to-many-relations) on single-to-many relationship model). The rest are little details I intend to add to the app later to give it some spice.

You can run `npx prisma studio` to view live changes to your table and edit the database yourself!

I created an authentication handling action in my `index.tsx` (to avoid a messy post layout, I would refrain from adding all the code changes and instead link the repo at the end of this article) and linked it to a custom Remix `<Form>`. Let's rewind a bit on something, I am storing the user's password in the database? Yes, and we are going to use `bcryptjs` that we installed earlier to hash our passwords so no one would be able to decipher it (even the admin!)

If you think you can easily break a hashed password, try this:
- Hashed version of password "password" is: *$5$MnfsQ4iN$ZMTppKN16y/tIsUYs/obHlhdP.Os80yXhTurpBMUbA5* using the "SHA-256 crypt" hash type. 
- Using bcrypt hash type, the same password would end up as *$2a$05$bvIG6Nmid91Mu9RcmmWZfO5HJIMCT8riNW0hEp8f6/FuA2/mHZFpe*. Not really an easy thing to crack. 

After setting up my Form, it was time to style it and test it out.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uhsjuszh4o8awvy40vhz.png)

> Form look with some basic styling

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rg09od9zfu3hw7scy3h9.png)
 
> Signed In!

Ok, now we have successfully signed in. Let's add a logout function. That can be easily done by creating a `logout` route and then just having a loader that redirects to the login page.

```js
 //logout.tsx

import type { ActionFunction, LoaderFunction } from "remix";
// import "redirect" from Remix
import { redirect } from "remix";

//import our logout function
import { logout } from "~/utils/session.server";

export const action: ActionFunction = async ({
  request
}) => {
// run the logout request
  return logout(request);
};

export const loader: LoaderFunction = async () => {
// redirect the user
  return redirect("/");
};
```

## <u>🧳 Wrapping Up:</u>

Let's wrap up the basic function of our App. We need to save and get the user's tasks when they edit it. I decided to use real-time saving. Meaning each time they add or delete a task, it gets updated immediately, meanwhile, the deleted tasks would get deleted permanently each time the user signs out as we won't save it (*we can cache it for another time though 🤔*). 

We have the basic create + delete set up, but it takes a while to register. Let's give the user some indication that something is happening

And that's it for a basic task tracker app! Time to [push to github](https://github.com/ShafSpecs/Task-Tracker_Remix) and deploy. I hope to add extra features to it later as a personal challenge.

---

That's the end of the article series. This app was super fun to make and I am enjoying Remix more, issues I faced while making this app were more from prisma's end (*Ha!*), an example is weird disconnection from the database and random schema generation. I think Remix is good to go for a full-stack -large-scale application. Remix currently has a huge drawback for me currently, and that's a problem with importing ESM modules. Good news is that is currently getting fixed by the Remix's team, for now, there are work arounds that might successfully or unsuccessfully import the ESM module. Besides that, Remix all the way for me 🚀!

Like always, have fun learning and coding and don't forget to take breaks! Till next time 👋.