diff --git a/backend/rme-time-tracking.sql b/backend/rme-time-tracking.sql
new file mode 100644
index 0000000..e2b7427
--- /dev/null
+++ b/backend/rme-time-tracking.sql
@@ -0,0 +1,53 @@
+-- MariaDB dump 10.19 Distrib 10.4.24-MariaDB, for Win64 (AMD64)
+--
+-- Host: localhost Database: rme-time-tracking
+-- ------------------------------------------------------
+-- Server version 10.4.24-MariaDB
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8mb4 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Table structure for table `entries`
+--
+
+DROP TABLE IF EXISTS `entries`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `entries` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `checked_in` time DEFAULT NULL,
+ `checked_out` time DEFAULT NULL,
+ `date` date DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `entries`
+--
+
+LOCK TABLES `entries` WRITE;
+/*!40000 ALTER TABLE `entries` DISABLE KEYS */;
+INSERT INTO `entries` VALUES (2,'18:15:00','20:12:00','2022-04-30'),(5,'08:00:00','14:00:00','2022-04-28'),(6,'08:00:00','17:00:00','2022-04-22'),(7,'08:04:00','15:23:00','2022-05-30');
+/*!40000 ALTER TABLE `entries` ENABLE KEYS */;
+UNLOCK TABLES;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+-- Dump completed on 2022-05-03 21:29:23
diff --git a/backend/routes/api/entry.js b/backend/routes/api/entry.js
index 2d683c2..ad3c2de 100644
--- a/backend/routes/api/entry.js
+++ b/backend/routes/api/entry.js
@@ -106,6 +106,7 @@ router.get("/all/:monthYear?", request_handler.LoggerHandler, (req, res) => {
result[i].checked_in,
result[i].checked_out
),
+ result: "-1:20",
});
}
}
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index 9c8cb50..4ccf58e 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -1,22 +1,17 @@
import "./css/app.scss";
import ServerProvider from "./contexts/ServerContext";
-import Table from "./components/table/Table";
+import TableView from "./views/TableView";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
function App() {
return (
-
-
-
- } />
-
-
-
-
+
+
+ } />
+
+
);
diff --git a/frontend/src/components/Nav.jsx b/frontend/src/components/Nav.jsx
new file mode 100644
index 0000000..5fb0f99
--- /dev/null
+++ b/frontend/src/components/Nav.jsx
@@ -0,0 +1,157 @@
+import React, { useState, useEffect } from "react";
+import { useParams, useNavigate, useLocation } from "react-router-dom";
+
+import "../css/components/nav.scss";
+
+import arrows from "../images/arrows.svg";
+
+function Nav() {
+ const params = useParams();
+ const navigate = useNavigate();
+ const location = useLocation();
+ const [monthYear, setMonthYear] = useState(params.monthYear);
+ const [month, setMonth] = useState(params.month);
+ const [year, setYear] = useState(params.year);
+ const [gz, setGz] = useState("+ 01:22");
+ const [workingHours, setWorkingHours] = useState("07:00");
+ let workingHoursChangeStep = 15;
+
+ const months = [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December",
+ ];
+
+ useEffect(() => {
+ setMonth(monthYear.split("-")[0]);
+ setYear(monthYear.split("-")[1]);
+ console.log(gz.substring(0, 1));
+ }, [monthYear]);
+
+ useEffect(() => {
+ setMonthYear(params.monthYear);
+ }, [location]);
+
+ function nextMonth() {
+ let month = parseInt(monthYear.split("-")[0]);
+ let newUrl = "";
+
+ if (month === 12) {
+ newUrl = `/table/${1}-${parseInt(monthYear.split("-")[1]) + 1}`;
+ } else {
+ newUrl = `/table/${month + 1}-${monthYear.split("-")[1]}`;
+ }
+
+ navigate(newUrl, {
+ replace: true,
+ });
+ }
+
+ function previousMonth() {
+ let month = parseInt(monthYear.split("-")[0]);
+ let newUrl = "";
+
+ if (month === 1) {
+ newUrl = `/table/${12}-${parseInt(monthYear.split("-")[1]) - 1}`;
+ } else {
+ newUrl = `/table/${month - 1}-${monthYear.split("-")[1]}`;
+ }
+ navigate(newUrl, {
+ replace: true,
+ });
+ }
+
+ function plusWorkingHours() {
+ let date = new Date("01/01/2000 " + workingHours);
+ date.setMinutes(date.getMinutes() + workingHoursChangeStep);
+
+ setWorkingHours(
+ `${date.getHours() < 10 ? "0" + date.getHours() : date.getHours()}:${
+ date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()
+ }`
+ );
+ }
+
+ function minusWorkingHours() {
+ let date = new Date("01/01/2000 " + workingHours);
+ date.setMinutes(date.getMinutes() - workingHoursChangeStep);
+
+ setWorkingHours(
+ `${date.getHours() < 10 ? "0" + date.getHours() : date.getHours()}:${
+ date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()
+ }`
+ );
+ }
+
+ return (
+
+
+
+
+
+
+ {months[month - 1]} / {year}
+
+
+
+
+
+
+ );
+}
+
+export default Nav;
diff --git a/frontend/src/components/Sidebar.jsx b/frontend/src/components/Sidebar.jsx
new file mode 100644
index 0000000..504dff5
--- /dev/null
+++ b/frontend/src/components/Sidebar.jsx
@@ -0,0 +1,9 @@
+function Sidebar() {
+ return (
+
+ );
+}
+
+export default Sidebar;
diff --git a/frontend/src/components/table/Header.jsx b/frontend/src/components/table/Header.jsx
deleted file mode 100644
index 4779b92..0000000
--- a/frontend/src/components/table/Header.jsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import "../../css/components/table.scss";
-
-function Header({ date, checkedIn, checkedOut, ind, norm }) {
- return (
-
-
- {date}
-
-
- {checkedIn}
-
-
- {checkedOut}
-
-
- {ind}
-
-
- {norm}
-
-
- );
-}
-
-export default Header;
diff --git a/frontend/src/components/table/Row.jsx b/frontend/src/components/table/Row.jsx
index 4b18ef3..876eaad 100644
--- a/frontend/src/components/table/Row.jsx
+++ b/frontend/src/components/table/Row.jsx
@@ -1,24 +1,16 @@
-import "../../css/components/table.scss";
+import "../../css/components/table/table.scss";
-function Row({ date, checkedIn, checkedOut, ind, norm }) {
+function Row({ weekDay, date, checkedIn, checkedOut, ind, norm, result }) {
return (
-
-
- {date ? date : "-"}
-
-
- {checkedIn ? checkedIn : "-"}
-
-
- {checkedOut ? checkedOut : "-"}
-
-
- {ind ? ind : "-"}
-
-
- {norm ? norm : "-"}
-
-
+
+ | {weekDay ? weekDay : "-"} |
+ {date ? date : "-"} |
+ {checkedIn ? checkedIn : "-"} |
+ {checkedOut ? checkedOut : "-"} |
+ {ind ? ind : "-"} |
+ {norm ? norm : "-"} |
+ {result ? result : "-"} |
+
);
}
diff --git a/frontend/src/components/table/Table.jsx b/frontend/src/components/table/Table.jsx
index bb261b2..437350a 100644
--- a/frontend/src/components/table/Table.jsx
+++ b/frontend/src/components/table/Table.jsx
@@ -1,14 +1,16 @@
+/* eslint-disable react-hooks/exhaustive-deps */
import React, { useState, useContext, useEffect } from "react";
-import { ServerContext } from "../../contexts/ServerContext";
-import { useParams } from "react-router-dom";
-import "../../css/components/table.scss";
+import { ServerContext } from "../../contexts/ServerContext";
+import { useParams, useLocation } from "react-router-dom";
+
+import "../../css/components/table/table.scss";
import Row from "./Row";
-import Header from "./Header";
function Table() {
const params = useParams();
+ const location = useLocation();
const { URL } = useContext(ServerContext);
const weekDays = ["Sat.", "Sun.", "Mon.", "Tue.", "Wed.", "Thu.", "Fri."];
const [entries, setEntries] = useState([]);
@@ -16,9 +18,11 @@ function Table() {
const [rows, setRows] = useState([]);
async function fetchEntries() {
- let response = await fetch(URL + `/api/entry/all/` + monthYear);
- let data = await response.json();
- setEntries(data);
+ // Set entries after fetching them from the server
+ let response = await fetch(URL + `/api/entry/all/` + monthYear).then(
+ (res) => res.json()
+ );
+ setEntries(response);
}
function daysInMonth() {
@@ -28,14 +32,19 @@ function Table() {
return new Date(year, month, 0).getDate();
}
+ useEffect(() => {
+ setMonthYear(params.monthYear);
+ }, [location]);
+
useEffect(() => {
fetchEntries();
- }, []);
+ }, [monthYear]);
useEffect(() => {
let month = monthYear.split("-")[0];
let year = monthYear.split("-")[1];
- setRows([]);
+ let temp_rows = [];
+
for (let i = 1; i <= daysInMonth(); i++) {
let date = `${i < 10 ? "0" + i : i}.${
month < 10 ? "0" + month : month
@@ -46,65 +55,39 @@ function Table() {
let entry = entries.find((entry) => entry.date === date);
if (entry) {
- setRows((...rows) => [
- rows,
+ console.log(entry);
+ temp_rows.push(
,
- ]);
+ result={entry.result}
+ />
+ );
} else {
- setRows((...rows) => [rows,
]);
+ temp_rows.push(
);
}
}
- console.log(rows);
+ setRows(temp_rows);
}, [entries]);
- function nextMonth() {
- let month = parseInt(monthYear.split("-")[0]);
-
- if (month === 12) {
- window.location.href = `/table/${1}-${
- parseInt(monthYear.split("-")[1]) + 1
- }`;
- } else {
- window.location.href = `/table/${month + 1}-${monthYear.split("-")[1]}`;
- }
- }
-
- function previousMonth() {
- let month = parseInt(monthYear.split("-")[0]);
-
- if (month === 1) {
- window.location.href = `/table/${12}-${
- parseInt(monthYear.split("-")[1]) - 1
- }`;
- } else {
- window.location.href = `/table/${month - 1}-${monthYear.split("-")[1]}`;
- }
- }
-
return (
-
-
-
-
- {/* ROWS */}
+
+
+
+ | Weekday |
+ Date |
+ Checked in |
+ Checked out |
+ Ind |
+ Norm |
+ Result |
+
{rows}
-
+
);
}
diff --git a/frontend/src/css/App.scss b/frontend/src/css/App.scss
index 3f62f07..109d731 100644
--- a/frontend/src/css/App.scss
+++ b/frontend/src/css/App.scss
@@ -1,37 +1,3 @@
#app {
- display: grid;
- grid-template-columns: 2fr 1fr;
height: 100vh;
-
- .app-container {
- display: flex;
- height: 100%;
- grid-area: auto;
- padding-left: 20px;
- padding-right: 20px;
- }
-
- #content {
- }
-
- #sidebar {
- border-left: 4px solid #575757;
- }
-}
-
-@media screen and (max-width: 1000px) {
- #app {
- grid-template-columns: 1fr 1fr;
- }
-}
-
-@media screen and (max-width: 730px) {
- #app {
- grid-template-columns: 1fr;
- }
-
- #sidebar {
- border-left: 0px solid transparent !important;
- border-top: 4px solid #575757;
- }
}
diff --git a/frontend/src/css/components/nav.scss b/frontend/src/css/components/nav.scss
new file mode 100644
index 0000000..08064f0
--- /dev/null
+++ b/frontend/src/css/components/nav.scss
@@ -0,0 +1,195 @@
+.nav {
+ width: 100%;
+ height: 30px;
+ background-color: rgb(13, 13, 13);
+ display: grid;
+ grid-template-columns: 0.5fr 0.5fr 1fr 0.5fr 0.5fr;
+ padding-top: 10px;
+ padding-bottom: 10px;
+
+ a {
+ border: 1px solid transparent;
+ font-weight: bold;
+ color: white;
+ text-decoration: none;
+ padding: 5px;
+ padding-top: 3px;
+ border-radius: 2px;
+ transition: all 100ms linear;
+
+ &:hover {
+ box-shadow: 0px 0px 25px -10px #9f9f9f;
+ }
+ }
+
+ div {
+ grid-area: auto;
+
+ .nav-overview {
+ margin-top: 3px;
+ margin-left: 30px;
+ a {
+ background-color: #0f9f5f;
+
+ &:hover {
+ background-color: #10b374;
+ border: 1px solid #61ffc2;
+ }
+ }
+ }
+
+ .nav-info {
+ p {
+ font-weight: bold;
+ font-size: 15pt;
+ }
+
+ .text-positive {
+ color: #0f9f5f;
+ }
+
+ .text-negative {
+ color: #ff0000;
+ }
+ }
+
+ .working-hours {
+ height: 100%;
+ justify-items: center;
+
+ small {
+ display: block;
+ height: 10px;
+ width: 150px;
+ margin-top: 0px;
+ line-height: 12px;
+ font-size: 9pt;
+ margin-left: auto;
+ margin-right: auto;
+ text-align: center;
+ font-weight: bold;
+ color: #0f9f5f;
+ }
+
+ .working-hours-input-block {
+ display: block;
+ width: 150px;
+ margin-left: auto;
+ margin-right: auto;
+
+ .working-hours-input-container {
+ display: flex;
+ height: 100%;
+ justify-items: center;
+ button {
+ background-color: #0f9f5f;
+ border: 2px solid transparent;
+ font-weight: bold;
+ font-size: 25pt;
+ color: white;
+ text-decoration: none;
+ width: 25px;
+ height: 25px;
+ transition: all 100ms linear;
+ cursor: pointer;
+ text-align: center;
+
+ &:hover {
+ background-color: #10b374;
+ border: 2px solid #61ffc2;
+ box-shadow: 0px 0px 25px -10px #9f9f9f;
+ }
+ }
+
+ #workingHoursBtnPlus {
+ line-height: 18px;
+ }
+
+ #workingHoursBtnMinus p {
+ // Fucky weil ein minus nicht genau in er mitte ist vertikal.......... :/
+ font-size: 30pt;
+ line-height: 10px;
+ padding-bottom: 5px;
+ font-family: Verdana, Geneva, Tahoma, sans-serif;
+ vertical-align: middle;
+ }
+
+ input {
+ width: calc(100% - 25px * 2);
+ height: 23px;
+ border: 1px solid #0f9f5f;
+ text-align: center;
+ font-size: 15pt;
+ background-color: #b1dac8;
+ outline: 0;
+ transition: all 100ms linear;
+ -moz-appearance: textfield;
+
+ &:hover {
+ border: 1px solid #10b374;
+ box-shadow: 0px 0px 25px -10px #9f9f9f;
+ }
+
+ &::-webkit-outer-spin-button,
+ &::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ .month-navigation {
+ display: grid;
+ grid-template-columns: 1fr 2fr 1fr;
+
+ div {
+ background-color: transparent;
+ width: 30px;
+ height: 30px;
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+ cursor: pointer;
+ transition: all 50ms linear;
+ background-repeat: no-repeat;
+ background-position: 0 0;
+ filter: brightness(0.6);
+
+ &:hover {
+ filter: brightness(1);
+ }
+ }
+
+ .nav-arrows-previous {
+ transform: rotate(180deg);
+ }
+
+ h3 {
+ text-align: center;
+ padding-bottom: 10px;
+ }
+ }
+ .nav-account {
+ display: flex;
+
+ p {
+ padding-top: 3px;
+ font-size: 12pt;
+ font-weight: bold;
+ color: #0f9f5f;
+ }
+ .logout-a {
+ margin-left: 20px;
+ background-color: #9f0f0f;
+ margin-bottom: 3px;
+
+ &:hover {
+ background-color: #e62f2f;
+ border: 1px solid #f07a7a;
+ }
+ }
+ }
+}
diff --git a/frontend/src/css/components/table.scss b/frontend/src/css/components/table.scss
deleted file mode 100644
index 08a9522..0000000
--- a/frontend/src/css/components/table.scss
+++ /dev/null
@@ -1,59 +0,0 @@
-#table {
- height: 100%;
- width: 100%;
-
- .table-nav {
- display: grid;
- grid-template-columns: 1fr 1fr 1fr;
- padding-top: 10px;
- padding-bottom: 10px;
-
- div {
- background-color: red;
- width: 50px;
- height: 50px;
- display: block;
- margin-left: auto;
- margin-right: auto;
- cursor: pointer;
- }
-
- h2 {
- text-align: center;
- padding-top: 10px;
- }
- }
-
- .table-container {
- height: 100%;
- width: 100%;
-
- text-align: center;
- font-size: 1rem;
-
- .table-header {
- display: grid;
- grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
- width: 100%;
- background-color: rgb(28, 28, 28);
- font-size: 1.2rem;
- font-weight: bold;
- border-bottom: 2px solid rgb(157, 157, 157);
- }
-
- .table-row {
- display: grid;
- grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
- width: 100%;
- background-color: rgb(61, 61, 61);
- border-top: 1px solid rgb(85, 85, 85);
- }
-
- .table-cell {
- grid-area: auto;
- padding: 10px;
- border-right: 1px solid rgb(85, 85, 85);
- border-left: 1px solid rgb(85, 85, 85);
- }
- }
-}
diff --git a/frontend/src/css/components/table/table.scss b/frontend/src/css/components/table/table.scss
new file mode 100644
index 0000000..6bb3e6f
--- /dev/null
+++ b/frontend/src/css/components/table/table.scss
@@ -0,0 +1,35 @@
+.table-container {
+ height: 100%;
+ width: 100%;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow-x: hidden;
+
+ table {
+ width: 100%;
+ height: 100%;
+ margin-bottom: 50px;
+ border-collapse: collapse;
+ overflow-x: hidden;
+
+ tr {
+ height: 40px;
+ text-align: center;
+ background-color: #323232;
+ &:nth-child(even) {
+ background-color: #1d1d1d;
+ }
+
+ th {
+ padding-top: 2px;
+ padding-bottom: 2px;
+ background-color: #131313;
+ }
+
+ td {
+ padding-top: 4px;
+ padding-bottom: 4px;
+ }
+ }
+ }
+}
diff --git a/frontend/src/css/index.scss b/frontend/src/css/index.scss
index f5a8050..ee7518a 100644
--- a/frontend/src/css/index.scss
+++ b/frontend/src/css/index.scss
@@ -1,3 +1,8 @@
+// Scrollbar styling
+$scrollbar-background-color: rgba(255, 255, 255, 0);
+$scrollbar-foreground-color: rgb(216, 242, 242);
+$scrollbar-width: 6px;
+
* {
margin: 0;
padding: 0;
@@ -14,4 +19,20 @@ html {
height: 100vh;
color: white;
background-color: #2b2b2b;
+ overflow: hidden;
+}
+
+/* Scrollbar Webkit */
+*::-webkit-scrollbar {
+ width: $scrollbar-width;
+}
+
+*::-webkit-scrollbar-track {
+ background: $scrollbar-background-color;
+}
+
+*::-webkit-scrollbar-thumb {
+ background-color: $scrollbar-foreground-color;
+ border-radius: 10px;
+ border: 3px solid transparent;
}
diff --git a/frontend/src/css/views/tableView.scss b/frontend/src/css/views/tableView.scss
new file mode 100644
index 0000000..8afe458
--- /dev/null
+++ b/frontend/src/css/views/tableView.scss
@@ -0,0 +1,12 @@
+#tableView {
+ height: 100%;
+ .tableView-container {
+ display: grid;
+ grid-template-columns: 1fr 0.5fr;
+ height: 100%;
+
+ div {
+ grid-area: auto;
+ }
+ }
+}
diff --git a/frontend/src/images/arrows.svg b/frontend/src/images/arrows.svg
new file mode 100644
index 0000000..2668070
--- /dev/null
+++ b/frontend/src/images/arrows.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/views/TableView.jsx b/frontend/src/views/TableView.jsx
new file mode 100644
index 0000000..b38894f
--- /dev/null
+++ b/frontend/src/views/TableView.jsx
@@ -0,0 +1,18 @@
+import Nav from "../components/Nav.jsx";
+import Sidebar from "../components/Sidebar.jsx";
+import Table from "../components/table/Table.jsx";
+import "../css/views/tableView.scss";
+
+function TableView() {
+ return (
+
+ );
+}
+
+export default TableView;