3 Commits

Author SHA1 Message Date
be6b465684 Added: vehicle creation 2024-12-31 15:53:15 +01:00
aded859a79 Added: tables for fuel-stats 2024-12-31 14:21:41 +01:00
c29bd7cbab Edited: App is rebranded to Fuel Stats 2024-12-31 11:34:39 +01:00
25 changed files with 261 additions and 293 deletions

View File

@@ -208,8 +208,8 @@ If you develop a new program, and you want it to be of the greatest possible use
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.
habit-tracker Fuel Stats
Copyright (C) 2024 fr Copyright (C) 2024 Filip Rojek
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
@@ -221,7 +221,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:
habit-tracker Copyright (C) 2024 fr Fuel Stats Copyright (C) 2024 Filip Rojek
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.

View File

@@ -1,32 +1,32 @@
# Habit Tracker # Fuel Stats
An app for tracking habits and motivation to achieve personal goals An app for tracking your fuel consumption and optimizing your driving efficiency.
## Used technologies ## Used Technologies
- **Frontend:** HTML, CSS, JavaScript - **Frontend:** HTML, CSS, JavaScript
- **Backend:** PHP (OOP) - **Backend:** PHP (OOP)
- **Database:** MariaDB - **Database:** MariaDB
## How to build ## How to Build
### Build using docker ### Build Using Docker
Run the container using docker-compose Run the container using docker-compose:
```bash ```bash
docker-compose up docker-compose --profile <dev|prod> up -d
``` ```
The app should be available at http://localhost:8000 The app should be available at http://localhost:8000.
PhpMyAdmin should be available at http://localhost:8080 PhpMyAdmin should be available at http://localhost:8080.
### Build manually ### Build Manually
1. Clone the repo 1. Clone the repository:
```bash ```bash
git clone https://git.filiprojek.cz/fr/habit-tracker.git git clone https://git.filiprojek.cz/fr/fuel-stats.git
``` ```
2. Create `config/environment.php` 2. Create `config/environment.php`:
- It should have following structure: - It should have the following structure:
```php ```php
<?php <?php
@@ -35,21 +35,23 @@ define('DB_USER', 'your db username');
define('DB_PASS', 'your db password'); define('DB_PASS', 'your db password');
define('DB_NAME', 'your db name'); define('DB_NAME', 'your db name');
``` ```
- For the database, you can use included `docker-compose.yaml` which have both MariaDB and PhpMyAdmin - For the database, you can use the included `docker-compose.yaml` which includes both MariaDB and PhpMyAdmin.
3. Start an local web server 3. Start a local web server:
- You can use php's integrated server by running this: - You can use PHP's integrated server by running this:
```bash ```bash
php -S localhost:8000 -t ./public php -S localhost:8000 -t ./public
``` ```
- You can use any host and any port you want. - You can use any host and any port you prefer.
## Usage ## Usage
1. Register and Login to the app. 1. Register and log in to the app.
2. Add your habits. 2. Add your vehicles with their details (fuel type, registration, etc.).
3. Mark your habits when you're done doing them. 3. Record each refueling:
4. Earn point and unlock achievements by completing you're habits! - Select your vehicle.
- Input the number of liters, price per liter, and total cost.
## Licence 4. Track your fuel consumption and spending through the dashboard.
This project is licensed under GPL3.0 and later. More information is availabe in `LICENSE` file. 5. View detailed stats and graphs to analyze your driving habits.
## License
This project is licensed under GPL3.0 and later. More information is available in the `LICENSE` file.

View File

@@ -1,12 +1,12 @@
<?php <?php
class DashboardController extends Controller { class DashboardController extends Controller {
public function index() { public function index() {
$habit = new Habit(); $vehicle = new Vehicle();
$habits = $habit->getHabitsByUser($_SESSION['user']['id']); $vehicles = $vehicle->getVehiclesByUser($_SESSION['user']['id']);
$this->view('dashboard/index', [ $this->view('dashboard/index', [
'title' => 'Dashboard', 'title' => 'Dashboard',
'habits' => $habits, 'vehicles' => $vehicles,
]); ]);
} }

View File

@@ -1,57 +0,0 @@
<?php
class HabitController extends Controller {
public function index() {
$habit = new Habit();
$habits = $habit->getHabitsByUser($_SESSION['user']['id']);
$this->view('habits/index', ['title' => 'Habits', 'habits' => $habits]);
}
public function create() {
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
$frequency = $_POST['frequency'] ?? 'Daily';
$customFrequency = null;
if (empty($name)) {
$this->view('habits/create', ['error' => 'Habit name is required.']);
return;
}
if ($frequency === 'Custom') {
$daysOfWeek = $_POST['days_of_week'] ?? [];
$daysOfMonth = $_POST['days_of_month'] ?? '*';
$months = $_POST['months'] ?? '*';
// Combine into crontab-like string
$customFrequency = implode(',', $daysOfWeek) . " $daysOfMonth $months";
}
$habit = new Habit();
$result = $habit->create([
'name' => $name,
'frequency' => $frequency,
'custom_frequency' => $customFrequency,
'reward_points' => intval($_POST['difficulty'] ?? 1),
'user_id' => $_SESSION['user']['id'],
]);
if ($result) {
$this->redirect('/habits');
} else {
$this->view('habits/create', ['error' => 'Failed to create habit.']);
}
} else {
$this->view('habits/create', ['title' => 'Create Habit']);
}
}
public function edit() {
// Edit habit (to be implemented later)
}
public function delete() {
// Delete habit (to be implemented later)
}
}

View File

@@ -0,0 +1,61 @@
<?php
class VehicleController extends Controller {
public function index() {
$vehicle = new Vehicle();
$vehicles = $vehicle->getVehiclesByUser($_SESSION['user']['id']);
$this->view('vehicles/index', ['title' => 'Vehicles', 'vehicles' => $vehicles]);
}
public function create() {
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
$registration_plate = $_POST['registration_plate'] ?? '';
$fuel_type = $_POST['fuel_type'] ?? '';
$note = $_POST['note'] ?? '';
$validator = new Validator();
$validator->required('name', $name);
$validator->required('registration_plate', $registration_plate);
$validator->required('fuel_type', $fuel_type);
if($note == "") $note = NULL;
if (!$validator->passes()) {
$this->view('vehicle/create', [
'error' => 'Please correct the errors below.',
'validationErrors' => $validator->errors() ?: [],
]);
return;
}
$vehicle = new Vehicle();
$result = $vehicle->create([
'name' => $name,
'registration_plate' => strtoupper($registration_plate),
'fuel_type' => $fuel_type,
'note' => $note,
'user_id' => $_SESSION['user']['id'],
]);
if ($result === true) {
$this->redirect('/vehicles');
} else {
$this->view('vehicles/create', ['title' => 'Create vehicle', 'error' => $result, 'validationErrors' => []] );
}
} else {
$this->view('vehicles/create', ['title' => 'Create Vehicle']);
}
}
public function edit() {
// Edit vehicle (to be implemented later)
}
public function delete() {
// Delete vehicle (to be implemented later)
}
}

View File

@@ -1,46 +0,0 @@
<?php
class Habit {
private $db;
public function __construct() {
$this->db = Database::getInstance()->getConnection();
}
public function create($data) {
$stmt = $this->db->prepare("
INSERT INTO habits (user_id, title, frequency, custom_frequency, reward_points, created_at)
VALUES (?, ?, ?, ?, ?, NOW())
");
$stmt->bind_param(
"isssi", // Bind types: int, string, string, string, int
$data['user_id'],
$data['name'],
$data['frequency'],
$data['custom_frequency'], // Bind the custom_frequency field
$data['reward_points']
);
if ($stmt->execute()) {
return true;
} else {
error_log("Failed to create habit: " . $stmt->error);
return false;
}
}
public function getHabitsByUser($userId) {
$stmt = $this->db->prepare("SELECT id, title, frequency, custom_frequency, reward_points, created_at FROM habits WHERE user_id = ?");
$stmt->bind_param("i", $userId);
$stmt->execute();
$result = $stmt->get_result();
$habits = [];
while ($row = $result->fetch_assoc()) {
$habits[] = $row;
}
return $habits;
}
}

49
app/models/Vehicle.php Normal file
View File

@@ -0,0 +1,49 @@
<?php
class Vehicle {
private $db;
public function __construct() {
$this->db = Database::getInstance()->getConnection();
}
public function create($data) {
try{
$stmt = $this->db->prepare("
INSERT INTO vehicles (user_id, name, registration_plate, fuel_type, note, created_at)
VALUES (?, ?, ?, ?, ?, NOW())
");
$stmt->bind_param(
"issss",
$data['user_id'],
$data['name'],
$data['registration_plate'],
$data['fuel_type'],
$data['note'],
);
if ($stmt->execute()) {
return true;
} else {
return "Error: " . $stmt->error;
}
} catch(mysqli_sql_exception $e) {
return $e->getMessage();
}
}
public function getVehiclesByUser($userId) {
$stmt = $this->db->prepare("SELECT id, name, registration_plate, fuel_type, note, created_at FROM vehicles WHERE user_id = ?");
$stmt->bind_param("i", $userId);
$stmt->execute();
$result = $stmt->get_result();
$vehicles = [];
while ($row = $result->fetch_assoc()) {
$vehicles[] = $row;
}
return $vehicles;
}
}

View File

@@ -2,8 +2,8 @@
<link rel="stylesheet" href="/css/form.css"> <link rel="stylesheet" href="/css/form.css">
<section class="form signin"> <section class="form signin">
<div class="header-form"> <div class="header-form">
<img src="/img/logo.jpg" alt="Habit Tracker Logo"> <img src="/img/logo.jpg" alt="Fuel Stats Logo">
<h1>Sign in to Habit Tracker</h1> <h1>Sign in to Fuel Stats</h1>
</div> </div>
<?php if ($this->get('error')): ?> <?php if ($this->get('error')): ?>
@@ -27,7 +27,7 @@
</form> </form>
<div class="bordered"> <div class="bordered">
<p>New to Habit Tracker?</p> <p>New to Fuel Stats?</p>
<a href="/auth/signup">Create an account</a> <a href="/auth/signup">Create an account</a>
</div> </div>
</section> </section>

View File

@@ -2,8 +2,8 @@
<link rel="stylesheet" href="/css/form.css"> <link rel="stylesheet" href="/css/form.css">
<section class="form signup"> <section class="form signup">
<div class="header-form"> <div class="header-form">
<img src="/img/logo.jpg" alt="Habit Tracker Logo"> <img src="/img/logo.jpg" alt="Fuel Stats Logo">
<h1>Sign up to Habit Tracker</h1> <h1>Sign up to Fuel Stats</h1>
</div> </div>
<?php if ($this->get('error')): ?> <?php if ($this->get('error')): ?>

View File

@@ -3,8 +3,8 @@
<section class="dashboard"> <section class="dashboard">
<h1>Welcome, <?= htmlspecialchars($_SESSION['user']['username']) ?>!</h1> <h1>Welcome, <?= htmlspecialchars($_SESSION['user']['username']) ?>!</h1>
<div> <div>
<a href="/habits/create" class="btn-green">Create new habit!</a> <a href="/refuel/add" class="btn-green">Add new refuel record!</a>
<a href="/habits" class="btn-primary">List all habits</a> <a href="/vehicles" class="btn-primary">List all vehicles</a>
</div> </div>
<div class="card-wrapper"> <div class="card-wrapper">
<section class="card upcoming"> <section class="card upcoming">

View File

@@ -4,7 +4,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Habit Tracker | Error 494</title> <title>Fuel Stats | Error 494</title>
</head> </head>
<body> <body>
<h1>Error 404 - Page not found</h1> <h1>Error 404 - Page not found</h1>

View File

@@ -1,70 +0,0 @@
<link rel="stylesheet" href="/css/form.css">
<link rel="stylesheet" href="/css/habits_create.css">
<section class="form habit-create">
<h1 class="header-form"><?= $this->get('title', 'Create Habit') ?></h1>
<?php if ($this->get('error')): ?>
<div class="error" style="color: red; margin-bottom: 1rem;">
<?= htmlspecialchars($this->get('error')) ?>
</div>
<?php endif; ?>
<form method="POST" action="/habits/create">
<label for="name">Habit Name</label>
<input type="text" name="name" id="name" required value="<?= htmlspecialchars($_POST['name'] ?? '') ?>">
<label for="frequency">Frequency</label>
<select name="frequency" id="frequency" onchange="toggleCustomFrequency(this.value)">
<option value="Daily">Daily</option>
<option value="Weekly">Weekly</option>
<option value="Custom">Custom</option>
</select>
<div id="custom-frequency" style="display: none;">
<label id="lbl_dow">Days of the Week</label>
<div class="dow_chb_wrapper">
<label for="dow_mon">Monday</label>
<input type="checkbox" name="days_of_week[]" id="dow_mon" value="1">
</div>
<div class="dow_chb_wrapper">
<label for="dow_tue">Tuesday</label>
<input type="checkbox" name="days_of_week[]" id="dow_tue" value="2">
</div>
<div class="dow_chb_wrapper">
<label for="dow_wed">Wednesday</label>
<input type="checkbox" name="days_of_week[]" id="dow_wed" value="3">
</div>
<div class="dow_chb_wrapper">
<label for="dow_thu">Thursday</label>
<input type="checkbox" name="days_of_week[]" id="dow_thu" value="4">
</div>
<div class="dow_chb_wrapper">
<label for="dow_fri">Friday</label>
<input type="checkbox" name="days_of_week[]" id="dow_fri" value="5">
</div>
<div class="dow_chb_wrapper">
<label for="dow_sat">Saturday</label>
<input type="checkbox" name="days_of_week[]" id="dow_sat" value="6">
</div>
<div class="dow_chb_wrapper">
<label for="dow_sun">Sunday</label>
<input type="checkbox" name="days_of_week[]" id="dow_sun" value="7">
</div>
<label for="days_of_month" id="lbl_dom">Days of the Month</label>
<input type="text" name="days_of_month" id="days_of_month" placeholder="1,15 (comma-separated)">
<label for="months">Months</label>
<input type="text" name="months" id="months" placeholder="1,7,12 (comma-separated)">
</div>
<input type="submit" value="Create Habit">
</form>
</section>
<script>
function toggleCustomFrequency(value) {
const customFrequencyDiv = document.getElementById('custom-frequency');
customFrequencyDiv.style.display = value === 'Custom' ? 'flex' : 'none';
}
</script>

View File

@@ -1,24 +0,0 @@
<link rel="stylesheet" href="/css/habits_dashboard.css">
<section class="habits">
<?php if (empty($this->get('habits'))): ?>
<p>No habits yet. <a href="/habits/create">Create your first habit</a>.</p>
<?php else: ?>
<div class="habits-wrapper">
<?php foreach ($this->get('habits') as $habit): ?>
<div class="habit bordered">
<b><?= htmlspecialchars($habit['title']) ?></b>
<p>Frequency: <?= htmlspecialchars($habit['frequency']) ?></p>
<?php if (isset($habit['custom_frequency'])): ?>
<p><?= htmlspecialchars($habit['custom_frequency'] ?? 'N/A') ?></p>
<?php endif; ?>
<p><?= htmlspecialchars($habit['reward_points']) ?></p>
<p><?= htmlspecialchars($habit['created_at']) ?></p>
<a href="/habits/done">Mark as done</a> |
<a href="/habits/edit?id=<?= $habit['id'] ?>">Edit</a> |
<a href="/habits/delete?id=<?= $habit['id'] ?>" onclick="return confirm('Are you sure you want to delete this habit?')">Delete</a>
</div>
<?php endforeach; ?>
</div>
<a href="/habits/create" class="btn-green">Create new habit!</a>
<?php endif; ?>
</section>

View File

@@ -1,4 +1,4 @@
<div> <div>
<h1>Welcome to Habit Tracker!</h1> <h1>Welcome to Fuel Stats!</h1>
<p>Track your habits and achieve your goals.</p> <p>Keep track of your refuels.</p>
</div> </div>

View File

@@ -6,7 +6,7 @@
<meta name="author" content="Filip Rojek | http://filiprojek.cz"> <meta name="author" content="Filip Rojek | http://filiprojek.cz">
<meta name="email" content="webmaster(@)fofrweb.com"> <meta name="email" content="webmaster(@)fofrweb.com">
<meta name="copyright" content="(c) filiprojek.cz"> <meta name="copyright" content="(c) filiprojek.cz">
<title>Habit Tracker | <?= $data['title'] ?></title> <title>Fuel Stats | <?= $data['title'] ?></title>
<link rel="stylesheet" href="/css/main.css"> <link rel="stylesheet" href="/css/main.css">
<link rel="stylesheet" href="/css/global.css"> <link rel="stylesheet" href="/css/global.css">
<link rel="stylesheet" href="/css/vars.css"> <link rel="stylesheet" href="/css/vars.css">

View File

@@ -6,7 +6,7 @@
<meta name="author" content="Filip Rojek | http://filiprojek.cz"> <meta name="author" content="Filip Rojek | http://filiprojek.cz">
<meta name="email" content="webmaster(@)fofrweb.com"> <meta name="email" content="webmaster(@)fofrweb.com">
<meta name="copyright" content="(c) filiprojek.cz"> <meta name="copyright" content="(c) filiprojek.cz">
<title>Habit Tracker | <?= $data['title'] ?></title> <title>Fuel Stats | <?= $data['title'] ?></title>
<link rel="stylesheet" href="/css/main.css"> <link rel="stylesheet" href="/css/main.css">
<link rel="stylesheet" href="/css/global.css"> <link rel="stylesheet" href="/css/global.css">
<link rel="stylesheet" href="/css/vars.css"> <link rel="stylesheet" href="/css/vars.css">

View File

@@ -0,0 +1,35 @@
<link rel="stylesheet" href="/css/form.css">
<link rel="stylesheet" href="/css/vehicle_create.css">
<section class="form">
<h1 class="header-form"><?= $this->get('title', 'Create Vehicle') ?></h1>
<?php if ($this->get('error')): ?>
<div class="error" style="color: red; margin-bottom: 1rem;">
<?= htmlspecialchars($this->get('error')) ?>
</div>
<?php endif; ?>
<form method="POST" action="/vehicles/add">
<label for="name">Vehicle name</label>
<input type="text" name="name" id="name" required value="<?= htmlspecialchars($_POST['name'] ?? '') ?>">
<label for="registration_plate">Registration plate</label>
<input type="text" name="registration_plate" id="registration_plate" maxlength="10" onkeypress="return event.charCode != 32" required value="<?= htmlspecialchars($_POST['registration_plate'] ?? '') ?>">
<label for="fuel_type">Fuel type</label>
<select name="fuel_type" id="fuel_type">
<option value="Diesel">Diesel</option>
<option value="Gasoline 95">Gasoline 95</option>
<option value="Gasoline 98">Gasoline 98</option>
<option value="Premium Diesel">Premium Diesel</option>
<option value="Premium Gasoline 95">Premium Gasoline 95</option>
<option value="Premium Gasoline 98">Premium Gasoline 98</option>
<option value="Other">Other</option>
</select>
<label for="note">Note</label>
<input type="text" name="note" id="note" value="<?= htmlspecialchars($_POST['note'] ?? '') ?>">
<input type="submit" value="Create vehicle">
</form>
</section>

View File

@@ -0,0 +1,19 @@
<link rel="stylesheet" href="/css/vehicles.css">
<section class="vehicles">
<?php if (empty($this->get('vehicles'))): ?>
<p>No vehicles yet. <a href="/vehicles/add">Add your first vehicle</a>.</p>
<?php else: ?>
<div class="vehicle-wrapper">
<?php foreach ($this->get('vehicles') as $vehicle): ?>
<div class="vehicle bordered">
<b><?= htmlspecialchars($vehicle['name']) ?></b>
<a href="/vehicles/edit?id=<?= $vehicle['id'] ?>">Edit</a> |
<a href="/vehicles/delete?id=<?= $vehicle['id'] ?>" onclick="return confirm('Are you sure you want to delete this habit?')">Delete</a>
</div>
<?php endforeach; ?>
</div>
<br>
<a href="/vehicles/create" class="btn-green">Add new vehicle!</a>
<?php endif; ?>
</section>

View File

@@ -1,6 +1,6 @@
<?php <?php
define('DB_HOST', '0.0.0.0'); define('DB_HOST', '0.0.0.0');
define('DB_NAME', 'habit_tracker'); define('DB_NAME', 'fuel_stats');
define('DB_USER', 'username'); define('DB_USER', 'username');
define('DB_PASS', 'password'); define('DB_PASS', 'password');

View File

@@ -57,7 +57,7 @@ class Database {
* Check and create required tables if they don't exist * Check and create required tables if they don't exist
*/ */
private function checkAndCreateTables() { private function checkAndCreateTables() {
// Create users table // Create tables
$usersTableQuery = "CREATE TABLE IF NOT EXISTS users ( $usersTableQuery = "CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY, id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL, username VARCHAR(50) NOT NULL,
@@ -71,36 +71,52 @@ class Database {
die("Failed to create users table: " . $this->connection->error); die("Failed to create users table: " . $this->connection->error);
} }
// Create progress table $vehiclesTableQuery = "
$progressTableQuery = "CREATE TABLE IF NOT EXISTS progress ( CREATE TABLE IF NOT EXISTS vehicles (
id INT AUTO_INCREMENT PRIMARY KEY, id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL, user_id INT NOT NULL,
habit_id INT NOT NULL, name VARCHAR(100) NOT NULL,
date DATE NOT NULL, registration_plate VARCHAR(50) NOT NULL UNIQUE,
status ENUM('Done', 'Pending') DEFAULT 'Pending', fuel_type ENUM('Diesel', 'Gasoline 95', 'Gasoline 98', 'Premium Diesel', 'Premium Gasoline 95', 'Premium Gasoline 98', 'Other') NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id) note VARCHAR(150) NULL,
) ENGINE=InnoDB;"; created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB;
";
if (!$this->connection->query($progressTableQuery)) { if (!$this->connection->query($vehiclesTableQuery)) {
die("Failed to create progress table: " . $this->connection->error); die("Failed to create vehicles table: " . $this->connection->error);
} }
$refuelingTableQuery = "
// Create habits table CREATE TABLE IF NOT EXISTS refueling_records (
$habitsTableQuery = "CREATE TABLE IF NOT EXISTS habits ( id INT AUTO_INCREMENT PRIMARY KEY,
vehicle_id INT NOT NULL,
fuel_type ENUM('Diesel', 'Gasoline 95', 'Gasoline 98', 'Premium Diesel', 'Premium Gasoline 95', 'Premium Gasoline 98', 'Other') NOT NULL,
liters DECIMAL(10, 2) NOT NULL,
price_per_liter DECIMAL(10, 2) NOT NULL,
total_price DECIMAL(10, 2) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (vehicle_id) REFERENCES vehicles(id) ON DELETE CASCADE
) ENGINE=InnoDB;
";
if (!$this->connection->query($refuelingTableQuery)) {
die("Failed to create refueling_records table: " . $this->connection->error);
}
/*
// Create table_name table
$usersTableQuery = "CREATE TABLE IF NOT EXISTS table_name (
id INT AUTO_INCREMENT PRIMARY KEY, id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL, username VARCHAR(50) NOT NULL,
title VARCHAR(100) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
frequency ENUM('Daily', 'Weekly', 'Custom') NOT NULL,
custom_frequency VARCHAR(255) DEFAULT NULL, -- Store crontab-like string
reward_points INT DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB;"; ) ENGINE=InnoDB;";
if (!$this->connection->query($habitsTableQuery)) { if (!$this->connection->query($usersTableQuery)) {
die("Failed to create habits table: " . $this->connection->error); die("Failed to create table_name table: " . $this->connection->error);
} }
*/
} }
/** /**

View File

@@ -17,7 +17,7 @@ services:
- PMA_ARBITRARY=1 - PMA_ARBITRARY=1
profiles: ["dev"] profiles: ["dev"]
habittracker: fuelstats:
build: build:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile

View File

@@ -1,21 +0,0 @@
.form form .dow_chb_wrapper input[type="checkbox"] {
width: 1rem;
}
.form form .dow_chb_wrapper {
display: flex;
justify-content: space-between;
}
#lbl_dow {
margin-bottom: .5rem;
}
#lbl_dom {
margin-top: .5rem;
}
#custom-frequency {
flex-direction: column;
justify-content: space-between;
}

View File

@@ -0,0 +1,3 @@
#registration_plate {
text-transform: uppercase;
}

View File

@@ -20,7 +20,8 @@ require_once '../core/Database.php';
require_once '../core/middlewares/RequireAuth.php'; require_once '../core/middlewares/RequireAuth.php';
require_once models . 'User.php'; require_once models . 'User.php';
require_once models . 'Habit.php'; require_once models . 'Vehicle.php';
#require_once models . 'Refueling.php';
// Initialize router // Initialize router
$router = new Router(); $router = new Router();
@@ -41,11 +42,11 @@ $router->group('/auth', [], function ($router) {
$router->add('/dashboard', 'DashboardController@index', ['RequireAuth']); $router->add('/dashboard', 'DashboardController@index', ['RequireAuth']);
// habits routes // habits routes
$router->group('/habits', ['RequireAuth'], function ($router) { $router->group('/vehicles', ['RequireAuth'], function ($router) {
$router->add('', 'HabitController@index'); $router->add('', 'VehicleController@index');
$router->add('/create', 'HabitController@create'); $router->add('/add', 'VehicleController@create');
$router->add('/edit/{id}', 'HabitController@edit'); $router->add('/edit/{id}', 'VehicleController@edit');
$router->add('/delete/{id}', 'HabitController@delete'); $router->add('/delete/{id}', 'VehicleController@delete');
}); });
$router->dispatch(); $router->dispatch();