Gay ass
This commit is contained in:
parent
7bc638bf8c
commit
57a1a0105f
9
backend/package-lock.json
generated
9
backend/package-lock.json
generated
@ -13,6 +13,7 @@
|
||||
"chalk": "^4.0.0",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"moment": "^2.30.1",
|
||||
"prisma": "^5.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -569,6 +570,14 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/moment": {
|
||||
"version": "2.30.1",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
||||
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
|
@ -14,6 +14,7 @@
|
||||
"chalk": "^4.0.0",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"moment": "^2.30.1",
|
||||
"prisma": "^5.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -17,9 +17,9 @@ model users {
|
||||
}
|
||||
|
||||
model Mitarbeiter {
|
||||
ID String @id @default(dbgenerated("uuid_generate_v4()")) @db.Uuid
|
||||
ID String @id @default(dbgenerated("uuid_generate_v4()")) @db.Uuid
|
||||
Vorname String
|
||||
Nachname String
|
||||
Anstelldatum DateTime @db.Date
|
||||
Geburtstag DateTime @db.Date
|
||||
Anstelldatum DateTime? @db.Date
|
||||
Geburtstag DateTime? @db.Date
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ export function errorBuilder(type: string, message: string): Types.ErrorResponse
|
||||
|
||||
const Errors = {
|
||||
MISSING_ITEMS: errorBuilder("missing_items", "Die Anfrage ist Fehlerhaft."),
|
||||
INVALID_ITEMS: errorBuilder("invalid_items", "Die Anfrage ist Fehlerhaft."),
|
||||
INVALID_CREDENTIALS: errorBuilder("invalid_credentials", "Die eingegebenen Anmeldedaten sind inkorrekt!"),
|
||||
NOT_FOUND: errorBuilder("not_found", "Die angeforderte Ressource wurde nicht gefunden!"),
|
||||
}
|
||||
@ -24,4 +25,9 @@ export async function authorize(token: string) {
|
||||
|
||||
if (!user) return false
|
||||
return user
|
||||
}
|
||||
|
||||
export function getFormatNumber(number: number, digits: number): string {
|
||||
// format the number with the digits. so if the digits is 2 and the number is 9 return 09
|
||||
return number.toString().padStart(digits, '0')
|
||||
}
|
@ -2,9 +2,10 @@ import { PrismaClient } from '@prisma/client'
|
||||
import express from 'express'
|
||||
import dotenv from 'dotenv'
|
||||
import init from './init'
|
||||
import Errors, { authorize } from './functions'
|
||||
import Errors, { authorize, getFormatNumber } from './functions'
|
||||
import fs from 'fs'
|
||||
import crypto from 'crypto'
|
||||
import moment from 'moment'
|
||||
|
||||
dotenv.config()
|
||||
|
||||
@ -210,6 +211,144 @@ app.delete('/api/users/delete/:id', async (req, res) => {
|
||||
|
||||
|
||||
|
||||
|
||||
app.get('/api/toshow/:targetDate?', async (req, res) => {
|
||||
const { targetDate } = req.params;
|
||||
if(targetDate && targetDate.length !== 10) return res.status(400).send(Errors.INVALID_ITEMS)
|
||||
const token = req.headers.authorization?.split(' ')[1]
|
||||
|
||||
if (!token) return res.status(401).send(Errors.INVALID_CREDENTIALS)
|
||||
|
||||
const user = await authorize(token)
|
||||
if (!user) return res.status(401).send(Errors.INVALID_CREDENTIALS)
|
||||
|
||||
let dates: Types.Mitarbeiter[] = await prisma.mitarbeiter.findMany({})
|
||||
|
||||
let currDate;
|
||||
if(targetDate) currDate = moment(targetDate, "YYYY-MM-DD");
|
||||
else currDate = moment();
|
||||
for (let i in dates) {
|
||||
let validity = false;
|
||||
|
||||
|
||||
// `${currDate.getFullYear()}-${getFormatNumber(date.getMonth(), 2)}-${getFormatNumber(date.getDay(), 2)}`
|
||||
|
||||
if (dates[i].Anstelldatum) {
|
||||
const date = dates[i].Anstelldatum;
|
||||
const dateWithoutYear = moment(date).format("MM-DD");
|
||||
|
||||
if (
|
||||
date &&
|
||||
(
|
||||
(
|
||||
moment(dateWithoutYear,"MM-DD") >= moment(currDate).subtract(14, "days") &&
|
||||
moment(dateWithoutYear,"MM-DD") <= currDate
|
||||
)
|
||||
||
|
||||
(
|
||||
moment(dateWithoutYear,"MM-DD").subtract(1, "year") >= moment(currDate).subtract(14, "days") &&
|
||||
moment(dateWithoutYear,"MM-DD").subtract(1, "year") <= currDate
|
||||
)
|
||||
)
|
||||
) {
|
||||
validity = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (dates[i].Geburtstag) {
|
||||
const date = dates[i].Geburtstag;
|
||||
const dateWithoutYear = moment(date).format("MM-DD");
|
||||
|
||||
if (
|
||||
date &&
|
||||
(
|
||||
(
|
||||
moment(dateWithoutYear,"MM-DD") >= moment(currDate).subtract(14, "days") &&
|
||||
moment(dateWithoutYear,"MM-DD") <= currDate
|
||||
)
|
||||
||
|
||||
(
|
||||
moment(dateWithoutYear,"MM-DD").subtract(1, "year") >= moment(currDate).subtract(14, "days") &&
|
||||
moment(dateWithoutYear,"MM-DD").subtract(1, "year") <= currDate
|
||||
)
|
||||
)
|
||||
) {
|
||||
validity = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!validity) delete dates[i];
|
||||
}
|
||||
dates = dates.filter((date) => date !== null);
|
||||
|
||||
|
||||
for(let i = 14; i >= 1; i--) {
|
||||
console.log(i);
|
||||
const date = moment(currDate).subtract(i, "days")
|
||||
const dayOfWeek = date.format("dddd");
|
||||
|
||||
if(["Saturday", "Sunday"].includes(dayOfWeek)) continue;
|
||||
|
||||
for(let j in dates) {
|
||||
let validity = false;
|
||||
|
||||
if (dates[j].Anstelldatum) {
|
||||
const dateWithoutYear = moment(dates[j].Anstelldatum, "YYYY-MM-DD").format("MM-DD");
|
||||
|
||||
if (
|
||||
date &&
|
||||
(
|
||||
(
|
||||
moment(dateWithoutYear,"MM-DD") >= moment(currDate).subtract(14, "days") &&
|
||||
moment(dateWithoutYear,"MM-DD") <= moment(currDate).subtract(i, "days")
|
||||
)
|
||||
||
|
||||
(
|
||||
moment(dateWithoutYear,"MM-DD").subtract(1, "year") >= moment(currDate).subtract(14, "days") &&
|
||||
moment(dateWithoutYear,"MM-DD").subtract(1, "year") <= moment(currDate).subtract(i, "days")
|
||||
)
|
||||
)
|
||||
) {
|
||||
validity = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (dates[j].Geburtstag) {
|
||||
const dateWithoutYear = moment(dates[j].Geburtstag, "YYYY-MM-DD").format("MM-DD");
|
||||
|
||||
if (
|
||||
date &&
|
||||
(
|
||||
(
|
||||
moment(dateWithoutYear,"MM-DD") >= moment(currDate).subtract(14, "days") &&
|
||||
moment(dateWithoutYear,"MM-DD") <= moment(currDate).subtract(i, "days")
|
||||
)
|
||||
||
|
||||
(
|
||||
moment(dateWithoutYear,"MM-DD").subtract(1, "year") >= moment(currDate).subtract(14, "days") &&
|
||||
moment(dateWithoutYear,"MM-DD").subtract(1, "year") <= moment(currDate).subtract(i, "days")
|
||||
)
|
||||
)
|
||||
) {
|
||||
validity = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
console.log(date);
|
||||
console.log(date.format("dddd"), dates[j].Vorname, dates[j].Nachname, validity);
|
||||
|
||||
if (validity) delete dates[j];
|
||||
}
|
||||
dates = dates.filter((date) => date !== null);
|
||||
}
|
||||
|
||||
res.send(dates)
|
||||
})
|
||||
|
||||
|
||||
|
||||
app.listen(process.env.PORT, () => {
|
||||
console.log(`Server is running on port ${process.env.PORT}`)
|
||||
})
|
8
backend/src/types.d.ts
vendored
8
backend/src/types.d.ts
vendored
@ -4,4 +4,12 @@ declare namespace Types {
|
||||
type: string
|
||||
message: string
|
||||
}
|
||||
|
||||
interface Mitarbeiter {
|
||||
ID: string;
|
||||
Vorname: string;
|
||||
Nachname: string;
|
||||
Anstelldatum: Date | null;
|
||||
Geburtstag: Date | null;
|
||||
}
|
||||
}
|
25
frontend/src/components/CompareDate.tsx
Normal file
25
frontend/src/components/CompareDate.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import axios from 'axios';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { getBaseURL } from '../functions';
|
||||
|
||||
const CompareDate = () => {
|
||||
axios
|
||||
.get(`${getBaseURL()}/api/workers`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem("token")}`,
|
||||
},
|
||||
})
|
||||
.then(response => {
|
||||
console.log(response.data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
});
|
||||
return (
|
||||
<div>
|
||||
<h1>Compare Date</h1>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CompareDate;
|
@ -1,21 +1,68 @@
|
||||
import { Avatar, Box, Stack, Typography } from "@mui/material";
|
||||
import { Box, Typography } from "@mui/material";
|
||||
import { useEffect, useState } from "react";
|
||||
import PhilSwift from "../components/PhilSwift";
|
||||
import axios from "axios";
|
||||
import { getBaseURL } from "../functions";
|
||||
import CompareDate from "../components/CompareDate";
|
||||
|
||||
function LandingPage() {
|
||||
const [isHalloween, setIsHalloween] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const currentDate = new Date();
|
||||
const halloweenDate = new Date("2024-03-04");
|
||||
|
||||
setIsHalloween(
|
||||
currentDate.getMonth() === halloweenDate.getMonth() &&
|
||||
currentDate.getDate() === halloweenDate.getDate()
|
||||
);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box sx={{
|
||||
width: "100%",
|
||||
height: "100vh",
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}>
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
height: "100vh",
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<PhilSwift />
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: "center",
|
||||
width: "100%",
|
||||
height: "100vh",
|
||||
top: 0,
|
||||
left: 0,
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
zIndex: 10,
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "2rem",
|
||||
color: "red",
|
||||
textAlign: "center",
|
||||
fontWeight: "bold",
|
||||
textShadow: "2px 2px 4px #000000",
|
||||
zIndex: 10,
|
||||
}}
|
||||
>
|
||||
{isHalloween
|
||||
? "Happy Halloween"
|
||||
: "Keine Geburtstage oder Jubiläen heute."}
|
||||
</Typography>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1,13 +1,18 @@
|
||||
import React, { useState, ChangeEvent, FormEvent } from "react";
|
||||
import Alert from "@mui/material/Alert";
|
||||
import { Box, Button, Typography } from "@mui/material";
|
||||
import { DataGrid, GridColDef } from "@mui/x-data-grid";
|
||||
import moment from "moment";
|
||||
|
||||
function Import() {
|
||||
let correct = 0;
|
||||
let incorrect = 0;
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
const [csvData, setCsvData] = useState<
|
||||
Array<{ [key: string]: string } | null>
|
||||
>([]);
|
||||
const [correctCount, setCorrectCount] = useState(0);
|
||||
const [incorrectCount, setIncorrectCount] = useState(0);
|
||||
|
||||
const fileReader = new FileReader();
|
||||
|
||||
@ -37,6 +42,25 @@ function Import() {
|
||||
.filter(Boolean);
|
||||
|
||||
setCsvData(newArray);
|
||||
|
||||
newArray.forEach((row) => {
|
||||
let isValid = true;
|
||||
for (const key in row) {
|
||||
if (!key.includes("name") && row[key]) {
|
||||
if (!moment(row[key], "DD.MM.YYYY", false).isValid()) {
|
||||
isValid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isValid) {
|
||||
correct++;
|
||||
} else {
|
||||
incorrect++;
|
||||
}
|
||||
});
|
||||
setCorrectCount(correct);
|
||||
setIncorrectCount(incorrect);
|
||||
};
|
||||
|
||||
const handleOnSubmit = (e: FormEvent) => {
|
||||
@ -70,8 +94,31 @@ function Import() {
|
||||
{csvData.length > 0 ? (
|
||||
<div>
|
||||
<Typography variant="h4">Fehlerhafte Daten</Typography>
|
||||
|
||||
<Alert variant="filled" severity="error" sx={{textAlign:"center"}}>
|
||||
{incorrectCount} von {correctCount + incorrectCount} Datensätze
|
||||
enthalten fehlerhafte Daten und wurden nicht importiert.Üperprüfen Sie die Daten und korrigieren Sie die Fehler.
|
||||
</Alert>
|
||||
<DataGrid
|
||||
rows={csvData.map((row, index) => ({ id: index, ...row }))}
|
||||
rows={(csvData || [])
|
||||
.map((row, index) => ({ id: index, ...row }))
|
||||
.filter((row: { [key: string]: any }) => {
|
||||
for (const key in row) {
|
||||
if (row.hasOwnProperty(key)) {
|
||||
const value = row[key];
|
||||
if (
|
||||
!key.includes("name") &&
|
||||
value &&
|
||||
value.length > 0 &&
|
||||
!moment(value, "DD.MM.YYYY", false).isValid()
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
correct++;
|
||||
return false;
|
||||
})}
|
||||
columns={
|
||||
csvData.length > 0
|
||||
? Object.keys(csvData[0] || {}).map(
|
||||
@ -79,7 +126,7 @@ function Import() {
|
||||
({
|
||||
field: header,
|
||||
headerName: header.replace(/"/g, ""),
|
||||
width: 150,
|
||||
width: 250,
|
||||
editable: true,
|
||||
valueFormatter: (params) => {
|
||||
if (params.value) {
|
||||
@ -88,15 +135,21 @@ function Import() {
|
||||
params.value,
|
||||
"DD.MM.YYYY",
|
||||
false
|
||||
).isValid() && !header.includes("name")
|
||||
).isValid()
|
||||
) {
|
||||
return params.value;
|
||||
}
|
||||
|
||||
return `Falsches Datum: ${params.value}`;
|
||||
if (
|
||||
!header.includes("name") &&
|
||||
params.value.length > 0
|
||||
) {
|
||||
incorrect++;
|
||||
return `Error: ${params.value}`;
|
||||
}
|
||||
return "";
|
||||
},
|
||||
correct++;
|
||||
return params.value;
|
||||
}
|
||||
},
|
||||
} as GridColDef)
|
||||
)
|
||||
: []
|
||||
@ -106,6 +159,14 @@ function Import() {
|
||||
) : (
|
||||
<p>Keine Daten zum anzeigen</p>
|
||||
)}
|
||||
<Button
|
||||
sx={{
|
||||
marginTop: 2,
|
||||
}}
|
||||
variant="contained"
|
||||
>
|
||||
Daten einspielen
|
||||
</Button>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
@ -1,11 +1,24 @@
|
||||
|
||||
|
||||
import React from "react";
|
||||
import { Typography } from "@mui/material";
|
||||
import axios from "axios";
|
||||
import Calendar from "react-calendar";
|
||||
|
||||
function Kalender() {
|
||||
return (
|
||||
<div className="container">
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default Kalender;
|
||||
return (
|
||||
axios.get('https://feiertage-api.de/api/')
|
||||
.then(response => {
|
||||
console.log(response.data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
}),
|
||||
<div className="container">
|
||||
<Typography variant="h4" style={{ margin: "20px 0" }}>
|
||||
Kalender
|
||||
</Typography>
|
||||
<Calendar/>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default Kalender;
|
||||
|
Loading…
Reference in New Issue
Block a user