# RFiD Time Tracker

# Introduction

RFID Time Tracker is a website tool to help you track and overview your work hours in the RoboTeam.

<p class="callout success">Tracked hours will be used to calculate how much compensation you receive from FOBOS, so be sure to check in!</p>

## Features

1. Registering a physical NFC tag to check in/out physically at the office.
2. check in/out remotely if you forgot to do in real life.
3. setting up your weekly hour quota
4. Viewing your statistics compared to a weekly/monthly progress bar. Total for today/week/month…
5. For admins - viewing different team member's stats, viewing team's statistics in bar charts with members comparison.

It works in combination with physical box mounted onto the wall, created by RoboTeam members.  
It is advised to track your working hours for convenience.

## Tech overview

The RFID Tracker consists of two parts: a physical box to scan your RFID tag, and a web dashboard to see your statistics.

### Web dashboard

<span style="white-space:pre-wrap;">codename midas, it as a </span>**Django**<span style="white-space:pre-wrap;"> application. Unlike the landing page project, this one uses </span>`<span class="editor-theme-code">nix</span>`<span style="white-space:pre-wrap;"> to manage system dependencies and </span>`<span class="editor-theme-code">uv</span>`<span style="white-space:pre-wrap;"> to manage Python packages.</span>

<span style="white-space:pre-wrap;">Its source code lives at </span>[https://github.com/RoboTeamTwente/rfid-tracker-server.](https://github.com/RoboTeamTwente/rfid-tracker-server.)

### RFID scanner

<span style="white-space:pre-wrap;">Its source code lives at </span>[https://github.com/RoboTeamTwente/RFiD-Time-Tracker-Scanner.](https://github.com/RoboTeamTwente/RFiD-Time-Tracker-Scanner.)

<p class="callout warning">WIP</p>

# Web app

# Getting Started

## Tech Stack

- **Language:**<span style="white-space: pre-wrap;"> Python 3.14 (Managed via Nix)</span>
- **Framework:**<span style="white-space: pre-wrap;"> Django</span>
- **Package Manager:**<span style="white-space: pre-wrap;"> </span>[uv](https://github.com/astral-sh/uv)<span style="white-space: pre-wrap;"> (Fastest Python resolver/installer)</span>
- **Environment:**<span style="white-space: pre-wrap;"> </span>[Nix](https://nixos.org/)<span style="white-space: pre-wrap;"> (with the </span>`<span class="editor-theme-code">std</span>`<span style="white-space: pre-wrap;"> library)</span>
- **Command Runner:**<span style="white-space: pre-wrap;"> </span>`<span class="editor-theme-code">just</span>`<span style="white-space: pre-wrap;"> (alternative to </span>`<span class="editor-theme-code">make</span>`)

## Setting Up the Environment

<p class="callout danger">FIXME: this is wrong</p>

<span style="white-space: pre-wrap;">You do not need to install Python or Django manually. You only need </span>**Nix**.

### Step 1: Install Nix

If you don't have it, install Nix and enable “experimental features” (Flakes and Nix Command).

Consider doing the latter like that:  
<span style="white-space: pre-wrap;">1) </span>`<span class="editor-theme-code">sudo mkdir /root/.config/nix </span>`

<span style="white-space: pre-wrap;">2) </span>`<span class="editor-theme-code">sudoedit /root/.config/nix/nix.conf</span>`

<span style="white-space: pre-wrap;">3) In there, add this line </span>`<span class="editor-theme-code">experimental-features = nix-command flakes</span>`

### Step 2: Enter the Development Shell

Navigate to the project root and run:

`<span class="editor-theme-code">nix develop</span>`

**What happens when you run this?**<span style="white-space: pre-wrap;"> Nix reads </span>`<span class="editor-theme-code">shells.nix</span>`<span style="white-space: pre-wrap;"> and </span>`<span class="editor-theme-code">packages.nix</span>`<span style="white-space: pre-wrap;"> to:</span>

1. <span style="white-space: pre-wrap;">Download and provide </span>**Python 3.14**.
2. <span style="white-space: pre-wrap;">Install system tools like </span>`<span class="editor-theme-code">curl</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">git</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">uv</span>`<span style="white-space: pre-wrap;">, and </span>`<span class="editor-theme-code">just</span>`.
3. <span style="white-space: pre-wrap;">Set up your </span>`<span class="editor-theme-code">PATH</span>`<span style="white-space: pre-wrap;"> to include the project’s virtual environment (</span>`<span class="editor-theme-code">.venv/bin</span>`).
4. Activate a custom shell prompt (the “embed console”).

### Step 3: The “Just” Command Runner

<span style="white-space: pre-wrap;">Once inside the Nix shell, we use a tool called </span>`<span class="editor-theme-code">just</span>`<span style="white-space: pre-wrap;"> to run common tasks.</span>

<table id="bkmrk-commandactionjustlis" style="margin-bottom: 32px;"><colgroup><col></col><col></col></colgroup><tbody><tr><td style="border: 1px solid;">**Command**

</td><td style="border: 1px solid;">**Action**

</td></tr><tr><td style="border: 1px solid;">`<span class="editor-theme-code">just</span>`

</td><td style="border: 1px solid;">Lists all available commands.

</td></tr><tr><td style="border: 1px solid;">**`<strong class="editor-theme-bold editor-theme-code">just init-db</strong>`**

</td><td style="border: 1px solid;">**Run this first.**<span style="white-space: pre-wrap;"> It migrates the DB and asks you to create a Superuser.</span>

</td></tr><tr><td style="border: 1px solid;">**`<strong class="editor-theme-bold editor-theme-code">just dev</strong>`**

</td><td style="border: 1px solid;">Starts the Django development server.

</td></tr><tr><td style="border: 1px solid;">`<span class="editor-theme-code">just make-migrations</span>`

</td><td style="border: 1px solid;">Generates new DB migration files after model changes.

</td></tr><tr><td style="border: 1px solid;">`<span class="editor-theme-code">just fmt</span>`

</td><td style="border: 1px solid;"><span style="white-space: pre-wrap;">Automatically formats all code using </span>`<span class="editor-theme-code">treefmt</span>`.

</td></tr><tr><td style="border: 1px solid;">`<span class="editor-theme-code">just test</span>`

</td><td style="border: 1px solid;">Runs the Django test suite.

</td></tr></tbody></table>

### Step 4: Running the dev server

Consider using these commands after all previous steps:

`<span class="editor-theme-code">nix init-db </span>`<span style="white-space: pre-wrap;"> creates and initializes the DB, prompting for superuser credentials.</span>  
`<span class="editor-theme-code">nix dev </span>`<span style="white-space: pre-wrap;"> starts a local dev server.</span>  
**Congratulations! You are ready to develop.**

# Structure of the project

## Architecture &amp; Frontend Patterns (Midas)

<span style="white-space: pre-wrap;">The RFID Tracker (codename </span>**Midas**) follows a traditional Django structure but uses a “Single File Component” philosophy for its views.

## Project Organization

The project is split into the core configuration and the functional app logic.

<table id="bkmrk-directory-%2F-filerole"><colgroup><col></col><col></col></colgroup><tbody><tr><td>**Directory / File**

</td><td>**Role**

</td></tr><tr><td>**`<strong class="editor-theme-bold editor-theme-code">midas/</strong>`**

</td><td>The active module containing the latest logic, models, and views.

</td></tr><tr><td>**`<strong class="editor-theme-bold editor-theme-code">webui/</strong>`**

</td><td><span style="white-space: pre-wrap;">Legacy code kept for bookkeeping; </span>**do not use**<span style="white-space: pre-wrap;"> for new features.</span>

</td></tr><tr><td>**`<strong class="editor-theme-bold editor-theme-code">templates/midas/</strong>`**

</td><td>The “Face” of the app. Contains HTML layouts, CSS, and JS.

</td></tr><tr><td>**`<strong class="editor-theme-bold editor-theme-code">models.py</strong>`**

</td><td>Database schema (RFID tags, teams, hours).

</td></tr><tr><td>**`<strong class="editor-theme-bold editor-theme-code">views.py</strong>`**

</td><td>The “Controller.” Fetches data from DB and performs calculations.

</td></tr><tr><td>**`<strong class="editor-theme-bold editor-theme-code">urls.py</strong>`**

</td><td><span style="white-space: pre-wrap;">Maps URLs to specific Python functions in </span>`<span class="editor-theme-code">views.py</span>`.

</td></tr></tbody></table>

---

## The Frontend Pattern

### Layout Strategy

Every page follows this block-based hierarchy:

1. **`<strong class="editor-theme-bold editor-theme-code">{% extends 'midas/base.html' %}</strong>`**: Inherits the sidebar, navbar, and global styles.
2. **`<strong class="editor-theme-bold editor-theme-code">{% block head %}</strong>`**: Contains page-specific CSS and external libraries (like Chart.js).
3. **`<strong class="editor-theme-bold editor-theme-code">{% block main %}</strong>`**: The actual HTML content (cards, forms, tables).
4. **`<strong class="editor-theme-bold editor-theme-code"><script></strong>`**: Local logic for charts or UI interactions.

## The “Data Bridge” (Python to JavaScript)

To keep the code clean and secure, we use a specific pattern to pass data from the Python backend to the JavaScript frontend.

### <span style="white-space: pre-wrap;">The </span>`<span class="editor-theme-code">json_script</span>`<span style="white-space: pre-wrap;"> Filter</span>

<span style="white-space: pre-wrap;">Instead of messy string concatenation, we use Django's </span>`<span class="editor-theme-code">json_script</span>`<span style="white-space: pre-wrap;"> tag. This safely injects Python dictionaries into the HTML as a JSON object that JS can read.</span>

**In the HTML Template:**  
`<span class="editor-theme-code">{{ page_data|json_script:"frontend-data" }}</span>`

**In the JavaScript block:**  
`<span class="editor-theme-code">const appData = JSON.parse(document.getElementById('frontend-data').textContent);</span>`  
`<span class="editor-theme-code">// Now appData.chart.labels is ready for Chart.js!</span>`

## Backend Logic &amp; Calculation

The heavy lifting is done in the Python files before the page even loads:

- **Calculations:**<span style="white-space: pre-wrap;"> Logic like “Total Hours” or “Avg per Member” is calculated in </span>`<span class="editor-theme-code">views.py</span>`<span style="white-space: pre-wrap;"> or helper files like </span>`<span class="editor-theme-code">statistics.py</span>`.
- **Database Interaction:**<span style="white-space: pre-wrap;"> Uses Django’s ORM (Object-Relational Mapper) to query the </span>`<span class="editor-theme-code">db.sqlite3</span>`<span style="white-space: pre-wrap;"> (dev) or the production DB.</span>
- **Forms:**<span style="white-space: pre-wrap;"> Django’s </span>`<span class="editor-theme-code">forms.py</span>`<span style="white-space: pre-wrap;"> handles input validation when you change dates or teams in the dashboard.</span>

## Admin dashboard

Django provides its own built-in admin dashboard which can be reached through “Admin Dashboard” button on the sidebar. (if you are a superuser).

# RFID Scanner