From 2201430f590c1823dc59a6a2de7d0d500d06410a Mon Sep 17 00:00:00 2001 From: Filip Rojek Date: Sun, 26 Jan 2025 22:22:12 +0100 Subject: [PATCH] Partially done --- TODO.md | 12 +- app/controllers/VehicleController.php | 15 ++- app/views/dashboard/index.php | 7 +- public/css/dashboard.css | 18 +++ public/css/global.css | 8 +- public/css/vars.css | 1 + public/index.php | 5 + public/js/offline-records.js | 170 +++++++++++++++++++++++--- 8 files changed, 215 insertions(+), 21 deletions(-) diff --git a/TODO.md b/TODO.md index a75f5a2..94d3732 100644 --- a/TODO.md +++ b/TODO.md @@ -11,5 +11,13 @@ - [ ] specific car view - charts, fuel records - [ ] remove/edit fuel record -- [ ] IndexDB - - [ ] +## Until release +- [ ] Sync offline data from locale storage +- [ ] Include kilometer state of an car +- [ ] More charts + - [ ] Average fuel conusption + - [ ] Kilometer state +- [ ] More cards + - [ ] Average fuel conusption in last 30 days + - [ ] Kilometer state in last 30 days` +- [ ] Offline navigation between dashboard and offline form diff --git a/app/controllers/VehicleController.php b/app/controllers/VehicleController.php index 0ea430e..7ef6dcf 100644 --- a/app/controllers/VehicleController.php +++ b/app/controllers/VehicleController.php @@ -52,10 +52,21 @@ class VehicleController extends Controller { public function edit() { - // Edit vehicle (to be implemented later) + // TODO: Edit vehicle (to be implemented later) } public function delete() { - // Delete vehicle (to be implemented later) + // TODO: Delete vehicle (to be implemented later) + } + + public function api_get() { + if(!$_SERVER['REQUEST_METHOD'] === 'GET') { + echo "Wrong method, use GET"; + return; + } + + $vehicle = new Vehicle(); + $result = $vehicle->getVehiclesByUser($_SESSION['user']['id']); + echo json_encode($result); } } diff --git a/app/views/dashboard/index.php b/app/views/dashboard/index.php index 4e8d959..cd2231e 100644 --- a/app/views/dashboard/index.php +++ b/app/views/dashboard/index.php @@ -1,11 +1,14 @@ + + +

Welcome, !

-
+
diff --git a/public/css/dashboard.css b/public/css/dashboard.css index e1106bd..20e2642 100644 --- a/public/css/dashboard.css +++ b/public/css/dashboard.css @@ -19,3 +19,21 @@ width: 18rem; padding: 1rem; } + +#btn-offline-add { + display: none; +} + +.alert-warning { + background-color: var(--clr-warning-muted); + border: var(--borderWidth-thin) solid var(--clr-border-danger); + padding: 1rem; + border-radius: var(--border-radious); +} + +.alert-danger { + background-color: var(--clr-danger-muted); + border: var(--borderWidth-thin) solid var(--clr-border-danger); + padding: 1rem; + border-radius: var(--border-radious); +} diff --git a/public/css/global.css b/public/css/global.css index 357c3c0..f32ba14 100644 --- a/public/css/global.css +++ b/public/css/global.css @@ -20,7 +20,8 @@ h1 { .btn-secondary, .btn-tertiary, .btn-green, -.btn-danger { +.btn-danger, +.btn-warning { background-color: var(--clr-primary); padding: .5rem; text-decoration: none; @@ -46,3 +47,8 @@ h1 { background-color: var(--clr-danger-muted); border: var(--borderWidth-thin) solid var(--clr-border-danger); } + +.btn-warning { + background-color: var(--clr-warning-muted); + border: var(--borderWidth-thin) solid var(--clr-border-danger); +} diff --git a/public/css/vars.css b/public/css/vars.css index 2feb4ee..1b9f23c 100644 --- a/public/css/vars.css +++ b/public/css/vars.css @@ -5,6 +5,7 @@ --clr-tertiary: #151b23; --clr-green: #238636; --clr-danger-muted: #f851491a; + --clr-warning-muted: #e08e455e; --clr-link-blue: #4493f8; --clr-light-blue: #39a2ae; diff --git a/public/index.php b/public/index.php index 6c219fd..256fa97 100644 --- a/public/index.php +++ b/public/index.php @@ -53,4 +53,9 @@ $router->group('/refuel', ['RequireAuth'], function ($router) { $router->add('/create', 'RefuelController@create'); }); +// API +$router->group('/api/v1', ['RequireAuth'], function ($router) { + $router->add('/vehicles/get', 'VehicleController@api_get'); +}); + $router->dispatch(); diff --git a/public/js/offline-records.js b/public/js/offline-records.js index 95b5744..ec4628d 100644 --- a/public/js/offline-records.js +++ b/public/js/offline-records.js @@ -18,32 +18,152 @@ async function checkOnline() { } } +function showDashboard() { + const offline = document.querySelector(".offline"); + offline.remove(); + document.querySelector(".dashboard").style.display = "flex"; +} + +const btnOffline = document.querySelector("#btn-offline-add"); +const divActions = document.querySelector("#actions"); +let visible = true; + setInterval(async () => { const isOnline = await checkOnline(); + //const isOnline = false; // REMOVE!!! if (!isOnline) { - console.log("OFFLINE!!!"); - } -}, 5000); + if (visible) { + console.log("OFFLINE!!!"); + Array.from(divActions.children).forEach( + (el) => (el.style.display = "none"), + ); + visible = false; -const offbtn = document.querySelector("#btn-offline-add"); -offbtn.addEventListener("click", (e) => { + btnOffline.style.display = "block"; + + document.querySelector(".hd-left").addEventListener("click", () => { + showDashboard(); + }); + } + + if (localStorage.getItem("refuelOfflineData")) { + btnOffline.textContent = "Sync data"; + btnOffline.setAttribute("disabled", "disabled"); + } + } + + if (isOnline && !visible) { + console.log("BACK ONLINE!!!"); + visible = true; + btnOffline.removeAttribute("disabled", "disabled"); + // TODO: show buttons back, add sync button instead of record creation + // If user is in a process of adding new offline refuel record, let him finish + // Clear the local storage on each login + } + //}, 5000); +}, 1000); + +window.onload = async () => { + const rawData = await fetch("/api/v1/vehicles/get", { + method: "GET", + credentials: "include", + }); + const data = await rawData.json(); + console.log("Fetched:", data); + localStorage.setItem("vehicles", JSON.stringify(data)); + console.log(JSON.parse(localStorage.getItem("vehicles"))); +}; + +btnOffline.addEventListener("click", async (e) => { e.preventDefault(); + + if (btnOffline.textContent == "Sync data") { + if (!visible) { + alert("You're still offline. Try again later"); + return; + } + + try { + let data = localStorage.getItem("refuelOfflineData"); + if (!data) { + console.error("No offline data found"); + alert("No offline data found"); + return; + } + + data = JSON.parse(data); + const formData = new FormData(); + + for (const key in data) { + if (data.hasOwnProperty(key)) { + formData.append(key, data[key]); + } + } + + const res = await fetch("/refuel/create", { + method: "POST", + body: formData, + credentials: "include", + }); + + if (!res.ok) { + throw new Error(`Server error: ${res.statusText}`); + } + + localStorage.removeItem("refuelOfflineData"); + location.reload(); + } catch (err) { + console.error(err); + alert("Something went wrong"); + location.reload(); + } + return; + } + document.querySelector("section.dashboard").style.display = "none"; + + try { + vehicles = localStorage.getItem("vehicles"); + if (vehicles === null) throw new Error("No data was saved locally"); + vehicles = JSON.parse(vehicles); + } catch (err) { + console.error(err); + const offline = document.createElement("div"); + offline.classList.add("offline"); + offline.innerHTML = ` +
+ You're Offline +

No data was saved locally, please try again later

+
+ `; + document.querySelector("main").appendChild(offline); + // TODO: Add button to navigate back to offline dashboard + return; + } + const offline = document.createElement("div"); offline.classList.add("offline"); offline.innerHTML = ` - You're Offline -

You can create an fuel record locally on your device and sync it later

+
+ You're Offline +

You can create an fuel record locally on your device and sync it later

+
-

get('title') ?>

+

Create offline record

-
+ + - + - + - + - +
`; document.querySelector("main").appendChild(offline); + const btnSubmit = document.querySelector("#btn-offline-submit"); + btnSubmit.addEventListener("click", (e) => { + e.preventDefault(); + const formData = { + vehicle: document.querySelector("form#offline_refuel_add #vehicle").value, + fuel_type: document.querySelector("form#offline_refuel_add #fuel_type") + .value, + liters: document.querySelector("form#offline_refuel_add #liters").value, + price_per_liter: document.querySelector( + "form#offline_refuel_add #price_per_liter", + ).value, + total_price: document.querySelector( + "form#offline_refuel_add #total_price", + ).value, + note: document.querySelector("form#offline_refuel_add #note").value, + }; + + console.log("formData", formData); + localStorage.setItem("refuelOfflineData", JSON.stringify(formData)); + alert("Data was locally saved. Sync it later!"); + showDashboard(); + }); });