implemented settings and user page (darkmode is still missing)

This commit is contained in:
2024-03-24 21:02:56 +01:00
parent acb7bb7cb6
commit 45a4b58f26
36 changed files with 2283 additions and 1313 deletions

View File

@ -71,6 +71,32 @@ export const signUp = async (req, res, next) => {
} }
}; };
// Update user password to Database
export const updatePasswordById = async (req, res, next) => {
try {
const id = req.body.id;
let sql = `UPDATE users SET password = ? WHERE id = ?`;
bcrypt.hash(req.body.password, 10, async (err, hash) => {
if (err) {
throw err;
return res.status(500).send({
message: err,
});
} else {
const results = await ownConn.query(sql, [hash, id]);
return res.status(200).send({
message: 'Password changed!',
});
}
});
}
catch (err) {
// Manage Errors
console.log("SQL error : ", err);
result(err, null);
}
};
export const login = async (req, res, next) => { export const login = async (req, res, next) => {
try { try {
let sql = `SELECT * FROM users WHERE username = ?`; let sql = `SELECT * FROM users WHERE username = ?`;

View File

@ -38,10 +38,7 @@ export const validateRegister = (req, res, next) => {
}); });
} }
// password (repeat) must match // password (repeat) must match
if ( if (req.body.password != req.body.password_repeat) {
!req.body.password_repeat ||
req.body.password != req.body.password_repeat
) {
return res.status(400).send({ return res.status(400).send({
message: 'Both passwords must match', message: 'Both passwords must match',
}); });

View File

@ -46,8 +46,9 @@ export const getSelectedUsersByUser = async (selected, result) => {
export const updateUserById = async (data, result) => { export const updateUserById = async (data, result) => {
try { try {
const id = data.id; const id = data.id;
let sql = `UPDATE users SET username = ?, password = ?, fullName = ?, email = ?, phonenumber = ?, address = ?, city = ?, postcode = ?, adminBool = ?, technicianBool = ?, readerBool = ? WHERE id = ?`; let sql = `UPDATE users SET username = ?, fullName = ?, email = ?, phonenumber = ?, address = ?, city = ?, postcode = ?, adminBool = ?, technicianBool = ?, readerBool = ? WHERE id = ?`;
const results = await ownConn.query(sql, [data.username, data.password, data.fullName, data.email, data.phonenumber, data.address, data.city, data.postcode, data.adminBool, data.technicianBool,, data.readerBool, id]); const results = await ownConn.query(sql, [data.username, data.fullName, data.email, data.phonenumber, data.address, data.city, data.postcode, data.adminBool, data.technicianBool, data.readerBool, id]);
results.insertId = results.insertId.toString();
result(null, results); result(null, results);
} }
catch (err) { catch (err) {
@ -57,12 +58,12 @@ export const updateUserById = async (data, result) => {
} }
}; };
// Delete user to Database // Delete user to Database
export const deleteUserById = async (id, result) => { export const deleteUserById = async (id, result) => {
try { try {
let sql = `DELETE FROM users WHERE id = ?`; let sql = `DELETE FROM users WHERE id = ?`;
const results = await ownConn.query(sql, [id]) const results = await ownConn.query(sql, [id])
results.insertId = results.insertId.toString();
result(null, results); result(null, results);
} }
catch (err) { catch (err) {

View File

@ -108,6 +108,7 @@ import {
import { import {
signUp, signUp,
updatePasswordById,
login, login,
showUsers, showUsers,
showUserById, showUserById,
@ -603,6 +604,9 @@ router.delete("/issueVariantsByIssueSlipId/:id", deleteIssueVariantByIssueSlipId
// sign-up process // sign-up process
router.post('/signUp', userMiddleware.validateRegister, signUp); router.post('/signUp', userMiddleware.validateRegister, signUp);
// update password process
router.put('/updatePassword', updatePasswordById);
// login process // login process
router.post('/login', login); router.post('/login', login);

View File

@ -26,8 +26,11 @@
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Password:</div> <div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Password:</div>
</label> </label>
<div :class="['input-field', darkMode ? 'input-darkmode' : 'input-lightmode']"> <div :class="['input-field', darkMode ? 'input-darkmode' : 'input-lightmode']">
<input type="text" id="password-input" placeholder="*******"> <input :type="showPassword ? 'text' : 'password'" id="password-input" placeholder="*******">
<input type="button" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="show-password-toggle" value="Show"> <input v-if="!showPassword" type="button" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']"
id="show-password-toggle" value="Show" @click="togglePasswordVisibility">
<input v-if="showPassword" type="button" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']"
id="show-password-toggle" value="Hide" @click="togglePasswordVisibility">
</div> </div>
</div> </div>
</div> </div>
@ -37,24 +40,42 @@
</label> </label>
</div> </div>
<div class="buttons"> <div class="buttons">
<input type="button" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="login-button" value="Login" @click="handleLogin"> <input type="button" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="login-button" value="Login"
<input type="button" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="signup-button" value="Signup" @click="testFunctionSignup"> @click="handleLogin">
<!-- <input type="button" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="signup-button" value="Signup" @click="testFunctionSignup"> -->
</div> </div>
</form> </form>
</template> </template>
<script setup> <script setup>
import { useRouter } from 'vue-router'; // import { useRouter } from 'vue-router';
import { ref } from 'vue'; import { ref, onBeforeUnmount } from 'vue';
import Axios from '../axios.config.js'; import Axios from '../axios.config.js';
import clientsideConfig from '../clientsideConfig.js'; import clientsideConfig from '../clientsideConfig.js';
import { useStore } from 'vuex';
const store = useStore();
const { signIn } = useAuth() const { signIn } = useAuth()
const router = useRouter(); // const router = useRouter();
const darkMode = ref(true); const darkMode = ref(true);
const isError = ref(false); const isError = ref(false);
const showPassword = ref(false);
const errorMsg = ref(''); const errorMsg = ref('');
function setItem(item, value) {
if (process.client) {
localStorage.setItem(item, value)
return true
} else {
return false
}
}
const togglePasswordVisibility = () => {
showPassword.value = !showPassword.value;
}
const handleLogin = async () => { const handleLogin = async () => {
isError.value = false; isError.value = false;
errorMsg.value = ''; errorMsg.value = '';
@ -82,69 +103,105 @@ const handleLogin = async () => {
// sucessfully logged in // sucessfully logged in
router.push('/home')*/ router.push('/home')*/
let res = await signIn( credentials, { callbackUrl: '/home' }) let resBody = await signIn(credentials, { callbackUrl: '/home' })
// console.log("res", res) try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/login`);
setItem('logged-in-bool', true);
setItem('logged-in-user-id', response.data.id)
setItem('logged-in-user-username', response.data.username)
setItem('logged-in-user-registered', response.data.registered)
setItem('logged-in-user-lastLogin', response.data.lastLogin)
setItem('logged-in-user-fullName', response.data.fullName)
setItem('logged-in-user-email', response.data.email)
setItem('logged-in-user-phonenumber', response.data.phonenumber)
setItem('logged-in-user-address', response.data.address)
setItem('logged-in-user-city', response.data.city)
setItem('logged-in-user-postcode', response.data.postcode)
setItem('logged-in-user-adminBool', response.data.adminBool)
setItem('logged-in-user-technicianBool', response.data.technicianBool)
setItem('logged-in-user-readerBool', response.data.readerBool)
setTimeout(() => {
}, 500);
store.commit('setLocalStorageChanged');
} catch (err) {
console.log(err.response.statusText);
}
} catch (err) { } catch (err) {
// handle the error // handle the error
console.log(err.response.statusText)
isError.value = true; isError.value = true;
errorMsg.value = err.response.statusText; errorMsg.value = 'Username or password is incorrect.';
document.getElementById('password-input').value = '';
} }
} }
const testFunctionSignup = async () => { // const testFunctionSignup = async () => {
isError.value = false; // isError.value = false;
errorMsg.value = ''; // errorMsg.value = '';
const username = 'adm_tueit' // const username = 'adm_tueit'
const password = 'SvF=?bfEx7_hV,cMEu4m' // const password = 'SvF=?bfEx7_hV,cMEu4m'
const password_repeat = 'SvF=?bfEx7_hV,cMEu4m' // const password_repeat = 'SvF=?bfEx7_hV,cMEu4m'
const fullName = 'administrator' // const fullName = 'administrator'
const email = 'support@tueit.de' // const email = 'support@tueit.de'
const phonenumber = '' // const phonenumber = ''
const address = '' // const address = ''
const city = '' // const city = ''
const postcode = '' // const postcode = ''
const adminBool = true // const adminBool = true
const technician1Bool = false // const technician1Bool = false
const technician2Bool = false // const technician2Bool = false
const technicianMonitoringBool = false // const technicianMonitoringBool = false
const merchantBool = false // const merchantBool = false
const internBool = true // const internBool = true
const requestBody = { // const requestBody = {
username: username, // username: username,
password: password, // password: password,
password_repeat: password_repeat, // password_repeat: password_repeat,
fullName: fullName, // fullName: fullName,
email: email, // email: email,
phonenumber: phonenumber, // phonenumber: phonenumber,
address: address, // address: address,
city: city, // city: city,
postcode: postcode, // postcode: postcode,
adminBool: adminBool, // adminBool: adminBool,
technician1Bool: technician1Bool, // technician1Bool: technician1Bool,
technician2Bool: technician2Bool, // technician2Bool: technician2Bool,
technicianMonitoringBool: technicianMonitoringBool, // technicianMonitoringBool: technicianMonitoringBool,
merchantBool: merchantBool, // merchantBool: merchantBool,
internBool: internBool, // internBool: internBool,
// }
// try {
// let res = await Axios.post(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/signup`, requestBody);
// // something to do with the res?
// // console.log(res)
// } catch (err) {
// // handle the error
// console.log(err.response.statusText)
// isError.value = true;
// errorMsg.value = err.response.statusText;
// }
// }
onMounted(() => {
document.addEventListener('keyup', handleKeyUp);
document.getElementById('username-input').value = '';
document.getElementById('password-input').value = '';
});
onBeforeUnmount(() => {
document.removeEventListener('keyup', handleKeyUp);
});
const handleKeyUp = (event) => {
if (event.key === 'Enter') {
handleLogin();
} }
};
try {
let res = await Axios.post(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/signup`, requestBody);
// something to do with the res?
// console.log(res)
} catch (err) {
// handle the error
console.log(err.response.statusText)
isError.value = true;
errorMsg.value = err.response.statusText;
}
}
</script> </script>
<script> <script>
@ -157,8 +214,8 @@ export default {
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
* { * {
@ -178,10 +235,12 @@ export default {
padding: 2.5rem 1.875rem; padding: 2.5rem 1.875rem;
gap: 1.875rem; gap: 1.875rem;
} }
.form-darkmode { .form-darkmode {
border: 0.0625rem solid #000; border: 0.0625rem solid #000;
background-color: #2c2c2c; background-color: #2c2c2c;
} }
.form-lightmode { .form-lightmode {
border: 0.0625rem solid #8e8e8e; border: 0.0625rem solid #8e8e8e;
background-color: #fff; background-color: #fff;
@ -202,6 +261,7 @@ export default {
width: 3.125rem; width: 3.125rem;
height: 3.125rem; height: 3.125rem;
} }
.title-icon>img { .title-icon>img {
width: 3.125rem; width: 3.125rem;
height: 3.125rem; height: 3.125rem;
@ -210,14 +270,24 @@ export default {
overflow: hidden; overflow: hidden;
} }
#show-password-toggle:hover {
cursor: pointer;
}
.title { .title {
margin: 0; margin: 0;
letter-spacing: 0.05rem; letter-spacing: 0.05rem;
white-space: nowrap; white-space: nowrap;
font: 400 1.875rem/1.875rem Overpass, sans-serif; font: 400 1.875rem/1.875rem Overpass, sans-serif;
} }
.title-darkmode { color: #ffffff; }
.title-lightmode { color: #000000; } .title-darkmode {
color: #ffffff;
}
.title-lightmode {
color: #000000;
}
@ -259,28 +329,43 @@ label {
width: 1.875rem; width: 1.875rem;
height: 1.875rem; height: 1.875rem;
} }
.icon>img { .icon>img {
object-fit: contain; object-fit: contain;
object-position: center; object-position: center;
overflow: hidden; overflow: hidden;
} }
#username-icon>img { #username-icon>img {
width: auto; width: auto;
height: 0.9375rem; height: 0.9375rem;
} }
#password-icon>img { #password-icon>img {
width: 0.9375rem; width: 0.9375rem;
height: auto; height: auto;
} }
.icon-darkmode>img { filter: invert(100%); }
.icon-lightmode>img { filter: invert(0%); } .icon-darkmode>img {
filter: invert(100%);
}
.icon-lightmode>img {
filter: invert(0%);
}
.label { .label {
letter-spacing: 0.02rem; letter-spacing: 0.02rem;
font: 400 0.9375rem/1.875rem Overpass, sans-serif; font: 400 0.9375rem/1.875rem Overpass, sans-serif;
} }
.label-darkmode { color: #ffffff; }
.label-lightmode { color: #000000; } .label-darkmode {
color: #ffffff;
}
.label-lightmode {
color: #000000;
}
.input-field { .input-field {
display: flex; display: flex;
@ -293,11 +378,18 @@ label {
border-radius: 0.3125rem; border-radius: 0.3125rem;
padding: 0.1875rem 0.625rem; padding: 0.1875rem 0.625rem;
box-shadow: 0.0625rem 0.0625rem 0.25rem 0rem rgba(0, 0, 0, 0.25) inset; box-shadow: 0.0625rem 0.0625rem 0.25rem 0rem rgba(0, 0, 0, 0.25) inset;
} }
.input-darkmode { background-color: #212121; }
.input-lightmode { background-color: #EBEBEB; }
input[type=text] { .input-darkmode {
background-color: #212121;
}
.input-lightmode {
background-color: #EBEBEB;
}
input[type=text],
input[type=password] {
width: 100%; width: 100%;
height: 100%; height: 100%;
background-color: #00000000; background-color: #00000000;
@ -360,6 +452,12 @@ input[type=button] {
white-space: nowrap; white-space: nowrap;
font: 600 1.125rem/1.875rem Overpass, sans-serif; font: 600 1.125rem/1.875rem Overpass, sans-serif;
} }
.button-darkmode { color: #ffffff; }
.button-lightmode { color: #000000; } .button-darkmode {
color: #ffffff;
}
.button-lightmode {
color: #000000;
}
</style> </style>

View File

@ -0,0 +1,476 @@
<template>
<section v-if="!addBool" :class="['information', darkMode ? 'section-darkmode' : 'section-lightmode']">
<h2 v-if="!editable" :class="['employee-name', darkMode ? 'h2-darkmode' : 'h2-lightmode']">{{
employee.fullName }}</h2>
<input v-if="editable" v-model="employee.fullName" @change="updateEmpl()"
:class="['data', 'employee-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']">
<div class="employee-data">
<div class="username-registered-lastLogin">
<div class="data-field" id="username">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Username:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']"> {{ employee.username }}</pre>
</div>
<div class="data-field" id="registered">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Registered:</pre>
<pre
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']"> {{ employee.registered }}</pre>
</div>
<div class="data-field" id="lastLogin">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Last login:</pre>
<pre
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']"> {{ employee.lastLogin }}</pre>
</div>
</div>
<div class="info">
<div class="city-phonenumber">
<div class="data-field" id="city">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">City:</pre>
<pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ employee.city }}</pre>
<input v-if="editable" v-model="employee.city" @change="updateEmpl()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
<div class="data-field" id="phonenumber">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Phonenumber:</pre>
<pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ employee.phonenumber }}</pre>
<input v-if="editable" v-model="employee.phonenumber" @change="updateEmpl()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
</div>
<div class="postcode-email">
<div class="data-field" id="postcode">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Postcode:</pre>
<pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ employee.postcode }}</pre>
<input v-if="editable" v-model="employee.postcode" @change="updateEmpl()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
<div class="data-field" id="email">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Email:</pre>
<pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ employee.email }}</pre>
<input v-if="editable" v-model="employee.email" @change="updateEmpl()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
</div>
<div class="address">
<div class="data-field" id="address">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Address:</pre>
<pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']"> {{ employee.address }}</pre>
<input v-if="editable" v-model="employee.address" @change="updateEmpl()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
<div class="data-field" id="empty">
&nbsp;
</div>
</div>
</div>
</div>
</section>
<section v-if="addBool" :class="['information', darkMode ? 'section-darkmode' : 'section-lightmode']">
<input v-model="newFullName" @change="updateEmployee()"
:class="['data', 'employee-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']">
<div class="employee-data">
<div class="username-registered-lastLogin">
<div class="data-field" id="username">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Username:</pre>
<input v-model="newUsername" @change="updateEmployee()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
<div class="data-field" id="password">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Password:</pre>
<input v-model="newPassword" @change="updateEmployee()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
<div class="data-field" id="passwordRepeated">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Password repeated:</pre>
<input v-model="newPasswordRepeated" @change="updateEmployee()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
</div>
<div class="info">
<div class="city-phonenumber">
<div class="data-field" id="city">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">City:</pre>
<input v-model="newCity" @change="updateEmployee()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
<div class="data-field" id="phonenumber">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Phonenumber:</pre>
<input v-model="newPhonenumber" @change="updateEmployee()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
</div>
<div class="postcode-email">
<div class="data-field" id="postcode">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Postcode:</pre>
<input v-model="newPostcode" @change="updateEmployee()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
<div class="data-field" id="email">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Email:</pre>
<input v-model="newEmail" @change="updateEmployee()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
</div>
<div class="address">
<div class="data-field" id="address">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Address:</pre>
<input v-model="newAddress" @change="updateEmployee()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
<div class="data-field" id="empty">
&nbsp;
</div>
</div>
</div>
</div>
</section>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue';
import Axios from '../axios.config.js';
import clientsideConfig from '../../clientsideConfig.js';
import { useStore } from 'vuex';
import { computed } from 'vue';
const store = useStore();
const editable = computed(() => store.state.editable);
const chosenEmployeeId = computed(() => store.state.chosenEmployeeId);
const deleteBool = computed(() => store.state.deleteBool);
const addBool = computed(() => store.state.new);
const darkMode = ref(true);
const employee = ref({});
const newUsername = ref('');
const newPassword = ref('');
const newPasswordRepeated = ref('');
const newFullName = ref('');
const newEmail = ref('');
const newPhonenumber = ref('');
const newAddress = ref('');
const newCity = ref('');
const newPostcode = ref('');
// get employee from id
const getEmployeeById = async () => {
if (!addBool.value) {
try {
const response = await Axios.get(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getEmployee/${chosenEmployeeId.value}`
);
employee.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
}
// update employee fields in the store
const updateEmployee = () => {
const employee = {
username: newUsername.value,
password: newPassword.value,
passwordRepeated: newPasswordRepeated.value,
fullName: newFullName.value,
email: newEmail.value,
phonenumber: newPhonenumber.value,
address: newAddress.value,
city: newCity.value,
postcode: newPostcode.value
};
store.commit('updateEmployeeComponent', employee);
}
//update data
const updateEmpl = async () => {
if (employee.value.fullName.trim() === "") {
alert("Please add a name!");
return;
}
if (employee.value.city.trim() === "") {
alert("Please add a city!");
return;
}
if (employee.value.address.trim() === "") {
alert("Please add an address!");
return;
}
if (!validateEMail(employee.value.email)) {
alert("Please add a valid email!");
return;
}
if (!validatePhonenumber(employee.value.phonenumber)) {
alert("Please add a valid phonenumber!");
return;
}
if (!validatePostcode(employee.value.postcode)) {
alert("Please add a valid postcode!");
return;
}
try {
await Axios.put(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/updateEmployee`,
{
id: employee.value.id,
username: employee.value.username,
fullName: employee.value.fullName,
email: employee.value.email,
phonenumber: employee.value.phonenumber,
address: employee.value.address,
city: employee.value.city,
postcode: employee.value.postcode,
adminBool: employee.value.adminBool,
technicianBool: employee.value.technicianBool,
readerBool: employee.value.readerBool,
}
)
await getEmployeeById();
} catch (err) {
console.log(err.response.statusText);
}
}
const confirmDeleteEmployee = async () => {
if (deleteBool.value === true) {
if (confirm("Do you really want to delete this employee? It cannot be undone!")) {
try {
await Axios.delete(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/deleteEmployee/${chosenEmployeeId.value}`);
store.commit('undoDelete');
store.commit('resetStore');
store.commit('changeToEmployeelist');
} catch (err) {
console.log(err.response.statusText);
}
} else {
store.commit('undoDelete');
}
}
}
// to validate the email address
const validateEMail = (email) => {
const emailRegex = new RegExp(/^[A-Za-z0-9_!#$%&'*+\/=?`{|}~^.-]+@[A-Za-z0-9.-]+$/, "gm");
if (email === "") {
return true
}
return emailRegex.test(email);
}
// to validate the phonenumber
const validatePhonenumber = (number) => {
const mobilephonenumberRegex = new RegExp(/^(((((00|\+){1,2})49([ \-/]?|[ \()/]?))|0)[1]([0-2]|[4-7])([0-9]{1})([ \-/]?|[ \()/]?)([0-9]{8}))$/, "gm");
const landlineRegex = new RegExp(/^0(30|40|69|89|20[12389]|21[24]|228|234|335|340|3[3-9][15]|906|[2-9][1-9]1|3(?:3(?:[0237][127]|0[3-6]|2[89]|3[458]|[46][1246]|7[589]|8[1256]|9[145])|4(?:[2347][135]|[34]7|[69][146]|48|62|76|93)|5(?:[04679][14]|[238][135]|[2469]2|[4789]6|[278]8|63|73|37|29)|6(?:[024689][13]|[03789]5|06|2[2489]|3[1246]|44|47|7[1279]|82|86)|7(?:[236][135]|2[2467]|37|4[145]|62|64|7[1-4])|8(?:[234678]1|3[468]|4[347]|6[035-9]|7[467]|83|86)|9(?:[236][135]|[04689]4|[04789]1|[03468]7|02|09|28|4[369]|6[2689]|73|76|96|98))|3[3-9][0-9]{3}|13[078]|180[235]|18[01]|19[0-9]{3}|[789]00|[2-9][0-9]{3})([0-9]{1,})$/, "gm");
if (number === "") {
return true
}
if (mobilephonenumberRegex.test(number)) {
return true
} else if (landlineRegex.test(number)) {
return true;
}
return false;
}
// to validate the postcode
const validatePostcode = (postcode) => {
const postcodeRegex = new RegExp(/^\d{5}$/);
if (postcode === "") {
return true
}
return postcodeRegex.test(postcode);
}
watch(deleteBool, confirmDeleteEmployee);
onMounted(() => {
getEmployeeById();
});
</script>
<script>
export default {
name: "Employee",
}
</script>
<style scoped>
.information {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
padding: 1.25rem 1.875rem;
border-radius: 0.625rem;
box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25);
}
.section-darkmode {
background-color: #2c2c2c;
}
.section-lightmode {
background-color: #fff;
}
.employee-name {
align-self: stretch;
padding: 1rem 0;
letter-spacing: 5%;
text-decoration-line: underline;
font: italic 400 1rem/187.5% Overpass, -apple-system, Roboto, Helvetica,
sans-serif;
}
.employee-name-input {
padding: 1rem 0;
margin: 1rem;
font-size: initial;
letter-spacing: 5%;
text-decoration-line: underline;
font: italic 400 1rem/187.5% Overpass, -apple-system, Roboto, Helvetica,
sans-serif;
}
.h2-darkmode {
color: #fff;
}
.h2-lightmode {
color: #000;
}
.data-field {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
width: 100%;
padding: 0.8rem 1.875rem;
gap: 1.25rem;
border-radius: 0.625rem;
}
.h2-input-darkmode {
background-color: #212121;
}
.h2-input-lightmode {
background-color: #EBEBEB;
}
.data-field#street-name {
width: 70%;
}
.data-field#street-no {
width: 30%;
}
.label {
letter-spacing: 5%;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
}
.pre-darkmode {
color: #fff;
}
.pre-lightmode {
color: #000;
}
.input {
border: none;
}
.data {
display: flex;
overflow-x: auto;
align-items: flex-start;
padding: 0 0.625rem;
border-radius: 0.3125rem;
box-shadow: 0.0625rem 0.0625rem 0.25rem 0rem rgba(0, 0, 0, 0.25) inset;
letter-spacing: 5%;
font: 400 0.75rem/250% Overpass, sans-serif;
}
.data-darkmode {
background-color: #212121;
color: #fff;
}
.data-lightmode {
background-color: #EBEBEB;
color: #000;
}
.data#notes,
.data#description {
align-self: stretch;
/* width: 45%; */
scrollbar-width: none;
overflow-x: auto;
}
.employee-data {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
align-self: stretch;
}
.username-registered-lastLogin,
.info {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
line-height: normal;
width: 50%;
padding: 0 0;
border-radius: 0.3125rem;
}
.additional {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
line-height: normal;
width: 50%;
padding: 0rem 0.625rem;
border-radius: 0.3125rem;
}
.area-title {
letter-spacing: 5%;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
}
.h3-darkmode {
color: #fff;
}
.h3-lightmode {
color: #000;
}
.city-phonenumber,
.postcode-email {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
align-self: stretch;
padding: 0 1.875rem 0 0;
gap: 0.625rem;
}
</style>

View File

@ -0,0 +1,485 @@
<template>
<section v-if="!addBool" :class="['group-information', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'div-darkmode' : 'div-lightmode']" id="group">Groups:</div>
<div class="asset-data">
<div class="checkbox-container">
<div class="checkbox-group">
<label :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']" for="admin-checkbox">Admin</label>
<input :readonly="!editable" id="admin-checkbox" type="checkbox" v-model="adminBoolean"
@click="toggleAdminBool()">
</div>
<div class="checkbox-group">
<label :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']" for="technician-checkbox">Technician</label>
<input :readonly="!editable" id="technician-checkbox" type="checkbox"
v-model="technicianBoolean" @click="toggleTechnicianBool()">
</div>
<div class="checkbox-group">
<label :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']" for="reader-checkbox">Reader</label>
<input :readonly="!editable" id="reader-checkbox" type="checkbox" v-model="readerBoolean"
@click="toggleReaderBool()">
</div>
</div>
</div>
</section>
<section v-if="addBool" :class="['group-information', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'div-darkmode' : 'div-lightmode']" id="group">Groups:</div>
<div class="asset-data">
<div class="checkbox-container">
<div class="checkbox-group">
<label :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']" for="admin-checkbox">Admin</label>
<input id="admin-checkbox" type="checkbox" v-model="newAdminBool">
</div>
<div class="checkbox-group">
<label :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']" for="technician-checkbox">Technician</label>
<input id="technician-checkbox" type="checkbox" v-model="newTechnicianBool">
</div>
<div class="checkbox-group">
<label :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']" for="reader-checkbox">Reader</label>
<input id="reader-checkbox" type="checkbox" v-model="newReaderBool">
</div>
</div>
</div>
</section>
<section v-if="addBool" id="saveNewEmployee">
<button :class="[darkMode ? 'saveNewEmployee-darkmode' : 'saveNewEmployee-lightmode']"
@click="addEmployee()">Save</button>
</section>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import Axios from '../axios.config.js';
import clientsideConfig from '../../clientsideConfig.js';
import { useStore } from 'vuex';
import { computed } from 'vue';
const store = useStore();
const editable = computed(() => store.state.editable);
const chosenEmployeeId = computed(() => store.state.chosenEmployeeId);
const addBool = computed(() => store.state.new);
const newUsernameEmp = computed(() => store.state.newUsernameEmp);
const newPasswordEmp = computed(() => store.state.newPasswordEmp);
const newPasswordRepeatedEmp = computed(() => store.state.newPasswordRepeatedEmp);
const newFullNameEmp = computed(() => store.state.newFullNameEmp);
const newEmailEmp = computed(() => store.state.newEmailEmp);
const newPhonenumberEmp = computed(() => store.state.newPhonenumberEmp);
const newAddressEmp = computed(() => store.state.newAddressEmp);
const newCityEmp = computed(() => store.state.newCityEmp);
const newPostcodeEmp = computed(() => store.state.newPostcodeEmp);
const darkMode = ref(true)
const employee = ref({});
const adminBoolean = ref(false);
const technicianBoolean = ref(false);
const readerBoolean = ref(false);
const newAdminBool = ref(false);
const newTechnicianBool = ref(false);
const newReaderBool = ref(false);
const employees = ref([]);
// get employee from id
const getEmployeeById = async () => {
if (!addBool.value) {
try {
const response = await Axios.get(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getEmployee/${chosenEmployeeId.value}`
);
employee.value = response.data;
if (employee.value.adminBool == 1) {
adminBoolean.value = true;
};
if (employee.value.technicianBool == 1) {
technicianBoolean.value = true;
};
if (employee.value.readerBool == 1) {
readerBoolean.value = true;
};
} catch (err) {
console.log(err.response.statusText);
}
}
}
const toggleTechnicianBool = () => {
technicianBoolean.value = !technicianBoolean.value;
update();
}
const toggleAdminBool = () => {
adminBoolean.value = !adminBoolean.value;
update();
}
const toggleReaderBool = () => {
readerBoolean.value = !readerBoolean.value;
update();
}
//update data
const update = async () => {
if (adminBoolean.value) {
employee.value.adminBool = 1;
} else {
employee.value.adminBool = 0;
}
if (technicianBoolean.value) {
employee.value.technicianBool = 1;
} else {
employee.value.technicianBool = 0;
}
if (readerBoolean.value) {
employee.value.readerBool = 1;
} else {
employee.value.readerBool = 0;
}
try {
await Axios.put(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/updateEmployee`,
{
id: employee.value.id,
username: employee.value.username,
fullName: employee.value.fullName,
email: employee.value.email,
phonenumber: employee.value.phonenumber,
address: employee.value.address,
city: employee.value.city,
postcode: employee.value.postcode,
adminBool: employee.value.adminBool,
technicianBool: employee.value.technicianBool,
readerBool: employee.value.readerBool,
}
);
} catch (err) {
console.log(err.response.statusText);
}
await getEmployeeById();
}
// add new employee
const addEmployee = async () => {
// check if all input data is valid
if (newUsernameEmp.value.trim() === "") {
alert("Please add an username!");
return;
} else {
var counter = 0;
// check if the username already exists
employees.value.forEach(empl => {
if (empl.username === newUsernameEmp.value) {
counter += 1;
}
});
if (counter == 1) {
alert("This username already exists. Please choose an unique username or modify respectively delete the old one!");
return;
}
}
if (newPasswordEmp.value.trim() === "") {
alert("Please add a password!");
return;
}
// username min length 5
if (!newUsernameEmp.value || newUsernameEmp.value.length < 5) {
alert("Please choose an username with minimal five characters!");
return
}
// password min 8 chars
if (!newPasswordEmp.value || newPasswordEmp.value.length < 8) {
alert("Please choose a password with minimal eight characters!");
return
}
// password (repeat) must match
if (
!newPasswordRepeatedEmp.value ||
newPasswordEmp.value != newPasswordRepeatedEmp.value
) {
alert("Your passwords don't match.");
return
}
if (newFullNameEmp.value.length === 0) {
alert("Please add a name!");
return;
}
if (newCityEmp.value.length === 0) {
alert("Please add a city!");
return;
}
if (newAddressEmp.value.length === 0) {
alert("Please add an address!");
return;
}
if (!validateEMail(newEmailEmp.value)) {
alert("Please add a valid email!");
return;
}
if (!validatePhonenumber(newPhonenumberEmp.value)) {
alert("Please add a valid phonenumber!");
return;
}
if (!validatePostcode(newPostcodeEmp.value)) {
alert("Please add a valid postcode!");
return;
}
if ((newPhonenumberEmp.value.length === 0) && (newEmailEmp.value.length === 0)) {
alert("Please add a phonenumber or an email!");
return;
}
if (! (newAdminBool.value || newTechnicianBool.value || newReaderBool.value)) {
alert("Please choose at least one group!");
return;
}
try {
let res = await Axios.post(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/signup`,
{
username: newUsernameEmp.value,
password: newPasswordEmp.value,
password_repeat: newPasswordRepeatedEmp.value,
fullName: newFullNameEmp.value,
email: newEmailEmp.value,
phonenumber: newPhonenumberEmp.value,
address: newAddressEmp.value,
city: newCityEmp.value,
postcode: newPostcodeEmp.value,
adminBool: newAdminBool.value,
technicianBool: newTechnicianBool.value,
readerBool: newReaderBool.value,
});
store.commit('resetStore');
store.commit('changeToEmployeelist');
} catch (err) {
console.log(err.response.statusText);
}
}
//get all employees
const getEmployees = async () => {
try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllEmployees`);
employees.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
// to validate the email address
const validateEMail = (email) => {
const emailRegex = new RegExp(/^[A-Za-z0-9_!#$%&'*+\/=?`{|}~^.-]+@[A-Za-z0-9.-]+$/, "gm");
if (email === "") {
return true
}
return emailRegex.test(email);
}
// to validate the phonenumber
const validatePhonenumber = (number) => {
const mobilephonenumberRegex = new RegExp(/^(((((00|\+){1,2})49([ \-/]?|[ \()/]?))|0)[1]([0-2]|[4-7])([0-9]{1})([ \-/]?|[ \()/]?)([0-9]{8}))$/, "gm");
const landlineRegex = new RegExp(/^0(30|40|69|89|20[12389]|21[24]|228|234|335|340|3[3-9][15]|906|[2-9][1-9]1|3(?:3(?:[0237][127]|0[3-6]|2[89]|3[458]|[46][1246]|7[589]|8[1256]|9[145])|4(?:[2347][135]|[34]7|[69][146]|48|62|76|93)|5(?:[04679][14]|[238][135]|[2469]2|[4789]6|[278]8|63|73|37|29)|6(?:[024689][13]|[03789]5|06|2[2489]|3[1246]|44|47|7[1279]|82|86)|7(?:[236][135]|2[2467]|37|4[145]|62|64|7[1-4])|8(?:[234678]1|3[468]|4[347]|6[035-9]|7[467]|83|86)|9(?:[236][135]|[04689]4|[04789]1|[03468]7|02|09|28|4[369]|6[2689]|73|76|96|98))|3[3-9][0-9]{3}|13[078]|180[235]|18[01]|19[0-9]{3}|[789]00|[2-9][0-9]{3})([0-9]{1,})$/, "gm");
if (number === "") {
return true
}
if (mobilephonenumberRegex.test(number)) {
return true
} else if (landlineRegex.test(number)) {
return true;
}
return false;
}
// to validate the postcode
const validatePostcode = (postcode) => {
const postcodeRegex = new RegExp(/^\d{5}$/);
if (postcode === "") {
return true
}
return postcodeRegex.test(postcode);
}
// include delay to avoid 503 error
const triggerBackendCallsWithDelay = async (fetchDataFunc) => {
setTimeout(() => {
fetchDataFunc();
}, 1000);
}
onMounted(() => {
triggerBackendCallsWithDelay(getEmployeeById);
triggerBackendCallsWithDelay(getEmployees);
});
</script>
<script>
export default {
name: "EmployeeGroups",
};
</script>
<style scoped>
.group-information {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
padding: 1.25rem 1.875rem;
border-radius: 0.625rem;
box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25);
}
.section-darkmode {
background-color: #2c2c2c;
}
.section-lightmode {
background-color: #fff;
}
.data-field {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
width: 100%;
padding: 0.8rem 1.875rem;
gap: 1.25rem;
border-radius: 0.625rem;
}
.label {
letter-spacing: 5%;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
}
.div-darkmode {
color: #fff;
}
.div-lightmode {
color: #000;
}
.label#network {
padding-top: 1rem;
padding-bottom: 1rem;
}
.data {
display: flex;
flex-direction: row;
align-items: flex-start;
padding: 0 0.625rem;
border-radius: 0.3125rem;
box-shadow: 0.0625rem 0.0625rem 0.25rem 0rem rgba(0, 0, 0, 0.25) inset;
letter-spacing: 5%;
font: 400 0.75rem/250% Overpass, sans-serif;
}
.data-darkmode {
background-color: #212121;
color: #fff;
}
.data-lightmode {
background-color: #EBEBEB;
color: #000;
}
.asset-data {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
align-self: stretch;
}
.IPv4-MAC,
.IPv6-subnetmask {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
line-height: normal;
width: 50%;
padding: 0 0;
border-radius: 0.3125rem;
}
.saveNewEmployee-darkmode {
background: #2c2c2c;
color: #fff;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
border: none;
padding: 1rem 1.875rem;
width: 8%;
border-radius: 0.625rem;
box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25);
}
.saveNewEmployee-lightmode {
background: #EBEBEB;
color: #212121;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
border: none;
padding: 1rem 1.875rem;
width: 8%;
border-radius: 0.625rem;
box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25);
}
.saveNewEmployee-darkmode:hover {
background-color: #444444;
cursor: pointer;
}
.saveNewEmployee-lightmode:hover {
background-color: #ACACAC;
cursor: pointer;
}
#saveNewEmployee {
text-align: center;
}
.input {
border: none;
}
.checkbox-container {
padding-bottom: 0.8rem;
display: flex;
justify-content: center;
}
.checkbox-group {
display: flex;
flex-direction: column;
align-items: center;
width: 20rem;
}
.checkbox-group label {
margin-bottom: 5px;
}
.checkbox-group input {
margin-bottom: 10px;
}
.label {
letter-spacing: 5%;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
}
.pre-darkmode {
color: #fff;
}
.pre-lightmode {
color: #000;
}
input[type=checkbox]{
accent-color: #000;
}
</style>

View File

@ -15,17 +15,17 @@
:class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']"> :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']">
<td <td
:class="['Name', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']"> :class="['Name', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
<nuxt-link to="/assets" id="nuxt-link" class="button" <nuxt-link to="/employees" id="nuxt-link" class="button"
:class="[darkMode ? 'button-darkmode' : 'button-lightmode']" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']"
@click="goToChosenAsset(u.id)"> @click="goToChosenEmployee(u.id)">
{{ u.fullName }} {{ u.fullName }}
</nuxt-link> </nuxt-link>
</td> </td>
<td <td
:class="['Username', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Username-darkmode' : 'Username-lightmode']"> :class="['Username', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Username-darkmode' : 'Username-lightmode']">
<nuxt-link to="/assets" id="nuxt-link" class="button" <nuxt-link to="/employees" id="nuxt-link" class="button"
:class="[darkMode ? 'button-darkmode' : 'button-lightmode']" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']"
@click="goToChosenAsset(u.id)"> @click="goToChosenEmployee(u.id)">
{{ u.username }} {{ u.username }}
</nuxt-link> </nuxt-link>
</td> </td>
@ -45,7 +45,7 @@ import { computed } from 'vue';
// get accesss to the store // get accesss to the store
const store = useStore() const store = useStore()
const goToChosenAsset = (id) => { const goToChosenEmployee = (id) => {
store.commit('setChosenEmployee', id); store.commit('setChosenEmployee', id);
store.commit('changeToEmployee'); store.commit('changeToEmployee');
}; };

View File

@ -45,7 +45,7 @@
<td v-if="!editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']"> {{ todo.commets <td v-if="!editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']"> {{ todo.commets
}}</td> }}</td>
<td v-if="editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']"> <input type="text" <td v-if="editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']"> <input type="text"
v-model="todo.commets" @change="updateMVTTodo(todo)" v-model="todo.commets" @change="updateMVTTodo(todo)"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']"> <button :class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']"> <button
:class="[darkMode ? 'deleteMvtTodos-darkmode' : 'deleteMvtTodos-lightmode']" :class="[darkMode ? 'deleteMvtTodos-darkmode' : 'deleteMvtTodos-lightmode']"
@click="deleteMVTTodo(todo.primaryID)">-</button> @click="deleteMVTTodo(todo.primaryID)">-</button>
@ -149,6 +149,8 @@ import Axios from '../axios.config.js';
import clientsideConfig from '../../clientsideConfig.js'; import clientsideConfig from '../../clientsideConfig.js';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { computed } from 'vue'; import { computed } from 'vue';
// import VueInputAutowidth from 'vue-input-autowidth';
// Vue.use(VueInputAutowidth);
const store = useStore(); const store = useStore();
const addBool = computed(() => store.state.new); const addBool = computed(() => store.state.new);

View File

@ -2,32 +2,243 @@
<section :class="['userAccount', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section :class="['userAccount', darkMode ? 'section-darkmode' : 'section-lightmode']">
<h2 :class="['heading', darkMode ? 'heading-darkmode' : 'heading-lightmode']">Account:</h2> <h2 :class="['heading', darkMode ? 'heading-darkmode' : 'heading-lightmode']">Account:</h2>
<div class="userData"> <div class="userData">
<div class="data-field" id="email"> <div class="username-email">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">E-Mail:</pre> <div class="data-field" id="username">
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Username:</pre>
<pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ loggedInUserUsername }}</pre>
<input v-if="editable" v-model="loggedInUserUsername" @change="updateUsername()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
<div class="data-field" id="email">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Email:</pre>
<pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ loggedInUserEmail }}</pre>
<input v-if="editable" v-model="loggedInUserEmail" @change="updateUser()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
<input v-if="editable" :class="[darkMode ? 'input-darkmode' : '', !darkMode ? 'input-lightmode' : '',]"
type="button" id="changePassword" value="Change Password" @click="changePassword">
</div> </div>
<div class="data-field" id="password"> <div v-if="changePasswordBool && editable" class="password">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Password:</pre> <div class="data-field" id="password">
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">*******</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">New Password:</pre>
<input v-if="editable" v-model="loggedInUserNewPassword"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
<div class="data-field" id="passwordRepeated">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Repeat:</pre>
<input v-if="editable" v-model="loggedInUserNewPasswordRepeated"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
<input :class="[darkMode ? 'input-darkmode' : '', !darkMode ? 'input-lightmode' : '',]" type="button"
id="savePassword" value="Save Password" @click="savePassword">
</div> </div>
</div> </div>
</section> </section>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
import Axios from '../axios.config.js';
import clientsideConfig from '../../clientsideConfig.js';
const store = useStore();
const editable = computed(() => store.state.editable);
const changePasswordBool = ref(false);
const loggedInUserId = ref('');
const loggedInUserUsername = ref('');
const loggedInUserRegistered = ref('');
const loggedInUserLastLogin = ref('');
const loggedInUserFullName = ref('');
const loggedInUserEmail = ref('');
const loggedInUserPhonenumber = ref('');
const loggedInUserAddress = ref('');
const loggedInUserCity = ref('');
const loggedInUserPostcode = ref('');
const loggedInUserAdminBool = ref('');
const loggedInUserTechnicianBool = ref('');
const loggedInUserReaderBool = ref('');
const loggedInUserNewPassword = ref('');
const loggedInUserNewPasswordRepeated = ref('');
const employees = ref([]);
const darkMode = ref(true) const darkMode = ref(true)
const changePassword = () => {
changePasswordBool.value = !changePasswordBool.value
loggedInUserNewPassword.value = '';
loggedInUserNewPasswordRepeated.value = '';
}
const savePassword = async () => {
// hier weiter machen
if (loggedInUserNewPassword.value.length < 8) {
alert("Please choose a password with minimal eight characters!");
return
}
// password (repeat) must match
if (loggedInUserNewPassword.value != loggedInUserNewPasswordRepeated.value) {
alert("Your passwords don't match.");
return
}
try {
await Axios.put(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/updatePasswordEmployee`,
{
id: loggedInUserId.value,
password: loggedInUserNewPassword.value,
}
)
alert("Password successfully updatet!");
changePasswordBool.value = false;
loggedInUserNewPassword.value = '';
loggedInUserNewPasswordRepeated.value = '';
} catch (err) {
console.log(err);
};
}
const getSession = async () => {
loggedInUserId.value = getItem('logged-in-user-id');
loggedInUserUsername.value = getItem('logged-in-user-username');
loggedInUserRegistered.value = getItem('logged-in-user-registered');
loggedInUserLastLogin.value = getItem('logged-in-user-lastLogin');
loggedInUserFullName.value = getItem('logged-in-user-fullName');
loggedInUserEmail.value = getItem('logged-in-user-email');
loggedInUserPhonenumber.value = getItem('logged-in-user-phonenumber');
loggedInUserAddress.value = getItem('logged-in-user-address');
loggedInUserCity.value = getItem('logged-in-user-city');
loggedInUserPostcode.value = getItem('logged-in-user-postcode');
loggedInUserAdminBool.value = getItem('logged-in-user-adminBool');
loggedInUserTechnicianBool.value = getItem('logged-in-user-technicianBool');
loggedInUserReaderBool.value = getItem('logged-in-user-readerBool');
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
const updateUsername = async () => {
if (loggedInUserUsername.value.length < 5) {
alert("Your username must have at least five characters!");
loggedInUserUsername.value = getItem('logged-in-user-username');
return;
}
var counter = 0;
// check if the username already exists
employees.value.forEach(empl => {
if (empl.username === loggedInUserUsername.value) {
counter += 1;
}
});
if (counter == 1) {
alert("This username already exists. Please choose an unique username!");
loggedInUserUsername.value = getItem('logged-in-user-username');
return;
}
await updateUser();
}
//update data
const updateUser = async () => {
if (!validateEMail(loggedInUserEmail.value)) {
alert("Please add a valid email!");
loggedInUserEmail.value = getItem('logged-in-user-email');
return;
}
if ((loggedInUserPhonenumber.value.length === 0) && (loggedInUserEmail.value.length === 0)) {
alert("Please add a phonenumber or an email!");
loggedInUserPhonenumber.value = getItem('logged-in-user-phonenumber');
loggedInUserEmail.value = getItem('logged-in-user-email')
return;
}
try {
await Axios.put(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/updateEmployee`,
{
id: loggedInUserId.value,
username: loggedInUserUsername.value,
fullName: loggedInUserFullName.value,
email: loggedInUserEmail.value,
phonenumber: loggedInUserPhonenumber.value,
address: loggedInUserAddress.value,
city: loggedInUserCity.value,
postcode: loggedInUserPostcode.value,
adminBool: loggedInUserAdminBool.value,
technicianBool: loggedInUserTechnicianBool.value,
readerBool: loggedInUserReaderBool.value,
}
)
setItem('logged-in-user-username', loggedInUserUsername.value)
setItem('logged-in-user-fullName', loggedInUserFullName.value)
setItem('logged-in-user-email', loggedInUserEmail.value)
setItem('logged-in-user-phonenumber', loggedInUserPhonenumber.value)
setItem('logged-in-user-address', loggedInUserAddress.value)
setItem('logged-in-user-city', loggedInUserCity.value)
setItem('logged-in-user-postcode', loggedInUserPostcode.value)
getSession();
store.commit('setLocalStorageChanged');
} catch (err) {
console.log(err.response.statusText);
}
}
// to validate the email address
const validateEMail = (email) => {
const emailRegex = new RegExp(/^[A-Za-z0-9_!#$%&'*+\/=?`{|}~^.-]+@[A-Za-z0-9.-]+$/, "gm");
if (email === "") {
return true
}
return emailRegex.test(email);
}
function setItem(item, value) {
if (process.client) {
localStorage.setItem(item, value)
return true
} else {
return false
}
}
//get all employees
const getEmployees = async () => {
try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllEmployees`);
employees.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
// include delay to avoid 503 error
const triggerBackendCallsWithDelay = async (fetchDataFunc) => {
setTimeout(() => {
fetchDataFunc();
}, 1000);
}
onMounted(async () => {
await getSession();
await triggerBackendCallsWithDelay(getEmployees);
});
</script> </script>
<script> <script>
export default { export default {
name: "UserAccount", name: "UserAccount",
}; };
</script> </script>
<style scoped> <style scoped>
.userAccount { .userAccount {
display: flex; display: flex;
@ -53,6 +264,47 @@ export default {
background-color: #fff; background-color: #fff;
} }
.input-darkmode {
color: #fff;
background-color: #212121;
}
input#changePassword:hover,
input#savePassword:hover {
background-color: #454545;
}
.input-lightmode {
color: #212121;
;
background-color: #EBEBEB;
}
.data-darkmode {
background-color: #212121;
color: #fff;
}
.data-lightmode {
background-color: #EBEBEB;
color: #000;
}
.data {
display: flex;
flex-direction: row;
align-items: flex-start;
padding: 0 0.625rem;
border-radius: 0.3125rem;
box-shadow: 0.0625rem 0.0625rem 0.25rem 0rem rgba(0, 0, 0, 0.25) inset;
letter-spacing: 5%;
font: 400 0.75rem/250% Overpass, sans-serif;
}
.input {
border: none;
}
.heading { .heading {
letter-spacing: 5%; letter-spacing: 5%;
font: 400 1rem/2rem Overpass, sans-serif; font: 400 1rem/2rem Overpass, sans-serif;
@ -66,9 +318,21 @@ export default {
color: #000; color: #000;
} }
.userData { .username-email,
.password {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: flex-start;
justify-content: center;
line-height: normal;
width: 50%;
padding: 0 1rem;
border-radius: 0.3125rem;
}
.userData {
display: flex;
flex-direction: row;
align-content: center; align-content: center;
gap: 0.625rem gap: 0.625rem
} }
@ -137,4 +401,22 @@ export default {
.label { .label {
width: 6.25rem; width: 6.25rem;
} }
input#changePassword,
input#savePassword {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
width: 10rem;
height: 2.5rem;
margin-top: 1rem;
border-radius: 0.625rem;
border: none;
text-align: center;
letter-spacing: 5%;
font: 400 0.875rem/2rem Overpass, sans-serif;
margin-right: 1.25rem;
box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25);
}
</style> </style>

View File

@ -5,28 +5,221 @@
<div class="rectangle-container"> <div class="rectangle-container">
<div :class="['rectangle', darkMode ? 'rectangle-darkmode' : 'rectangle-lightmode']"></div> <div :class="['rectangle', darkMode ? 'rectangle-darkmode' : 'rectangle-lightmode']"></div>
</div> </div>
<div class="data-field" id="username"> <div class="fullname-registered-lastLogin">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Username:</pre> <div class="data-field" id="fullName">
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Full name:</pre>
<pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ loggedInUserFullName }}</pre>
<input v-if="editable" v-model="loggedInUserFullName" @change="updateUser()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
<div class="data-field" id="registered">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Registered:</pre>
<pre
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']"> {{ loggedInUserRegistered }}</pre>
</div>
<div class="data-field" id="lastLogin">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Last login:</pre>
<pre
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']"> {{ loggedInUserLastLogin }}</pre>
</div>
</div>
<div class="info">
<div class="city-phonenumber">
<div class="data-field" id="city">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">City:</pre>
<pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ loggedInUserCity }}</pre>
<input v-if="editable" v-model="loggedInUserCity" @change="updateUser()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
<div class="data-field" id="phonenumber">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Phonenumber:</pre>
<pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ loggedInUserPhonenumber }}</pre>
<input v-if="editable" v-model="loggedInUserPhonenumber" @change="updateUser()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
</div>
<div class="postcode-address">
<div class="data-field" id="postcode">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Postcode:</pre>
<pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ loggedInUserPostcode }}</pre>
<input v-if="editable" v-model="loggedInUserPostcode" @change="updateUser()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
<div class="data-field" id="address">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Address:</pre>
<pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ loggedInUserAddress }}</pre>
<input v-if="editable" v-model="loggedInUserAddress" @change="updateUser()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
</div>
</div> </div>
</div> </div>
</section> </section>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { ref } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
import Axios from '../axios.config.js';
import clientsideConfig from '../../clientsideConfig.js';
const store = useStore();
const editable = computed(() => store.state.editable);
const loggedInUserId = ref('');
const loggedInUserUsername = ref('');
const loggedInUserRegistered = ref('');
const loggedInUserLastLogin = ref('');
const loggedInUserFullName = ref('');
const loggedInUserEmail = ref('');
const loggedInUserPhonenumber = ref('');
const loggedInUserAddress = ref('');
const loggedInUserCity = ref('');
const loggedInUserPostcode = ref('');
const loggedInUserAdminBool = ref('');
const loggedInUserTechnicianBool = ref('');
const loggedInUserReaderBool = ref('');
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
const getSession = async () => {
loggedInUserId.value = getItem('logged-in-user-id');
loggedInUserUsername.value = getItem('logged-in-user-username');
loggedInUserRegistered.value = getItem('logged-in-user-registered');
loggedInUserLastLogin.value = getItem('logged-in-user-lastLogin');
loggedInUserFullName.value = getItem('logged-in-user-fullName');
loggedInUserEmail.value = getItem('logged-in-user-email');
loggedInUserPhonenumber.value = getItem('logged-in-user-phonenumber');
loggedInUserAddress.value = getItem('logged-in-user-address');
loggedInUserCity.value = getItem('logged-in-user-city');
loggedInUserPostcode.value = getItem('logged-in-user-postcode');
loggedInUserAdminBool.value = getItem('logged-in-user-adminBool');
loggedInUserTechnicianBool.value = getItem('logged-in-user-technicianBool');
loggedInUserReaderBool.value = getItem('logged-in-user-readerBool');
}
const darkMode = ref(true) const darkMode = ref(true)
//update data
const updateUser = async () => {
if (loggedInUserFullName.value.length === 0) {
alert("Please add a valid name!");
loggedInUserFullName.value = getItem('logged-in-user-fullName');
return;
}
if (loggedInUserCity.value.length === 0) {
alert("Please add a city!");
loggedInUserCity.value = getItem('logged-in-user-city');
return;
}
if (loggedInUserAddress.value.length === 0) {
alert("Please add an address!");
loggedInUserAddress.value = getItem('logged-in-user-address');
return;
}
if (!validatePhonenumber(loggedInUserPhonenumber.value)) {
alert("Please add a valid phonenumber!");
loggedInUserPhonenumber.value = getItem('logged-in-user-phonenumber');
return;
}
if (!validatePostcode(loggedInUserPostcode.value)) {
alert("Please add a valid postcode!");
loggedInUserPostcode.value = getItem('logged-in-user-postcode');
return;
}
if ((loggedInUserPhonenumber.value.length === 0) && (loggedInUserEmail.value.length === 0)) {
alert("Please add a phonenumber or an email!");
loggedInUserPhonenumber.value = getItem('logged-in-user-phonenumber');
loggedInUserEmail.value = getItem('logged-in-user-email')
return;
}
try {
await Axios.put(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/updateEmployee`,
{
id: loggedInUserId.value,
username: loggedInUserUsername.value,
fullName: loggedInUserFullName.value,
email: loggedInUserEmail.value,
phonenumber: loggedInUserPhonenumber.value,
address: loggedInUserAddress.value,
city: loggedInUserCity.value,
postcode: loggedInUserPostcode.value,
adminBool: loggedInUserAdminBool.value,
technicianBool: loggedInUserTechnicianBool.value,
readerBool: loggedInUserReaderBool.value,
}
)
setItem('logged-in-user-username', loggedInUserUsername.value)
setItem('logged-in-user-fullName', loggedInUserFullName.value)
setItem('logged-in-user-email', loggedInUserEmail.value)
setItem('logged-in-user-phonenumber', loggedInUserPhonenumber.value)
setItem('logged-in-user-address', loggedInUserAddress.value)
setItem('logged-in-user-city', loggedInUserCity.value)
setItem('logged-in-user-postcode', loggedInUserPostcode.value)
getSession();
} catch (err) {
console.log(err.response.statusText);
}
}
function setItem(item, value) {
if (process.client) {
localStorage.setItem(item, value)
return true
} else {
return false
}
}
// to validate the phonenumber
const validatePhonenumber = (number) => {
const mobilephonenumberRegex = new RegExp(/^(((((00|\+){1,2})49([ \-/]?|[ \()/]?))|0)[1]([0-2]|[4-7])([0-9]{1})([ \-/]?|[ \()/]?)([0-9]{8}))$/, "gm");
const landlineRegex = new RegExp(/^0(30|40|69|89|20[12389]|21[24]|228|234|335|340|3[3-9][15]|906|[2-9][1-9]1|3(?:3(?:[0237][127]|0[3-6]|2[89]|3[458]|[46][1246]|7[589]|8[1256]|9[145])|4(?:[2347][135]|[34]7|[69][146]|48|62|76|93)|5(?:[04679][14]|[238][135]|[2469]2|[4789]6|[278]8|63|73|37|29)|6(?:[024689][13]|[03789]5|06|2[2489]|3[1246]|44|47|7[1279]|82|86)|7(?:[236][135]|2[2467]|37|4[145]|62|64|7[1-4])|8(?:[234678]1|3[468]|4[347]|6[035-9]|7[467]|83|86)|9(?:[236][135]|[04689]4|[04789]1|[03468]7|02|09|28|4[369]|6[2689]|73|76|96|98))|3[3-9][0-9]{3}|13[078]|180[235]|18[01]|19[0-9]{3}|[789]00|[2-9][0-9]{3})([0-9]{1,})$/, "gm");
if (number === "") {
return true
}
if (mobilephonenumberRegex.test(number)) {
return true
} else if (landlineRegex.test(number)) {
return true;
}
return false;
}
// to validate the postcode
const validatePostcode = (postcode) => {
const postcodeRegex = new RegExp(/^\d{5}$/);
if (postcode === "") {
return true
}
return postcodeRegex.test(postcode);
}
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>
export default { export default {
name: "UserProfile", name: "UserProfile",
}; };
</script> </script>
<style scoped> <style scoped>
.userProfile { .userProfile {
display: flex; display: flex;
@ -52,11 +245,19 @@ export default {
background-color: #fff; background-color: #fff;
} }
.input {
border: none;
}
.heading { .heading {
letter-spacing: 5%; letter-spacing: 5%;
font: 400 1rem/2rem Overpass, sans-serif; font: 400 1rem/2rem Overpass, sans-serif;
} }
.div#address.data-field {
padding-left: 3rem;
}
.heading-darkmode { .heading-darkmode {
color: #fff; color: #fff;
} }
@ -65,6 +266,18 @@ export default {
color: #000; color: #000;
} }
.fullname-registered-lastLogin,
.info {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
line-height: normal;
width: 50%;
padding: 0 1rem;
border-radius: 0.3125rem;
}
.userData { .userData {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@ -74,6 +287,26 @@ export default {
gap: 3.125rem gap: 3.125rem
} }
.city-phonenumber {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
align-self: stretch;
padding: 0 1.875rem 0 0;
gap: 0.625rem;
}
.postcode-address {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
align-self: stretch;
padding: 0 1.875rem 0 0;
gap: 0.625rem;
}
.rectangle-container { .rectangle-container {
display: flex; display: flex;
} }

View File

@ -1,4 +1,4 @@
<template> <!-- <template>
<div :class="['data', darkMode ? 'div-darkmode' : 'div-lightmode']"> <div :class="['data', darkMode ? 'div-darkmode' : 'div-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Rights:</div> <div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Rights:</div>
<table class="data-table" id="user-rights-list"> <table class="data-table" id="user-rights-list">
@ -212,4 +212,4 @@ th {
.label-lightmode { .label-lightmode {
color: #000; color: #000;
} }
</style> </style> -->

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
<mxfile host="Electron" modified="2024-03-15T19:12:52.812Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.0.3 Chrome/114.0.5735.289 Electron/25.8.4 Safari/537.36" etag="paCwt5s8ml-fbCSaMHOa" version="22.0.3" type="device" pages="2"> <mxfile host="Electron" modified="2024-03-15T20:17:22.734Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.0.3 Chrome/114.0.5735.289 Electron/25.8.4 Safari/537.36" etag="57kzY8uiA-w2JTHS5BZR" version="22.0.3" type="device" pages="2">
<diagram name="Seite-1" id="VLuSDTVFFHJCdRpH-1WC"> <diagram name="Seite-1" id="VLuSDTVFFHJCdRpH-1WC">
<mxGraphModel dx="410" dy="2842" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"> <mxGraphModel dx="410" dy="2842" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root> <root>

View File

@ -91,9 +91,9 @@
<pre v-if="isExpanded" :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Instance</pre> <pre v-if="isExpanded" :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Instance</pre>
</Transition> </Transition>
</button> </button>
<router-link v-if="addSolutionIcon" to="/solutions" class="button" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="solutions-button"> <router-link v-if="addSolutionIcon" to="/solutions" class="button"
<button :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="new-solution" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="solutions-button">
@click="addSolution"> <button :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="new-solution" @click="addSolution">
<div class="icon" id="new-icon"> <div class="icon" id="new-icon">
<img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy" <img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="/icons/actionbar-icons/Add-New-Icon.svg" /> src="/icons/actionbar-icons/Add-New-Icon.svg" />
@ -128,10 +128,11 @@
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { computed } from 'vue'; import { computed } from 'vue';
const changeToSet = computed(() => store.state.changeToSet);
const addIcon = computed(() => store.state.addIcon); const addIcon = computed(() => store.state.addIcon);
const addInstanceIcon = computed(() => store.state.addInstanceIcon); const addInstanceIcon = computed(() => store.state.addInstanceIcon);
const addSolutionIcon = computed(() => store.state.addSolutionIcon); const addSolutionIcon = computed(() => store.state.addSolutionIcon);
@ -178,8 +179,22 @@ const changeToSolutions = () => {
store.commit('changeToSolutionlistAsset'); store.commit('changeToSolutionlistAsset');
} }
// const changeToSettingsPage = () => {
// store.commit('changeToSettings');
// if (changeToSet.value) {
// store.commit('toggleChangeToSet');
// }
// console.log('set')
// }
// watch(changeToSet, changeToSettingsPage)
onMounted(() => { onMounted(() => {
store.commit('changeToAssetlist') store.commit('changeToAssetlist')
if (changeToSet.value) {
store.commit('toggleChangeToSet');
store.commit('changeToSettings');
}
}); });
</script> </script>

View File

@ -1,29 +1,98 @@
<template> <template>
<header :class="[darkMode ? 'header-darkmode' : 'header-lightmode']"> <header :class="[darkMode ? 'header-darkmode' : 'header-lightmode']">
<img id="header-logo" loading="lazy" src="/tüit-logo.svg.png" /> <img id="header-logo" loading="lazy" src="/tüit-logo.svg.png" />
<div class="profile"> <router-link v-if="visibilityBool" to="/settings" class="button"
<pre :class="['username', darkMode ? 'username-darkmode' : 'username-lightmode']" id='uname'>username</pre> :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" @click="goToSettings">
<div :class="['picture', darkMode ? 'picture-darkmode' : 'picture-lightmode']"> <div v-if="visibilityBool" class="profile">
<img id="picture" loading="lazy" src="" /> <pre :class="['username', darkMode ? 'username-darkmode' : 'username-lightmode']"
id='username'>{{ loggedInUserUsername }}</pre>
<div v-if="visibilityBool"
:class="['picture', visibilityBool && !darkMode ? 'picture-loggedin-lightmode' : '', !visibilityBool && !darkMode ? 'picture-not-loggedin-lightmode' : '', visibilityBool && darkMode ? 'picture-loggedin-darkmode' : '', !visibilityBool && darkMode ? 'picture-not-loggedin-darkmode' : '']">
<img id="picture" loading="lazy" src="" />
</div>
</div> </div>
</div> </router-link>
</header> </header>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { ref, watch, onMounted } from 'vue';
import { useStore } from 'vuex';
const store = useStore();
const loggedInUserUsername = ref('');
const loggedInBool = ref(false);
const visibilityBool = computed(() => loggedInBool.value);
const storeChanged = computed(() => store.state.localStorageChanged);
const route = useRoute()
const id = computed(() => route)
const darkMode = ref(true) const darkMode = ref(true)
const username = ref('username');
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
const goToSettings = () => {
store.commit('resetStore');
store.commit('toggleChangeToSet');
store.commit('changeToSettings');
};
const getSession = async () => {
if ((!(id.value.fullPath == '/login')) && (!(id.value.fullPath == '/settings'))) {
loggedInBool.value = false;
loggedInBool.value = getItem('logged-in-bool');
loggedInUserUsername.value = getItem('logged-in-user-username');
}
if (storeChanged.value) {
loggedInBool.value = getItem('logged-in-bool');
loggedInUserUsername.value = getItem('logged-in-user-username');
store.commit('resetLocalStorageChanged');
}
}
const checkPath = async () => {
if (id.value.fullPath == '/login') {
loggedInBool.value = false;
localStorage.setItem('logged-in-bool', false);
localStorage.removeItem('logged-in-user-id');
localStorage.removeItem('logged-in-user-username');
localStorage.removeItem('logged-in-user-registered');
localStorage.removeItem('logged-in-user-lastLogin');
localStorage.removeItem('logged-in-user-fullName');
localStorage.removeItem('logged-in-user-email');
localStorage.removeItem('logged-in-user-phonenumber');
localStorage.removeItem('logged-in-user-address');
localStorage.removeItem('logged-in-user-city');
localStorage.removeItem('logged-in-user-postcode');
localStorage.removeItem('logged-in-user-adminBool');
localStorage.removeItem('logged-in-user-technicianBool');
localStorage.removeItem('logged-in-user-readerBool'); store.commit('logout');
}
}
watch(storeChanged, getSession);
watch(visibilityBool, getSession);
onMounted(async () => {
await checkPath();
await getSession();
});
</script> </script>
<script> <script>
export default { export default {
name: "PageHeader", name: "PageHeader",
} }
</script> </script>
@ -90,6 +159,10 @@ header {
color: #000000; color: #000000;
} }
.pre#username {
text-decoration: none;
}
.picture { .picture {
display: flex; display: flex;
width: 1.875rem; width: 1.875rem;
@ -97,11 +170,19 @@ header {
border-radius: 50%; border-radius: 50%;
} }
.picture-darkmode { .picture-loggedin-darkmode {
background-color: #ffffff; background-color: #ffffff;
} }
.picture-lightmode { .picture-not-loggedin-darkmode {
background-color: #212121;
}
.picture-loggedin-lightmode {
background-color: #000000; background-color: #000000;
} }
.picture-not-loggedin-lightmode {
background-color: #ebebeb;
}
</style> </style>

View File

@ -10,7 +10,6 @@
import PageHeader from "../layouts/PageHeader.vue"; import PageHeader from "../layouts/PageHeader.vue";
const darkMode = ref(true) const darkMode = ref(true)
</script> </script>
<script> <script>

View File

@ -21,7 +21,7 @@ export default defineNuxtConfig({
type: 'refresh', type: 'refresh',
endpoints: { endpoints: {
signIn: { path: '/login', method: 'post' }, signIn: { path: '/login', method: 'post' },
signout: false, signOut: { path: '/logout', method: 'get' },
signUp: { path: '/signup', method: 'post' }, signUp: { path: '/signup', method: 'post' },
getSession: { path: '/session', method: 'get' }, getSession: { path: '/session', method: 'get' },
refresh: { path: '/refresh', method: 'post' } refresh: { path: '/refresh', method: 'post' }

19
package-lock.json generated
View File

@ -23,6 +23,7 @@
"typescript": "^5.3.3", "typescript": "^5.3.3",
"uuid": "^9.0.1", "uuid": "^9.0.1",
"vite": "^5.1.0", "vite": "^5.1.0",
"vue-input-autowidth": "^1.0.11",
"vue-tsc": "^2.0.5", "vue-tsc": "^2.0.5",
"vuex": "^4.1.0" "vuex": "^4.1.0"
}, },
@ -5260,6 +5261,11 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/es6-object-assign": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz",
"integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw=="
},
"node_modules/esbuild": { "node_modules/esbuild": {
"version": "0.20.1", "version": "0.20.1",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.1.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.1.tgz",
@ -8404,6 +8410,11 @@
} }
} }
}, },
"node_modules/nuxt-storage": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/nuxt-storage/-/nuxt-storage-1.2.2.tgz",
"integrity": "sha512-quJbZ87NO7QRCSp7YZolot6VwktciSLuTS/sRl8NPz5rAWA84U5Py0y9FmAsbKTiaqJtFcCKSaJGzky948jA3w=="
},
"node_modules/nuxt/node_modules/estree-walker": { "node_modules/nuxt/node_modules/estree-walker": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
@ -12648,6 +12659,14 @@
"integrity": "sha512-RutnB7X8c5hjq39NceArgXg28WZtZpGc3+J16ljMiYnFhKvd8hITxSWQSQ5bvldxMDU6gG5mkxl1MTQLXckVSQ==", "integrity": "sha512-RutnB7X8c5hjq39NceArgXg28WZtZpGc3+J16ljMiYnFhKvd8hITxSWQSQ5bvldxMDU6gG5mkxl1MTQLXckVSQ==",
"dev": true "dev": true
}, },
"node_modules/vue-input-autowidth": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/vue-input-autowidth/-/vue-input-autowidth-1.0.11.tgz",
"integrity": "sha512-uwIUHBRfueDacjjS7/lTXMHE6bDRA/RH/Jgg7WnM+Z3NnOMXlOz3hMOOBPqZZn13dT78Pc835RX8eX+Z6qNG/w==",
"dependencies": {
"es6-object-assign": "^1.1.0"
}
},
"node_modules/vue-router": { "node_modules/vue-router": {
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.3.0.tgz", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.3.0.tgz",

View File

@ -37,6 +37,7 @@
"typescript": "^5.3.3", "typescript": "^5.3.3",
"uuid": "^9.0.1", "uuid": "^9.0.1",
"vite": "^5.1.0", "vite": "^5.1.0",
"vue-input-autowidth": "^1.0.11",
"vue-tsc": "^2.0.5", "vue-tsc": "^2.0.5",
"vuex": "^4.1.0" "vuex": "^4.1.0"
} }

View File

@ -8,7 +8,8 @@
<div id="content-body"> <div id="content-body">
<EmployeeSearch v-if="onEmployeelist" /> <EmployeeSearch v-if="onEmployeelist" />
<Employeetable v-if="onEmployeelist" /> <Employeetable v-if="onEmployeelist" />
<Asset v-if="onEmployee" /> <Employee v-if="onEmployee" />
<EmployeeGroups v-if="onEmployee" />
</div> </div>
</section> </section>
</template> </template>
@ -19,7 +20,8 @@
import EmployeeSearch from "../components/EmployeeSearch.vue"; import EmployeeSearch from "../components/EmployeeSearch.vue";
import Employeetable from "../components/server/EmployeeTable.vue"; import Employeetable from "../components/server/EmployeeTable.vue";
import Asset from "../components/server/Asset.vue"; import Employee from "../components/server/Employee.vue";
import EmployeeGroups from "../components/server/EmployeeGroups.vue";
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { computed } from 'vue'; import { computed } from 'vue';

View File

@ -10,8 +10,8 @@
</div> </div>
</section> </section>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { ref } from 'vue';
@ -24,16 +24,16 @@ definePageMeta({
title: 'Home' title: 'Home'
}) })
const darkMode = ref(true) const darkMode = ref(true);
</script> </script>
<script> <script>
export default { export default {
name: "HomePage", name: "HomePage",
} }
</script> </script>
<style> <style>
* { * {
box-sizing: border-box; box-sizing: border-box;

View File

@ -1,7 +1,7 @@
<template> <template>
<section id="content"> <section id="content">
<div id="content-header"> <div id="content-header">
<pre :class="[darkMode ? 'pre-darkmode' : 'pre-lightmode']" id="page-name"> </pre> <pre :class="[darkMode ? 'pre-darkmode' : 'pre-lightmode']" id="page-name-login"></pre>
</div> </div>
<div id="content-body"> <div id="content-body">
<LoginForm /> <LoginForm />
@ -59,7 +59,8 @@ export default {
height: 3.125rem; height: 3.125rem;
} }
#page-name { #page-name-login {
text-decoration: none;
letter-spacing: 5%; letter-spacing: 5%;
font: 400 1.5rem/125% Overpass, -apple-system, Roboto, Helvetica, sans-serif; font: 400 1.5rem/125% Overpass, -apple-system, Roboto, Helvetica, sans-serif;
} }

View File

@ -39,8 +39,8 @@
</div> </div>
</section> </section>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { ref } from 'vue';
@ -75,15 +75,15 @@ const defaultMasterChecklistPage = () => {
store.commit('changeToTemplatelist') store.commit('changeToTemplatelist')
} }
</script> </script>
<script> <script>
export default { export default {
name: "MaintenanceVisitsPage", name: "MaintenanceVisitsPage",
} }
</script> </script>
<style scoped> <style scoped>
* { * {
box-sizing: border-box; box-sizing: border-box;
@ -115,6 +115,7 @@ export default {
letter-spacing: 5%; letter-spacing: 5%;
font: 400 1.5rem/125% Overpass, -apple-system, Roboto, Helvetica, font: 400 1.5rem/125% Overpass, -apple-system, Roboto, Helvetica,
sans-serif; sans-serif;
text-decoration: none;
} }
#active-page-name { #active-page-name {

View File

@ -27,20 +27,20 @@
</router-link> </router-link>
</div> </div>
<div id="content-body"> <div id="content-body">
<CustomerSearch v-if="onTemplatelist"/> <CustomerSearch v-if="onTemplatelist" />
<ProductionOrdersTemplateTable v-if="onTemplatelist"/> <ProductionOrdersTemplateTable v-if="onTemplatelist" />
<!-- <ProductionOrdersTemplateTableNoCustomer v-if="onCustomerTemplatelist"/> --> <!-- <ProductionOrdersTemplateTableNoCustomer v-if="onCustomerTemplatelist"/> -->
<ProductionOrdersTemplate v-if="onTemplate"/> <ProductionOrdersTemplate v-if="onTemplate" />
<TemplateChecklist v-if="onTemplate"/> <TemplateChecklist v-if="onTemplate" />
<TemplateSearch v-if="onInstancelist"/> <TemplateSearch v-if="onInstancelist" />
<ProductionOrdersInstanceTable v-if="onInstancelist"/> <ProductionOrdersInstanceTable v-if="onInstancelist" />
<ProductionOrdersInstance v-if="onInstance"/> <ProductionOrdersInstance v-if="onInstance" />
<InstanceChecklist v-if="onInstance"/> <InstanceChecklist v-if="onInstance" />
</div> </div>
</section> </section>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { ref } from 'vue';
@ -75,14 +75,14 @@ const defaultMasterChecklistPage = () => {
store.commit('changeToTemplatelist') store.commit('changeToTemplatelist')
} }
</script> </script>
<script> <script>
export default { export default {
name: "ProductionOrdersPage", name: "ProductionOrdersPage",
} }
</script> </script>
<style scoped> <style scoped>
* { * {
box-sizing: border-box; box-sizing: border-box;
@ -114,6 +114,7 @@ export default {
letter-spacing: 5%; letter-spacing: 5%;
font: 400 1.5rem/125% Overpass, -apple-system, Roboto, Helvetica, font: 400 1.5rem/125% Overpass, -apple-system, Roboto, Helvetica,
sans-serif; sans-serif;
text-decoration: none;
} }
#active-page-name { #active-page-name {

View File

@ -6,37 +6,39 @@
<div id="content-body"> <div id="content-body">
<div class="buttonOptions"> <div class="buttonOptions">
<input :class="[(darkMode && accountSelected) ? 'selected-input-darkmode' : '', <input :class="[(darkMode && accountSelected) ? 'selected-input-darkmode' : '',
(darkMode && !accountSelected) ? 'input-darkmode' : '', (darkMode && !accountSelected) ? 'input-darkmode' : '',
(!darkMode && accountSelected) ? 'selected-input-lightmode' : '', (!darkMode && accountSelected) ? 'selected-input-lightmode' : '',
(!darkMode && !accountSelected) ? 'input-lightmode' : '',]" type="button" id="account" value="Account" (!darkMode && !accountSelected) ? 'input-lightmode' : '',]" type="button" id="account" value="Account"
@click="ActivateAccount"> @click="ActivateAccount">
<input :class="[(darkMode && appearanceSelected) ? 'selected-input-darkmode' : '', <input :class="[(darkMode && appearanceSelected) ? 'selected-input-darkmode' : '',
(darkMode && !appearanceSelected) ? 'input-darkmode' : '', (darkMode && !appearanceSelected) ? 'input-darkmode' : '',
(!darkMode && appearanceSelected) ? 'selected-input-lightmode' : '', (!darkMode && appearanceSelected) ? 'selected-input-lightmode' : '',
(!darkMode && !appearanceSelected) ? 'input-lightmode' : '',]" type="button" id="appearance" (!darkMode && !appearanceSelected) ? 'input-lightmode' : '',]" type="button" id="appearance"
value="Appearance" @click="ActivateAppearance"> value="Appearance" @click="ActivateAppearance">
<input :class="[(darkMode && usersSelected) ? 'selected-input-darkmode' : '', <input :class="[(darkMode) ? 'input-darkmode' : '',
(darkMode && !usersSelected) ? 'input-darkmode' : '', (!darkMode) ? 'input-lightmode' : '',]" type="button" id="logout" value="Logout" @click="handleLogout">
(!darkMode && usersSelected) ? 'selected-input-lightmode' : '',
(!darkMode && !usersSelected) ? 'input-lightmode' : '',]" type="button" id="users" value="Users"
@click="ActivateUsers">
</div> </div>
<UserProfile v-if="accountSelected"/> <UserProfile v-if="accountSelected" />
<UserAccount v-if="accountSelected"/> <UserAccount v-if="accountSelected" />
<UserAppearance v-if="appearanceSelected"/> <UserAppearance v-if="appearanceSelected" />
<UserRightsList v-if="usersSelected"/> <!-- <UserRightsList v-if="usersSelected"/> -->
</div> </div>
</section> </section>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { ref } from 'vue';
import UserProfile from "../components/server/UserProfile.vue"; import UserProfile from "../components/server/UserProfile.vue";
import UserAccount from "../components/server/UserAccount.vue"; import UserAccount from "../components/server/UserAccount.vue";
import UserAppearance from "../components/server/UserAppearance.vue"; import UserAppearance from "../components/server/UserAppearance.vue";
import UserRightsList from "../components/server/UserRightsList.vue"; // import UserRightsList from "../components/server/UserRightsList.vue";
import { useStore } from "vuex";
const store = useStore();
const { signOut } = useAuth()
definePageMeta({ definePageMeta({
layout: 'default', layout: 'default',
@ -47,33 +49,54 @@ const darkMode = ref(true)
const accountSelected = ref(true) const accountSelected = ref(true)
const appearanceSelected = ref(false) const appearanceSelected = ref(false)
const usersSelected = ref(false)
const handleLogout = async () => {
localStorage.setItem('logged-in-bool', false);
localStorage.removeItem('logged-in-user-id');
localStorage.removeItem('logged-in-user-username');
localStorage.removeItem('logged-in-user-registered');
localStorage.removeItem('logged-in-user-lastLogin');
localStorage.removeItem('logged-in-user-fullName');
localStorage.removeItem('logged-in-user-email');
localStorage.removeItem('logged-in-user-phonenumber');
localStorage.removeItem('logged-in-user-address');
localStorage.removeItem('logged-in-user-city');
localStorage.removeItem('logged-in-user-postcode');
localStorage.removeItem('logged-in-user-adminBool');
localStorage.removeItem('logged-in-user-technicianBool');
localStorage.removeItem('logged-in-user-readerBool');
store.commit('resetChangeToSet');
store.commit('setLocalStorageChanged');
let res = await signOut({ callbackUrl: '/login' })
store.commit('resetStore');
store.commit('logout');
}
// fuctions to change the option button // fuctions to change the option button
const ActivateAccount = () => { const ActivateAccount = () => {
accountSelected.value = true; accountSelected.value = true;
appearanceSelected.value = false; appearanceSelected.value = false;
usersSelected.value = false; // usersSelected.value = false;
}; };
const ActivateAppearance = () => { const ActivateAppearance = () => {
accountSelected.value = false; accountSelected.value = false;
appearanceSelected.value = true; appearanceSelected.value = true;
usersSelected.value = false; // usersSelected.value = false;
};
const ActivateUsers = () => {
accountSelected.value = false;
appearanceSelected.value = false;
usersSelected.value = true;
}; };
// const ActivateUsers = () => {
// accountSelected.value = false;
// appearanceSelected.value = false;
// usersSelected.value = true;
// };
</script> </script>
<script> <script>
export default { export default {
name: "SettingsPage", name: "SettingsPage",
} }
</script> </script>
<style> <style>
* { * {
box-sizing: border-box; box-sizing: border-box;
@ -131,7 +154,7 @@ export default {
input#account, input#account,
input#appearance, input#appearance,
input#users { input#logout {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
@ -157,6 +180,10 @@ input#users {
background-color: #454545; background-color: #454545;
} }
input#logout:hover {
background-color: #454545;
}
.input-lightmode { .input-lightmode {
color: #000; color: #000;
background-color: #E4E4E4; background-color: #E4E4E4;

View File

@ -132,6 +132,32 @@ const store = createStore({
onEmployeelist: true, onEmployeelist: true,
onEmployee: false, onEmployee: false,
chosenEmployeeId: -1, chosenEmployeeId: -1,
newUsernameEmp: '',
newPasswordEmp: '',
newPasswordRepeatedEmp: '',
newFullNameEmp: '',
newEmailEmp: '',
newPhonenumberEmp: '',
newAddressEmp: '',
newCityEmp: '',
newPostcodeEmp: '',
loggedInUserId: '',
loggedInUserUsername: '',
loggedInUserRegistered: '',
loggedInUserLastLogin: '',
loggedInUserFullName: '',
loggedInUserEmail: '',
loggedInUserPhonenumber: '',
loggedInUserAddress: '',
loggedInUserCity: '',
loggedInUserPostcode: '',
loggedInUserAdminBool: false,
loggedInUserTechnicianBool: false,
loggedInUserReaderBool: false,
localStorageChanged: false,
changeToSet: false,
}; };
}, },
mutations: { mutations: {
@ -139,6 +165,12 @@ const store = createStore({
toggleEditable(state) { toggleEditable(state) {
state.editable = !state.editable state.editable = !state.editable
}, },
toggleChangeToSet(state) {
state.changeToSet = !state.changeToSet
},
resetChangeToSet(state) {
state.changeToSet = false
},
toggleFiltered(state) { toggleFiltered(state) {
if (state.filtered == false) { if (state.filtered == false) {
state.filtered = true state.filtered = true
@ -458,8 +490,8 @@ const store = createStore({
state.addSolutionIcon = false state.addSolutionIcon = false
state.solutionIcon = false state.solutionIcon = false
state.addInstanceIcon = false state.addInstanceIcon = false
state.filterIcon = true state.filterIcon = false
state.searchIcon = true state.searchIcon = false
state.instancesIcon = false state.instancesIcon = false
state.attachmentsIcon = false state.attachmentsIcon = false
state.sellIcon = false state.sellIcon = false
@ -522,6 +554,21 @@ const store = createStore({
state.deleteIcon = true state.deleteIcon = true
}, },
changeToSettings(state) {
state.addIcon = false
state.addSolutionIcon = false
state.solutionIcon = false
state.addInstanceIcon = false
state.filterIcon = false
state.searchIcon = false
state.instancesIcon = false
state.attachmentsIcon = false
state.sellIcon = false
state.archiveIcon = false
state.editIcon = true
state.deleteIcon = false
},
// functions to update the asset // functions to update the asset
updateAssetComponent(state, asset) { updateAssetComponent(state, asset) {
state.newAssetName = asset.assetName state.newAssetName = asset.assetName
@ -629,6 +676,56 @@ const store = createStore({
state.newPropertiesII = is.properties state.newPropertiesII = is.properties
}, },
// functions to update the employee component
updateEmployeeComponent(state, employee) {
state.newUsernameEmp = employee.username
state.newPasswordEmp = employee.password
state.newPasswordRepeatedEmp = employee.passwordRepeated
state.newFullNameEmp = employee.fullName
state.newEmailEmp = employee.email
state.newPhonenumberEmp = employee.phonenumber
state.newAddressEmp = employee.address
state.newCityEmp = employee.city
state.newPostcodeEmp = employee.postcode
},
setLocalStorageChanged(state) {
state.localStorageChanged = true
},
resetLocalStorageChanged(state) {
state.localStorageChanged = false
},
// function to set the logged in user
setLoggedInUser(state, user) {
state.loggedInUserId = user.id
state.loggedInUserUsername = user.username
state.loggedInUserRegistered = user.registered
state.loggedInUserLastLogin = user.lastLogin
state.loggedInUserFullName = user.fullName
state.loggedInUserEmail = user.email
state.loggedInUserPhonenumber = user.phonenumber
state.loggedInUserAddress = user.address
state.loggedInUserCity = user.city
state.loggedInUserPostcode = user.postcode
if (user.adminBool == 1) {
state.loggedInUserAdminBool = true
} else {
state.loggedInUserAdminBool = false
}
if (user.technicianBool == 1) {
state.loggedInUserTechnicianBool = true
} else {
state.loggedInUserTechnicianBool = false
}
if (user.readerBool == 1) {
state.loggedInUserReaderBool = true
} else {
state.loggedInUserReaderBool = false
}
},
// function to set the chosen asset // function to set the chosen asset
setChosenAsset(state, id) { setChosenAsset(state, id) {
state.chosenAssetId = id state.chosenAssetId = id
@ -664,8 +761,8 @@ const store = createStore({
state.chosenIssueVariantId = id state.chosenIssueVariantId = id
}, },
// function to set the chosen user // function to set the chosen user
setChosenEmployee(state, id) { setChosenEmployee(state, id) {
state.chosenEmployeeId = id state.chosenEmployeeId = id
}, },
@ -776,6 +873,32 @@ const store = createStore({
// reset the employee page variables // reset the employee page variables
state.chosenEmployeeId = -1 state.chosenEmployeeId = -1
state.newUsernameEmp = ''
state.newPasswordEmp = ''
state.newPasswordRepeatedEmp = ''
state.newFullNameEmp = ''
state.newEmailEmp = ''
state.newPhonenumberEmp = ''
state.newAddressEmp = ''
state.newCityEmp = ''
state.newPostcodeEmp = ''
},
// function to logout
logout(state) {
state.loggedInUserId = ''
state.loggedInUserUsername = ''
state.loggedInUserRegistered = ''
state.loggedInUserLastLogin = ''
state.loggedInUserFullName = ''
state.loggedInUserEmail = ''
state.loggedInUserPhonenumber = ''
state.loggedInUserAddress = ''
state.loggedInUserCity = ''
state.loggedInUserPostcode = ''
state.loggedInUserAdminBool = false
state.loggedInUserTechnicianBool = false
state.loggedInUserReaderBool = false
}, },
// functions to (undo) delete an asset // functions to (undo) delete an asset

View File

@ -2,9 +2,8 @@ import axios, { AxiosError } from 'axios';
import serversideConfig from '../../../serversideConfig'; import serversideConfig from '../../../serversideConfig';
import https from 'https'; import https from 'https';
let loggedInUser = {};
let errorMsg = 'error'; let errorMsg = 'error';
//const { data } = useAuthState()
export default eventHandler(async (event) => { export default eventHandler(async (event) => {
@ -29,20 +28,19 @@ export default eventHandler(async (event) => {
password: body.password, password: body.password,
}); });
const sessionToken = res.data.token; const sessionToken = res.data.token;
const user = res.data.user; loggedInUser = res.data.user;
console.log('sessionToken: ', sessionToken); // console.log('sessionToken: ', sessionToken);
console.log('user: ', user);
setResponseStatus(event, 200); setResponseStatus(event, 200);
const resBody = { const resBody = {
token: sessionToken, token: sessionToken,
message: 'Login successful' message: 'Login successful',
}; };
console.log('resBody: ', resBody); console.log('resBody: ', resBody);
return resBody; return resBody;
} }
catch (err) { catch (err) {
if (axios.isAxiosError(err)) { if (axios.isAxiosError(err)) {
const axiosError = err as AxiosError; const axiosError = err as AxiosError;
@ -67,8 +65,6 @@ export default eventHandler(async (event) => {
statusCode: 400, statusCode: 400,
statusMessage: errorMsg, statusMessage: errorMsg,
}) })
}) })
@ -93,3 +89,5 @@ export default defineEventHandler(async (event) => {
}; };
return resBody; return resBody;
})*/ })*/
export { loggedInUser, errorMsg };

View File

@ -0,0 +1,3 @@
import { eventHandler } from 'h3'
export default eventHandler(() => ({ status: 'OK ' }))

View File

@ -0,0 +1,23 @@
import { errorMsg } from "../../middleware/employees";
import { OutgoingMessage } from 'http';
export default defineEventHandler(async (event) => {
const headers: Record<string, Parameters<OutgoingMessage['setHeader']>[1]> = {
'Access-Control-Allow-Origin': 'https://tueitapp.tueit.de',
'Access-Control-Allow-Headers': 'authorization, content-type',
'Access-Control-Allow-Methods': 'OPTIONS,GET,HEAD,PUT,PATCH,POST,DELETE',
'Access-Control-Allow-Credentials': 'true',
};
setResponseHeaders(event, headers)
if (!(errorMsg === '')) {
throw createError({
statusCode: 400,
statusMessage: errorMsg,
})
}
setResponseStatus(event, 200)
return
})

View File

@ -0,0 +1,23 @@
import { employee, errorMsg } from "../../middleware/employees";
import { OutgoingMessage } from 'http';
export default defineEventHandler(async (event) => {
const headers: Record<string, Parameters<OutgoingMessage['setHeader']>[1]> = {
'Access-Control-Allow-Origin': 'https://tueitapp.tueit.de',
'Access-Control-Allow-Headers': 'authorization, content-type',
'Access-Control-Allow-Methods': 'OPTIONS,GET,HEAD,PUT,PATCH,POST,DELETE',
'Access-Control-Allow-Credentials': 'true',
};
setResponseHeaders(event, headers)
if (!(errorMsg === '')) {
throw createError({
statusCode: 400,
statusMessage: errorMsg,
})
}
setResponseStatus(event, 200)
return employee
})

16
server/api/login.ts Normal file
View File

@ -0,0 +1,16 @@
import { loggedInUser } from "../api/auth/login";
import { OutgoingMessage } from 'http';
export default defineEventHandler(async (event) => {
const headers: Record<string, Parameters<OutgoingMessage['setHeader']>[1]> = {
'Access-Control-Allow-Origin': 'https://tueitapp.tueit.de',
'Access-Control-Allow-Headers': 'authorization, content-type',
'Access-Control-Allow-Methods': 'GET,HEAD,PUT,PATCH,POST,DELETE',
'Access-Control-Allow-Credentials': 'true',
};
setResponseHeaders(event, headers)
setResponseStatus(event, 200)
return loggedInUser
})

View File

@ -0,0 +1,14 @@
import { errorMsg } from "../middleware/employees";
export default defineEventHandler(async (event) => {
if (!(errorMsg === '')) {
throw createError({
statusCode: 400,
statusMessage: errorMsg,
})
}
setResponseStatus(event, 200)
return errorMsg
})

View File

@ -0,0 +1,14 @@
import { errorMsg } from "../middleware/employees";
export default defineEventHandler(async (event) => {
if (!(errorMsg === '')) {
throw createError({
statusCode: 400,
statusMessage: errorMsg,
})
}
setResponseStatus(event, 200)
return errorMsg
})

View File

@ -3,7 +3,7 @@ import serversideConfig from '../../serversideConfig';
import https from 'https'; import https from 'https';
let employees = []; let employees = [];
let configItem = {}; let employee = {};
let errorMsg = ''; let errorMsg = '';
let selectedEmployeesByEmployee = []; let selectedEmployeesByEmployee = [];
let configItemsFromCustomer = []; let configItemsFromCustomer = [];
@ -51,37 +51,37 @@ export default defineEventHandler(async (event) => {
} }
} }
// if (event.path.startsWith("/api/getConfigItem")) { if (event.path.startsWith("/api/getEmployee")) {
// // get all config items object from backend // get employee object from backend
// let itemId = null; let employeeId = null;
// const path = event._path; const path = event._path;
// const pathSegments = path.split('/'); const pathSegments = path.split('/');
// itemId = pathSegments[pathSegments.length - 1]; employeeId = pathSegments[pathSegments.length - 1];
// try { try {
// let res = await axiosInstance.get(`https://${serversideConfig.url}:${serversideConfig.port}/configItem/${itemId}`); let res = await axiosInstance.get(`https://${serversideConfig.url}:${serversideConfig.port}/user/${employeeId}`);
// configItem = res.data; employee = res.data;
// } catch (err) { } catch (err) {
// if (axios.isAxiosError(err)) { if (axios.isAxiosError(err)) {
// const axiosError = err as AxiosError; const axiosError = err as AxiosError;
// if (axiosError.response) { if (axiosError.response) {
// // Axios error // Axios error
// console.error(axiosError.response.data.message); console.error(axiosError.response.data.message);
// errorMsg = axiosError.response.data.message; errorMsg = axiosError.response.data.message;
// } else if (axiosError.request) { } else if (axiosError.request) {
// // If error was caused by the request // If error was caused by the request
// console.error(axiosError.request); console.error(axiosError.request);
// } else { } else {
// // Other errors // Other errors
// console.error('Error', axiosError.message); console.error('Error', axiosError.message);
// } }
// } else { } else {
// // No AxiosError // No AxiosError
// console.error('Error', err); console.error('Error', err);
// } }
// } }
// } }
// if (event.path.startsWith("/api/getCIFromCustomer")) { // if (event.path.startsWith("/api/getCIFromCustomer")) {
// // get all config items from a customer from backend // // get all config items from a customer from backend
@ -115,93 +115,93 @@ export default defineEventHandler(async (event) => {
// } // }
// } // }
// if (event.path.startsWith("/api/updateConfigItem")) { if (event.path.startsWith("/api/updateEmployee")) {
// const body = await readBody(event) const body = await readBody(event)
// // update the config item in the backend // update the employee in the backend
// try { try {
// let res = await axiosInstance.put(`https://${serversideConfig.url}:${serversideConfig.port}/configItem`, body); let res = await axiosInstance.put(`https://${serversideConfig.url}:${serversideConfig.port}/user`, body);
// } catch (err) { } catch (err) {
// if (axios.isAxiosError(err)) { if (axios.isAxiosError(err)) {
// const axiosError = err as AxiosError; const axiosError = err as AxiosError;
// if (axiosError.response) { if (axiosError.response) {
// // Axios error // Axios error
// console.error(axiosError.response.data.message); console.error(axiosError.response.data.message);
// errorMsg = axiosError.response.data.message; errorMsg = axiosError.response.data.message;
// } else if (axiosError.request) { } else if (axiosError.request) {
// console.log(err) console.log(err)
// // If error was caused by the request // If error was caused by the request
// console.error(axiosError.request); console.error(axiosError.request);
// } else { } else {
// // Other errors // Other errors
// console.error('Error', axiosError.message); console.error('Error', axiosError.message);
// } }
// } else { } else {
// // No AxiosError // No AxiosError
// console.error('Error', err); console.error('Error', err);
// } }
// } }
// } }
// if (event.path.startsWith("/api/addConfigItem")) { if (event.path.startsWith("/api/updatePasswordEmployee")) {
// const body = await readBody(event) const body = await readBody(event)
// // add the config item in the backend // update the employee in the backend
// try { try {
// let res = await axiosInstance.post(`https://${serversideConfig.url}:${serversideConfig.port}/configItems`, body); let res = await axiosInstance.put(`https://${serversideConfig.url}:${serversideConfig.port}/updatePassword`, body);
// } catch (err) { } catch (err) {
// if (axios.isAxiosError(err)) { if (axios.isAxiosError(err)) {
// const axiosError = err as AxiosError; const axiosError = err as AxiosError;
// if (axiosError.response) { if (axiosError.response) {
// // Axios error // Axios error
// console.error(axiosError.response.data.message); console.error(axiosError.response.data.message);
// errorMsg = axiosError.response.data.message; errorMsg = axiosError.response.data.message;
// } else if (axiosError.request) { } else if (axiosError.request) {
// console.log(err) console.log(err)
// // If error was caused by the request // If error was caused by the request
// console.error(axiosError.request); console.error(axiosError.request);
// } else { } else {
// // Other errors // Other errors
// console.error('Error', axiosError.message); console.error('Error', axiosError.message);
// } }
// } else { } else {
// // No AxiosError // No AxiosError
// console.error('Error', err); console.error('Error', err);
// } }
// } }
// } }
// if (event.path.startsWith("/api/deleteConfigItem")) { if (event.path.startsWith("/api/deleteEmployee")) {
// let itemId = null; let employeeId = null;
// const path = event._path; const path = event._path;
// const pathSegments = path.split('/'); const pathSegments = path.split('/');
// itemId = pathSegments[pathSegments.length - 1]; employeeId = pathSegments[pathSegments.length - 1];
// // delete the config item in the backend // delete the user in the backend
// try { try {
// let res = await axiosInstance.delete(`https://${serversideConfig.url}:${serversideConfig.port}/configItems/${itemId}`); let res = await axiosInstance.delete(`https://${serversideConfig.url}:${serversideConfig.port}/user/${employeeId}`);
// } catch (err) { } catch (err) {
// if (axios.isAxiosError(err)) { if (axios.isAxiosError(err)) {
// const axiosError = err as AxiosError; const axiosError = err as AxiosError;
// if (axiosError.response) { if (axiosError.response) {
// // Axios error // Axios error
// console.error(axiosError.response.data.message); console.error(axiosError.response.data.message);
// errorMsg = axiosError.response.data.message; errorMsg = axiosError.response.data.message;
// } else if (axiosError.request) { } else if (axiosError.request) {
// console.log(err) console.log(err)
// // If error was caused by the request // If error was caused by the request
// console.error(axiosError.request); console.error(axiosError.request);
// } else { } else {
// // Other errors // Other errors
// console.error('Error', axiosError.message); console.error('Error', axiosError.message);
// } }
// } else { } else {
// // No AxiosError // No AxiosError
// console.error('Error', err); console.error('Error', err);
// } }
// } }
// } }
if (event.path.startsWith("/api/getSelectedEmployeesByEmployee")) { if (event.path.startsWith("/api/getSelectedEmployeesByEmployee")) {
// get selected employees object by employee from backend // get selected employees object by employee from backend
@ -268,4 +268,4 @@ export default defineEventHandler(async (event) => {
// } // }
}) })
export { employees, configItem, selectedEmployeesByEmployee, selectedConfigItemsByAsset, configItemsFromCustomer, errorMsg }; export { employees, employee, selectedEmployeesByEmployee, selectedConfigItemsByAsset, configItemsFromCustomer, errorMsg };

View File

@ -17,7 +17,7 @@ export default defineEventHandler(async (event) => {
httpsAgent: agent httpsAgent: agent
}); });
if (event.path.startsWith("/signup")) { if (event.path.startsWith("/api/signup")) {
const body = await readBody(event) const body = await readBody(event)
// do the post request in the backend // do the post request in the backend