added stuff

This commit is contained in:
Janis
2022-05-03 21:29:38 +02:00
parent 9f41203234
commit cdc1b2fa3a
16 changed files with 557 additions and 203 deletions

View File

@@ -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

View File

@@ -106,6 +106,7 @@ router.get("/all/:monthYear?", request_handler.LoggerHandler, (req, res) => {
result[i].checked_in,
result[i].checked_out
),
result: "-1:20",
});
}
}

View File

@@ -1,23 +1,18 @@
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 (
<ServerProvider>
<div id="app">
<div id="content" className="app-container">
<Router>
<Routes>
<Route exact path="/table/:monthYear" element={<Table />} />
<Route exact path="/table/:monthYear" element={<TableView />} />
</Routes>
</Router>
</div>
<div id="sidebar" className="app-container">
<h1>Sidebar</h1>
</div>
</div>
</ServerProvider>
);
}

View File

@@ -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 (
<div className="nav">
<div>
<div className="nav-overview">
<a className="" href="/">
Overview
</a>
</div>
</div>
<div>
<div className="nav-info">
<p
className={
gz.substring(0, 1) === "+" ? "text-positive" : "text-negative"
}
>
{gz} GZ
</p>
</div>
</div>
<div className="month-navigation">
<div
className="nav-arrows-previous"
style={{ backgroundImage: `url("${arrows}")` }}
onClick={previousMonth}
></div>
<h3>
{months[month - 1]} / {year}
</h3>
<div
className="nav-arrow-next"
style={{ backgroundImage: `url("${arrows}")` }}
onClick={nextMonth}
></div>
</div>
<div>
<div className="working-hours">
<div className="working-hours-input-block">
<div className="working-hours-input-container">
<button onClick={plusWorkingHours} id="workingHoursBtnPlus">
+
</button>
<input type="text" name="workingHours" value={workingHours} />
<button onClick={minusWorkingHours} id="workingHoursBtnMinus">
<p>-</p>
</button>
</div>
</div>
<small>Working hours</small>
</div>
</div>
<div className="nav-account">
<p>Welcome back, Username!</p>
<a className="logout-a" href="/logout">
Log out
</a>
</div>
</div>
);
}
export default Nav;

View File

@@ -0,0 +1,9 @@
function Sidebar() {
return (
<div id="sidebar">
<h1>sidebar</h1>
</div>
);
}
export default Sidebar;

View File

@@ -1,25 +0,0 @@
import "../../css/components/table.scss";
function Header({ date, checkedIn, checkedOut, ind, norm }) {
return (
<div className="table-header">
<div className="table-cell">
<span>{date}</span>
</div>
<div className="table-cell">
<span>{checkedIn}</span>
</div>
<div className="table-cell">
<span>{checkedOut}</span>
</div>
<div className="table-cell">
<span>{ind}</span>
</div>
<div className="table-cell">
<span>{norm}</span>
</div>
</div>
);
}
export default Header;

View File

@@ -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 (
<div className="table-row">
<div className="table-cell">
<span>{date ? date : "-"}</span>
</div>
<div className="table-cell">
<span>{checkedIn ? checkedIn : "-"}</span>
</div>
<div className="table-cell">
<span>{checkedOut ? checkedOut : "-"}</span>
</div>
<div className="table-cell">
<span>{ind ? ind : "-"}</span>
</div>
<div className="table-cell">
<span>{norm ? norm : "-"}</span>
</div>
</div>
<tr>
<td>{weekDay ? weekDay : "-"}</td>
<td>{date ? date : "-"}</td>
<td>{checkedIn ? checkedIn : "-"}</td>
<td>{checkedOut ? checkedOut : "-"}</td>
<td>{ind ? ind : "-"}</td>
<td>{norm ? norm : "-"}</td>
<td>{result ? result : "-"}</td>
</tr>
);
}

View File

@@ -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(
<Row
weekDay={dayOfWeek}
date={entry.date}
checkedIn={entry.checkedIn}
checkedOut={entry.checkedOut}
ind={entry.ind}
norm={entry.norm}
/>,
]);
result={entry.result}
/>
);
} else {
setRows((...rows) => [rows, <Row date={`${dayOfWeek} - ${date}`} />]);
temp_rows.push(<Row weekDay={dayOfWeek} date={`${date}`} />);
}
}
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 (
<div id="table">
<div className="table-nav">
<div onClick={previousMonth}> </div>
<h2>{monthYear}</h2>
<div onClick={nextMonth}> </div>
</div>
<div className="table-container">
<Header
date="Date"
checkedIn="In"
checkedOut="Out"
ind="Ind."
norm="Norm."
/>
{/* ROWS */}
<table>
<tr>
<th>Weekday</th>
<th>Date</th>
<th>Checked in</th>
<th>Checked out</th>
<th>Ind</th>
<th>Norm</th>
<th>Result</th>
</tr>
{rows}
</div>
</table>
</div>
);
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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;
}

View File

@@ -0,0 +1,12 @@
#tableView {
height: 100%;
.tableView-container {
display: grid;
grid-template-columns: 1fr 0.5fr;
height: 100%;
div {
grid-area: auto;
}
}
}

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><defs><style>.cls-1{fill:#10b374;}</style></defs><title>Asset 15</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M63,29.9,25.65.56a2.68,2.68,0,0,0-4.32,2.11V13.92L4.32.56A2.72,2.72,0,0,0,1.49.27,2.71,2.71,0,0,0,0,2.67V61.34a2.72,2.72,0,0,0,1.49,2.4A2.74,2.74,0,0,0,2.67,64a2.66,2.66,0,0,0,1.65-.56l17-13.36V61.34a2.71,2.71,0,0,0,1.5,2.4A2.66,2.66,0,0,0,24,64a2.63,2.63,0,0,0,1.65-.56L63,34.11a2.7,2.7,0,0,0,0-4.21ZM5.33,55.84V8.16l16,12.56,5.34,4.19,9,7.09-9,7.1Zm21.34,0V45.9l15-11.79a2.68,2.68,0,0,0,0-4.21l-15-11.79V8.16L57,32Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 718 B

View File

@@ -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 (
<div id="tableView">
<Nav />
<div className="tableView-container">
<Table />
<Sidebar />
</div>
</div>
);
}
export default TableView;