23 Commits

Author SHA1 Message Date
944b7d0503 implemented rights and fixed some appearance bugs 2024-03-26 22:54:13 +01:00
3f88f6b821 implemented mode change 2024-03-25 23:23:37 +01:00
45a4b58f26 implemented settings and user page (darkmode is still missing) 2024-03-24 21:02:56 +01:00
acb7bb7cb6 implemented userTable 2024-03-15 21:04:53 +01:00
8b237e8080 Merge pull request 'modularActionbar' (#23) from modularActionbar into main
Reviewed-on: jo.kuehner/TueIT_App#23
2024-03-15 19:05:31 +00:00
29fd2e0a15 added right actionbar icons and asset solution list 2024-03-15 20:05:01 +01:00
3613565b39 added bools for actionbar rendering 2024-03-12 20:36:26 +01:00
7af5c0ce0d bugfix credentials 2024-03-12 18:32:35 +01:00
ba8073b6f4 added cors header 2024-03-12 18:14:31 +01:00
acae90ee13 fixed signup and renaming problems 2024-03-12 17:46:44 +01:00
d1bdffb834 resolved missing authstore errors 2024-03-11 20:21:08 +01:00
3f111743ed tried to solve errors 2024-03-11 20:12:39 +01:00
cbc1e73bb0 Merge branch 'AccountingPages' 2024-03-11 19:57:54 +01:00
e56af94a88 implemented accounting pages 2024-03-11 19:44:31 +01:00
9954158475 del dublicate icon 2024-03-11 18:31:49 +01:00
a7bbfea9c1 Merge branch 'authentication' into main 2024-03-11 18:27:29 +01:00
6d6b36bdd9 implemented authentication with sidebase/nuxt-auth 2024-03-11 18:19:11 +01:00
fa29921afe replaced clients/s with customer/s (2) 2024-03-04 20:07:31 +01:00
889eb3571f Merge branch 'main' of https://git.tueit.de/jo.kuehner/TueIT_App into main 2024-03-04 19:31:17 +01:00
6a4a53ce4b replaced client/s with customer/s 2024-03-04 18:43:19 +01:00
3a1e468789 Merge pull request 'mv templates and solutions' (#21) from potInstances into main
Reviewed-on: jo.kuehner/TueIT_App#21
2024-03-04 09:25:46 +00:00
7c19ee9215 implemented authentication 2024-02-29 21:05:08 +01:00
601449d7e0 added page titles and icon 2024-02-27 16:53:28 +01:00
208 changed files with 24455 additions and 4715 deletions

14
app.vue
View File

@ -7,9 +7,21 @@
<script setup> <script setup>
//import { createPinia } from "pinia";
//import piniaPluginPersistedState from "pinia-plugin-persistedstate"
//const layout = "empty";
//const layout = "empty";
//const route = useRoute();
//const pinia = createPinia();
//pinia.use(piniaPluginPersistedState);
useHead({
//title: `Tüit ERP - ${route.meta.title}`,
title: `tüit app`,
link: [{ rel: "icon", type: "image/png", href: "/favicon-gelb-rot-32x32.png" }]
})
</script> </script>

View File

@ -1,14 +1,30 @@
import axios from 'axios'; import axios, {AxiosError} from 'axios';
import clientsideConfig from './clientsideConfig'
//create axios instance //create axios instance
const Axios = axios.create({ const Axios = axios.create({
// baseURL: `https://${serversideConfig.url}:${serversideConfig.port}`, //baseURL: `https://${serversideConfig.url}:${serversideConfig.port}/`,
baseURL: `https://${clientsideConfig.url}:${clientsideConfig.port}/`,
headers: { headers: {
// 'Accept': 'application/json', // 'Accept': 'application/json',
'Content-Type': 'application/json', 'Content-Type': 'application/json',
//Authorization: `Bearer`, //Authorization: `Bearer`,
Accept: "*", Accept: "*",
}, },
withCredentials: true,
credentials: true,
}) })
Axios.interceptors.response.use((response) => response, (error) => {
if (error instanceof AxiosError) {
console.error('Status: ', error.response?.status, '\nHeaders: '. error.response?.headers, '\nMessage: '. error.response?.data.message)
} else { console.error('Error: ', error); };
if (error.response?.status === 403) { window.location.href = '/login'; };
return Promise.reject(error);
});
export default Axios; export default Axios;

View File

@ -5,6 +5,8 @@ import {
deleteIssueById, deleteIssueById,
insertIssue, insertIssue,
getAllIssues, getAllIssues,
getSelectedIssuesByState,
getSelectedIssuesByIssueName,
} from "../models/issuesModel.js"; } from "../models/issuesModel.js";
//get all issues //get all issues
@ -18,6 +20,28 @@ export const showIssues = (req, res) => {
}); });
}; };
//get all selected issues by name
export const showSelectedIssuesByIssueName = (req, res) => {
getSelectedIssuesByIssueName(req.params.id, (err, results) => {
if (err) {
res.send(err);
} else {
res.json(results);
}
});
};
//get all selected issues by state
export const showSelectedIssuesByState = (req, res) => {
getSelectedIssuesByState(req.params.id, (err, results) => {
if (err) {
res.send(err);
} else {
res.json(results);
}
});
};
// Delete issue // Delete issue
export const deleteIssue = (req, res) => { export const deleteIssue = (req, res) => {
const id = req.params.id; const id = req.params.id;

View File

@ -10,6 +10,7 @@ import {
getUserById, getUserById,
updateUserById, updateUserById,
deleteUserById, deleteUserById,
getSelectedUsersByUser,
} from "../models/usersModel.js"; } from "../models/usersModel.js";
//insert user to databased //insert user to databased
@ -40,7 +41,7 @@ export const signUp = async (req, res, next) => {
minute: '2-digit' minute: '2-digit'
}; };
const dateTimeString = currentTime.toLocaleString('de-DE', options); const dateTimeString = currentTime.toLocaleString('de-DE', options);
const results = ownConn.query(`INSERT INTO users(id, username, password, registered, fullName, email, phonenumber, address, city, postcode, adminBool, technician1Bool, technician2Bool, technicianMonitoringBool, merchantBool, internBool) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, const results = ownConn.query(`INSERT INTO users(id, username, password, registered, fullName, email, phonenumber, address, city, postcode, adminBool, technicianBool, readerBool, darkModeBool) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
[ [
uuidv4(), uuidv4(),
req.body.username, req.body.username,
@ -53,11 +54,9 @@ export const signUp = async (req, res, next) => {
req.body.city, req.body.city,
req.body.postcode, req.body.postcode,
req.body.adminBool, req.body.adminBool,
req.body.technician1Bool, req.body.technicianBool,
req.body.technician2Bool, req.body.readerBool,
req.body.technicianMonitoringBool, req.body.darkModeBool,
req.body.merchantBool,
req.body.internBool,
]); ]);
return res.status(201).send({ return res.status(201).send({
message: "Registered!", message: "Registered!",
@ -73,6 +72,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 = ?`;
@ -93,7 +118,15 @@ export const login = async (req, res, next) => {
} }
if (bResult) { if (bResult) {
// password match // password match
const token = jwt.sign( const authtoken = jwt.sign(
{
username: result[0].username,
userId: result[0].id,
},
'SECRETTUEITKEY',
{ expiresIn: '300s' } // 5min
);
const refreshtoken = jwt.sign(
{ {
username: result[0].username, username: result[0].username,
userId: result[0].id, userId: result[0].id,
@ -115,7 +148,7 @@ export const login = async (req, res, next) => {
const results = await ownConn.query(sql1, [dateTimeString, result[0].id]); const results = await ownConn.query(sql1, [dateTimeString, result[0].id]);
return res.status(200).send({ return res.status(200).send({
message: 'Logged in!', message: 'Logged in!',
token, token: { authToken: authtoken, refreshToken: refreshtoken },
user: result[0], user: result[0],
}); });
} }
@ -153,6 +186,18 @@ export const showUserById = (req, res) => {
}); });
}; };
//get all selected users by user
export const showSelectedUsersByUser = (req, res) => {
getSelectedUsersByUser(req.params.id, (err, results) => {
if (err) {
res.send(err);
} else {
res.json(results);
}
});
};
// Update user // Update user
export const updateUser = (req, res) => { export const updateUser = (req, res) => {
const data = req.body; const data = req.body;

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

@ -61,6 +61,7 @@ export const deleteIssueSlipById = async (id, result) => {
try { try {
let sql = `DELETE FROM issueslips WHERE primaryID = ?`; let sql = `DELETE FROM issueslips WHERE primaryID = ?`;
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) {
@ -75,6 +76,7 @@ export const deleteIssueSlipByTicketNo = async (id, result) => {
try { try {
let sql = `DELETE FROM issueslips WHERE ticketNo = ?`; let sql = `DELETE FROM issueslips WHERE ticketNo = ?`;
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) {
@ -87,7 +89,8 @@ export const deleteIssueSlipByTicketNo = async (id, result) => {
//insert issue slip to database //insert issue slip to database
export const insertIssueSlip = async (data, result) => { export const insertIssueSlip = async (data, result) => {
try { try {
const results = await ownConn.query(`INSERT INTO issueslips(customerID, customer, ticketNo, creationDate, lastView, user, notes, supplierRequest, supplierOffer, clientOffer, clientOrder, supplierOrder, ingress, egress, ingressBill, egressBill) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [data.customerID, data.customer, data.ticketNo, data.creationDate, data.lastView, data.user, data.notes, data.supplierRequest, data.supplierOffer, data.clientOffer, data.clientOrder, data.supplierOrder, data.ingress, data.egress, data.ingressBill, data.egressBill]) const results = await ownConn.query(`INSERT INTO issueslips(customerID, customer, ticketNo, creationDate, lastView, user, notes, deliveryAddress, supplierRequestDate, supplierRequest, supplierOfferDate, supplierOffer, clientOfferDate, clientOffer, clientOrderDate, clientOrder, supplierOrderDate, supplierOrder, ingressDate, ingress, egressDate, egress, ingressBillDate, ingressBill, egressBillDate, egressBill) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [data.customerID, data.customer, data.ticketNo, data.creationDate, data.lastView, data.user, data.notes, data.deliveryAddress, data.supplierRequestDate, data.supplierRequest, data.supplierOfferDate, data.supplierOffer, data.clientOfferDate, data.clientOffer, data.clientOrderDate, data.clientOrder, data.supplierOrderDate, data.supplierOrder, data.ingressDate, data.ingress, data.egressDate, data.egress, data.ingressBillDate, data.ingressBill, data.egressBillDate, data.egressBill])
results.insertId = results.insertId.toString();
result(null, results); result(null, results);
} }
catch (err) { catch (err) {
@ -129,8 +132,9 @@ export const getIssueSlipById = async (id, result) => {
export const updateIssueSlipById = async (data, result) => { export const updateIssueSlipById = async (data, result) => {
const id = data.primaryID; const id = data.primaryID;
try { try {
let sql = `UPDATE issueslips SET customerID = ?, customer = ?, ticketNo = ?, creationDate = ?, lastView = ?, user = ?, notes = ?, supplierRequest = ?, supplierOffer = ?, clientOffer = ?, clientOrder = ?, supplierOrder = ?, ingress = ?, egress = ?, ingressBill = ?, egressBill = ? WHERE primaryID = ?`; let sql = `UPDATE issueslips SET customerID = ?, customer = ?, ticketNo = ?, creationDate = ?, lastView = ?, user = ?, notes = ?, deliveryAddress = ?, supplierRequestDate = ?, supplierRequest = ?, supplierOfferDate = ?, supplierOffer = ?, clientOfferDate = ?, clientOffer = ?, clientOrderDate = ?, clientOrder = ?, supplierOrderDate = ?, supplierOrder = ?, ingressDate = ?, ingress = ?, egressDate = ?, egress = ?, ingressBillDate = ?, ingressBill = ?, egressBillDate = ?, egressBill = ? WHERE primaryID = ?`;
const results = await ownConn.query(sql, [data.customerID, data.customer, data.ticketNo, data.creationDate, data.lastView, data.user, data.notes, data.supplierRequest, data.supplierOffer, data.clientOffer, data.clientOrder, data.supplierOrder, data.ingress, data.egress, data.ingressBill, data.egressBill, id]) const results = await ownConn.query(sql, [data.customerID, data.customer, data.ticketNo, data.creationDate, data.lastView, data.user, data.notes, data.deliveryAddress, data.supplierRequestDate, data.supplierRequest, data.supplierOfferDate, data.supplierOffer, data.clientOfferDate, data.clientOffer, data.clientOrderDate, data.clientOrder, data.supplierOrderDate, data.supplierOrder, data.ingressDate, data.ingress, data.egressDate, data.egress, data.ingressBillDate, data.ingressBill, data.egressBillDate, data.egressBill, id])
results.insertId = results.insertId.toString();
result(null, results); result(null, results);
} }
catch (err) { catch (err) {

View File

@ -19,7 +19,7 @@ export const getIssueVariantById = async (id, result) => {
try { try {
let sql = `SELECT * FROM issuevariants WHERE primaryID = ? ORDER BY primaryID ASC`; let sql = `SELECT * FROM issuevariants WHERE primaryID = ? ORDER BY primaryID ASC`;
const results = await ownConn.execute(sql, [id]) const results = await ownConn.execute(sql, [id])
result(null, results); result(null, results[0]);
} }
catch (err) { catch (err) {
// Manage Errors // Manage Errors
@ -62,6 +62,7 @@ export const updateIssueVariantById = async (data, result) => {
const id = data.primaryID; const id = data.primaryID;
let sql = `UPDATE issuevariants SET issueID = ?, name = ? , properties = ?, state = ?, amount = ?, price = ? WHERE primaryID = ?`; let sql = `UPDATE issuevariants SET issueID = ?, name = ? , properties = ?, state = ?, amount = ?, price = ? WHERE primaryID = ?`;
const results = await ownConn.query(sql, [data.issueID, data.name, data.properties, data.state, data.amount, data.price, id]) const results = await ownConn.query(sql, [data.issueID, data.name, data.properties, data.state, data.amount, data.price, id])
results.insertId = results.insertId.toString();
result(null, results); result(null, results);
} }
catch (err) { catch (err) {
@ -77,6 +78,7 @@ export const deleteIssueVariantById = async (id, result) => {
try { try {
let sql = `DELETE FROM issuevariants WHERE primaryID = ?`; let sql = `DELETE FROM issuevariants WHERE primaryID = ?`;
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) {
@ -91,6 +93,7 @@ export const deleteIssueVariantByIssueSlipId = async (id, result) => {
try { try {
let sql = `DELETE FROM issuevariants WHERE issueID = ?`; let sql = `DELETE FROM issuevariants WHERE issueID = ?`;
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) {
@ -104,6 +107,7 @@ export const deleteIssueVariantByIssueSlipId = async (id, result) => {
export const insertIssueVariant = async (data, result) => { export const insertIssueVariant = async (data, result) => {
try { try {
const results = await ownConn.query(`INSERT INTO issuevariants(issueID, name, properties, state, amount, price) VALUES(?, ?, ?, ?, ?, ?)`, [data.issueID, data.name, data.properties, data.state, data.amount, data.price]) const results = await ownConn.query(`INSERT INTO issuevariants(issueID, name, properties, state, amount, price) VALUES(?, ?, ?, ?, ?, ?)`, [data.issueID, data.name, data.properties, data.state, data.amount, data.price])
results.insertId = results.insertId.toString();
result(null, results); result(null, results);
} }
catch (err) { catch (err) {

View File

@ -14,12 +14,40 @@ export const getAllIssues = async (result) => {
} }
}; };
//get all selected issues by state
export const getSelectedIssuesByState = async (selected, result) => {
try {
let sql = `SELECT * FROM issues WHERE state LIKE '%${selected}%' ORDER BY state ASC`;
const results = await ownConn.execute(sql)
result(null, results);
}
catch (err) {
// Manage Errors
console.log("SQL error : ", err);
result(err, null);
}
};
//get all selected issues by issue name
export const getSelectedIssuesByIssueName = async (selected, result) => {
try {
let sql = `SELECT * FROM issues WHERE name LIKE '%${selected}%' ORDER BY name ASC`;
const results = await ownConn.execute(sql)
result(null, results);
}
catch (err) {
// Manage Errors
console.log("SQL error : ", err);
result(err, null);
}
};
//get single issue //get single issue
export const getIssueById = async (id, result) => { export const getIssueById = async (id, result) => {
try { try {
let sql = `SELECT * FROM issues WHERE primaryID = ? ORDER BY primaryID ASC`; let sql = `SELECT * FROM issues WHERE primaryID = ? ORDER BY primaryID ASC`;
const results = await ownConn.execute(sql, [id]) const results = await ownConn.execute(sql, [id])
result(null, results); result(null, results[0]);
} }
catch (err) { catch (err) {
// Manage Errors // Manage Errors
@ -34,6 +62,7 @@ export const updateIssueById = async (data, result) => {
const id = data.primaryID; const id = data.primaryID;
let sql = `UPDATE issues SET name = ?, type = ? , state = ?, amount = ?, properties = ? WHERE primaryID = ?`; let sql = `UPDATE issues SET name = ?, type = ? , state = ?, amount = ?, properties = ? WHERE primaryID = ?`;
const results = await ownConn.query(sql, [data.name, data.type, data.state, data.amount, data.properties, id]) const results = await ownConn.query(sql, [data.name, data.type, data.state, data.amount, data.properties, id])
results.insertId = results.insertId.toString();
result(null, results); result(null, results);
} }
catch (err) { catch (err) {
@ -48,6 +77,7 @@ export const deleteIssueById = async (id, result) => {
try { try {
let sql = `DELETE FROM issues WHERE primaryID = ?`; let sql = `DELETE FROM issues WHERE primaryID = ?`;
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) {
@ -61,6 +91,7 @@ export const deleteIssueById = async (id, result) => {
export const insertIssue = async (data, result) => { export const insertIssue = async (data, result) => {
try { try {
const results = await ownConn.query(`INSERT INTO issues(name, type, state, amount, properties) VALUES(?, ?, ?, ?, ?)`, [data.name, data.type, data.state, data.amount, data.properties]) const results = await ownConn.query(`INSERT INTO issues(name, type, state, amount, properties) VALUES(?, ?, ?, ?, ?)`, [data.name, data.type, data.state, data.amount, data.properties])
results.insertId = results.insertId.toString();
result(null, results); result(null, results);
} }
catch (err) { catch (err) {

View File

@ -20,6 +20,7 @@ export const updateOrderingInfoIssueSlipById = async (data, result) => {
const id = data.primaryID; const id = data.primaryID;
let sql = `UPDATE orderinginfoissueslips SET issueSlipID = ?, article = ? , amount = ?, price = ?, comment = ? WHERE primaryID = ?`; let sql = `UPDATE orderinginfoissueslips SET issueSlipID = ?, article = ? , amount = ?, price = ?, comment = ? WHERE primaryID = ?`;
const results = await ownConn.query(sql, [data.issueSlipID, data.article, data.amount, data.price, data.comment, id]) const results = await ownConn.query(sql, [data.issueSlipID, data.article, data.amount, data.price, data.comment, id])
results.insertId = results.insertId.toString();
result(null, results); result(null, results);
} }
catch (err) { catch (err) {
@ -35,6 +36,7 @@ export const deleteOrderingInfoIssueSlipById = async (id, result) => {
try { try {
let sql = `DELETE FROM orderinginfoissueslips WHERE primaryID = ?`; let sql = `DELETE FROM orderinginfoissueslips WHERE primaryID = ?`;
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) {
@ -49,6 +51,7 @@ export const deleteOrderingInfoIssueSlipByIssueSlipId = async (id, result) => {
try { try {
let sql = `DELETE FROM orderinginfoissueslips WHERE issueSlipID = ?`; let sql = `DELETE FROM orderinginfoissueslips WHERE issueSlipID = ?`;
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) {
@ -62,6 +65,7 @@ export const deleteOrderingInfoIssueSlipByIssueSlipId = async (id, result) => {
export const insertOrderingInfoIssueSlip = async (data, result) => { export const insertOrderingInfoIssueSlip = async (data, result) => {
try { try {
const results = await ownConn.query(`INSERT INTO orderinginfoissueslips(issueSlipID, article, amount, price, comment) VALUES(?, ?, ?, ?, ?)`, [data.issueSlipID, data.article, data.amount, data.price, data.comment]) const results = await ownConn.query(`INSERT INTO orderinginfoissueslips(issueSlipID, article, amount, price, comment) VALUES(?, ?, ?, ?, ?)`, [data.issueSlipID, data.article, data.amount, data.price, data.comment])
results.insertId = results.insertId.toString();
result(null, results); result(null, results);
} }
catch (err) { catch (err) {

View File

@ -103,8 +103,8 @@ export const getSelectedSolutionsBySolutionName = async (selected, result) => {
//get all selected solutions by asset name //get all selected solutions by asset name
export const getSelectedSolutionsByAssetName = async (selected, result) => { export const getSelectedSolutionsByAssetName = async (selected, result) => {
try { try {
let sql = `SELECT * FROM solutions WHERE LOWER(assetName) LIKE '%${selected.toLowerCase()}%' ORDER BY assetName ASC`; let sql = `SELECT * FROM solutions WHERE assetName = ? ORDER BY solutionName ASC`;
const results = await ownConn.execute(sql) const results = await ownConn.execute(sql, [selected])
result(null, results); result(null, results);
} }
catch (err) { catch (err) {

View File

@ -28,12 +28,11 @@ export const getUserById = async (id, result) => {
} }
}; };
// Update user to Database //get all selected users by full name
export const updateUserById = async (data, result) => { export const getSelectedUsersByUser = async (selected, result) => {
try { try {
const id = data.id; let sql = `SELECT * FROM users WHERE LOWER(fullName) LIKE '%${selected.toLowerCase()}%' ORDER BY fullName ASC`;
let sql = `UPDATE users SET username = ?, password = ?, fullName = ?, email = ?, phonenumber = ?, address = ?, city = ?, postcode = ?, adminBool = ?, technician1Bool = ?, technician2Bool = ?, technicianMonitoringBool = ?, merchantBool = ?, internBool = ? WHERE id = ?`; const results = await ownConn.execute(sql)
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.technician1Bool, data.technician2Bool, data.technicianMonitoringBool, data.merchantBool, data.internBool, id]);
result(null, results); result(null, results);
} }
catch (err) { catch (err) {
@ -43,12 +42,28 @@ export const updateUserById = async (data, result) => {
} }
}; };
// Update user to Database
export const updateUserById = async (data, result) => {
try {
const id = data.id;
let sql = `UPDATE users SET username = ?, fullName = ?, email = ?, phonenumber = ?, address = ?, city = ?, postcode = ?, adminBool = ?, technicianBool = ?, readerBool = ?, darkModeBool = ? WHERE 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, data.darkModeBool, id]);
results.insertId = results.insertId.toString();
result(null, results);
}
catch (err) {
// Manage Errors
console.log("SQL error : ", err);
result(err, null);
}
};
// 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,11 +108,13 @@ import {
import { import {
signUp, signUp,
updatePasswordById,
login, login,
showUsers, showUsers,
showUserById, showUserById,
updateUser, updateUser,
deleteUser, deleteUser,
showSelectedUsersByUser,
} from "../controller/users.js"; } from "../controller/users.js";
import * as userMiddleware from "../middleware/users.js"; import * as userMiddleware from "../middleware/users.js";
@ -166,6 +168,8 @@ import {
showIssueById, showIssueById,
updateIssue, updateIssue,
showIssues, showIssues,
showSelectedIssuesByIssueName,
showSelectedIssuesByState,
} from "../controller/issues.js"; } from "../controller/issues.js";
import { import {
@ -552,6 +556,12 @@ router.get("/issues", showIssues);
//get issue by id //get issue by id
router.get("/issues/:id", showIssueById); router.get("/issues/:id", showIssueById);
//get all issues by selected name
router.get("/selectedIssuesByIssueName/:id", showSelectedIssuesByIssueName)
//get all issues by selected state
router.get("/selectedIssuesByState/:id", showSelectedIssuesByState)
// Update issue // Update issue
router.put("/issues", updateIssue); router.put("/issues", updateIssue);
@ -594,12 +604,18 @@ 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);
// get all users // get all users
router.get("/users", showUsers); router.get("/users", showUsers);
// get all users by user
router.get("/selectedUsersByUser/:id", showSelectedUsersByUser)
//get user by id //get user by id
router.get("/user/:id", showUserById); router.get("/user/:id", showUserById);

View File

@ -1,15 +1,61 @@
<template> <template>
<section :class="['asset-search', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section :class="['asset-search', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Asset:</div> <div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Asset:</div>
<pre :class="['data', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Asset name</pre> <pre :class="['data', darkMode ? 'pre-darkmode' : 'pre-lightmode']">{{ asset.assetName }}</pre>
</section> </section>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; 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 darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const chosenAssetId = computed(() => store.state.chosenAssetId);
const asset = ref({});
const darkMode = ref('');
// get config item from id
const getItemById = async () => {
try {
const response = await Axios.get(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getConfigItem/${chosenAssetId.value}`
);
asset.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
getSession();
await getItemById();
});
</script> </script>
<script> <script>
@ -79,4 +125,3 @@ export default {
color: #000; color: #000;
} }
</style> </style>

View File

@ -1,45 +1,79 @@
<template> <template>
<section :class="['client-search', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section :class="['customer-search', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Customer</div> <div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Customer</div>
<pre v-if="!filtered" :class="['data', darkMode ? 'pre-darkmode' : 'pre-lightmode']">{{ clientFilter }}</pre> <pre v-if="!filtered"
<input v-if="filtered" v-model="clientFilter" @change="filterConfigItemList()" :class="['data', 'pre-customer', darkMode ? 'pre-darkmode' : 'pre-lightmode']">{{ customerFilter }}</pre>
<input v-if="filtered" v-model="customerFilter" @change="filterList()"
:class="['data', 'input-customer', darkMode ? 'data-darkmode' : 'data-lightmode']"> :class="['data', 'input-customer', darkMode ? 'data-darkmode' : 'data-lightmode']">
</section> </section>
</template> </template>
<script setup> <script setup>
import { ref, watch } 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 store = useStore(); const store = useStore();
const filtered = computed(() => store.state.filtered); const modeChanged = computed(() => store.state.updateDarkMode);
const filteredTerm = computed(() => store.state.filteredByClient);
const clientFilter = ref(store.state.filteredByClient);
const darkMode = ref(true) const filtered = computed(() => store.state.filtered);
const filteredTerm = computed(() => store.state.filteredByCustomer);
const customerFilter = ref(store.state.filteredByCustomer);
const darkMode = ref('');
// update filtered term // update filtered term
const updateFilterTerm = () => { const updateFilterTerm = () => {
clientFilter.value = filteredTerm.value customerFilter.value = filteredTerm.value
}
const checkFiltered = () => {
if (!filtered.value) {
customerFilter.value = ''
filterList();
}
} }
// update the filtered term in the store // update the filtered term in the store
const filterConfigItemList = () => { const filterList = () => {
store.commit('updateFilterbyClient', clientFilter.value); store.commit('updateFilterbyCustomer', customerFilter.value);
} }
watch(filteredTerm, updateFilterTerm) watch(filteredTerm, updateFilterTerm)
watch(filtered, checkFiltered)
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>
export default { export default {
name: "ClientSearch", name: "CustomerSearch",
}; };
</script> </script>
<style scoped> <style scoped>
.client-search { .customer-search {
display: flex; display: flex;
align-items: center; align-items: center;
padding: 0.625em 1.875em; padding: 0.625em 1.875em;
@ -103,6 +137,10 @@ export default {
margin-left: 1rem; margin-left: 1rem;
} }
.pre-customer {
margin-left: 1rem;
}
.data-darkmode { .data-darkmode {
background-color: #212121; background-color: #212121;
color: #fff; color: #fff;

View File

@ -6,7 +6,8 @@
value="My Maintenance Visits"> value="My Maintenance Visits">
<input :class="[darkMode ? 'input-darkmode' : 'input-lightmode']" type="button" id="production-orders" <input :class="[darkMode ? 'input-darkmode' : 'input-lightmode']" type="button" id="production-orders"
value="My Production Orders"> value="My Production Orders">
<input :class="[darkMode ? 'input-darkmode' : 'input-lightmode']" type="button" id="solutions" value="My Solutions"> <input :class="[darkMode ? 'input-darkmode' : 'input-lightmode']" type="button" id="solutions"
value="My Solutions">
<input :class="[darkMode ? 'input-darkmode' : 'input-lightmode']" type="button" id="issue-slips" <input :class="[darkMode ? 'input-darkmode' : 'input-lightmode']" type="button" id="issue-slips"
value="My Issue Slips"> value="My Issue Slips">
</div> </div>
@ -15,9 +16,41 @@
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const modeChangedLocalstorage = computed(() => store.state.modeDashboard);
const darkMode = ref('');
const getSession = async () => {
if (modeChangedLocalstorage.value) {
store.commit('resetModeDashboardChanged');
}
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
watch(modeChangedLocalstorage, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>

View File

@ -0,0 +1,153 @@
<template>
<section :class="['employee-search', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Employee</div>
<pre v-if="!filtered"
:class="['data', 'pre-customer', darkMode ? 'pre-darkmode' : 'pre-lightmode']">{{ employeeFilter }}</pre>
<input v-if="filtered" v-model="employeeFilter" @change="filterList()"
:class="['data', 'input-customer', darkMode ? 'data-darkmode' : 'data-lightmode']">
</section>
</template>
<script setup>
import { ref, watch, onMounted } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const filtered = computed(() => store.state.filtered);
const filteredTerm = computed(() => store.state.filteredByCustomer);
const employeeFilter = ref(store.state.filteredByCustomer);
const darkMode = ref('');
// update filtered term
const updateFilterTerm = () => {
employeeFilter.value = filteredTerm.value
}
const checkFiltered = () => {
if (!filtered.value) {
employeeFilter.value = ''
filterList();
}
}
// update the filtered term in the store
const filterList = () => {
store.commit('updateFilterbyCustomer', employeeFilter.value);
}
watch(filteredTerm, updateFilterTerm)
watch(filtered, checkFiltered)
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script>
<script>
export default {
name: "EmployeeSearch",
};
</script>
<style scoped>
.employee-search {
display: flex;
align-items: center;
padding: 0.625em 1.875em;
gap: 1.25em;
width: 30.125em;
height: 3.125em;
box-shadow: 0.25em 0.25em 0.25em rgba(0, 0, 0, 0.25);
border-radius: 0.625em;
}
.section-darkmode {
background-color: #2c2c2c;
}
.section-lightmode {
background-color: #fff;
}
.label {
width: 2.5625em;
height: 1.875em;
font-family: "Overpass";
font-style: normal;
font-weight: 400;
font-size: 0.875em;
line-height: 1.875;
letter-spacing: 0.05em;
}
.label-darkmode {
color: #FFFFFF;
}
.label-lightmode {
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;
}
.pre-darkmode {
background-color: #212121;
color: #fff;
}
.pre-lightmode {
background-color: #EBEBEB;
color: #000;
}
.input-customer {
border: none;
margin-left: 1rem;
}
.pre-customer {
margin-left: 1rem;
}
.data-darkmode {
background-color: #212121;
color: #fff;
}
.data-lightmode {
background-color: #EBEBEB;
color: #000;
}
</style>

View File

@ -0,0 +1,153 @@
<template>
<section :class="['issue-state-search', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Issue state</div>
<pre v-if="!filtered"
:class="['data', 'pre-issue', darkMode ? 'pre-darkmode' : 'pre-lightmode']">{{ issueStateFilter }}</pre>
<input v-if="filtered" v-model="issueStateFilter" @change="filterList()"
:class="['data', 'input-state', darkMode ? 'data-darkmode' : 'data-lightmode']">
</section>
</template>
<script setup>
import { ref, watch, onMounted } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const filtered = computed(() => store.state.filtered);
const filteredTerm = computed(() => store.state.filteredByCustomer);
const issueStateFilter = ref(store.state.filteredByCustomer);
const darkMode = ref('');
// update filtered term
const updateFilterTerm = () => {
issueStateFilter.value = filteredTerm.value
}
const checkFiltered = () => {
if (!filtered.value) {
issueStateFilter.value = ''
filterList();
}
}
// update the filtered term in the store
const filterList = () => {
store.commit('updateFilterbyCustomer', issueStateFilter.value);
}
watch(filteredTerm, updateFilterTerm)
watch(filtered, checkFiltered)
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script>
<script>
export default {
name: "IssueStateSearch",
};
</script>
<style scoped>
.issue-state-search {
display: flex;
align-items: center;
padding: 0.625em 1.875em;
gap: 1.25em;
width: 30.125em;
height: 3.125em;
box-shadow: 0.25em 0.25em 0.25em rgba(0, 0, 0, 0.25);
border-radius: 0.625em;
}
.section-darkmode {
background-color: #2c2c2c;
}
.section-lightmode {
background-color: #fff;
}
.label {
width: 5.5625em;
height: 1.875em;
font-family: "Overpass";
font-style: normal;
font-weight: 400;
font-size: 0.875em;
line-height: 1.875;
letter-spacing: 0.05em;
}
.label-darkmode {
color: #FFFFFF;
}
.label-lightmode {
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;
}
.pre-darkmode {
background-color: #212121;
color: #fff;
}
.pre-lightmode {
background-color: #EBEBEB;
color: #000;
}
.input-state {
border: none;
margin-left: 1rem;
}
.pre-issue {
margin-left: 1rem;
}
.data-darkmode {
background-color: #212121;
color: #fff;
}
.data-lightmode {
background-color: #EBEBEB;
color: #000;
}
</style>

View File

@ -4,13 +4,13 @@
<span class="title-icon" id="logo-icon"> <span class="title-icon" id="logo-icon">
<img loading="lazy" srcSet="../favicon-gelb-rot-32x32.png" /> <img loading="lazy" srcSet="../favicon-gelb-rot-32x32.png" />
</span> </span>
<pre :class="['title', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Login</pre> <pre :class="['title', darkMode ? 'title-darkmode' : 'title-lightmode']">Login</pre>
</div> </div>
<div class="login-field"> <div class="login-field">
<div class="form-field" id="username-field"> <div class="form-field" id="username-field">
<label for="username-input" id="username-label"> <label for="username-input" id="username-label">
<span :class="['icon', darkMode ? 'icon-darkmode' : 'icon-lightmode']" id="username-icon"> <span :class="['icon', darkMode ? 'icon-darkmode' : 'icon-lightmode']" id="username-icon">
<img loading="lazy" src="../icons/Mail-Icon.svg" /> <img loading="lazy" src="/icons/Mail-Icon.svg" />
</span> </span>
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Username:</div> <div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Username:</div>
</label> </label>
@ -21,14 +21,16 @@
<div class="form-field" id="password-field"> <div class="form-field" id="password-field">
<label for="password-input" id="password-label"> <label for="password-input" id="password-label">
<span :class="['icon', darkMode ? 'icon-darkmode' : 'icon-lightmode']" id="password-icon"> <span :class="['icon', darkMode ? 'icon-darkmode' : 'icon-lightmode']" id="password-icon">
<img loading="lazy" src="../icons/Lock-Icon.svg" /> <img loading="lazy" src="/icons/Lock-Icon.svg" />
</span> </span>
<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" <input v-if="!showPassword" type="button" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']"
value="Show"> 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,25 +39,43 @@
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']"> {{ errorMsg }} </div> <div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']"> {{ errorMsg }} </div>
</label> </label>
</div> </div>
<div class="buttons">
<input type="button" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="login-button" value="Login" <input type="button" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="login-button" value="Login"
@click="handleLogin"> @click="handleLogin">
<input type="button" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="login-button" value="Signup" <!-- <input type="button" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="signup-button" value="Signup" @click="testFunctionSignup"> -->
@click="testFunctionSignup"> </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, onMounted } 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 router = useRouter(); const store = useStore();
const { signIn } = useAuth()
// 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 = '';
@ -63,78 +83,148 @@ const handleLogin = async () => {
const username = document.getElementById('username-input').value; const username = document.getElementById('username-input').value;
const password = document.getElementById('password-input').value; const password = document.getElementById('password-input').value;
const requestBody = { //const requestBody = {
const credentials = {
username: username, username: username,
password: password, password: password,
} }
try { try {
let res = await Axios.post(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/login`, requestBody); /*let res = await Axios.post(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/login`, requestBody);
const sessionToken = useCookie('token', {maxAge: 604800, sameSite: true});
sessionToken.value = res.data.token;
Axios.defaults.headers.common['Authorization'] = `${username}`;
const userToken = useCookie('user', {maxAge: 604800, sameSite: true});
userToken.value = username;
// something to do with the res? // something to do with the res?
console.log(res.data) console.log(sessionToken)
console.log(res.data.message)
// sucessfully logged in // sucessfully logged in
router.push('/') router.push('/home')*/
} catch (err) { let resBody = await signIn(credentials, { callbackUrl: '/home' })
// handle the error // let resBody = await signIn(credentials, { callbackUrl: await delayRedirect(callbackUrl, delayInSeconds * 1000) });
console.log(err.response.statusText)
isError.value = true;
errorMsg.value = err.response.statusText;
}
}
const testFunctionSignup = async () => {
isError.value = false;
errorMsg.value = '';
const username = 'franzzzzzrtg'
const password = '112345678'
const password_repeat = '112345678'
const fullName = 'hallo'
const email = 'test.sdj@web.de'
const phonenumber = '015736283729'
const address = 'Strasse'
const city = 'tuebingen'
const postcode = '72121'
const adminBool = false
const technician1Bool = false
const technician2Bool = false
const technicianMonitoringBool = false
const merchantBool = false
const internBool = true
const requestBody = {
username: username,
password: password,
password_repeat: password_repeat,
fullName: fullName,
email: email,
phonenumber: phonenumber,
address: address,
city: city,
postcode: postcode,
adminBool: adminBool,
technician1Bool: technician1Bool,
technician2Bool: technician2Bool,
technicianMonitoringBool: technicianMonitoringBool,
merchantBool: merchantBool,
internBool: internBool,
}
try { try {
let res = await Axios.post(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/signup`, requestBody); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/login`);
setItem('logged-in-bool', true);
// something to do with the res? setItem('logged-in-user-id', response.data.id)
console.log(res) 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)
setItem('logged-in-user-darkMode', response.data.darkModeBool)
store.commit('setLocalStorageChanged');
store.commit('setModeChanged');
store.commit('setModeQuickAccessChanged');
store.commit('setModeDashboardChanged');
store.commit('setModeNavbarChanged');
store.commit('setModeLayoutChanged');
} 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 () => {
// isError.value = false;
// errorMsg.value = '';
// const username = 'adm_tueit'
// const password = 'SvF=?bfEx7_hV,cMEu4m'
// const password_repeat = 'SvF=?bfEx7_hV,cMEu4m'
// const fullName = 'administrator'
// const email = 'support@tueit.de'
// const phonenumber = ''
// const address = ''
// const city = ''
// const postcode = ''
// const adminBool = true
// const technician1Bool = false
// const technician2Bool = false
// const technicianMonitoringBool = false
// const merchantBool = false
// const internBool = true
// const requestBody = {
// username: username,
// password: password,
// password_repeat: password_repeat,
// fullName: fullName,
// email: email,
// phonenumber: phonenumber,
// address: address,
// city: city,
// postcode: postcode,
// adminBool: adminBool,
// technician1Bool: technician1Bool,
// technician2Bool: technician2Bool,
// technicianMonitoringBool: technicianMonitoringBool,
// merchantBool: merchantBool,
// 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;
// }
// }
const getSession = async () => {
// const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
// if (loggedInUserDarkModeBool == 1) {
// darkMode.value = true;
// } else {
// darkMode.value = false;
// }
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
onMounted(() => {
getSession();
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();
}
};
</script> </script>
<script> <script>
@ -162,7 +252,8 @@ export default {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 31.25rem; width: 31.25rem;
height: 33rem; min-height: 33rem;
height: fit-content;
border-radius: 0.625rem; border-radius: 0.625rem;
padding: 2.5rem 1.875rem; padding: 2.5rem 1.875rem;
gap: 1.875rem; gap: 1.875rem;
@ -178,6 +269,7 @@ export default {
background-color: #fff; background-color: #fff;
} }
.title-field { .title-field {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -201,23 +293,27 @@ export default {
overflow: hidden; overflow: hidden;
} }
#show-password-toggle:hover {
cursor: pointer;
}
.title { .title {
margin: 0; margin: 0;
letter-spacing: 5%; 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;
} }
.pre-darkmode,
.title-darkmode { .title-darkmode {
color: #fff; color: #ffffff;
} }
.pre-lightmode,
.title-lightmode { .title-lightmode {
color: #000; color: #000000;
} }
.login-field { .login-field {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -227,6 +323,7 @@ export default {
gap: 1.25rem; gap: 1.25rem;
} }
.form-field { .form-field {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -238,16 +335,6 @@ export default {
gap: 0.625rem; gap: 0.625rem;
} }
.form-field-error-msg {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
width: 25rem;
height: 3rem;
gap: 0.4rem;
}
label { label {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@ -272,14 +359,6 @@ label {
overflow: hidden; overflow: hidden;
} }
.icon-darkmode>img {
filter: invert(100%);
}
.icon-lightmode>img {
filter: invert(0%);
}
#username-icon>img { #username-icon>img {
width: auto; width: auto;
height: 0.9375rem; height: 0.9375rem;
@ -290,17 +369,25 @@ label {
height: auto; height: auto;
} }
.icon-darkmode>img {
filter: invert(100%);
}
.icon-lightmode>img {
filter: invert(0%);
}
.label { .label {
letter-spacing: 2%; letter-spacing: 0.02rem;
font: 400 0.9375rem/1.875rem Overpass, sans-serif; font: 400 0.9375rem/1.875rem Overpass, sans-serif;
} }
.label-darkmode { .label-darkmode {
color: #fff; color: #ffffff;
} }
.label-lightmode { .label-lightmode {
color: #000; color: #000000;
} }
.input-field { .input-field {
@ -324,46 +411,76 @@ label {
background-color: #EBEBEB; background-color: #EBEBEB;
} }
input[type=text] { input[type=text],
input[type=password] {
width: 100%; width: 100%;
height: 100%; height: 100%;
background-color: #00000000; background-color: #00000000;
border: none; border: none;
color: #8e8e8e; color: #8e8e8e;
letter-spacing: 5%; letter-spacing: 0.01rem;
white-space: nowrap; white-space: nowrap;
font: 100 0.75rem/1.25rem Overpass, sans-serif; font: 100 0.75rem/1.25rem Overpass, sans-serif;
} }
input[type=button] { #show-password-toggle {
width: fit-content; width: fit-content;
height: auto;
align-self: flex-end; align-self: flex-end;
padding: 0;
border-radius: 0;
background-color: #00000000; background-color: #00000000;
background: none;
border: none; border: none;
letter-spacing: 5%; letter-spacing: 0.01rem;
white-space: nowrap; white-space: nowrap;
font: 300 0.75rem/1.25rem Overpass, sans-serif; font: 300 0.75rem/1.25rem Overpass, sans-serif;
} }
.button-darkmode {
color: #fff;
.form-field-error-msg {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
width: 25rem;
height: 3rem;
gap: 0.4rem;
} }
.button-lightmode {
color: #000;
.buttons {
display: flex;
flex-direction: row;
height: fit-content;
width: 100%;
align-items: center;
justify-content: center;
padding: 0.625rem 0.625rem 0;
gap: 2.5rem;
} }
#login-button {
width: 13.75rem; input[type=button] {
height: 4.375rem; width: 9.375rem;
height: 3.125rem;
padding: 0.625rem; padding: 0.625rem;
border-radius: 0.625rem; border-radius: 0.625rem;
align-self: center; align-self: center;
border: none; border: none;
color: #000;
background: linear-gradient(93deg, #ff0f00 3.67%, #ffe608 100%); background: linear-gradient(93deg, #ff0f00 3.67%, #ffe608 100%);
letter-spacing: 2%; letter-spacing: 0.02rem;
white-space: nowrap; white-space: nowrap;
font: 600 1.25rem/1.875rem Overpass, sans-serif; font: 600 1.125rem/1.875rem Overpass, sans-serif;
}
.button-darkmode {
color: #ffffff;
}
.button-lightmode {
color: #000000;
} }
</style> </style>

View File

@ -13,9 +13,42 @@
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const modeChangedLocalstorage = computed(() => store.state.modeQuickAccess);
const darkMode = ref('');
const getSession = async () => {
if (modeChangedLocalstorage.value) {
store.commit('resetModeQuickAccessChanged');
}
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
watch(modeChangedLocalstorage, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>

View File

@ -7,9 +7,37 @@
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const darkMode = ref('');
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>
@ -79,4 +107,3 @@ export default {
color: #000; color: #000;
} }
</style> </style>

View File

@ -1,8 +1,207 @@
<template> <template>
<section :class="['accounting-information', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section v-if="!addBool" :class="['accounting-information', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']" id="accounting">Accounting: <div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']" id="accounting">Accounting:
<div class="asset-data"> <div class="asset-data">
<table class="data-table" id="asset-table-no-client"> <table class="data-table" id="asset-table-no-client">
<tbody>
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th
:class="['Action', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Action-darkmode' : 'Action-lightmode']">
Action</th>
<th
:class="['Date', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
Date</th>
<th :class="['Comments', darkMode ? 'th-darkmode' : 'th-lightmode']">Comments</th>
</tr>
<tr :class="['table-row', darkMode ? 'first-tr-darkmode' : 'first-tr-lightmode']" id="row-1">
<td
:class="['Action', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Action-darkmode' : 'Action-lightmode']">
Supplier request</td>
<td v-if="!editable"
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
{{
issueSlip.supplierRequestDate }}</td>
<td v-if="editable"
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
<input type="text" v-model="issueSlip.supplierRequestDate" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td v-if="!editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">{{
issueSlip.supplierRequest }}</td>
<td v-if="editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="issueSlip.supplierRequest" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
</tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td
:class="['Action', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Action-darkmode' : 'Action-lightmode']">
Supplier offer</td>
<td v-if="!editable"
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
{{
issueSlip.supplierOfferDate }}</td>
<td v-if="editable"
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
<input type="text" v-model="issueSlip.supplierOfferDate" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td v-if="!editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">{{
issueSlip.supplierOffer }}</td>
<td v-if="editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="issueSlip.supplierOffer" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
</tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td
:class="['Action', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Action-darkmode' : 'Action-lightmode']">
Customer offer</td>
<td v-if="!editable"
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
{{
issueSlip.clientOfferDate }}</td>
<td v-if="editable"
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
<input type="text" v-model="issueSlip.clientOfferDate" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td v-if="!editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">{{
issueSlip.clientOffer }}</td>
<td v-if="editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="issueSlip.clientOffer" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
</tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td
:class="['Action', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Action-darkmode' : 'Action-lightmode']">
Customer order</td>
<td v-if="!editable"
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
{{
issueSlip.clientOrderDate }}</td>
<td v-if="editable"
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
<input type="text" v-model="issueSlip.clientOrderDate" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td v-if="!editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">{{
issueSlip.clientOrder }}</td>
<td v-if="editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="issueSlip.clientOrder" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
</tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td
:class="['Action', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Action-darkmode' : 'Action-lightmode']">
Supplier order</td>
<td v-if="!editable"
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
{{
issueSlip.supplierOrderDate }}</td>
<td v-if="editable"
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
<input type="text" v-model="issueSlip.supplierOrderDate" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td v-if="!editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">{{
issueSlip.supplierOrder }}</td>
<td v-if="editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="issueSlip.supplierOrder" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
</tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td
:class="['Action', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Action-darkmode' : 'Action-lightmode']">
Ingress</td>
<td v-if="!editable"
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
{{
issueSlip.ingressDate }}</td>
<td v-if="editable"
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
<input type="text" v-model="issueSlip.ingressDate" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td v-if="!editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">{{
issueSlip.ingress }}</td>
<td v-if="editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="issueSlip.ingress" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
</tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td
:class="['Action', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Action-darkmode' : 'Action-lightmode']">
Egress</td>
<td v-if="!editable"
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
{{
issueSlip.egressDate }}</td>
<td v-if="editable"
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
<input type="text" v-model="issueSlip.egressDate" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td v-if="!editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">{{
issueSlip.egress }}</td>
<td v-if="editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="issueSlip.egress" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
</tr>
<tr :class="['table-row', darkMode ? 'final-tr-darkmode' : 'final-tr-lightmode']" id="row-2">
<td
:class="['Action', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Action-darkmode' : 'Action-lightmode']">
Ingress bill</td>
<td v-if="!editable"
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
{{
issueSlip.ingressBillDate }}</td>
<td v-if="editable"
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
<input type="text" v-model="issueSlip.ingressBillDate" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td v-if="!editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">{{
issueSlip.ingressBill }}</td>
<td v-if="editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="issueSlip.ingressBill" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
</tr>
<tr :class="['table-row', darkMode ? 'final-tr-darkmode' : 'final-tr-lightmode']" id="row-1">
<td
:class="['Action', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Action-darkmode' : 'Action-lightmode']">
Egress bill</td>
<td v-if="!editable"
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
{{
issueSlip.egressBillDate }}</td>
<td v-if="editable"
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
<input type="text" v-model="issueSlip.egressBillDate" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td v-if="!editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">{{
issueSlip.egressBill }}</td>
<td v-if="editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="issueSlip.egressBill" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section v-if="addBool" :class="['accounting-information', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']" id="accounting">Accounting:
<div class="asset-data">
<table class="data-table" id="asset-table-no-customer">
<tbody> <tbody>
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head"> <tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th <th
@ -19,8 +218,13 @@
Supplier request</td> Supplier request</td>
<td <td
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']"> :class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
...</td> <input type="text" v-model="newSupplierRequestDate" @change="updateIS()"
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">...</td> :class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="newSupplierRequest" @change="updateIS()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
</tr> </tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1"> <tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td <td
@ -28,8 +232,13 @@
Supplier offer</td> Supplier offer</td>
<td <td
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']"> :class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
...</td> <input type="text" v-model="newSupplierOfferDate" @change="updateIS()"
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">...</td> :class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="newSupplierOffer" @change="updateIS()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
</tr> </tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1"> <tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td <td
@ -37,8 +246,13 @@
Customer offer</td> Customer offer</td>
<td <td
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']"> :class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
...</td> <input type="text" v-model="newClientOfferDate" @change="updateIS()"
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">...</td> :class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="newClientOffer" @change="updateIS()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
</tr> </tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1"> <tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td <td
@ -46,8 +260,13 @@
Customer order</td> Customer order</td>
<td <td
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']"> :class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
...</td> <input type="text" v-model="newClientOrderDate" @change="updateIS()"
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">...</td> :class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="newClientOrder" @change="updateIS()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
</tr> </tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1"> <tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td <td
@ -55,8 +274,13 @@
Supplier order</td> Supplier order</td>
<td <td
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']"> :class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
...</td> <input type="text" v-model="newSupplierOrderDate" @change="updateIS()"
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">...</td> :class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="newSupplierOrder" @change="updateIS()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
</tr> </tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1"> <tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td <td
@ -64,8 +288,13 @@
Ingress</td> Ingress</td>
<td <td
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']"> :class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
...</td> <input type="text" v-model="newIngressDate" @change="updateIS()"
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">...</td> :class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="newIngress" @change="updateIS()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
</tr> </tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1"> <tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td <td
@ -73,8 +302,13 @@
Egress</td> Egress</td>
<td <td
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']"> :class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
...</td> <input type="text" v-model="newEgressDate" @change="updateIS()"
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">...</td> :class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="newEgress" @change="updateIS()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
</tr> </tr>
<tr :class="['table-row', darkMode ? 'final-tr-darkmode' : 'final-tr-lightmode']" id="row-2"> <tr :class="['table-row', darkMode ? 'final-tr-darkmode' : 'final-tr-lightmode']" id="row-2">
<td <td
@ -82,8 +316,13 @@
Ingress bill</td> Ingress bill</td>
<td <td
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']"> :class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
...</td> <input type="text" v-model="newIngressBillDate" @change="updateIS()"
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">...</td> :class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="newIngressBill" @change="updateIS()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
</tr> </tr>
<tr :class="['table-row', darkMode ? 'final-tr-darkmode' : 'final-tr-lightmode']" id="row-1"> <tr :class="['table-row', darkMode ? 'final-tr-darkmode' : 'final-tr-lightmode']" id="row-1">
<td <td
@ -91,20 +330,246 @@
Egress bill</td> Egress bill</td>
<td <td
:class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']"> :class="['Date', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Date-darkmode' : 'Date-lightmode']">
...</td> <input type="text" v-model="newEgressBillDate" @change="updateIS()"
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">...</td> :class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="newEgressBill" @change="updateIS()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
</section> </section>
<section v-if="addBool" id="saveNewItem">
<button :class="[darkMode ? 'saveNewItem-darkmode' : 'saveNewItem-lightmode']"
@click="addIssueSlip()">Save</button>
</section>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; 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 darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const editable = computed(() => store.state.editable);
const chosenIssueSlipId = computed(() => store.state.chosenIssueSlipId);
const addBool = computed(() => store.state.new);
const newTicketNoIS = computed(() => store.state.newTicketNoIS);
const newCustomerIdIS = computed(() => store.state.newCustomerIdIS);
const newCustomerIS = computed(() => store.state.newCustomerIS);
const newNotesIS = computed(() => store.state.newNotesIS);
const newUserIS = computed(() => store.state.newUserIS);
const newDeliveryAddressIS = computed(() => store.state.newDeliveryAddressIS);
const newAddRowOI = computed(() => store.state.newAddRowOI);
const newOIs = computed(() => store.state.newOIs);
const newClientOffer = ref('');
const newClientOrder = ref('');
const newSupplierOffer = ref('');
const newSupplierOrder = ref('');
const newSupplierRequest = ref('');
const newIngress = ref('');
const newIngressBill = ref('');
const newEgress = ref('');
const newEgressBill = ref('');
const newClientOfferDate = ref('');
const newClientOrderDate = ref('');
const newSupplierOfferDate = ref('');
const newSupplierOrderDate = ref('');
const newSupplierRequestDate = ref('');
const newIngressDate = ref('');
const newIngressBillDate = ref('');
const newEgressDate = ref('');
const newEgressBillDate = ref('');
const darkMode = ref('')
const issueSlip = ref({});
// get issue slip from id
const getIssueSlipById = async () => {
try {
const response = await Axios.get(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getIssueSlip/${chosenIssueSlipId.value}`
);
issueSlip.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
// update accounting fields in the store
const updateIS = () => {
const is = {
supplierRequestDate: newSupplierRequestDate.value,
supplierRequest: newSupplierRequest.value,
supplierOfferDate: newSupplierOfferDate.value,
supplierOffer: newSupplierOffer.value,
clientOfferDate: newClientOfferDate.value,
clientOffer: newClientOffer.value,
clientOrderDate: newClientOrderDate.value,
clientOrder: newClientOrder.value,
supplierOrderDate: newSupplierOrderDate.value,
supplierOrder: newSupplierOrder.value,
ingressDate: newIngressDate.value,
ingress: newIngress.value,
egressDate: newEgressDate.value,
egress: newEgress.value,
ingressBillDate: newIngressBillDate.value,
ingressBill: newIngressBill.value,
egressBillDate: newEgressBillDate.value,
egressBill: newEgressBill.value,
};
store.commit('updateAccountingComponent', is);
}
//update data
const updateIssueSlip = async () => {
try {
await Axios.put(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/updateIssueSlip`,
{
primaryID: issueSlip.value.primaryID,
customerID: issueSlip.value.customerID,
customer: issueSlip.value.customer,
ticketNo: issueSlip.value.ticketNo,
creationDate: issueSlip.value.creationDate,
lastView: issueSlip.value.lastView,
user: issueSlip.value.user,
notes: issueSlip.value.notes,
deliveryAddress: issueSlip.value.deliveryAddress,
supplierRequestDate: issueSlip.value.supplierRequestDate,
supplierRequest: issueSlip.value.supplierRequest,
supplierOfferDate: issueSlip.value.supplierOfferDate,
supplierOffer: issueSlip.value.supplierOffer,
clientOfferDate: issueSlip.value.clientOfferDate,
clientOffer: issueSlip.value.clientOffer,
clientOrderDate: issueSlip.value.clientOrderDate,
clientOrder: issueSlip.value.clientOrder,
supplierOrder: issueSlip.value.supplierOrder,
supplierOrderDate: issueSlip.value.supplierOrderDate,
ingressDate: issueSlip.value.ingressDate,
ingress: issueSlip.value.ingress,
egressDate: issueSlip.value.egressDate,
egress: issueSlip.value.egress,
ingressBillDate: issueSlip.value.ingressBillDate,
ingressBill: issueSlip.value.ingressBill,
egressBillDate: issueSlip.value.egressBillDate,
egressBill: issueSlip.value.egressBill,
}
)
await getIssueSlipById();
} catch (err) {
console.log(err.response.statusText);
}
}
// add new issue slip
const addIssueSlip = async () => {
if (newTicketNoIS.value.length === 0) {
alert("Please add a ticket number!");
return;
}
if (newCustomerIS.value.length === 0) {
alert("Please choose a customer!");
return;
}
// get the time and date
const today = new Date();
const date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
const time = today.getHours() + ":" + today.getMinutes();
const dateTime = date + ' ' + time;
let allFine = true;
newOIs.value.forEach(oi => {
if (oi.article.length === 0 && oi.amount.length === 0 && oi.price.length === 0 && oi.comment.length === 0) {
alert(`Please add data for all ordering info.`);
allFine = false
}
})
if (!allFine) {
return
}
try {
const response = await Axios.post(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/addIssueSlip`,
{
customerID: newCustomerIdIS.value,
customer: newCustomerIS.value,
ticketNo: newTicketNoIS.value,
creationDate: dateTime,
lastView: '',
user: newUserIS.value,
notes: newNotesIS.value,
deliveryAddress: newDeliveryAddressIS.value,
supplierRequestDate: newSupplierRequestDate.value,
supplierRequest: newSupplierRequest.value,
supplierOfferDate: newSupplierOfferDate.value,
supplierOffer: newSupplierOffer.value,
clientOfferDate: newClientOfferDate.value,
clientOffer: newClientOffer.value,
clientOrderDate: newClientOrderDate.value,
clientOrder: newClientOrder.value,
supplierOrderDate: newClientOrderDate.value,
supplierOrder: newSupplierOrder.value,
ingressDate: newIngressDate.value,
ingress: newIngress.value,
egressDate: newEgressDate.value,
egress: newEgress.value,
ingressBillDate: newIngressBillDate.value,
ingressBill: newIngressBill.value,
egressBillDate: newEgressBillDate.value,
egressBill: newEgressBill.value,
});
newOIs.value.forEach(async oi => {
try {
const res = await Axios.post(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/addOrderingInfo`,
{
issueSlipID: response.data,
article: oi.article,
amount: oi.amount,
price: oi.price,
comment: oi.comment,
});
} catch (err) {
console.log(err);
}
store.commit('resetStore');
store.commit('changeToIssueSliplist');
})
} catch (err) {
console.log(err.response.statusText);
}
}
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
getIssueSlipById();
});
</script> </script>
<script> <script>
@ -134,6 +599,31 @@ export default {
background-color: #fff; background-color: #fff;
} }
.input {
border: none;
}
.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;
}
.label { .label {
letter-spacing: 5%; letter-spacing: 5%;
font: 400 1rem/1.875rem Overpass, sans-serif; font: 400 1rem/1.875rem Overpass, sans-serif;
@ -204,6 +694,41 @@ export default {
background-color: #EBEBEB; background-color: #EBEBEB;
} }
.saveNewItem-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);
}
.saveNewItem-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);
}
.saveNewItem-darkmode:hover {
background-color: #444444;
cursor: pointer;
}
.saveNewItem-lightmode:hover {
background-color: #ACACAC;
cursor: pointer;
}
#saveNewItem {
text-align: center;
}
th, th,
td { td {

View File

@ -5,8 +5,8 @@
<input v-if="editable" v-model="item.assetName" @change="updateConfigItem()" <input v-if="editable" v-model="item.assetName" @change="updateConfigItem()"
:class="['data', 'asset-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']"> :class="['data', 'asset-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']">
<div class="asset-data"> <div class="asset-data">
<div class="client-location"> <div class="customer-location">
<div class="data-field" id="client"> <div class="data-field" id="customer">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre>
<pre v-if="!editable" <pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']"> {{ item.customer }}</pre> :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']"> {{ item.customer }}</pre>
@ -81,8 +81,8 @@
<input v-model="newAssetName" @change="updateAsset()" <input v-model="newAssetName" @change="updateAsset()"
:class="['data', 'asset-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']"> :class="['data', 'asset-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']">
<div class="asset-data"> <div class="asset-data">
<div class="client-location"> <div class="customer-location">
<div class="data-field" id="client"> <div class="data-field" id="customer">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre>
<select id="customersDropDownChosenCI" v-model="newCustomer" @change="updateNewCustomerID()" <select id="customersDropDownChosenCI" v-model="newCustomer" @change="updateNewCustomerID()"
:class="[darkMode ? 'select-darkmode' : 'select-lightmode']"> :class="[darkMode ? 'select-darkmode' : 'select-lightmode']">
@ -153,12 +153,15 @@ import { useStore } from 'vuex';
import { computed } from 'vue'; import { computed } from 'vue';
const store = useStore(); const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const editable = computed(() => store.state.editable); const editable = computed(() => store.state.editable);
const chosenAssetId = computed(() => store.state.chosenAssetId); const chosenAssetId = computed(() => store.state.chosenAssetId);
const deleteBool = computed(() => store.state.deleteBool); const deleteBool = computed(() => store.state.deleteBool);
const addBool = computed(() => store.state.new); const addBool = computed(() => store.state.new);
const darkMode = ref(true); const darkMode = ref('');
const item = ref({}); const item = ref({});
const customer = ref({}); const customer = ref({});
const configItems = ref([]); const configItems = ref([]);
@ -217,7 +220,7 @@ const updateConfigItem = async () => {
counter += 1; counter += 1;
} }
}); });
if (counter == 1) { if (counter == 2) {
alert("This asset name already exists. Please choose an unique asset name or modify respectively delete the old one!"); alert("This asset name already exists. Please choose an unique asset name or modify respectively delete the old one!");
item.value.assetName = ''; item.value.assetName = '';
return; return;
@ -280,6 +283,7 @@ const confirmDeleteAsset = async () => {
try { try {
await Axios.delete(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/deleteConfigItem/${chosenAssetId.value}`); await Axios.delete(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/deleteConfigItem/${chosenAssetId.value}`);
store.commit('undoDelete'); store.commit('undoDelete');
store.commit('resetStore');
store.commit('changeToAssetlist'); store.commit('changeToAssetlist');
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
@ -330,11 +334,30 @@ const triggerBackendCallsWithDelay = async (fetchDataFunc) => {
}, 1500); }, 1500);
} }
watch(deleteBool, confirmDeleteAsset); const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
onMounted(() => { function getItem(item) {
getItemById(); if (process.client) {
getConfigItems(); return localStorage.getItem(item)
} else {
return undefined
}
}
watch(deleteBool, confirmDeleteAsset);
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
await getItemById();
triggerBackendCallsWithDelay(getConfigItems);
triggerBackendCallsWithDelay(getCustomers); triggerBackendCallsWithDelay(getCustomers);
}); });
</script> </script>
@ -474,7 +497,7 @@ export default {
align-self: stretch; align-self: stretch;
} }
.client-location, .customer-location,
.info { .info {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@ -1,4 +1,14 @@
<template> <template>
<section v-if="searchable" :class="['solution-search', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['solutionLabel', darkMode ? 'label-darkmode' : 'label-lightmode']">Solution</div>
<input v-model="solutionSearchFilter" @change="searchSolution()"
:class="['dataInput', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</section>
<section v-if="filtered" :class="['solution-search', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['solutionLabel', darkMode ? 'label-darkmode' : 'label-lightmode']">Type</div>
<input v-model="typeSearchFilter" @change="filterSolutionByType()"
:class="['dataInput', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</section>
<div :class="['data', darkMode ? 'div-darkmode' : 'div-lightmode']"> <div :class="['data', darkMode ? 'div-darkmode' : 'div-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Solutions:</div> <div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Solutions:</div>
<table class="data-table" id="solution-checkklist"> <table class="data-table" id="solution-checkklist">
@ -9,23 +19,148 @@
Solution</th> Solution</th>
<th :class="['Type', darkMode ? 'th-darkmode' : 'th-lightmode']">Type</th> <th :class="['Type', darkMode ? 'th-darkmode' : 'th-lightmode']">Type</th>
</tr> </tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1"> <tr v-for="sol in solutions" :key="sol.primaryID"
:class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td <td
:class="['Solution', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Solution-darkmode' : 'Solution-lightmode']"> :class="['Solution', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Solution-darkmode' : 'Solution-lightmode']">
...</td> <nuxt-link to="/solutions" id="nuxt-link" class="button"
<td :class="['Type', darkMode ? 'td-darkmode' : 'td-lightmode']">...</td> :class="[darkMode ? 'button-darkmode' : 'button-lightmode', darkMode ? 'nuxt-link-darkmode' : 'nuxt-link-lightmode']"
@click="goToChosenSolution(sol.primaryID)">
{{ sol.solutionName }}
</nuxt-link>
</td>
<td :class="['Type', darkMode ? 'td-darkmode' : 'td-lightmode']">{{ sol.type }}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; 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 darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const chosenAssetId = computed(() => store.state.chosenAssetId);
const searchable = computed(() => store.state.searchable);
const filtered = computed(() => store.state.filtered);
const solutionSearchFilter = ref('');
const typeSearchFilter = ref('');
const asset = ref({});
const solutions = ref([]);
const solutionsBySol = ref([]);
const solutionsByType = ref([]);
const darkMode = ref('')
//get all solutions from the chosen asset
const getSolutions = async () => {
try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getSelectedSolutionsByAsset/${asset.value.assetName}`);
solutions.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
// update search term
const updateSearchTerm = async () => {
solutionSearchFilter.value = '';
await getSolutions();
}
// update filter term
const updateFilterTerm = async () => {
typeSearchFilter.value = '';
await getSolutions();
}
const goToChosenSolution = (id) => {
store.commit('setChosenSolution', id);
store.commit('changeToSolution');
};
// get config item from id
const getItemById = async () => {
try {
const response = await Axios.get(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getConfigItem/${chosenAssetId.value}`
);
asset.value = response.data;
await getSolutions();
} catch (err) {
console.log(err.response.statusText);
}
}
//get all solutions based on the searched solution name
const searchSolution = async () => {
if (solutionSearchFilter.value === '') {
await getSolutions();
} else {
try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getSelectedSolutionsBySolution/${solutionSearchFilter.value}`);
solutionsBySol.value = response.data;
solutions.value = filterObjectsWithMatchingIds(solutions.value, solutionsBySol.value);
} catch (err) {
console.log(err.response.statusText);
}
}
}
//get all solutions based on the searched solution name
const filterSolutionByType = async () => {
if (typeSearchFilter.value === '') {
await getSolutions();
} else {
try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getSelectedSolutionsByType/${typeSearchFilter.value}`);
solutionsByType.value = response.data;
solutions.value = filterObjectsWithMatchingIds(solutions.value, solutionsByType.value);
} catch (err) {
console.log(err.response.statusText);
}
}
}
const filterObjectsWithMatchingIds = (arr1, arr2) => {
return arr1.filter(obj1 => {
return arr2.some(obj2 => obj2.primaryID === obj1.primaryID);
});
};
watch(searchable, updateSearchTerm);
watch(filtered, updateFilterTerm);
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
getItemById();
});
</script> </script>
<script> <script>
@ -57,6 +192,70 @@ export default {
background-color: #fff; background-color: #fff;
} }
.solutionLabel {
width: 5.5625em;
height: 1.875em;
font-family: "Overpass";
font-style: normal;
font-weight: 400;
font-size: 0.875em;
line-height: 1.875;
letter-spacing: 0.05em;
}
.nuxt-link-darkmode {
color: white;
}
.nuxt-link-lightmode {
color: #000;
}
.data-darkmode {
background-color: #212121;
color: #fff;
}
.data-lightmode {
background-color: #EBEBEB;
color: #000;
}
.dataInput {
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;
}
.section-darkmode {
background-color: #2c2c2c;
}
.section-lightmode {
background-color: #fff;
}
.solution-search {
display: flex;
align-items: center;
padding: 0.625em 1.875em;
gap: 1.25em;
width: 30.125em;
height: 3.125em;
box-shadow: 0.25em 0.25em 0.25em rgba(0, 0, 0, 0.25);
border-radius: 0.625em;
box-sizing: border-box;
}
.data-table { .data-table {
width: 100%; width: 100%;
padding: 0 0.625rem; padding: 0 0.625rem;
@ -73,6 +272,10 @@ export default {
gap: 0.625rem; gap: 0.625rem;
} }
#nuxt-link {
text-decoration: none;
}
.tr-head-darkmode { .tr-head-darkmode {
border-top: none; border-top: none;
border-bottom: 0.0625rem solid #000000; border-bottom: 0.0625rem solid #000000;

View File

@ -1,6 +1,6 @@
<template> <template>
<section v-if="searchable" :class="['asset-search', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section v-if="assetSearchable" :class="['asset-search', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['clientLabel', darkMode ? 'label-darkmode' : 'label-lightmode']">Config item</div> <div :class="['customerLabel', darkMode ? 'label-darkmode' : 'label-lightmode']">Config item</div>
<input v-model="assetSearchFilter" @change="searchConfigItem()" <input v-model="assetSearchFilter" @change="searchConfigItem()"
:class="['dataInput', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']"> :class="['dataInput', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</section> </section>
@ -10,7 +10,7 @@
<tbody> <tbody>
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head"> <tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th <th
:class="['Client', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Client-darkmode' : 'Client-lightmode']"> :class="['Customer', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Customer-darkmode' : 'Customer-lightmode']">
Customer</th> Customer</th>
<th <th
:class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']"> :class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
@ -26,13 +26,13 @@
<tr v-for="item in configItemList" :key="item.primaryID" <tr v-for="item in configItemList" :key="item.primaryID"
:class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']"> :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']">
<td <td
:class="['Client', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Client-darkmode' : 'Client-lightmode']"> :class="['Customer', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Customer-darkmode' : 'Customer-lightmode']">
{{ item.customer }} {{ item.customer }}
</td> </td>
<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="/assets" id="nuxt-link" class="button"
:class="[darkMode ? 'button-darkmode' : 'button-lightmode']" :class="[darkMode ? 'button-darkmode' : 'button-lightmode', darkMode ? 'nuxt-link-darkmode' : 'nuxt-link-lightmode']"
@click="goToChosenAsset(item.primaryID)"> @click="goToChosenAsset(item.primaryID)">
{{ item.assetName }} {{ item.assetName }}
</nuxt-link> </nuxt-link>
@ -59,15 +59,18 @@ import { computed } from 'vue';
// get accesss to the store // get accesss to the store
const store = useStore() const store = useStore()
const modeChanged = computed(() => store.state.updateDarkMode);
const goToChosenAsset = (id) => { const goToChosenAsset = (id) => {
store.commit('setChosenAsset', id); store.commit('setChosenAsset', id);
store.commit('changeToAsset'); store.commit('changeToAsset');
}; };
const clientFilter = computed(() => store.state.filteredByClient); const customerFilter = computed(() => store.state.filteredByCustomer);
const searchable = computed(() => store.state.searchable); const assetSearchable = computed(() => store.state.searchable);
const assetSearchFilter = ref(''); const assetSearchFilter = ref('');
const darkMode = ref(true) const darkMode = ref('')
const configItemList = ref([]); const configItemList = ref([]);
// update search term // update search term
@ -78,8 +81,8 @@ const updateSearchTerm = async () => {
//get all config items //get all config items
const getConfigItems = async () => { const getConfigItems = async () => {
if (!(clientFilter.value === '')) { if (!(customerFilter.value === '')) {
await getFilteredConfigItemsByClient(); await getFilteredConfigItemsByCustomer();
} else { } else {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllConfigItems`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllConfigItems`);
@ -90,10 +93,10 @@ const getConfigItems = async () => {
} }
} }
//get all config items based on the searched client //get all config items based on the searched customer
const getFilteredConfigItemsByClient = async () => { const getFilteredConfigItemsByCustomer = async () => {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getSelectedConfigItemsByClient/${clientFilter.value}`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getSelectedConfigItemsByCustomer/${customerFilter.value}`);
configItemList.value = response.data; configItemList.value = response.data;
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
@ -114,10 +117,29 @@ const searchConfigItem = async () => {
} }
} }
watch(clientFilter, getConfigItems); const getSession = async () => {
watch(searchable, updateSearchTerm); const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(customerFilter, getConfigItems);
watch(assetSearchable, updateSearchTerm);
watch(modeChanged, getSession)
onMounted(async () => { onMounted(async () => {
await getSession();
await getConfigItems(); await getConfigItems();
}); });
</script> </script>
@ -252,15 +274,15 @@ th {
font: 700 0.875rem/1.875rem Overpass, sans-serif; font: 700 0.875rem/1.875rem Overpass, sans-serif;
} }
.Client { .Customer {
width: 33.3%; width: 33.3%;
} }
.Client-darkmode { .Customer-darkmode {
border-right: 0.0625rem solid #000000; border-right: 0.0625rem solid #000000;
} }
.Client-lightmode { .Customer-lightmode {
border-right: 0.0625rem solid #8e8e8e; border-right: 0.0625rem solid #8e8e8e;
} }
@ -315,7 +337,7 @@ th {
letter-spacing: 0.05em; letter-spacing: 0.05em;
} }
.clientLabel { .customerLabel {
width: 5.5625em; width: 5.5625em;
height: 1.875em; height: 1.875em;
font-family: "Overpass"; font-family: "Overpass";
@ -336,6 +358,13 @@ th {
#nuxt-link { #nuxt-link {
text-decoration: none; text-decoration: none;
}
.nuxt-link-darkmode {
color: white; color: white;
} }
.nuxt-link-lightmode {
color: #000;
}
</style> </style>

View File

@ -1,186 +0,0 @@
<template>
<div :class="['data', darkMode ? 'div-darkmode' : 'div-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Assets:</div>
<table class="data-table" id="asset-table-no-client">
<tbody>
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th
:class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
Name</th>
<th
:class="['Type', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Type-darkmode' : 'Type-lightmode']">
Type</th>
<th
:class="['State', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'State-darkmode' : 'State-lightmode']">
State</th>
<th :class="['User', darkMode ? 'th-darkmode' : 'th-lightmode']">User</th>
</tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td
:class="['Name', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
...</td>
<td
:class="['Type', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Type-darkmode' : 'Type-lightmode']">
...</td>
<td
:class="['State', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'State-darkmode' : 'State-lightmode']">
...</td>
<td :class="['User', darkMode ? 'td-darkmode' : 'td-lightmode']">...</td>
</tr>
</tbody>
</table>
</div>
</template>
<script setup>
import { ref } from 'vue';
const darkMode = ref(true)
</script>
<script>
export default {
name: "AssetTableNoClient",
};
</script>
<style scoped>
.data {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
align-self: stretch;
width: 100%;
padding: 1.25rem 1.875rem;
gap: 1.25rem;
border-radius: 0.625rem;
box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25);
}
.div-darkmode {
background-color: #2c2c2c;
}
.div-lightmode {
background-color: #fff;
}
.data-table {
width: 100%;
padding: 0 0.625rem;
table-layout: fixed;
border-collapse: collapse;
}
.table-row {
display: flex;
flex-direction: row;
align-items: center;
height: 3.125rem;
padding: 0.625rem;
gap: 0.625rem;
}
.tr-head-darkmode {
border-top: none;
border-bottom: 0.0625rem solid #000000;
}
.tr-head-lightmode {
border-top: none;
border-bottom: 0.0625rem solid #8e8e8e;
}
.tr-darkmode {
border-top: 0.0625rem solid #000000;
}
.tr-lightmode {
border-top: 0.0625rem solid #8e8e8e;
}
th,
td {
height: 1.875rem;
text-align: left;
padding: 0;
letter-spacing: 5%;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
}
.th-darkmode,
.td-darkmode {
color: #ffffff;
}
.th-lightmode,
.td-lightmode {
color: #000;
}
th {
font: 700 0.875rem/1.875rem Overpass, sans-serif;
}
.Name {
width: 50%;
}
.Name-darkmode {
border-right: 0.0625rem solid #000000;
}
.Name-lightmode {
border-right: 0.0625rem solid #8e8e8e;
}
.Type {
width: 20%;
}
.Type-darkmode {
border-right: 0.0625rem solid #000000;
}
.Type-lightmode {
border-right: 0.0625rem solid #8e8e8e;
}
.State {
width: 20%;
}
.State-darkmode {
border-right: 0.0625rem solid #000000;
}
.State-lightmode {
border-right: 0.0625rem solid #8e8e8e;
}
.User {
width: 10%;
}
.label {
width: 6.0625em;
height: 1.875em;
font-family: 'Overpass';
font-style: normal;
font-weight: 400;
font-size: 1em;
line-height: 1.875em;
letter-spacing: 0.05em;
}
.label-darkmode {
color: #FFFFFF;
}
.label-lightmode {
color: #000;
}
</style>

View File

@ -1,143 +0,0 @@
<template>
<section :class="[darkMode ? 'section-darkmode' : 'section-lightmode']">
<pre :class="['title', darkMode ? 'title-darkmode' : 'title-lightmode']">Department name</pre>
<div class="data-group">
<div class="data-field" id="id">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">ID:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre>
</div>
<div class="data-field" id="client-id">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer ID:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre>
</div>
<div class="data-field" id="head">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Head:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre>
</div>
</div>
<div class="notes">
<pre :class="['area-title', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Notes:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']" id="notes">...</pre>
</div>
</section>
</template>
<script setup>
import { ref } from 'vue';
const darkMode = ref(true)
</script>
<script>
export default {
name: "ClientDepartment",
};
</script>
<style scoped>
* {
box-sizing: border-box;
margin: 0;
}
section {
display: flex;
flex-direction: column;
padding: 1.25rem 1.875rem;
border-radius: 0.625rem;
box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25);
align-items: stretch;
justify-content: center;
}
.section-darkmode { background-color: #2c2c2c; }
.section-lightmode { background-color: #ffffff; }
.title {
padding: 1.25rem 0;
letter-spacing: 0.04rem;
text-decoration-line: underline;
font: italic 400 1rem/1.875rem Overpass, sans-serif;
}
.title-darkmode { color: #ffffff; }
.title-lightmode { color: #000000; }
.data-group {
display: flex;
flex: auto;
width: 100%;
flex-direction: row;
padding: 0.625rem 0;
align-items: center;
justify-content: stretch;
}
.data-field {
display: flex;
flex: auto;
width: 30%;
flex-direction: row;
padding: 0.625rem 1.875rem;
align-items: center;
justify-content: flex-start;
gap: 1.25rem;
}
#head { width: 40%; }
.label {
letter-spacing: 0.02rem;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
}
.pre-darkmode { color: #ffffff; }
.pre-lightmode { color: #000000; }
.data {
display: flex;
flex-direction: row;
padding: 0 0.625rem;
border-radius: 0.3125rem;
box-shadow: 0.0625rem 0.0625rem 0.25rem 0rem rgba(0, 0, 0, 0.25) inset;
background-color: #212121;
align-items: center;
justify-content: flex-start;
letter-spacing: 0.02rem;
font: 400 0.75rem/1.875rem Overpass, sans-serif;
}
.data-darkmode {
background-color: #212121;
color: #ffffff;
}
.data-lightmode {
background-color: #ebebeb;
color: #000000;
}
.notes {
display: flex;
flex: auto;
flex-direction: column;
padding: 1.25rem 1.875rem 0.625rem;
align-items: flex-start;
justify-content: center;
gap: 0.625rem;
}
.area-title {
letter-spacing: 0.03rem;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
}
#notes { align-self: stretch; }
</style>

View File

@ -1,117 +0,0 @@
<template>
<section :class="['data', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Employees:</div>
<table class="data-table" id="client-employee-table">
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th :class="['ID', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']">ID</th>
<th :class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">Name</th>
<th :class="['JobTitle', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'JobTitle-darkmode' : 'JobTitle-lightmode']">Job Title</th>
<th :class="['Pronouns', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Pronouns-darkmode' : 'Pronouns-lightmode']">Pronouns</th>
</tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td :class="['ID', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']">...</td>
<td :class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">...</td>
<td :class="['JobTitle', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'JobTitle-darkmode' : 'JobTitle-lightmode']">...</td>
<td :class="['Pronouns', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Pronouns-darkmode' : 'Pronouns-lightmode']">...</td>
</tr>
</table>
</section>
</template>
<script setup>
import { ref } from 'vue';
const darkMode = ref(true)
</script>
<script>
export default {
name: "ClientDepartmentEmployeeList",
};
</script>
<style scoped>
.data {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
align-self: stretch;
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: #ffffff; }
.label {
padding: 1.25rem 0;
letter-spacing: 0.04rem;
text-decoration-line: underline;
font: 400 1rem/1.875rem Overpass, sans-serif;
}
.label-darkmode { color: #ffffff; }
.label-lightmode { color: #000000; }
.data-table {
width: 100%;
padding: 0 0.625rem;
table-layout: fixed;
border-collapse: collapse;
}
.table-row {
display: flex;
flex-direction: row;
align-items: center;
height: 3.125rem;
padding: 0.625rem;
gap: 0.625rem;
}
.tr-head-darkmode {
border-top: none;
border-bottom: 0.0625rem solid #000000;
}
.tr-head-lightmode {
border-top: none;
border-bottom: 0.0625rem solid #8e8e8e;
}
.tr-darkmode { border-top: 0.0625rem solid #000000; }
.tr-lightmode { border-top: 0.0625rem solid #8e8e8e; }
th, td {
height: 1.875rem;
width: 35%;
padding: 0;
text-align: left;
border-left: none;
letter-spacing: 0.02rem;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
}
th { font: 700 0.875rem/1.875rem Overpass, sans-serif; }
.th-darkmode, .td-darkmode {
color: #ffffff;
border-right: 0.0625rem solid #000000;
}
.th-lightmode, .td-lightmode {
color: #000000;
border-right: 0.0625rem solid #8e8e8e;
}
.ID { width: 20%; }
.Pronouns { width: 10%; }
.Pronouns-darkmode { border-right: none; }
.Pronouns-lightmode { border-right: none; }
</style>

View File

@ -1,116 +0,0 @@
<template>
<section :class="['data', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Employees:</div>
<table class="data-table" id="client-employee-table">
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th :class="['ID', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']">ID</th>
<th :class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">Name</th>
<th :class="['Department', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Department-darkmode' : 'Department-lightmode']">Department / Job Title</th>
<th :class="['Pronouns', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Pronouns-darkmode' : 'Pronouns-lightmode']">Pronouns</th>
</tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td :class="['ID', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']">...</td>
<td :class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">...</td>
<td :class="['Department', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Department-darkmode' : 'Department-lightmode']">...</td>
<td :class="['Pronouns', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Pronouns-darkmode' : 'Pronouns-lightmode']">...</td>
</tr>
</table>
</section>
</template>
<script setup>
import { ref } from 'vue';
const darkMode = ref(true)
</script>
<script>
export default {
name: "ClientEmployeeList",
};
</script>
<style scoped>
.data {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
align-self: stretch;
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: #ffffff; }
.label {
padding: 1.25rem 0;
letter-spacing: 0.04rem;
text-decoration-line: underline;
font: 400 1rem/1.875rem Overpass, sans-serif;
}
.label-darkmode { color: #ffffff; }
.label-lightmode { color: #000000; }
.data-table {
width: 100%;
padding: 0 0.625rem;
table-layout: fixed;
border-collapse: collapse;
}
.table-row {
display: flex;
flex-direction: row;
align-items: center;
height: 3.125rem;
padding: 0.625rem;
gap: 0.625rem;
}
.tr-head-darkmode {
border-top: none;
border-bottom: 0.0625rem solid #000000;
}
.tr-head-lightmode {
border-top: none;
border-bottom: 0.0625rem solid #8e8e8e;
}
.tr-darkmode { border-top: 0.0625rem solid #000000; }
.tr-lightmode { border-top: 0.0625rem solid #8e8e8e; }
th, td {
height: 1.875rem;
width: 35%;
padding: 0;
text-align: left;
border-left: none;
letter-spacing: 0.02rem;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
}
th { font: 700 0.875rem/1.875rem Overpass, sans-serif; }
.th-darkmode, .td-darkmode {
color: #ffffff;
border-right: 0.0625rem solid #000000;
}
.th-lightmode, .td-lightmode {
color: #000000;
border-right: 0.0625rem solid #8e8e8e;
}
.ID { width: 20%; }
.Pronouns { width: 10%; }
.Pronouns-darkmode { border-right: none; }
.Pronouns-lightmode { border-right: none; }
</style>

View File

@ -1,11 +1,11 @@
<template> <template>
<section :class="[darkMode ? 'section-darkmode' : 'section-lightmode']"> <section :class="[darkMode ? 'section-darkmode' : 'section-lightmode']">
<pre :class="['title', darkMode ? 'title-darkmode' : 'title-lightmode']">Customer name</pre> <pre :class="['title', darkMode ? 'title-darkmode' : 'title-lightmode']">Customer name</pre>
<div class="data-field" id="client-id"> <div class="data-field" id="customer-id">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">ID:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">ID:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre>
</div> </div>
<div class="client-data"> <div class="customer-data">
<div class="contact"> <div class="contact">
<pre :class="['area-title', darkMode ? 'h3-darkmode' : 'h3-lightmode']">Contact:</pre> <pre :class="['area-title', darkMode ? 'h3-darkmode' : 'h3-lightmode']">Contact:</pre>
<div class="data-field" id="contact-person"> <div class="data-field" id="contact-person">
@ -52,21 +52,47 @@
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const darkMode = ref('')
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>
export default { export default {
name: "Client", name: "Customer",
}; };
</script> </script>
<style scoped> <style scoped>
section { section {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -76,8 +102,14 @@ section {
align-items: stretch; align-items: stretch;
justify-content: center; justify-content: center;
} }
.section-darkmode { background-color: #2c2c2c; }
.section-lightmode { background-color: #ffffff; } .section-darkmode {
background-color: #2c2c2c;
}
.section-lightmode {
background-color: #ffffff;
}
.title { .title {
@ -86,21 +118,33 @@ section {
text-decoration-line: underline; text-decoration-line: underline;
font: italic 400 1rem/1.875rem Overpass, sans-serif; font: italic 400 1rem/1.875rem Overpass, sans-serif;
} }
.title-darkmode { color: #ffffff; }
.title-lightmode { color: #000000; } .title-darkmode {
color: #ffffff;
}
.title-lightmode {
color: #000000;
}
.data-field { .data-field {
display: flex; display: flex;
flex: auto; flex: auto;
flex-direction: row; flex-direction: row;
padding: 0 1.875rem; padding: 0.8rem 1.875rem;
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
gap: 1.25rem; gap: 1.25rem;
} }
.data-field#client-id { padding: 0.625rem 1.875rem; }
.data-field#street-name { flex: 3; } .data-field#customer-id {
padding: 0.625rem 1.875rem;
}
.data-field#street-name {
flex: 3;
}
.label { .label {
letter-spacing: 0.03rem; letter-spacing: 0.03rem;
@ -110,8 +154,14 @@ section {
pre { pre {
margin: 0; margin: 0;
} }
.pre-darkmode { color: #ffffff; }
.pre-lightmode { color: #000000; } .pre-darkmode {
color: #ffffff;
}
.pre-lightmode {
color: #000000;
}
.data { .data {
display: flex; display: flex;
@ -125,17 +175,19 @@ pre {
letter-spacing: 5%; letter-spacing: 5%;
font: 400 0.75rem/250% Overpass, sans-serif; font: 400 0.75rem/250% Overpass, sans-serif;
} }
.data-darkmode { .data-darkmode {
background-color: #212121; background-color: #212121;
color: #ffffff; color: #ffffff;
} }
.data-lightmode { .data-lightmode {
background-color: #ebebeb; background-color: #ebebeb;
color: #000000; color: #000000;
} }
.client-data { .customer-data {
display: flex; display: flex;
flex: auto; flex: auto;
flex-direction: row; flex-direction: row;
@ -145,7 +197,8 @@ pre {
gap: 0.625rem gap: 0.625rem
} }
.contact, .address { .contact,
.address {
display: flex; display: flex;
flex: auto; flex: auto;
flex-direction: column; flex-direction: column;
@ -159,8 +212,13 @@ pre {
font: 400 0.875rem/1.875rem Overpass, sans-serif; font: 400 0.875rem/1.875rem Overpass, sans-serif;
} }
.h3-darkmode { color: #ffffff; } .h3-darkmode {
.h3-lightmode { color: #000000; } color: #ffffff;
}
.h3-lightmode {
color: #000000;
}
.street-address { .street-address {
@ -180,6 +238,8 @@ pre {
justify-content: center; justify-content: center;
gap: 0.625rem; gap: 0.625rem;
} }
#notes { align-self: stretch; }
#notes {
align-self: stretch;
}
</style> </style>

View File

@ -0,0 +1,193 @@
<template>
<section :class="[darkMode ? 'section-darkmode' : 'section-lightmode']">
<pre :class="['title', darkMode ? 'title-darkmode' : 'title-lightmode']">Department name</pre>
<div class="data-group">
<div class="data-field" id="id">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">ID:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre>
</div>
<div class="data-field" id="customer-id">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer ID:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre>
</div>
<div class="data-field" id="head">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Head:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre>
</div>
</div>
<div class="notes">
<pre :class="['area-title', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Notes:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']" id="notes">...</pre>
</div>
</section>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const darkMode = ref('')
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script>
<script>
export default {
name: "CustomerDepartment",
};
</script>
<style scoped>
* {
box-sizing: border-box;
margin: 0;
}
section {
display: flex;
flex-direction: column;
padding: 1.25rem 1.875rem;
border-radius: 0.625rem;
box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25);
align-items: stretch;
justify-content: center;
}
.section-darkmode {
background-color: #2c2c2c;
}
.section-lightmode {
background-color: #ffffff;
}
.title {
padding: 1.25rem 0;
letter-spacing: 0.04rem;
text-decoration-line: underline;
font: italic 400 1rem/1.875rem Overpass, sans-serif;
}
.title-darkmode {
color: #ffffff;
}
.title-lightmode {
color: #000000;
}
.data-group {
display: flex;
flex: auto;
width: 100%;
flex-direction: row;
padding: 0.625rem 0;
align-items: center;
justify-content: stretch;
}
.data-field {
display: flex;
flex: auto;
width: 30%;
flex-direction: row;
padding: 0.8rem 1.875rem;
align-items: center;
justify-content: flex-start;
gap: 1.25rem;
}
#head {
width: 40%;
}
.label {
letter-spacing: 0.02rem;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
}
.pre-darkmode {
color: #ffffff;
}
.pre-lightmode {
color: #000000;
}
.data {
display: flex;
flex-direction: row;
padding: 0 0.625rem;
border-radius: 0.3125rem;
box-shadow: 0.0625rem 0.0625rem 0.25rem 0rem rgba(0, 0, 0, 0.25) inset;
background-color: #212121;
align-items: center;
justify-content: flex-start;
letter-spacing: 0.02rem;
font: 400 0.75rem/1.875rem Overpass, sans-serif;
}
.data-darkmode {
background-color: #212121;
color: #ffffff;
}
.data-lightmode {
background-color: #ebebeb;
color: #000000;
}
.notes {
display: flex;
flex: auto;
flex-direction: column;
padding: 1.25rem 1.875rem 0.625rem;
align-items: flex-start;
justify-content: center;
gap: 0.625rem;
}
.area-title {
letter-spacing: 0.03rem;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
}
#notes {
align-self: stretch;
}
</style>

View File

@ -0,0 +1,195 @@
<template>
<section :class="['data', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Employees:</div>
<table class="data-table" id="customer-employee-table">
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th
:class="['ID', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']">
ID</th>
<th
:class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
Name</th>
<th
:class="['JobTitle', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'JobTitle-darkmode' : 'JobTitle-lightmode']">
Job Title</th>
<th
:class="['Pronouns', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Pronouns-darkmode' : 'Pronouns-lightmode']">
Pronouns</th>
</tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td
:class="['ID', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']">
...</td>
<td
:class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
...</td>
<td
:class="['JobTitle', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'JobTitle-darkmode' : 'JobTitle-lightmode']">
...</td>
<td
:class="['Pronouns', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Pronouns-darkmode' : 'Pronouns-lightmode']">
...</td>
</tr>
</table>
</section>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const darkMode = ref('')
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script>
<script>
export default {
name: "CustomerDepartmentEmployeeList",
};
</script>
<style scoped>
.data {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
align-self: stretch;
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: #ffffff;
}
.label {
padding: 1.25rem 0;
letter-spacing: 0.04rem;
text-decoration-line: underline;
font: 400 1rem/1.875rem Overpass, sans-serif;
}
.label-darkmode {
color: #ffffff;
}
.label-lightmode {
color: #000000;
}
.data-table {
width: 100%;
padding: 0 0.625rem;
table-layout: fixed;
border-collapse: collapse;
}
.table-row {
display: flex;
flex-direction: row;
align-items: center;
height: 3.125rem;
padding: 0.625rem;
gap: 0.625rem;
}
.tr-head-darkmode {
border-top: none;
border-bottom: 0.0625rem solid #000000;
}
.tr-head-lightmode {
border-top: none;
border-bottom: 0.0625rem solid #8e8e8e;
}
.tr-darkmode {
border-top: 0.0625rem solid #000000;
}
.tr-lightmode {
border-top: 0.0625rem solid #8e8e8e;
}
th,
td {
height: 1.875rem;
width: 35%;
padding: 0;
text-align: left;
border-left: none;
letter-spacing: 0.02rem;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
}
th {
font: 700 0.875rem/1.875rem Overpass, sans-serif;
}
.th-darkmode,
.td-darkmode {
color: #ffffff;
border-right: 0.0625rem solid #000000;
}
.th-lightmode,
.td-lightmode {
color: #000000;
border-right: 0.0625rem solid #8e8e8e;
}
.ID {
width: 20%;
}
.Pronouns {
width: 10%;
}
.Pronouns-darkmode {
border-right: none;
}
.Pronouns-lightmode {
border-right: none;
}
</style>

View File

@ -1,7 +1,7 @@
<template> <template>
<section :class="['data', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section :class="['data', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Departments:</div> <div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Departments:</div>
<table class="data-table" id="client-employee-table"> <table class="data-table" id="customer-employee-table">
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head"> <tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th :class="['ID', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']">ID</th> <th :class="['ID', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']">ID</th>
<th :class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">Name</th> <th :class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">Name</th>
@ -18,14 +18,42 @@
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const darkMode = ref('')
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>
export default { export default {
name: "ClientDepartmentList", name: "CustomerDepartmentList",
}; };
</script> </script>

View File

@ -32,7 +32,7 @@
</div> </div>
</div> </div>
<div class="data-group" id="employment-data"> <div class="data-group" id="employment-data">
<div class="data-field" id="client-id"> <div class="data-field" id="customer-id">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer ID:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer ID:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre>
</div> </div>
@ -65,21 +65,48 @@
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const darkMode = ref('')
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>
export default { export default {
name: "ClientEmployee", name: "CustomerEmployee",
}; };
</script> </script>
<style scoped> <style scoped>
* { * {
box-sizing: border-box; box-sizing: border-box;
margin: 0; margin: 0;
@ -95,8 +122,14 @@ section {
align-items: stretch; align-items: stretch;
justify-content: center; justify-content: center;
} }
.section-darkmode { background-color: #2c2c2c; }
.section-lightmode { background-color: #ffffff; } .section-darkmode {
background-color: #2c2c2c;
}
.section-lightmode {
background-color: #ffffff;
}
.title { .title {
@ -105,8 +138,14 @@ section {
text-decoration-line: underline; text-decoration-line: underline;
font: italic 400 1rem/1.875rem Overpass, sans-serif; font: italic 400 1rem/1.875rem Overpass, sans-serif;
} }
.title-darkmode { color: #ffffff; }
.title-lightmode { color: #000000; } .title-darkmode {
color: #ffffff;
}
.title-lightmode {
color: #000000;
}
@ -119,13 +158,18 @@ section {
align-items: center; align-items: center;
justify-content: stretch; justify-content: stretch;
} }
#personal-data { #personal-data {
flex-direction: column; flex-direction: column;
align-items: stretch; align-items: stretch;
justify-content: center; justify-content: center;
gap: 0.625rem; gap: 0.625rem;
} }
#full-name, #other { padding: 0; }
#full-name,
#other {
padding: 0;
}
.data-field { .data-field {
@ -133,21 +177,37 @@ section {
flex: auto; flex: auto;
width: 20%; width: 20%;
flex-direction: row; flex-direction: row;
padding: 0 1.875rem; padding: 0.8rem 1.875rem;
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
gap: 1.25rem; gap: 1.25rem;
} }
#first-name, #last-name, #department, #job-title, #phone { width: 40%; }
#preferred-name, #mail { width: 60%; } #first-name,
#last-name,
#department,
#job-title,
#phone {
width: 40%;
}
#preferred-name,
#mail {
width: 60%;
}
.label { .label {
letter-spacing: 0.02rem; letter-spacing: 0.02rem;
font: 400 0.875rem/1.875rem Overpass, sans-serif; font: 400 0.875rem/1.875rem Overpass, sans-serif;
} }
.pre-darkmode { color: #ffffff; } .pre-darkmode {
.pre-lightmode { color: #000000; } color: #ffffff;
}
.pre-lightmode {
color: #000000;
}
.data { .data {
display: flex; display: flex;
@ -161,10 +221,12 @@ section {
letter-spacing: 0.02rem; letter-spacing: 0.02rem;
font: 400 0.75rem/1.875rem Overpass, sans-serif; font: 400 0.75rem/1.875rem Overpass, sans-serif;
} }
.data-darkmode { .data-darkmode {
background-color: #212121; background-color: #212121;
color: #ffffff; color: #ffffff;
} }
.data-lightmode { .data-lightmode {
background-color: #ebebeb; background-color: #ebebeb;
color: #000000; color: #000000;
@ -186,6 +248,7 @@ section {
font: 400 0.875rem/1.875rem Overpass, sans-serif; font: 400 0.875rem/1.875rem Overpass, sans-serif;
} }
#notes { align-self: stretch; } #notes {
align-self: stretch;
}
</style> </style>

View File

@ -0,0 +1,195 @@
<template>
<section :class="['data', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Employees:</div>
<table class="data-table" id="customer-employee-table">
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th
:class="['ID', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']">
ID</th>
<th
:class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
Name</th>
<th
:class="['Department', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Department-darkmode' : 'Department-lightmode']">
Department / Job Title</th>
<th
:class="['Pronouns', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Pronouns-darkmode' : 'Pronouns-lightmode']">
Pronouns</th>
</tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td
:class="['ID', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']">
...</td>
<td
:class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
...</td>
<td
:class="['Department', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Department-darkmode' : 'Department-lightmode']">
...</td>
<td
:class="['Pronouns', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Pronouns-darkmode' : 'Pronouns-lightmode']">
...</td>
</tr>
</table>
</section>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const darkMode = ref('')
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script>
<script>
export default {
name: "CustomerEmployeeList",
};
</script>
<style scoped>
.data {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
align-self: stretch;
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: #ffffff;
}
.label {
padding: 1.25rem 0;
letter-spacing: 0.04rem;
text-decoration-line: underline;
font: 400 1rem/1.875rem Overpass, sans-serif;
}
.label-darkmode {
color: #ffffff;
}
.label-lightmode {
color: #000000;
}
.data-table {
width: 100%;
padding: 0 0.625rem;
table-layout: fixed;
border-collapse: collapse;
}
.table-row {
display: flex;
flex-direction: row;
align-items: center;
height: 3.125rem;
padding: 0.625rem;
gap: 0.625rem;
}
.tr-head-darkmode {
border-top: none;
border-bottom: 0.0625rem solid #000000;
}
.tr-head-lightmode {
border-top: none;
border-bottom: 0.0625rem solid #8e8e8e;
}
.tr-darkmode {
border-top: 0.0625rem solid #000000;
}
.tr-lightmode {
border-top: 0.0625rem solid #8e8e8e;
}
th,
td {
height: 1.875rem;
width: 35%;
padding: 0;
text-align: left;
border-left: none;
letter-spacing: 0.02rem;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
}
th {
font: 700 0.875rem/1.875rem Overpass, sans-serif;
}
.th-darkmode,
.td-darkmode {
color: #ffffff;
border-right: 0.0625rem solid #000000;
}
.th-lightmode,
.td-lightmode {
color: #000000;
border-right: 0.0625rem solid #8e8e8e;
}
.ID {
width: 20%;
}
.Pronouns {
width: 10%;
}
.Pronouns-darkmode {
border-right: none;
}
.Pronouns-lightmode {
border-right: none;
}
</style>

View File

@ -2,20 +2,51 @@
<section :class="['quick-access', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section :class="['quick-access', darkMode ? 'section-darkmode' : 'section-lightmode']">
<h2 :class="['heading', darkMode ? 'heading-darkmode' : 'heading-lightmode']">Quick Access</h2> <h2 :class="['heading', darkMode ? 'heading-darkmode' : 'heading-lightmode']">Quick Access</h2>
<div class="shortcuts"> <div class="shortcuts">
<input :class="[darkMode ? 'input-darkmode' : 'input-lightmode']" type="button" id="maintenance-visits" value="Maintenance Visits"> <input :class="[darkMode ? 'input-darkmode' : 'input-lightmode']" type="button" id="maintenance-visits"
<input :class="[darkMode ? 'input-darkmode' : 'input-lightmode']" type="button" id="production-orders" value="Production Orders"> value="Maintenance Visits">
<input :class="[darkMode ? 'input-darkmode' : 'input-lightmode']" type="button" id="production-orders"
value="Production Orders">
<input :class="[darkMode ? 'input-darkmode' : 'input-lightmode']" type="button" id="issue-slips" value="Assets"> <input :class="[darkMode ? 'input-darkmode' : 'input-lightmode']" type="button" id="issue-slips" value="Assets">
<input :class="[darkMode ? 'input-darkmode' : 'input-lightmode']" type="button" id="solutions" value="Solutions"> <input :class="[darkMode ? 'input-darkmode' : 'input-lightmode']" type="button" id="solutions" value="Solutions">
<input :class="[darkMode ? 'input-darkmode' : 'input-lightmode']" type="button" id="issue-slips" value="Issue Slips"> <input :class="[darkMode ? 'input-darkmode' : 'input-lightmode']" type="button" id="issue-slips"
value="Issue Slips">
</div> </div>
</section> </section>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const darkMode = ref('')
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>

View File

@ -1,6 +1,6 @@
<template> <template>
<section :class="['data', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section :class="['data', darkMode ? 'section-darkmode' : 'section-lightmode']">
<table class="data-table" id="client-table"> <table class="data-table" id="customer-table">
<tbody> <tbody>
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head"> <tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th <th
@ -26,14 +26,42 @@
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const darkMode = ref('')
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>
export default { export default {
name: "ClientTable", name: "CustomerTable",
}; };
</script> </script>
@ -94,7 +122,8 @@ export default {
border-top: 0.0625rem solid #8e8e8e; border-top: 0.0625rem solid #8e8e8e;
} }
th, td { th,
td {
height: 1.875rem; height: 1.875rem;
text-align: left; text-align: left;
padding: 0; padding: 0;
@ -102,11 +131,13 @@ th, td {
font: 400 0.875rem/1.875rem Overpass, sans-serif; font: 400 0.875rem/1.875rem Overpass, sans-serif;
} }
.th-darkmode, .td-darkmode { .th-darkmode,
.td-darkmode {
color: #ffffff; color: #ffffff;
} }
.th-lightmode, .td-lightmode { .th-lightmode,
.td-lightmode {
color: #000000; color: #000000;
} }
@ -128,4 +159,5 @@ th {
.Name { .Name {
width: 60%; width: 60%;
}</style> }
</style>

View File

@ -0,0 +1,498 @@
<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 modeChanged = computed(() => store.state.updateDarkMode);
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('');
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);
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
await 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,510 @@
<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, 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 modeChanged = computed(() => store.state.updateDarkMode);
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('')
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 newDarkModeBool = 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,
darkModeBool: employee.value.darkModeBool,
}
);
} 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,
darkModeBool: newDarkModeBool.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);
}
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(() => {
getSession();
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

@ -0,0 +1,264 @@
<template>
<div :class="['data', darkMode ? 'div-darkmode' : 'div-lightmode']">
<table class="data-table" id="employeetable">
<tbody>
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th
:class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
Name</th>
<th
:class="['Username', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Username-darkmode' : 'Username-lightmode']">
Username</th>
<th :class="['ID', darkMode ? 'th-darkmode' : 'th-lightmode']">ID</th>
</tr>
<tr v-for="u in userList" :key="u.id" :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']">
<td
:class="['Name', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
<nuxt-link to="/employees" id="nuxt-link" class="button"
:class="[darkMode ? 'button-darkmode' : 'button-lightmode', darkMode ? 'nuxt-link-darkmode' : 'nuxt-link-lightmode']"
@click="goToChosenEmployee(u.id)">
{{ u.fullName }}
</nuxt-link>
</td>
<td
:class="['Username', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Username-darkmode' : 'Username-lightmode']">
<nuxt-link to="/employees" id="nuxt-link" class="button"
:class="[darkMode ? 'button-darkmode' : 'button-lightmode', darkMode ? 'nuxt-link-darkmode' : 'nuxt-link-lightmode']"
@click="goToChosenEmployee(u.id)">
{{ u.username }}
</nuxt-link>
</td>
<td :class="['ID', darkMode ? 'td-darkmode' : 'td-lightmode']"> {{ u.id }}</td>
</tr>
</tbody>
</table>
</div>
</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';
// get accesss to the store
const store = useStore()
const modeChanged = computed(() => store.state.updateDarkMode);
const goToChosenEmployee = (id) => {
store.commit('setChosenEmployee', id);
store.commit('changeToEmployee');
};
const employeeFilter = computed(() => store.state.filteredByCustomer);
const darkMode = ref('')
const userList = ref([]);
const adminBool = ref(false);
//get all users
const getEmployees = async () => {
if (adminBool.value) {
if (!(employeeFilter.value === '')) {
await getFilteredUsersByUser();
} else {
try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllEmployees`);
userList.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
}
}
//get all users based on the searched user
const getFilteredUsersByUser = async () => {
try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getSelectedEmployeesByEmployee/${employeeFilter.value}`);
userList.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
watch(employeeFilter, getEmployees);
const getSession = async () => {
const loggedInUserAdminBool = getItem('logged-in-user-adminBool');
if (loggedInUserAdminBool == 0) {
adminBool.value = false;
} else {
adminBool.value = true;
};
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
getSession();
await getEmployees();
});
</script>
<script>
export default {
name: "AssetTable",
};
</script>
<style scoped>
.data {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
align-self: stretch;
padding: 1.25rem 1.875rem;
gap: 1.25rem;
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;
}
.input {
border: none;
}
.data-darkmode {
background-color: #212121;
color: #fff;
}
.data-lightmode {
background-color: #EBEBEB;
color: #000;
}
.div-darkmode {
background-color: #2c2c2c;
}
.div-lightmode {
background-color: #fff;
}
.data-table {
width: 100%;
padding: 0 0.625rem;
table-layout: fixed;
border-collapse: collapse;
}
.table-row {
display: flex;
flex-direction: row;
align-items: center;
height: 3.125rem;
padding: 0.625rem;
gap: 0.625rem;
}
.tr-head-darkmode {
border-top: none;
border-bottom: 0.0625rem solid #000000;
}
.tr-head-lightmode {
border-top: none;
border-bottom: 0.0625rem solid #8e8e8e;
}
.tr-darkmode {
border-top: 0.0625rem solid #000000;
}
.tr-lightmode {
border-top: 0.0625rem solid #8e8e8e;
}
th,
td {
height: 1.875rem;
text-align: left;
padding: 0;
letter-spacing: 5%;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
}
.th-darkmode,
.td-darkmode {
color: #ffffff;
}
.th-lightmode,
.td-lightmode {
color: #000;
}
th {
font: 700 0.875rem/1.875rem Overpass, sans-serif;
}
.Name {
width: 40%;
}
.Name-darkmode {
border-right: 0.0625rem solid #000000;
}
.Name-lightmode {
border-right: 0.0625rem solid #8e8e8e;
}
.Username {
width: 35%;
}
.Username-darkmode {
border-right: 0.0625rem solid #000000;
}
.Username-lightmode {
border-right: 0.0625rem solid #8e8e8e;
}
.ID {
width: 25%;
}
#nuxt-link {
text-decoration: none;
}
.nuxt-link-darkmode {
color: white;
}
.nuxt-link-lightmode {
color: #000;
}
</style>

View File

@ -1,7 +1,8 @@
<template> <template>
<section v-if="hardwareBoolean && !addBool" <section v-if="hardwareBoolean && !addBool"
:class="['hardware-information', darkMode ? 'section-darkmode' : 'section-lightmode']"> :class="['hardware-information', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'div-darkmode' : 'div-lightmode']" id="hardware">Hardware specifications:</div> <div :class="['label', darkMode ? 'div-darkmode' : 'div-lightmode']" id="hardware">Hardware specifications:
</div>
<div class="asset-data"> <div class="asset-data">
<div class="model-CPU"> <div class="model-CPU">
<div class="data-field" id="model"> <div class="data-field" id="model">
@ -55,7 +56,8 @@
</div> </div>
</section> </section>
<section v-if="addBool" :class="['hardware-information', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section v-if="addBool" :class="['hardware-information', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'div-darkmode' : 'div-lightmode']" id="hardware">Hardware specifications:</div> <div :class="['label', darkMode ? 'div-darkmode' : 'div-lightmode']" id="hardware">Hardware specifications:
</div>
<div class="asset-data"> <div class="asset-data">
<div class="model-CPU"> <div class="model-CPU">
<div class="data-field" id="model"> <div class="data-field" id="model">
@ -104,13 +106,15 @@
<script setup> <script setup>
import { ref, onMounted } from 'vue'; import { ref, onMounted, watch } 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'; import { useStore } from 'vuex';
import { computed } from 'vue'; import { computed } from 'vue';
const store = useStore(); const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const editable = computed(() => store.state.editable); const editable = computed(() => store.state.editable);
const chosenAssetId = computed(() => store.state.chosenAssetId); const chosenAssetId = computed(() => store.state.chosenAssetId);
const addBool = computed(() => store.state.new); const addBool = computed(() => store.state.new);
@ -123,7 +127,7 @@ const newRAM = ref('');
const newStorageConfiguration = ref(''); const newStorageConfiguration = ref('');
const newMiscellaneous = ref(''); const newMiscellaneous = ref('');
const darkMode = ref(true) const darkMode = ref('')
const item = ref({}); const item = ref({});
const hardwareBoolean = ref(false) const hardwareBoolean = ref(false)
@ -204,8 +208,28 @@ const updateConfigItem = async () => {
} }
} }
onMounted(() => { const getSession = async () => {
getItemById(); const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
getSession();
await getItemById();
}); });
</script> </script>

View File

@ -40,9 +40,37 @@
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const darkMode = ref('')
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>

View File

@ -1,22 +1,33 @@
<template> <template>
<section :class="['information', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section v-if="!addBool" :class="['information', darkMode ? 'section-darkmode' : 'section-lightmode']">
<h2 :class="['issue-name', darkMode ? 'h2-darkmode' : 'h2-lightmode']">Name</h2> <h2 v-if="!editable" :class="['issue-name', darkMode ? 'h2-darkmode' : 'h2-lightmode']">{{ issue.name }}</h2>
<input v-if="editable" v-model="issue.name" @change="updateIssueItem()"
:class="['data', 'issue-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']">
<div class="issue-data"> <div class="issue-data">
<div class="type"> <div class="type">
<div class="data-field" id="type"> <div class="data-field" id="type">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Type:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Type:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ issue.type }}</pre>
<input v-if="editable" v-model="issue.type" @change="updateIssueItem()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div> </div>
</div> </div>
<div class="info"> <div class="info">
<div class="state-amount"> <div class="state-amount">
<div class="data-field" id="state"> <div class="data-field" id="state">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">State:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">State:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ issue.state }}</pre>
<input v-if="editable" v-model="issue.state" @change="updateIssueItem()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div> </div>
<div class="data-field" id="amount"> <div class="data-field" id="amount">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Amount:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Amount:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ issue.amount }}</pre>
<input v-if="editable" v-model="issue.amount" @change="updateIssueItem()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div> </div>
</div> </div>
</div> </div>
@ -25,7 +36,44 @@
<div class="additional"> <div class="additional">
<div class="properties"> <div class="properties">
<h3 :class="['area-title', darkMode ? 'h3-darkmode' : 'h3-lightmode']">Properties:</h3> <h3 :class="['area-title', darkMode ? 'h3-darkmode' : 'h3-lightmode']">Properties:</h3>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']" id="properties">...</pre> <input v-model="issue.properties" :readonly="!editable" @change="updateIssueItem()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']" id="properties">
</div>
</div>
</div>
</section>
<section v-if="addBool" :class="['information', darkMode ? 'section-darkmode' : 'section-lightmode']">
<input v-model="newName" @change="updateII()"
:class="['data', 'issue-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']">
<div class="issue-data">
<div class="type">
<div class="data-field" id="type">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Type:</pre>
<input v-model="newType" @change="updateII()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
</div>
<div class="info">
<div class="state-amount">
<div class="data-field" id="state">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">State:</pre>
<input v-model="newState" @change="updateII()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
<div class="data-field" id="amount">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Amount:</pre>
<input v-model="newAmount" @change="updateII()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
</div>
</div>
</div>
<div class="issue-data">
<div class="additional">
<div class="properties">
<h3 :class="['area-title', darkMode ? 'h3-darkmode' : 'h3-lightmode']">Properties:</h3>
<input v-model="newProperties" @change="updateII()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']" id="properties">
</div> </div>
</div> </div>
</div> </div>
@ -34,9 +82,157 @@
<script setup> <script setup>
import { ref } from 'vue'; 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 darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const editable = computed(() => store.state.editable);
const chosenIssueId = computed(() => store.state.chosenIssueId);
const deleteBool = computed(() => store.state.deleteBool);
const addBool = computed(() => store.state.new);
const darkMode = ref('');
const issue = ref({});
const issues = ref([]);
const newName = ref('');
const newType = ref('');
const newState = ref('');
const newAmount = ref('');
const newProperties = ref('');
//get all issue
const getIssues = async () => {
try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllIssues`);
issues.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
const confirmDeleteIssue = async () => {
if (deleteBool.value === true) {
if (confirm("Do you really want to delete this issue? It cannot be undone!")) {
try {
await Axios.delete(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/deleteIssueItem/${chosenIssueId.value}`);
} catch (err) {
console.log(err.response.statusText);
}
try {
await Axios.delete(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/deleteIV/${chosenIssueId.value}`);
} catch (err) {
console.log(err.response.statusText);
}
store.commit('undoDelete');
store.commit('resetStore');
store.commit('changeToIssueItemList');
} else {
store.commit('undoDelete');
}
}
}
//update data
const updateIssueItem = async () => {
if (issue.value.name.trim() === "") {
alert("Please add an issue name!");
return;
} else {
var counter = 0;
// check if the issue name already exists
issues.value.forEach(i => {
if (i.name === issue.value.name) {
counter += 1;
}
});
if (counter == 2) {
alert("This issue name already exists. Please choose an unique issue name or modify respectively delete the old one!");
issue.value.name = '';
return;
}
try {
await Axios.put(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/updateIssueItem`,
{
primaryID: issue.value.primaryID,
name: issue.value.name,
type: issue.value.type,
state: issue.value.state,
amount: issue.value.amount,
properties: issue.value.properties,
}
)
await getIssueById();
} catch (err) {
console.log(err.response.statusText);
}
}
}
// get issue from id
const getIssueById = async () => {
if (!addBool.value) {
try {
const response = await Axios.get(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getIssueItem/${chosenIssueId.value}`
);
issue.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
}
// update issue fields in the store
const updateII = () => {
const ii = {
name: newName.value,
type: newType.value,
state: newState.value,
amount: newAmount.value,
properties: newProperties.value,
};
store.commit('updateIssueComponent', ii);
}
// include delay to avoid 503 error
const triggerBackendCallsWithDelay = async (fetchDataFunc) => {
setTimeout(() => {
fetchDataFunc();
}, 1500);
}
watch(deleteBool, confirmDeleteIssue);
watch(modeChanged, getSession)
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
onMounted(async () => {
await getSession();
await getIssueById();
triggerBackendCallsWithDelay(getIssues);
});
</script> </script>
<script> <script>
@ -67,7 +263,27 @@ export default {
background-color: #fff; background-color: #fff;
} }
.issue-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-input-darkmode {
background-color: #212121;
}
.h2-input-lightmode {
background-color: #EBEBEB;
}
.input {
border: none;
}
.issue-name { .issue-name {
align-self: stretch; align-self: stretch;
@ -92,7 +308,7 @@ export default {
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
width: 100%; width: 100%;
padding: 0 1.875rem; padding: 0.8rem 1.875rem;
gap: 1.25rem; gap: 1.25rem;
border-radius: 0.625rem; border-radius: 0.625rem;
} }

View File

@ -1,22 +1,33 @@
<template> <template>
<section :class="['information', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section v-if="!addBool" :class="['information', darkMode ? 'section-darkmode' : 'section-lightmode']">
<h2 :class="['issueSlip-name', darkMode ? 'h2-darkmode' : 'h2-lightmode']">ID issue slips</h2> <h2 :class="['issueSlip-name', darkMode ? 'h2-darkmode' : 'h2-lightmode']">{{ issueSlip.primaryID }}</h2>
<div class="issueSlip-data"> <div class="issueSlip-data">
<div class="client"> <div class="customer">
<div class="data-field" id="client"> <div class="data-field" id="customer">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ issueSlip.customer }}</pre>
<select v-if="editable" id="customersDropDownChosenCI" v-model="issueSlip.customer"
@change="updateCustomerID()" :class="[darkMode ? 'select-darkmode' : 'select-lightmode']">
<option v-for="cust in customers" :key="cust.primaryID">
{{ cust.customername }}
</option>
</select>
</div> </div>
</div> </div>
<div class="info"> <div class="info">
<div class="ticketNo-user"> <div class="ticketNo-user">
<div class="data-field" id="ticketNo"> <div class="data-field" id="ticketNo">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Ticket No.:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Ticket No.:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ issueSlip.ticketNo }}</pre>
</div> </div>
<div class="data-field" id="user"> <div class="data-field" id="user">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">User:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">User:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ issueSlip.user }}</pre>
<input v-if="editable" v-model="issueSlip.user" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div> </div>
</div> </div>
</div> </div>
@ -25,18 +36,277 @@
<div class="additional"> <div class="additional">
<div class="notes"> <div class="notes">
<h3 :class="['area-title', darkMode ? 'h3-darkmode' : 'h3-lightmode']">Notes:</h3> <h3 :class="['area-title', darkMode ? 'h3-darkmode' : 'h3-lightmode']">Notes:</h3>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']" id="notes">...</pre> <input v-model="issueSlip.notes" :readonly="!editable" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']" id="notes">
</div>
</div>
<div class="additional">
<div class="deliveryAddress">
<h3 :class="['area-title', darkMode ? 'h3-darkmode' : 'h3-lightmode']">Different delivery address:
</h3>
<input v-model="issueSlip.deliveryAddress" :readonly="!editable" @change="updateIssueSlip()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']" id="deliveryAddress">
</div>
</div>
</div>
</section>
<section v-if="addBool" :class="['information', darkMode ? 'section-darkmode' : 'section-lightmode']">
<h2 :class="['issueSlip-name', darkMode ? 'h2-darkmode' : 'h2-lightmode']">Issue slip ID</h2>
<div class="issueSlip-data">
<div class="client">
<div class="data-field" id="client">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre>
<select id="customersDropDownChosenCI" v-model="newCustomer" @change="updateNewCustomerID()"
:class="[darkMode ? 'select-darkmode' : 'select-lightmode']">
<option v-for="cust in customers" :key="cust.primaryID">
{{ cust.customername }}
</option>
</select>
</div>
</div>
<div class="info">
<div class="ticketNo-user">
<div class="data-field" id="ticketNo">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Ticket No.:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']"></pre>
<!-- <select id="ticketNoDropDownChosenCI" v-model="newTicketNo" @change="updateIS()"
:class="[darkMode ? 'select-darkmode' : 'select-lightmode']">
<option v-for="po in productionOrders" :key="po.ticketNumber">
{{ po.ticketNumber }}
</option>
</select> -->
</div>
<div class="data-field" id="user">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">User:</pre>
<input v-model="newUser" @change="updateIS()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div>
</div>
</div>
</div>
<div class="issueSlip-data">
<div class="additional">
<div class="notes">
<h3 :class="['area-title', darkMode ? 'h3-darkmode' : 'h3-lightmode']">Notes:</h3>
<input v-model="newNotes" @change="updateIS()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']" id="notes">
</div>
</div>
<div class="additional">
<div class="deliveryAddress">
<h3 :class="['area-title', darkMode ? 'h3-darkmode' : 'h3-lightmode']">Different delivery address:
</h3>
<input v-model="newDeliveryAddress" @change="updateIS()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']" id="deliveryAddress">
</div> </div>
</div> </div>
</div> </div>
</section> </section>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; 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 darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const editable = computed(() => store.state.editable);
const chosenIssueSlipId = computed(() => store.state.chosenIssueSlipId);
const deleteBool = computed(() => store.state.deleteBool);
const addBool = computed(() => store.state.new);
const darkMode = ref('');
const issueSlip = ref({});
const customer = ref({});
const productionOrders = ref([]);
const customers = ref([]);
const newTicketNo = ref('');
const newCustomerID = ref('');
const newCustomer = ref('');
const newUser = ref('');
const newNotes = ref('');
const newDeliveryAddress = ref('');
// get issue slip from id
const getIssueSlipById = async () => {
if (!addBool.value) {
try {
const response = await Axios.get(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getIssueSlip/${chosenIssueSlipId.value}`
);
issueSlip.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
}
// update issue slip fields in the store
const updateIS = () => {
const is = {
customerId: newCustomerID.value,
customer: newCustomer.value,
// ticketNo: newTicketNo.value,
ticketNo: 1,
notes: newNotes.value,
user: newUser.value,
deliveryAddress: newDeliveryAddress.value,
};
store.commit('updateIssueSlipComponent', is);
}
//update data
const updateIssueSlip = async () => {
// delete later
issueSlip.value.ticketNo = 1;
if (issueSlip.value.ticketNo.length === 0) {
alert("Please add a ticket Number!");
return;
}
try {
await Axios.put(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/updateIssueSlip`,
{
primaryID: issueSlip.value.primaryID,
customerID: issueSlip.value.customerID,
customer: issueSlip.value.customer,
ticketNo: issueSlip.value.ticketNo,
creationDate: issueSlip.value.creationDate,
lastView: issueSlip.value.lastView,
user: issueSlip.value.user,
notes: issueSlip.value.notes,
deliveryAddress: issueSlip.value.deliveryAddress,
supplierRequestDate: issueSlip.value.supplierRequestDate,
supplierRequest: issueSlip.value.supplierRequest,
supplierOfferDate: issueSlip.value.supplierOfferDate,
supplierOffer: issueSlip.value.supplierOffer,
clientOfferDate: issueSlip.value.clientOfferDate,
clientOffer: issueSlip.value.clientOffer,
clientOrderDate: issueSlip.value.clientOrderDate,
clientOrder: issueSlip.value.clientOrder,
supplierOrder: issueSlip.value.supplierOrder,
supplierOrderDate: issueSlip.value.supplierOrderDate,
ingressDate: issueSlip.value.ingressDate,
ingress: issueSlip.value.ingress,
egressDate: issueSlip.value.egressDate,
egress: issueSlip.value.egress,
ingressBillDate: issueSlip.value.ingressBillDate,
ingressBill: issueSlip.value.ingressBill,
egressBillDate: issueSlip.value.egressBillDate,
egressBill: issueSlip.value.egressBill,
}
)
await getIssueSlipById();
} catch (err) {
console.log(err.response.statusText);
}
}
//get all customers
const getCustomers = async () => {
try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllCustomers`
);
customers.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
//get all production orders
const getProductionOrders = async () => {
// try {
// const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllCustomers`
// );
// customers.value = response.data;
// } catch (err) {
// console.log(err.response.statusText);
// }
}
const confirmDeleteIssueSlip = async () => {
if (deleteBool.value === true) {
if (confirm("Do you really want to delete this issue slip? It cannot be undone!")) {
try {
await Axios.delete(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/deleteIssueSlip/${chosenIssueSlipId.value}`);
} catch (err) {
console.log(err.response.statusText);
}
try {
await Axios.delete(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/deleteTodosOI/${chosenIssueSlipId.value}`);
} catch (err) {
console.log(err.response.statusText);
}
store.commit('undoDelete');
store.commit('resetStore');
store.commit('changeToIssueSliplist');
} else {
store.commit('undoDelete');
}
}
}
// update customerid if customer was changed
const updateCustomerID = async () => {
try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCustomerByName/${issueSlip.value.customer}`);
customer.value = response.data;
issueSlip.value.customerID = customer.value.customerID;
} catch (err) {
console.log(err.response.statusText);
}
await updateIssueSlip();
}
// update customerid if customer was changed
const updateNewCustomerID = async () => {
try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCustomerByName/${newCustomer.value}`);
newCustomerID.value = response.data.customerID;
} catch (err) {
console.log(err.response.statusText);
}
updateIS();
}
// include delay to avoid 503 error
const triggerBackendCallsWithDelay = async (fetchDataFunc) => {
setTimeout(() => {
fetchDataFunc();
}, 1500);
}
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(deleteBool, confirmDeleteIssueSlip);
watch(modeChanged, getSession)
onMounted(async () => {
getSession();
await getIssueSlipById();
await getProductionOrders();
triggerBackendCallsWithDelay(getCustomers);
});
</script> </script>
<script> <script>
@ -92,7 +362,7 @@ export default {
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
width: 100%; width: 100%;
padding: 0 1.875rem; padding: 0.8rem 1.875rem;
gap: 1.25rem; gap: 1.25rem;
border-radius: 0.625rem; border-radius: 0.625rem;
} }
@ -129,6 +399,10 @@ export default {
font: 400 0.75rem/250% Overpass, sans-serif; font: 400 0.75rem/250% Overpass, sans-serif;
} }
.input {
border: none;
}
.data-darkmode { .data-darkmode {
background-color: #212121; background-color: #212121;
color: #fff; color: #fff;
@ -147,7 +421,7 @@ export default {
align-self: stretch; align-self: stretch;
} }
.client, .customer,
.info { .info {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -165,7 +439,7 @@ export default {
align-items: flex-start; align-items: flex-start;
justify-content: center; justify-content: center;
line-height: normal; line-height: normal;
width: 100%; width: 50%;
padding: 0rem 0.625rem; padding: 0rem 0.625rem;
border-radius: 0.3125rem; border-radius: 0.3125rem;
} }
@ -193,10 +467,12 @@ export default {
gap: 0.625rem; gap: 0.625rem;
} }
.data#notes { .data#notes,
.data#deliveryAddress {
align-self: stretch; align-self: stretch;
} }
.deliveryAddress,
.notes { .notes {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -206,4 +482,20 @@ export default {
padding: 0.625rem 1.875rem 0.625rem 1.25rem; padding: 0.625rem 1.875rem 0.625rem 1.25rem;
padding-top: 0rem; padding-top: 0rem;
} }
.select-darkmode {
border: none;
color: white;
background: #212121;
padding: 0.4rem;
border-radius: 0.3125rem;
}
.select-lightmode {
border: none;
color: black;
background: #EBEBEB;
padding: 0.4rem;
border-radius: 0.3125rem;
}
</style> </style>

View File

@ -1,11 +1,16 @@
<template> <template>
<section v-if="searchable" :class="['issue-slip-search', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['clientLabel', darkMode ? 'label-darkmode' : 'label-lightmode']">Ticket No</div>
<input v-model="issueSlipSearchFilter" @change="searchIssueSlip()"
:class="['dataInput', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</section>
<div :class="['data', darkMode ? 'div-darkmode' : 'div-lightmode']"> <div :class="['data', darkMode ? 'div-darkmode' : 'div-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Last viewed:</div> <div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Last viewed:</div>
<table class="data-table" id="asset-table"> <table class="data-table" id="asset-table">
<tbody> <tbody>
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head"> <tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th <th
:class="['Client', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Client-darkmode' : 'Client-lightmode']"> :class="['Customer', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Customer-darkmode' : 'Customer-lightmode']">
Customer</th> Customer</th>
<th <th
:class="['ID', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']"> :class="['ID', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']">
@ -22,11 +27,16 @@
<tr v-for="issueSlip in issueSlips" :key="issueSlip.primaryID" <tr v-for="issueSlip in issueSlips" :key="issueSlip.primaryID"
:class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1"> :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td <td
:class="['Client', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Client-darkmode' : 'Client-lightmode']"> :class="['Customer', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Customer-darkmode' : 'Customer-lightmode']">
{{ issueSlip.customer }}</td> {{ issueSlip.customer }}</td>
<td <td
:class="['ID', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']"> :class="['ID', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']">
{{ issueSlip.primaryID }}</td> <nuxt-link to="/issueSlips" id="nuxt-link" class="button"
:class="[darkMode ? 'button-darkmode' : 'button-lightmode', darkMode ? 'nuxt-link-darkmode' : 'nuxt-link-lightmode']"
@click="goToChosenIssueSlip(issueSlip.primaryID)">
{{ issueSlip.primaryID }}
</nuxt-link>
</td>
<td <td
:class="['TicketNo', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'TicketNo-darkmode' : 'TicketNo-lightmode']"> :class="['TicketNo', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'TicketNo-darkmode' : 'TicketNo-lightmode']">
{{ issueSlip.ticketNo }}</td> {{ issueSlip.ticketNo }}</td>
@ -42,25 +52,97 @@
<script setup> <script setup>
import { ref, onMounted } from 'vue'; import { ref, onMounted, watch } 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';
import { computed } from 'vue';
const darkMode = ref(true) // get accesss to the store
const store = useStore()
const modeChanged = computed(() => store.state.updateDarkMode);
const goToChosenIssueSlip = (id) => {
store.commit('setChosenIssueSlip', id);
store.commit('changeToIssueSlip');
};
const customerFilter = computed(() => store.state.filteredByCustomer);
const searchable = computed(() => store.state.searchable);
const issueSlipSearchFilter = ref('');
const darkMode = ref('')
const issueSlips = ref([]); const issueSlips = ref([]);
// update search term
const updateSearchTerm = async () => {
issueSlipSearchFilter.value = '';
await getIssueSlips();
}
//get all issueSlips //get all issueSlips
const getIssueSlips = async () => { const getIssueSlips = async () => {
if (!(customerFilter.value === '')) {
await getFilteredIssueSlipsByClient();
} else {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllIssueSlips`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllIssueSlips`);
issueSlips.value = response.data; issueSlips.value = response.data;
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
}
} }
onMounted(() => { //get all issue slips based on the searched client
getIssueSlips(); const getFilteredIssueSlipsByClient = async () => {
try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getSelectedIssueSlipsByClient/${customerFilter.value}`);
issueSlips.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
//get all issue slips based on the searched issue slip id
const searchIssueSlip = async () => {
if (issueSlipSearchFilter.value === '') {
await getIssueSlips();
} else {
try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getSelectedIssueSlipsByTicketNo/${issueSlipSearchFilter.value}`);
issueSlips.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
}
watch(customerFilter, getIssueSlips);
watch(searchable, updateSearchTerm);
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
getSession();
await getIssueSlips();
}); });
</script> </script>
@ -77,7 +159,6 @@ export default {
align-items: flex-start; align-items: flex-start;
justify-content: center; justify-content: center;
align-self: stretch; align-self: stretch;
width: 100%;
padding: 1.25rem 1.875rem; padding: 1.25rem 1.875rem;
gap: 1.25rem; gap: 1.25rem;
border-radius: 0.625rem; border-radius: 0.625rem;
@ -92,6 +173,53 @@ export default {
background-color: #fff; background-color: #fff;
} }
#nuxt-link {
text-decoration: none;
}
.nuxt-link-darkmode {
color: white;
}
.nuxt-link-lightmode {
color: #000;
}
.issue-slip-search {
display: flex;
align-items: center;
padding: 0.625em 1.875em;
gap: 1.25em;
width: 30.125em;
height: 3.125em;
box-shadow: 0.25em 0.25em 0.25em rgba(0, 0, 0, 0.25);
border-radius: 0.625em;
box-sizing: border-box;
}
.dataInput {
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;
}
.section-darkmode {
background-color: #2c2c2c;
}
.section-lightmode {
background-color: #fff;
}
.input {
border: none;
}
.data-table { .data-table {
width: 100%; width: 100%;
padding: 0 0.625rem; padding: 0 0.625rem;
@ -118,6 +246,27 @@ export default {
border-bottom: 0.0625rem solid #8e8e8e; border-bottom: 0.0625rem solid #8e8e8e;
} }
.data-darkmode {
background-color: #212121;
color: #fff;
}
.data-lightmode {
background-color: #EBEBEB;
color: #000;
}
.clientLabel {
width: 5.5625em;
height: 1.875em;
font-family: "Overpass";
font-style: normal;
font-weight: 400;
font-size: 0.875em;
line-height: 1.875;
letter-spacing: 0.05em;
}
.tr-darkmode { .tr-darkmode {
border-top: 0.0625rem solid #000000; border-top: 0.0625rem solid #000000;
} }
@ -149,15 +298,15 @@ th {
font: 700 0.875rem/1.875rem Overpass, sans-serif; font: 700 0.875rem/1.875rem Overpass, sans-serif;
} }
.Client { .Customer {
width: 31.6%; width: 31.6%;
} }
.Client-darkmode { .Customer-darkmode {
border-right: 0.0625rem solid #000000; border-right: 0.0625rem solid #000000;
} }
.Client-lightmode { .Customer-lightmode {
border-right: 0.0625rem solid #8e8e8e; border-right: 0.0625rem solid #8e8e8e;
} }
@ -218,4 +367,5 @@ th {
.label-lightmode { .label-lightmode {
color: #000; color: #000;
}</style> }
</style>

View File

@ -1,187 +0,0 @@
<template>
<div :class="['data', darkMode ? 'div-darkmode' : 'div-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Issue slip:</div>
<table class="data-table" id="asset-table">
<tbody>
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th
:class="['ID', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']">
ID
</th>
<th
:class="['TicketNo', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'TicketNo-darkmode' : 'TicketNo-lightmode']">
Ticket No.</th>
<th
:class="['CreationDate', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'CreationDate-darkmode' : 'CreationDate-lightmode']">
Creation Date</th>
<th :class="['User', darkMode ? 'th-darkmode' : 'th-lightmode']">User</th>
</tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td
:class="['ID', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']">
...</td>
<td
:class="['TicketNo', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'TicketNo-darkmode' : 'TicketNo-lightmode']">
...</td>
<td
:class="['CreationDate', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'CreationDate-darkmode' : 'CreationDate-lightmode']">
...</td>
<td :class="['User', darkMode ? 'td-darkmode' : 'td-lightmode']">...</td>
</tr>
</tbody>
</table>
</div>
</template>
<script setup>
import { ref } from 'vue';
const darkMode = ref(true)
</script>
<script>
export default {
name: "IssueSlipTableNoClient",
};
</script>
<style scoped>
.data {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
align-self: stretch;
width: 100%;
padding: 1.25rem 1.875rem;
gap: 1.25rem;
border-radius: 0.625rem;
box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25);
}
.div-darkmode {
background-color: #2c2c2c;
}
.div-lightmode {
background-color: #fff;
}
.data-table {
width: 100%;
padding: 0 0.625rem;
table-layout: fixed;
border-collapse: collapse;
}
.table-row {
display: flex;
flex-direction: row;
align-items: center;
height: 3.125rem;
padding: 0.625rem;
gap: 0.625rem;
}
.tr-head-darkmode {
border-top: none;
border-bottom: 0.0625rem solid #000000;
}
.tr-head-lightmode {
border-top: none;
border-bottom: 0.0625rem solid #8e8e8e;
}
.tr-darkmode {
border-top: 0.0625rem solid #000000;
}
.tr-lightmode {
border-top: 0.0625rem solid #8e8e8e;
}
th,
td {
height: 1.875rem;
text-align: left;
padding: 0;
letter-spacing: 5%;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
}
.th-darkmode,
.td-darkmode {
color: #ffffff;
}
.th-lightmode,
.td-lightmode {
color: #000;
}
th {
font: 700 0.875rem/1.875rem Overpass, sans-serif;
}
.ID {
width: 47.5%;
}
.ID-darkmode {
border-right: 0.0625rem solid #000000;
}
.ID-lightmode {
border-right: 0.0625rem solid #8e8e8e;
}
.TicketNo {
width: 23.75%;
}
.TicketNo-darkmode {
border-right: 0.0625rem solid #000000;
}
.TicketNo-lightmode {
border-right: 0.0625rem solid #8e8e8e;
}
.CreationDate {
width: 23.75%;
}
.CreationDate-darkmode {
border-right: 0.0625rem solid #000000;
}
.CreationDate-lightmode {
border-right: 0.0625rem solid #8e8e8e;
}
.User {
width: 5%;
}
.label {
width: 6.0625em;
height: 1.875em;
font-family: 'Overpass';
font-style: normal;
font-weight: 400;
font-size: 1em;
line-height: 1.875em;
letter-spacing: 0.05em;
}
.label-darkmode {
color: #FFFFFF;
}
.label-lightmode {
color: #000;
}</style>

View File

@ -1,4 +1,9 @@
<template> <template>
<section v-if="searchable" :class="['issue-search', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['clientLabel', darkMode ? 'label-darkmode' : 'label-lightmode']">Issue name</div>
<input v-model="issueSearchFilter" @change="searchIssue()"
:class="['dataInput', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</section>
<div :class="['data', darkMode ? 'div-darkmode' : 'div-lightmode']"> <div :class="['data', darkMode ? 'div-darkmode' : 'div-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Issues:</div> <div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Issues:</div>
<table class="data-table" id="asset-table"> <table class="data-table" id="asset-table">
@ -19,7 +24,12 @@
:class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1"> :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<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']">
{{ issue.name }}</td> <nuxt-link to="/issueItems" id="nuxt-link" class="button"
:class="[darkMode ? 'button-darkmode' : 'button-lightmode', darkMode ? 'nuxt-link-darkmode' : 'nuxt-link-lightmode']"
@click="goToChosenIssue(issue.primaryID)">
{{ issue.name }}
</nuxt-link>
</td>
<td <td
:class="['Type', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Type-darkmode' : 'Type-lightmode']"> :class="['Type', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Type-darkmode' : 'Type-lightmode']">
{{ issue.type }}</td> {{ issue.type }}</td>
@ -35,25 +45,98 @@
<script setup> <script setup>
import { ref, onMounted } from 'vue'; import { ref, onMounted, watch } 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';
import { computed } from 'vue';
const darkMode = ref(true) // get accesss to the store
const store = useStore()
const modeChanged = computed(() => store.state.updateDarkMode);
const goToChosenIssue = (id) => {
store.commit('setChosenIssue', id);
store.commit('changeToIssueItem');
};
const stateFilter = computed(() => store.state.filteredByCustomer);
const searchable = computed(() => store.state.searchable);
const issueSearchFilter = ref('');
const darkMode = ref('');
const issues = ref([]); const issues = ref([]);
// update search term
const updateSearchTerm = async () => {
issueSearchFilter.value = '';
await getIssues();
}
//get all issue //get all issue
const getIssues = async () => { const getIssues = async () => {
if (!(stateFilter.value === '')) {
await getFilteredIssuesByState();
} else {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllIssues`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllIssues`);
issues.value = response.data; issues.value = response.data;
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
}
} }
onMounted(() => { //get all issues based on the searched state
getIssues(); const getFilteredIssuesByState = async () => {
try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getSelectedIssuesByState/${stateFilter.value}`);
issues.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
//get all issues based on the searched issue name
const searchIssue = async () => {
if (issueSearchFilter.value === '') {
await getIssues();
} else {
try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getSelectedIssuesByIssueName/${issueSearchFilter.value}`);
issues.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
}
watch(stateFilter, getIssues);
watch(searchable, updateSearchTerm);
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
getSession();
await getIssues();
}); });
</script> </script>
@ -87,6 +170,27 @@ export default {
background-color: #fff; background-color: #fff;
} }
.data-darkmode {
background-color: #212121;
color: #fff;
}
.data-lightmode {
background-color: #EBEBEB;
color: #000;
}
.clientLabel {
width: 5.5625em;
height: 1.875em;
font-family: "Overpass";
font-style: normal;
font-weight: 400;
font-size: 0.875em;
line-height: 1.875;
letter-spacing: 0.05em;
}
.data-table { .data-table {
width: 100%; width: 100%;
padding: 0 0.625rem; padding: 0 0.625rem;
@ -94,6 +198,53 @@ export default {
border-collapse: collapse; border-collapse: collapse;
} }
#nuxt-link {
text-decoration: none;
}
.nuxt-link-darkmode {
color: white;
}
.nuxt-link-lightmode {
color: #000;
}
.issue-search {
display: flex;
align-items: center;
padding: 0.625em 1.875em;
gap: 1.25em;
width: 30.125em;
height: 3.125em;
box-shadow: 0.25em 0.25em 0.25em rgba(0, 0, 0, 0.25);
border-radius: 0.625em;
box-sizing: border-box;
}
.dataInput {
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;
}
.section-darkmode {
background-color: #2c2c2c;
}
.section-lightmode {
background-color: #fff;
}
.input {
border: none;
}
.table-row { .table-row {
display: flex; display: flex;
flex-direction: row; flex-direction: row;

View File

@ -1,26 +1,40 @@
<template> <template>
<section :class="['information', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section :class="['information', darkMode ? 'section-darkmode' : 'section-lightmode']">
<h2 :class="['issue-variant-name', darkMode ? 'h2-darkmode' : 'h2-lightmode']">Name</h2> <h2 v-if="!editable" :class="['issue-variant-name', darkMode ? 'h2-darkmode' : 'h2-lightmode']">{{
issueVariant.name }}</h2>
<input v-if="editable" v-model="issueVariant.name" @change="updateIssueVariant()"
:class="['data', 'issue-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']">
<div class="issue-variant-data"> <div class="issue-variant-data">
<div class="variantOf"> <div class="variantOf">
<div class="data-field" id="variantOf"> <div class="data-field" id="variantOf">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Variant of:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Variant of:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']"><nuxt-link to="/issueItems" id="nuxt-link" :class="['button', darkMode ? 'nuxt-link-darkmode' : 'nuxt-link-lightmode']"
@click="goToChosenIssue(issue.primaryID)">{{ nameOfVariant }}</nuxt-link></pre>
</div> </div>
</div> </div>
<div class="info"> <div class="info">
<div class="state-amount-price"> <div class="state-amount-price">
<div class="data-field" id="state"> <div class="data-field" id="state">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">State:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">State:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ issueVariant.state }}</pre>
<input v-if="editable" v-model="issueVariant.state" @change="updateIssueVariant()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div> </div>
<div class="data-field" id="amount"> <div class="data-field" id="amount">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Amount:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Amount:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ issueVariant.amount }}</pre>
<input v-if="editable" v-model="issueVariant.amount" @change="updateIssueVariant()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div> </div>
<div class="data-field" id="price"> <div class="data-field" id="price">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Price:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Price:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ issueVariant.price }}</pre>
<input v-if="editable" v-model="issueVariant.price" @change="updateIssueVariant()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</div> </div>
</div> </div>
</div> </div>
@ -29,18 +43,164 @@
<div class="additional"> <div class="additional">
<div class="properties"> <div class="properties">
<h3 :class="['area-title', darkMode ? 'h3-darkmode' : 'h3-lightmode']">Properties:</h3> <h3 :class="['area-title', darkMode ? 'h3-darkmode' : 'h3-lightmode']">Properties:</h3>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']" id="properties">...</pre> <input v-model="issueVariant.properties" :readonly="!editable" @change="updateIssueVariant()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']" id="properties">
</div> </div>
</div> </div>
</div> </div>
</section> </section>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; 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 modeChanged = computed(() => store.state.updateDarkMode);
const editable = computed(() => store.state.editable);
const chosenIssueId = computed(() => store.state.chosenIssueId);
const chosenIssueVariantId = computed(() => store.state.chosenIssueVariantId);
const deleteBool = computed(() => store.state.deleteBool);
const darkMode = ref(true) const darkMode = ref(true)
const issue = ref({});
const issueVariant = ref({});
const issueVariants = ref([]);
const nameOfVariant = ref('');
//get all issue variants
const getIssueVariants = async () => {
try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllIssueVariants`);
issueVariants.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
const goToChosenIssue = (id) => {
store.commit('setChosenIssue', id);
store.commit('changeToIssueItem');
};
const confirmDeleteIssueVariant = async () => {
if (deleteBool.value === true) {
if (confirm("Do you really want to delete this issue variant? It cannot be undone!")) {
try {
await Axios.delete(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/deleteIssueVariant/${chosenIssueVariantId.value}`);
} catch (err) {
console.log(err.response.statusText);
}
store.commit('undoDelete');
store.commit('resetStore');
store.commit('changeToIssueItemList');
} else {
store.commit('undoDelete');
}
}
}
//update data
const updateIssueVariant = async () => {
if (issueVariant.value.name.trim() === "") {
alert("Please add an issue variant name!");
return;
} else {
var counter = 0;
// check if the issue variant name already exists
issueVariants.value.forEach(i => {
if (i.name === issueVariant.value.name) {
counter += 1;
}
});
if (counter == 2) {
alert("This issue variant name already exists. Please choose an unique issue variant name or modify respectively delete the old one!");
issueVariant.value.name = '';
return;
}
try {
await Axios.put(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/updateIssueVariant`,
{
primaryID: issueVariant.value.primaryID,
issueID: issueVariant.value.issueID,
name: issueVariant.value.name,
state: issueVariant.value.state,
amount: issueVariant.value.amount,
properties: issueVariant.value.properties,
price: issueVariant.value.price,
}
)
await getIssueVariantById();
} catch (err) {
console.log(err.response.statusText);
}
}
}
// include delay to avoid 503 error
const triggerBackendCallsWithDelay = async (fetchDataFunc) => {
setTimeout(() => {
fetchDataFunc();
}, 1500);
}
// get issue variant from id
const getIssueVariantById = async () => {
try {
const response = await Axios.get(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getIssueVariant/${chosenIssueVariantId.value}`
);
issueVariant.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
// get issue from id
const getIssueById = async () => {
try {
const response = await Axios.get(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getIssueItem/${chosenIssueId.value}`
);
issue.value = response.data;
nameOfVariant.value = issue.value.name;
} catch (err) {
console.log(err.response.statusText);
}
}
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(deleteBool, confirmDeleteIssueVariant);
watch(modeChanged, getSession)
onMounted(async () => {
getSession();
await getIssueVariantById();
await getIssueById();
triggerBackendCallsWithDelay(getIssueVariants);
});
</script> </script>
<script> <script>
@ -71,8 +231,6 @@ export default {
background-color: #fff; background-color: #fff;
} }
.issue-variant-name { .issue-variant-name {
align-self: stretch; align-self: stretch;
padding: 1rem 0; padding: 1rem 0;
@ -96,7 +254,7 @@ export default {
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
width: 100%; width: 100%;
padding: 0 1.875rem; padding: 0.8rem 1.875rem;
gap: 1.25rem; gap: 1.25rem;
border-radius: 0.625rem; border-radius: 0.625rem;
} }
@ -151,18 +309,46 @@ export default {
align-self: stretch; align-self: stretch;
} }
.variantOf, .variantOf {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
line-height: normal;
width: 30%;
padding: 0 0;
border-radius: 0.3125rem;
}
.info { .info {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
justify-content: center; justify-content: center;
line-height: normal; line-height: normal;
width: 50%; width: 70%;
padding: 0 0; padding: 0 0;
border-radius: 0.3125rem; border-radius: 0.3125rem;
} }
.issue-name-input {
margin: 1rem;
letter-spacing: 5%;
text-decoration-line: underline;
}
.h2-input-darkmode {
background-color: #212121;
}
.h2-input-lightmode {
background-color: #EBEBEB;
}
.input {
border: none;
}
.additional { .additional {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -210,4 +396,16 @@ export default {
padding: 0.625rem 1.875rem 0.625rem 1.25rem; padding: 0.625rem 1.875rem 0.625rem 1.25rem;
padding-top: 0rem; padding-top: 0rem;
} }
#nuxt-link {
text-decoration: none;
}
.nuxt-link-darkmode {
color: white;
}
.nuxt-link-lightmode {
color: #000;
}
</style> </style>

View File

@ -1,5 +1,6 @@
<template> <template>
<div :class="['data', darkMode ? 'div-darkmode' : 'div-lightmode']"> <section v-if="!addBool"
:class="['issue-variant-list-information', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Variants:</div> <div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Variants:</div>
<table class="data-table" id="issue-variants-table"> <table class="data-table" id="issue-variants-table">
<tbody> <tbody>
@ -18,30 +19,421 @@
Amount</th> Amount</th>
<th :class="['Price', darkMode ? 'th-darkmode' : 'th-lightmode']">Price</th> <th :class="['Price', darkMode ? 'th-darkmode' : 'th-lightmode']">Price</th>
</tr> </tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1"> <tr v-for="issueVar in issueVariants" :key="issueVar.primaryID"
:class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td v-if="!editable"
:class="['Name', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
<nuxt-link to="/issueItems" id="nuxt-link" class="button"
:class="[darkMode ? 'button-darkmode' : 'button-lightmode', darkMode ? 'nuxt-link-darkmode' : 'nuxt-link-lightmode']"
@click="goToChosenIssueVariant(issueVar.primaryID)">
{{ issueVar.name }}
</nuxt-link>
</td>
<td v-if="editable"
:class="['Name', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
<input type="text" v-model="issueVar.name" @change="updateIssueVariant(issueVar)"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td v-if="!editable"
:class="['Properties', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Properties-darkmode' : 'Properties-lightmode']">
{{ issueVar.properties }}</td>
<td v-if="editable"
:class="['Properties', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Properties-darkmode' : 'Properties-lightmode']">
<input type="text" v-model="issueVar.properties" @change="updateIssueVariant(issueVar)"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td v-if="!editable"
:class="['State', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'State-darkmode' : 'State-lightmode']">
{{ issueVar.state }}</td>
<td v-if="editable"
:class="['State', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'State-darkmode' : 'State-lightmode']">
<input type="text" v-model="issueVar.state" @change="updateIssueVariant(issueVar)"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td v-if="!editable"
:class="['Amount', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Amount-darkmode' : 'Amount-lightmode']">
{{ issueVar.amount }}</td>
<td v-if="editable"
:class="['Amount', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Amount-darkmode' : 'Amount-lightmode']">
<input type="text" v-model="issueVar.amount" @change="updateIssueVariant(issueVar)"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td v-if="!editable" :class="['Price', darkMode ? 'td-darkmode' : 'td-lightmode']">{{ issueVar.price
}}</td>
<td v-if="editable" :class="['Price', darkMode ? 'td-darkmode' : 'td-lightmode']"><input type="text"
v-model="issueVar.price" @change="updateIssueVariant(issueVar)"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']"><button
:class="[darkMode ? 'deleteIssueVariant-darkmode' : 'deleteIssueVariant-lightmode']"
@click="deleteIssueVariant(issueVar.primaryID)">-</button>
</td>
</tr>
<tr v-if="editable && addRow" :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']"
id="row-1">
<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']">
...</td> <input type="text" v-model="newNameIV"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td <td
:class="['Properties', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Properties-darkmode' : 'Properties-lightmode']"> :class="['Properties', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Properties-darkmode' : 'Properties-lightmode']">
...</td> <input type="text" v-model="newPropertiesIV"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td <td
:class="['State', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'State-darkmode' : 'State-lightmode']"> :class="['State', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'State-darkmode' : 'State-lightmode']">
...</td> <input type="text" v-model="newStateIV"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td <td
:class="['Amount', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Amount-darkmode' : 'Amount-lightmode']"> :class="['Amount', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Amount-darkmode' : 'Amount-lightmode']">
...</td> <input type="text" v-model="newAmountIV"
<td :class="['Price', darkMode ? 'td-darkmode' : 'td-lightmode']">...</td> :class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td :class="['Price', darkMode ? 'td-darkmode' : 'td-lightmode']"><input type="text"
v-model="newPriceIV"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']"> <button
:class="[darkMode ? 'saveIssueVariant-darkmode' : 'saveIssueVariant-lightmode']"
@click="addIssueVariant()">Save</button> <button
:class="[darkMode ? 'deleteLastIssueVariant-darkmode' : 'deleteLastIssueVariant-lightmode']"
@click="deleteNewRow()">-</button>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </section>
<section v-if="editable && !addBool" id="editIssueVariant">
<button :class="[darkMode ? 'editIssueVariant-darkmode' : 'editIssueVariant-lightmode']"
@click="addChecklistRow()">+</button>
</section>
<section v-if="addBool"
:class="['issue-variant-list-information', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Variants:</div>
<table class="data-table" id="issue-variants-table">
<tbody>
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th
:class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
Name</th>
<th
:class="['Properties', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Properties-darkmode' : 'Properties-lightmode']">
Properties</th>
<th
:class="['State', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'State-darkmode' : 'State-lightmode']">
State</th>
<th
:class="['Amount', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Amount-darkmode' : 'Amount-lightmode']">
Amount</th>
<th :class="['Price', darkMode ? 'th-darkmode' : 'th-lightmode']">Price</th>
</tr>
<tr v-for="(newIV, index) in newVariants" :key="index"
:class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td
:class="['Name', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
<input type="text" v-model="newIV.name"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td
:class="['Properties', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Properties-darkmode' : 'Properties-lightmode']">
<input type="text" v-model="newIV.properties"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td
:class="['State', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'State-darkmode' : 'State-lightmode']">
<input type="text" v-model="newIV.state"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td
:class="['Amount', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Amount-darkmode' : 'Amount-lightmode']">
<input type="text" v-model="newIV.amount"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td :class="['Price', darkMode ? 'td-darkmode' : 'td-lightmode']"><input type="text"
v-model="newIV.price"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']"> <button
:class="[darkMode ? 'deleteLastIssueVariant-darkmode' : 'deleteLastIssueVariant-lightmode']"
@click="deleteIssueVariantFromNewTodos(index)">-</button>
</td>
</tr>
</tbody>
</table>
</section>
<section v-if="addBool" id="editIssueVariant">
<button :class="[darkMode ? 'editIssueVariant-darkmode' : 'editIssueVariant-lightmode']"
@click="addRowForNewIVs()">+</button>
</section>
<section v-if="addBool" id="saveNewIssueVariant">
<button :class="[darkMode ? 'saveNewIssueVariant-darkmode' : 'saveNewIssueVariant-lightmode']"
@click="addIV()">Save</button>
</section>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; 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 darkMode = ref(true) const store = useStore();
const addBool = computed(() => store.state.new);
const editable = computed(() => store.state.editable);
const newName = computed(() => store.state.newNameII);
const newType = computed(() => store.state.newTypeII);
const newState = computed(() => store.state.newStateII);
const newAmount = computed(() => store.state.newAmountII);
const newProperties = computed(() => store.state.newPropertiesII);
const chosenIssueId = computed(() => store.state.chosenIssueId);
const darkMode = ref('');
const addRow = ref(false);
const issueVariants = ref([])
const issue = ref({})
const issues = ref([])
const newNameIV = ref('');
const newAmountIV = ref('');
const newStateIV = ref('');
const newPropertiesIV = ref('');
const newPriceIV = ref('');
const newVariants = reactive([]);
// delete new todo row
const deleteNewRow = () => {
newNameIV.value = '';
newAmountIV.value = '';
newPropertiesIV.value = '';
newStateIV.value = '';
newPriceIV.value = '';
addRow.value = false;
}
const goToChosenIssueVariant = (id) => {
store.commit('setChosenIssueVariant', id);
store.commit('changeToIssueItemVariant');
};
const deleteIssueVariantFromNewTodos = (index) => {
newVariants.splice(index, 1);
}
// add issue variant
const addIV = async () => {
// check if all input data is valid
if (newName.value.trim() === "") {
alert("Please add an issue name!");
return;
} else {
var counter = 0;
if (!(issues.value.length == null)) {
// check if issue name already exists
issues.value.forEach(i => {
if (i.name === newName.value) {
counter += 1;
}
});
if (counter >= 1) {
alert("This issue name already exists. Please choose an unique issue name or modify respectively delete the old one!");
return;
}
}
}
let allFine = true;
newVariants.forEach(variant => {
if (variant.name.length === 0) {
alert(`Please choose a name for all variants.`);
allFine = false
}
})
if (!allFine) {
return
}
try {
const response = await Axios.post(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/addII`,
{
name: newName.value,
type: newType.value,
state: newState.value,
amount: newAmount.value,
properties: newProperties.value,
});
store.commit('resetStore');
store.commit('changeToIssueItemList');
newVariants.forEach(async variant => {
try {
const res = await Axios.post(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/addIssueVariant`,
{
issueID: response.data,
name: variant.name,
properties: variant.properties,
state: variant.state,
amount: variant.amount,
price: variant.price,
});
} catch (err) {
console.log(err.response.statusText);
}
})
} catch (err) {
console.log(err.response.statusText);
}
}
// add new row of variant for the new issue
const addRowForNewIVs = async () => {
newVariants.push({
issueID: chosenIssueId.value,
name: '',
properties: '',
state: '',
amount: '',
price: ''
});
}
//update data
const updateIssueVariant = async (todo) => {
if (todo.name.length === 0) {
alert(`Please add the missing variant name!`);
return;
}
try {
await Axios.put(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/updateIssueVariant`,
{
primaryID: todo.primaryID,
issueID: todo.issueID,
name: todo.name,
properties: todo.properties,
asset: todo.asset,
state: todo.state,
amount: todo.amount,
price: todo.price,
}
);
await getIssueById();
} catch (err) {
console.log(err.response.statusText);
}
}
// add new issue variant
const addIssueVariant = async () => {
// check if all input data is valid
if (newNameIV.value.length === 0) {
alert("Please choose a name for the new issue variant!");
return;
}
try {
const response = await Axios.post(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/addIssueVariant`,
{
issueID: chosenIssueId.value,
name: newNameIV.value,
properties: newPropertiesIV.value,
state: newStateIV.value,
amount: newAmountIV.value,
price: newPriceIV.value,
});
addRow.value = false;
await getIssueVariantsById();
newNameIV.value = '';
newPropertiesIV.value = '';
newStateIV.value = '';
newAmountIV.value = '';
newPriceIV.value = '';
} catch (err) {
console.log(err.response.statusText);
}
}
// add new row for the issue variant
const addChecklistRow = async () => {
if (addRow.value) {
alert('Please confirm the last added row first.')
return
}
addRow.value = true
}
// get issue variants from id
const getIssueVariantsById = async () => {
if (!addBool.value) {
try {
const response = await Axios.get(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getIVs/${chosenIssueId.value}`
);
issueVariants.value = response.data;
} catch (err) {
// console.log(err.response.statusText);
console.log(err.response);
}
}
}
// get issue from id
const getIssueById = async () => {
if (!addBool.value) {
try {
const response = await Axios.get(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getIssueItem/${chosenIssueId.value}`
);
issue.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
}
const deleteIssueVariant = async (id) => {
if (confirm("Do you really want to delete this issue variant? It cannot be undone!")) {
try {
await Axios.delete(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/deleteIssueVariant/${id}`);
} catch (err) {
console.log(err.response.statusText);
}
}
await getIssueVariantsById();
}
// include delay to avoid 503 error
const triggerBackendCallsWithDelay = async (fetchDataFunc) => {
setTimeout(() => {
fetchDataFunc();
}, 1000);
}
//get all issue
const getAllIssues = async () => {
try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllIssues`);
issues.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
onMounted(async () => {
getSession();
await getIssueVariantsById();
await getIssueById();
triggerBackendCallsWithDelay(getAllIssues);
});
</script> </script>
<script> <script>
@ -55,22 +447,42 @@ export default {
<style scoped> <style scoped>
.data { .data {
display: flex; display: flex;
flex-direction: column; flex-direction: row;
align-items: flex-start; align-items: flex-start;
justify-content: center; padding: 0 0.625rem;
align-self: stretch; border-radius: 0.3125rem;
width: 100%; box-shadow: 0.0625rem 0.0625rem 0.25rem 0rem rgba(0, 0, 0, 0.25) inset;
padding: 1.25rem 1.875rem; letter-spacing: 5%;
gap: 1.25rem; font: 400 0.75rem/250% Overpass, sans-serif;
border-radius: 0.625rem;
box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25);
} }
.div-darkmode { .saveIssueVariant-darkmode {
background: #212121;
color: #fff;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
border: none;
border-radius: 0.625rem;
margin-left: 3.25rem;
padding-left: 0.9rem;
padding-right: 0.9rem;
}
.saveIssueVariant-lightmode {
background: #EBEBEB;
color: #212121;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
border: none;
border-radius: 0.625rem;
margin-left: 3.25rem;
padding-left: 0.9rem;
padding-right: 0.9rem;
}
.section-darkmode {
background-color: #2c2c2c; background-color: #2c2c2c;
} }
.div-lightmode { .section-lightmode {
background-color: #fff; background-color: #fff;
} }
@ -90,6 +502,64 @@ export default {
gap: 0.625rem; gap: 0.625rem;
} }
.deleteLastIssueVariant-darkmode {
background: #212121;
color: #fff;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
border: none;
border-radius: 0.625rem;
margin-left: 1rem;
padding-left: 0.9rem;
padding-right: 0.9rem;
}
.deleteLastIssueVariant-lightmode {
background: #EBEBEB;
color: #212121;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
border: none;
border-radius: 0.625rem;
margin-left: 1rem;
padding-left: 0.9rem;
padding-right: 0.9rem;
}
.editIssueVariant-darkmode {
background: #2c2c2c;
color: #fff;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
border: none;
padding: 0.825rem 0.7rem;
width: 4%;
border-radius: 0.625rem;
box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25);
}
.data-darkmode {
background-color: #212121;
color: #fff;
}
.editIssueVariant-lightmode {
background: #EBEBEB;
color: #212121;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
border: none;
margin-left: 15rem;
padding-left: 0.9rem;
padding-right: 0.9rem;
border-radius: 0.625rem;
}
.input {
border: none;
}
.data-lightmode {
background-color: #EBEBEB;
color: #000;
}
.tr-head-darkmode { .tr-head-darkmode {
border-top: none; border-top: none;
border-bottom: 0.0625rem solid #000000; border-bottom: 0.0625rem solid #000000;
@ -108,6 +578,38 @@ export default {
border-top: 0.0625rem solid #8e8e8e; border-top: 0.0625rem solid #8e8e8e;
} }
.deleteIssueVariant-darkmode {
background: #212121;
color: #fff;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
border: none;
border-radius: 0.625rem;
margin-left: 8rem;
padding-left: 0.9rem;
padding-right: 0.9rem;
}
.deleteIssueVariant-lightmode {
background: #EBEBEB;
color: #212121;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
border: none;
border-radius: 0.625rem;
margin-left: 8rem;
padding-left: 0.9rem;
padding-right: 0.9rem;
}
.issue-variant-list-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);
}
th, th,
td { td {
height: 1.875rem; height: 1.875rem;
@ -131,8 +633,58 @@ th {
font: 700 0.875rem/1.875rem Overpass, sans-serif; font: 700 0.875rem/1.875rem Overpass, sans-serif;
} }
.deleteIssueVariant-darkmode:hover,
.deleteLastIssueVariant-darkmode:hover,
.saveIssueVariant-darkmode:hover,
.editIssueVariant-darkmode:hover,
.saveNewIssueVariant-darkmode:hover {
background-color: #444444;
cursor: pointer;
}
.deleteIssueVariant-lightmode:hover,
.deleteLastIssueVariant-lightmode:hover,
.saveIssueVariant-lightmode:hover,
.editIssueVariant-lightmode:hover,
.saveNewIssueVariant-lightmode:hover {
background-color: #ACACAC;
cursor: pointer;
}
.saveNewIssueVariant-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);
}
.saveNewIssueVariant-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);
}
#saveNewIssueVariant {
text-align: center;
}
#editIssueVariant {
text-align: right;
}
.Properties { .Properties {
width: 30%; width: 25%;
} }
.Properties-darkmode { .Properties-darkmode {
@ -144,7 +696,7 @@ th {
} }
.Name { .Name {
width: 30%; width: 20%;
} }
.Name-darkmode { .Name-darkmode {
@ -180,7 +732,8 @@ th {
} }
.Price { .Price {
width: 10%; width: 25%;
display: flex;
} }
.label { .label {
@ -201,4 +754,16 @@ th {
.label-lightmode { .label-lightmode {
color: #000; color: #000;
} }
#nuxt-link {
text-decoration: none;
}
.nuxt-link-darkmode {
color: white;
}
.nuxt-link-lightmode {
color: #000;
}
</style> </style>

View File

@ -4,15 +4,15 @@
<div class="maintenance-visits-instance-data"> <div class="maintenance-visits-instance-data">
<div class="instanceInfo"> <div class="instanceInfo">
<div class="data-field" id="info"> <div class="data-field" id="info">
<div class="templateId-client-type" id="templateID"> <div class="templateId-customer-type" id="templateID">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Template ID:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Template ID:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre>
</div> </div>
<div class="templateId-client-type" id="client"> <div class="templateId-customer-type" id="customer">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre>
</div> </div>
<div class="templateId-client-type" id="type"> <div class="templateId-customer-type" id="type">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Type:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Type:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre>
</div> </div>
@ -72,9 +72,37 @@
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const darkMode = ref('');
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>
@ -129,14 +157,14 @@ export default {
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
width: 95%; width: 95%;
padding: 0 1.875rem; padding: 0.8rem 1.875rem;
gap: 1.25rem; gap: 1.25rem;
border-radius: 0.625rem; border-radius: 0.625rem;
} }
.maintenanceType-state-user, .maintenanceType-state-user,
.creationDate-completionDate-timeSpent, .creationDate-completionDate-timeSpent,
.templateId-client-type { .templateId-customer-type {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;

View File

@ -46,9 +46,37 @@
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const darkMode = ref('');
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>

View File

@ -5,8 +5,8 @@
<input v-if="editable" v-model="mvt.name" @change="updateMVT()" <input v-if="editable" v-model="mvt.name" @change="updateMVT()"
:class="['data', 'mvt-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']"> :class="['data', 'mvt-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']">
<div class="maintenance-visits-template-data"> <div class="maintenance-visits-template-data">
<div class="client-ID-type-user"> <div class="customer-ID-type-user">
<div class="data-field" id="client"> <div class="data-field" id="customer">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre>
<pre v-if="!editable" <pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ mvt.customer }}</pre> :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ mvt.customer }}</pre>
@ -20,7 +20,8 @@
<div class="data-field" id="info"> <div class="data-field" id="info">
<div class="id-type-user" id="ID"> <div class="id-type-user" id="ID">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">ID:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">ID:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ mvt.checklistID }}</pre> <pre
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ mvt.checklistID }}</pre>
</div> </div>
<div class="id-type-user" id="type"> <div class="id-type-user" id="type">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Type:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Type:</pre>
@ -53,8 +54,8 @@
<input v-model="newName" @change="updateMaintenanceVisit()" <input v-model="newName" @change="updateMaintenanceVisit()"
:class="['data', 'maintenance-visits-template-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']"> :class="['data', 'maintenance-visits-template-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']">
<div class="maintenance-visits-template-data"> <div class="maintenance-visits-template-data">
<div class="client-ID-type-user"> <div class="customer-ID-type-user">
<div class="data-field" id="client"> <div class="data-field" id="customer">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre>
<select id="customersDropDownChosenCI" v-model="newCustomer" @change="updateNewCustomerID()" <select id="customersDropDownChosenCI" v-model="newCustomer" @change="updateNewCustomerID()"
:class="[darkMode ? 'select-darkmode' : 'select-lightmode']"> :class="[darkMode ? 'select-darkmode' : 'select-lightmode']">
@ -102,12 +103,14 @@ import { useStore } from 'vuex';
import { computed } from 'vue'; import { computed } from 'vue';
const store = useStore(); const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const editable = computed(() => store.state.editable); const editable = computed(() => store.state.editable);
const chosenMVTId = computed(() => store.state.chosenMVTId); const chosenMVTId = computed(() => store.state.chosenMVTId);
const deleteBool = computed(() => store.state.deleteBool); const deleteBool = computed(() => store.state.deleteBool);
const addBool = computed(() => store.state.new); const addBool = computed(() => store.state.new);
const darkMode = ref(true) const darkMode = ref('');
const mvt = ref({}); const mvt = ref({});
const customers = ref([]); const customers = ref([]);
const customer = ref({}); const customer = ref({});
@ -137,8 +140,6 @@ const confirmDeleteMVT = async () => {
if (confirm("Do you really want to delete this maintenance visit template? It cannot be undone!")) { if (confirm("Do you really want to delete this maintenance visit template? It cannot be undone!")) {
try { try {
await Axios.delete(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/deleteMaintenanceVisitTemplate/${chosenMVTId.value}`); await Axios.delete(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/deleteMaintenanceVisitTemplate/${chosenMVTId.value}`);
store.commit('undoDelete');
store.commit('changeToTemplatelist');
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
@ -147,6 +148,9 @@ const confirmDeleteMVT = async () => {
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
store.commit('undoDelete');
store.commit('resetStore');
store.commit('changeToTemplatelist');
} else { } else {
store.commit('undoDelete'); store.commit('undoDelete');
} }
@ -208,8 +212,8 @@ const updateCustomerID = async () => {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCustomerByName/${mvt.value.customer}`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCustomerByName/${mvt.value.customer}`);
customer.value = response.data; customer.value = response.data;
mvt.value.customerID = customer.value.customerID; mvt.value.customerID = customer.value.customerID;
store.commit('toggleClientChanged'); store.commit('toggleCustomerChanged');
store.commit('toggleClientId', mvt.value.customerID); store.commit('toggleCustomerId', mvt.value.customerID);
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
@ -235,8 +239,8 @@ const updateNewCustomerID = async () => {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCustomerByName/${newCustomer.value}`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCustomerByName/${newCustomer.value}`);
newCustomerID.value = response.data.customerID; newCustomerID.value = response.data.customerID;
store.commit('toggleClientChanged'); store.commit('toggleCustomerChanged');
store.commit('toggleClientId', newCustomerID.value) store.commit('toggleCustomerId', newCustomerID.value)
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
@ -263,10 +267,29 @@ const triggerBackendCallsWithDelay = async (fetchDataFunc) => {
}, 1500); }, 1500);
} }
watch(deleteBool, confirmDeleteMVT); const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
onMounted(() => { function getItem(item) {
getMVTById(); if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(deleteBool, confirmDeleteMVT);
watch(modeChanged, getSession)
onMounted(async () => {
getSession();
await getMVTById();
triggerBackendCallsWithDelay(getMaintenanceVisitTemplates); triggerBackendCallsWithDelay(getMaintenanceVisitTemplates);
triggerBackendCallsWithDelay(getCustomers); triggerBackendCallsWithDelay(getCustomers);
}); });
@ -430,7 +453,7 @@ export default {
align-self: stretch; align-self: stretch;
} }
.client-ID-type-user, .customer-ID-type-user,
.info { .info {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@ -1,6 +1,6 @@
<template> <template>
<section v-if="searchable" :class="['mvt-search', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section v-if="searchable" :class="['mvt-search', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['clientLabel', darkMode ? 'label-darkmode' : 'label-lightmode']">Template:</div> <div :class="['customerLabel', darkMode ? 'label-darkmode' : 'label-lightmode']">Template:</div>
<input v-model="mvtSearchFilter" @change="searchMVT()" <input v-model="mvtSearchFilter" @change="searchMVT()"
:class="['dataInput', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']"> :class="['dataInput', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</section> </section>
@ -10,7 +10,7 @@
<tbody> <tbody>
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head"> <tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th <th
:class="['Client', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Client-darkmode' : 'Client-lightmode']"> :class="['Customer', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Customer-darkmode' : 'Customer-lightmode']">
Customer</th> Customer</th>
<th <th
:class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']"> :class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
@ -27,15 +27,16 @@
<tr v-for="template in maintenanceVisitTemplates" :key="template.checklistID" <tr v-for="template in maintenanceVisitTemplates" :key="template.checklistID"
:class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1"> :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td <td
:class="['Client', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Client-darkmode' : 'Client-lightmode']"> :class="['Customer', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Customer-darkmode' : 'Customer-lightmode']">
{{ template.customer }}</td> {{ template.customer }}</td>
<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="/maintenanceVisits" id="nuxt-link" class="button" <nuxt-link to="/maintenanceVisits" id="nuxt-link" class="button"
:class="[darkMode ? 'button-darkmode' : 'button-lightmode']" :class="[darkMode ? 'button-darkmode' : 'button-lightmode', darkMode ? 'nuxt-link-darkmode' : 'nuxt-link-lightmode']"
@click="goToChosenMVT(template.checklistID)"> @click="goToChosenMVT(template.checklistID)">
{{ template.name }} {{ template.name }}
</nuxt-link></td> </nuxt-link>
</td>
<td <td
:class="['ID', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']"> :class="['ID', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']">
{{ template.checklistID }}</td> {{ template.checklistID }}</td>
@ -59,22 +60,24 @@ import { computed } from 'vue';
// get accesss to the store // get accesss to the store
const store = useStore() const store = useStore()
const modeChanged = computed(() => store.state.updateDarkMode);
const goToChosenMVT = (id) => { const goToChosenMVT = (id) => {
store.commit('setChosenMVT', id); store.commit('setChosenMVT', id);
store.commit('changeToTemplate'); store.commit('changeToTemplate');
}; };
const clientFilter = computed(() => store.state.filteredByClient); const customerFilter = computed(() => store.state.filteredByCustomer);
const searchable = computed(() => store.state.searchable); const searchable = computed(() => store.state.searchable);
const mvtSearchFilter = ref(''); const mvtSearchFilter = ref('');
const darkMode = ref(true) const darkMode = ref('');
const maintenanceVisitTemplates = ref([]); const maintenanceVisitTemplates = ref([]);
//get all maintenance visit templates //get all maintenance visit templates
const getMaintenanceVisitTemplates = async () => { const getMaintenanceVisitTemplates = async () => {
if (!(clientFilter.value === '')) { if (!(customerFilter.value === '')) {
await getFilteredMVTByClient(); await getFilteredMVTByCustomer();
} else { } else {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllMaintenanceVisitTemplates`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllMaintenanceVisitTemplates`);
@ -105,20 +108,39 @@ const updateSearchTerm = async () => {
await getMaintenanceVisitTemplates(); await getMaintenanceVisitTemplates();
} }
//get all maintenance visit templates based on the searched client //get all maintenance visit templates based on the searched customer
const getFilteredMVTByClient = async () => { const getFilteredMVTByCustomer = async () => {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getSelectedMVTsByClient/${clientFilter.value}`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getSelectedMVTsByCustomer/${customerFilter.value}`);
maintenanceVisitTemplates.value = response.data; maintenanceVisitTemplates.value = response.data;
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
} }
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(searchable, updateSearchTerm); watch(searchable, updateSearchTerm);
watch(clientFilter, getMaintenanceVisitTemplates); watch(customerFilter, getMaintenanceVisitTemplates);
watch(modeChanged, getSession)
onMounted(async () => { onMounted(async () => {
getSession();
await getMaintenanceVisitTemplates(); await getMaintenanceVisitTemplates();
}); });
</script> </script>
@ -176,9 +198,16 @@ export default {
#nuxt-link { #nuxt-link {
text-decoration: none; text-decoration: none;
}
.nuxt-link-darkmode {
color: white; color: white;
} }
.nuxt-link-lightmode {
color: #000;
}
.dataInput { .dataInput {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@ -190,7 +219,7 @@ export default {
font: 400 0.75rem/250% Overpass, sans-serif; font: 400 0.75rem/250% Overpass, sans-serif;
} }
.clientLabel { .customerLabel {
width: 5.5625em; width: 5.5625em;
height: 1.875em; height: 1.875em;
font-family: "Overpass"; font-family: "Overpass";
@ -270,15 +299,15 @@ th {
font: 700 0.875rem/1.875rem Overpass, sans-serif; font: 700 0.875rem/1.875rem Overpass, sans-serif;
} }
.Client { .Customer {
width: 33.3%; width: 33.3%;
} }
.Client-darkmode { .Customer-darkmode {
border-right: 0.0625rem solid #000000; border-right: 0.0625rem solid #000000;
} }
.Client-lightmode { .Customer-lightmode {
border-right: 0.0625rem solid #8e8e8e; border-right: 0.0625rem solid #8e8e8e;
} }

View File

@ -1,187 +0,0 @@
<template>
<div :class="['data', darkMode ? 'div-darkmode' : 'div-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Templates:</div>
<table class="data-table" id="maintenance-visits-templat-table-no-client">
<tbody>
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th
:class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
Name</th>
<th
:class="['ID', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']">
ID
</th>
<th
:class="['Type', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Type-darkmode' : 'Type-lightmode']">
Type</th>
<th :class="['User', darkMode ? 'th-darkmode' : 'th-lightmode']">User</th>
</tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td
:class="['Name', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
...</td>
<td
:class="['ID', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']">
...</td>
<td
:class="['Type', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Type-darkmode' : 'Type-lightmode']">
...</td>
<td :class="['User', darkMode ? 'td-darkmode' : 'td-lightmode']">...</td>
</tr>
</tbody>
</table>
</div>
</template>
<script setup>
import { ref } from 'vue';
const darkMode = ref(true)
</script>
<script>
export default {
name: "MaintenanceVisitsTemplateTableNoClient",
};
</script>
<style scoped>
.data {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
align-self: stretch;
width: 100%;
padding: 1.25rem 1.875rem;
gap: 1.25rem;
border-radius: 0.625rem;
box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25);
}
.div-darkmode {
background-color: #2c2c2c;
}
.div-lightmode {
background-color: #fff;
}
.data-table {
width: 100%;
padding: 0 0.625rem;
table-layout: fixed;
border-collapse: collapse;
}
.table-row {
display: flex;
flex-direction: row;
align-items: center;
height: 3.125rem;
padding: 0.625rem;
gap: 0.625rem;
}
.tr-head-darkmode {
border-top: none;
border-bottom: 0.0625rem solid #000000;
}
.tr-head-lightmode {
border-top: none;
border-bottom: 0.0625rem solid #8e8e8e;
}
.tr-darkmode {
border-top: 0.0625rem solid #000000;
}
.tr-lightmode {
border-top: 0.0625rem solid #8e8e8e;
}
th,
td {
height: 1.875rem;
text-align: left;
padding: 0;
letter-spacing: 5%;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
}
.th-darkmode,
.td-darkmode {
color: #ffffff;
}
.th-lightmode,
.td-lightmode {
color: #000;
}
th {
font: 700 0.875rem/1.875rem Overpass, sans-serif;
}
.Name {
width: 50%;
}
.Name-darkmode {
border-right: 0.0625rem solid #000000;
}
.Name-lightmode {
border-right: 0.0625rem solid #8e8e8e;
}
.ID {
width: 22.5%;
}
.ID-darkmode {
border-right: 0.0625rem solid #000000;
}
.ID-lightmode {
border-right: 0.0625rem solid #8e8e8e;
}
.Type {
width: 22.5%;
}
.Type-darkmode {
border-right: 0.0625rem solid #000000;
}
.Type-lightmode {
border-right: 0.0625rem solid #8e8e8e;
}
.User {
width: 5%;
}
.label {
width: 6.0625em;
height: 1.875em;
font-family: 'Overpass';
font-style: normal;
font-weight: 400;
font-size: 1em;
line-height: 1.875em;
letter-spacing: 0.05em;
}
.label-darkmode {
color: #FFFFFF;
}
.label-lightmode {
color: #000;
}</style>

View File

@ -67,19 +67,21 @@
</div> </div>
</section> </section>
<section v-if="addBool" id="saveNewItem"> <section v-if="addBool" id="saveNewItem">
<button :class="[darkMode ? 'saveNewItem-darkmode' : 'saveNewItem-lightmode']" @click="addItem()">Safe</button> <button :class="[darkMode ? 'saveNewItem-darkmode' : 'saveNewItem-lightmode']" @click="addItem()">Save</button>
</section> </section>
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from 'vue'; import { ref, onMounted, watch } 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'; import { useStore } from 'vuex';
import { computed } from 'vue'; import { computed } from 'vue';
const store = useStore(); const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const editable = computed(() => store.state.editable); const editable = computed(() => store.state.editable);
const chosenAssetId = computed(() => store.state.chosenAssetId); const chosenAssetId = computed(() => store.state.chosenAssetId);
const addBool = computed(() => store.state.new); const addBool = computed(() => store.state.new);
@ -106,7 +108,7 @@ const newSoftware = computed(() => store.state.newSoftware);
const newVersion = computed(() => store.state.newVersion); const newVersion = computed(() => store.state.newVersion);
const newLicense = computed(() => store.state.newLicense); const newLicense = computed(() => store.state.newLicense);
const darkMode = ref(true) const darkMode = ref('');
const item = ref({}); const item = ref({});
const networkBoolean = ref(false); const networkBoolean = ref(false);
const inputIPv4 = ref(''); const inputIPv4 = ref('');
@ -356,7 +358,27 @@ const triggerBackendCallsWithDelay = async (fetchDataFunc) => {
}, 1000); }, 1000);
} }
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(() => { onMounted(() => {
getSession();
triggerBackendCallsWithDelay(getItemById); triggerBackendCallsWithDelay(getItemById);
triggerBackendCallsWithDelay(getConfigItems); triggerBackendCallsWithDelay(getConfigItems);
}); });

View File

@ -1,5 +1,92 @@
<template> <template>
<section :class="['ordering-information', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section v-if="!addBool" :class="['ordering-information', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']" id="ordering">Ordering information:
<div class="asset-data">
<table class="data-table" id="asset-table-no-customer">
<tbody>
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th
:class="['Article', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Article-darkmode' : 'Article-lightmode']">
Article</th>
<th
:class="['Amount', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Amount-darkmode' : 'Amount-lightmode']">
Amount</th>
<th
:class="['Price', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Price-darkmode' : 'Price-lightmode']">
Price</th>
<th :class="['Comments', darkMode ? 'th-darkmode' : 'th-lightmode']">Comments</th>
</tr>
<tr v-for="info in orderingInfo" :key="info.primaryID"
:class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td v-if="!editable"
:class="['Article', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Article-darkmode' : 'Article-lightmode']">
{{ info.article }}</td>
<td v-if="editable"
:class="['Article', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Article-darkmode' : 'Article-lightmode']">
<input type="text" v-model="info.article" @change="updateOrderingInfo(info)"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td v-if="!editable"
:class="['Amount', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Amount-darkmode' : 'Amount-lightmode']">
{{ info.amount }}</td>
<td v-if="editable"
:class="['Amount', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Amount-darkmode' : 'Amount-lightmode']">
<input type="text" v-model="info.amount" @change="updateOrderingInfo(info)"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td v-if="!editable"
:class="['Price', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Price-darkmode' : 'Price-lightmode']">
{{ info.price }}</td>
<td v-if="editable"
:class="['Price', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Price-darkmode' : 'Price-lightmode']">
<input type="text" v-model="info.price" @change="updateOrderingInfo(info)"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td v-if="!editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">{{
info.comment }}</td>
<td v-if="editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="info.comment" @change="updateOrderingInfo(info)"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']"> <button
:class="[darkMode ? 'deleteOrderingInfo-darkmode' : 'deleteOrderingInfo-lightmode']"
@click="deleteOrderingInfo(info.primaryID)">-</button>
</td>
</tr>
<tr v-if="editable && addRow" :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']"
id="row-1">
<td
:class="['Article', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Article-darkmode' : 'Article-lightmode']">
<input type="text" v-model="newArticle"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td
:class="['Amount', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Amount-darkmode' : 'Amount-lightmode']">
<input type="text" v-model="newAmount"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td
:class="['Price', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Price-darkmode' : 'Price-lightmode']">
<input type="text" v-model="newPrice"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']"><input type="text"
v-model="newComment"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']"> <button
:class="[darkMode ? 'saveOrderingInfo-darkmode' : 'saveOrderingInfo-lightmode']"
@click="addOrderingInfo()">Save</button> <button
:class="[darkMode ? 'deleteLastOrderingInfo-darkmode' : 'deleteLastOrderingInfo-lightmode']"
@click="deleteNewRow()">-</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section v-if="editable && !addBool" id="editOrderingInfo">
<button :class="[darkMode ? 'editOrderingInfo-darkmode' : 'editOrderingInfo-lightmode']"
@click="addChecklistRow()">+</button>
</section>
<section v-if="addBool" :class="['ordering-information', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']" id="ordering">Ordering information: <div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']" id="ordering">Ordering information:
<div class="asset-data"> <div class="asset-data">
<table class="data-table" id="asset-table-no-client"> <table class="data-table" id="asset-table-no-client">
@ -16,30 +103,206 @@
Price</th> Price</th>
<th :class="['Comments', darkMode ? 'th-darkmode' : 'th-lightmode']">Comments</th> <th :class="['Comments', darkMode ? 'th-darkmode' : 'th-lightmode']">Comments</th>
</tr> </tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1"> <tr v-for="(newOI, index) in newOIs" :key="index"
:class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td <td
:class="['Article', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Article-darkmode' : 'Article-lightmode']"> :class="['Article', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Article-darkmode' : 'Article-lightmode']">
...</td> <input type="text" v-model="newOI.article" @change="updateOI()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td <td
:class="['Amount', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Amount-darkmode' : 'Amount-lightmode']"> :class="['Amount', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Amount-darkmode' : 'Amount-lightmode']">
...</td> <input type="text" v-model="newOI.amount" @change="updateOI()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td <td
:class="['Price', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Price-darkmode' : 'Price-lightmode']"> :class="['Price', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Price-darkmode' : 'Price-lightmode']">
...</td> <input type="text" v-model="newOI.price" @change="updateOI()"
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">...</td> :class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td>
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']">
<input type="text" v-model="newOI.comment" @change="updateOI()"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']"> <button
:class="[darkMode ? 'deleteOrderingInfo-darkmode' : 'deleteOrderingInfo-lightmode']"
@click="deleteOIFromNewTodos(index)">-</button>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
</section> </section>
<section v-if="addBool" id="editOrderingInfo">
<button :class="[darkMode ? 'editOrderingInfo-darkmode' : 'editOrderingInfo-lightmode']"
@click="addRowForNewOI()">+</button>
</section>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; 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 darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const addBool = computed(() => store.state.new);
const editable = computed(() => store.state.editable);
const chosenIssueSlipId = computed(() => store.state.chosenIssueSlipId);
const addRow = ref(false);
const orderingInfo = ref([])
const newArticle = ref('');
const newAmount = ref('');
const newPrice = ref('');
const newComment = ref('');
const newOIs = reactive([]);
const darkMode = ref('');
// delete new todo row
const deleteNewRow = () => {
newArticle.value = '';
newAmount.value = '';
newPrice.value = '';
newComment.value = '';
addRow.value = false;
}
const deleteOIFromNewTodos = (index) => {
newOIs.splice(index, 1);
}
// add new ordering info
const addOrderingInfo = async () => {
// check if all input data is valid
if (newAmount.value.length === 0 && newArticle.value.length === 0 && newPrice.value.length === 0 && newComment.value.length === 0) {
alert(`Please add some data in the ordering info row!`);
return;
}
try {
const response = await Axios.post(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/addOrderingInfo`,
{
issueSlipID: chosenIssueSlipId.value,
article: newArticle.value,
amount: newAmount.value,
price: newPrice.value,
comment: newComment.value,
});
addRow.value = false;
await getOIById();
newArticle.value = '';
newAmount.value = '';
newPrice.value = '';
newComment.value = '';
} catch (err) {
console.log(err.response.statusText);
}
}
// update ordering info fields in the store
const updateOI = () => {
const infos = {
ois: newOIs,
};
store.commit('updateOrderingInfoComponent', infos);
}
// add new row of ordering info
const addRowForNewOI = async () => {
newOIs.push({
issueSlipID: -1,
article: '',
amount: '',
price: '',
comment: ''
});
}
//update data
const updateOrderingInfo = async (info) => {
if (info.amount.length === 0 && info.article.length === 0 && info.price.length === 0 && info.comment.length === 0) {
alert(`Please add some data in the ordering info row!`);
return;
}
try {
await Axios.put(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/updateOrderingInfo`,
{
primaryID: info.primaryID,
issueSlipID: info.issueSlipID,
article: info.article,
amount: info.amount,
price: info.price,
comment: info.comment,
}
);
await getOIById();
} catch (err) {
console.log(err.response.statusText);
}
}
// add new row for the ordering info
const addChecklistRow = async () => {
if (addRow.value) {
alert('Please confirm the last added row first.')
return
}
addRow.value = true
}
// get ordering info from id
const getOIById = async () => {
if (!addBool.value) {
try {
const response = await Axios.get(
`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getOrderingInfo/${chosenIssueSlipId.value}`
);
orderingInfo.value = response.data;
} catch (err) {
console.log(err.response.statusText);
}
}
}
const deleteOrderingInfo = async (id) => {
if (confirm("Do you really want to delete this ordering info? It cannot be undone!")) {
try {
await Axios.delete(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/deleteOrderingInfo/${id}`);
} catch (err) {
console.log(err.response.statusText);
}
}
await getOIById();
}
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
getSession();
await getOIById();
});
</script> </script>
<script> <script>
@ -70,6 +333,31 @@ export default {
background-color: #fff; background-color: #fff;
} }
.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;
}
.input {
border: none;
}
.label { .label {
letter-spacing: 5%; letter-spacing: 5%;
font: 400 1rem/1.875rem Overpass, sans-serif; font: 400 1rem/1.875rem Overpass, sans-serif;
@ -194,5 +482,116 @@ th {
.Comments { .Comments {
width: 50%; width: 50%;
display: flex;
}
.deleteOrderingInfo-darkmode {
background: #212121;
color: #fff;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
border: none;
border-radius: 0.625rem;
margin-left: 24.8rem;
padding-left: 0.9rem;
padding-right: 0.9rem;
}
.deleteLastOrderingInfo-darkmode {
background: #212121;
color: #fff;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
border: none;
border-radius: 0.625rem;
margin-left: 2rem;
padding-left: 0.9rem;
padding-right: 0.9rem;
}
.editOrderingInfo-darkmode {
background: #2c2c2c;
color: #fff;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
border: none;
padding: 0.825rem 0.7rem;
width: 4%;
border-radius: 0.625rem;
box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25);
}
.editOrderingInfo-lightmode {
background: #EBEBEB;
color: #212121;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
border: none;
margin-left: 15rem;
padding-left: 0.9rem;
padding-right: 0.9rem;
border-radius: 0.625rem;
}
.saveOrderingInfo-darkmode {
background: #212121;
color: #fff;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
border: none;
border-radius: 0.625rem;
margin-left: 19rem;
padding-left: 0.9rem;
padding-right: 0.9rem;
}
.saveOrderingInfo-lightmode {
background: #EBEBEB;
color: #212121;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
border: none;
border-radius: 0.625rem;
margin-left: 19rem;
padding-left: 0.9rem;
padding-right: 0.9rem;
}
.deleteOrderingInfo-lightmode {
background: #EBEBEB;
color: #212121;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
border: none;
border-radius: 0.625rem;
margin-left: 24.8rem;
padding-left: 0.9rem;
padding-right: 0.9rem;
}
.deleteLastOrderingInfo-lightmode {
background: #EBEBEB;
color: #212121;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
border: none;
border-radius: 0.625rem;
margin-left: 2rem;
padding-left: 0.9rem;
padding-right: 0.9rem;
}
.deleteOrderingInfo-darkmode:hover,
.deleteLastOrderingInfo-darkmode:hover,
.saveOrderingInfo-darkmode:hover,
.editOrderingInfo-darkmode:hover {
background-color: #444444;
cursor: pointer;
}
.deleteOrderingInfo-lightmode:hover,
.deleteLastOrderingInfo-lightmode:hover,
.saveOrderingInfo-lightmode:hover,
.editOrderingInfo-lightmode:hover {
background-color: #ACACAC;
cursor: pointer;
}
#editOrderingInfo {
text-align: right;
} }
</style> </style>

View File

@ -4,11 +4,11 @@
<div class="production-orders-instance-data"> <div class="production-orders-instance-data">
<div class="instanceInfo"> <div class="instanceInfo">
<div class="data-field" id="info"> <div class="data-field" id="info">
<div class="templateId-client" id="templateID"> <div class="templateId-customer" id="templateID">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Template ID:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Template ID:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre>
</div> </div>
<div class="templateId-client" id="client"> <div class="templateId-customer" id="customer">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre>
</div> </div>
@ -19,7 +19,8 @@
<div class="additional"> <div class="additional">
<div class="templateDescription"> <div class="templateDescription">
<h3 :class="['area-title', darkMode ? 'h3-darkmode' : 'h3-lightmode']">Template description:</h3> <h3 :class="['area-title', darkMode ? 'h3-darkmode' : 'h3-lightmode']">Template description:</h3>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']" id="templateDescription">...</pre> <pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']"
id="templateDescription">...</pre>
</div> </div>
</div> </div>
<div class="additional"> <div class="additional">
@ -78,9 +79,37 @@
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const darkMode = ref('');
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>
@ -135,7 +164,7 @@ export default {
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
width: 95%; width: 95%;
padding: 0 1.875rem; padding: 0.8rem 1.875rem;
gap: 1.25rem; gap: 1.25rem;
border-radius: 0.625rem; border-radius: 0.625rem;
} }
@ -163,7 +192,7 @@ export default {
} }
.creationDate-completionDate-timeSpent, .creationDate-completionDate-timeSpent,
.templateId-client { .templateId-customer {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
@ -250,7 +279,7 @@ export default {
border-radius: 0.3125rem; border-radius: 0.3125rem;
} }
div#client { div#customer {
padding-left: 2.9em; padding-left: 2.9em;
} }

View File

@ -52,9 +52,37 @@
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const darkMode = ref('');
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>

View File

@ -5,8 +5,8 @@
<input v-if="editable" v-model="pot.name" @change="updatePOT()" <input v-if="editable" v-model="pot.name" @change="updatePOT()"
:class="['data', 'pot-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']"> :class="['data', 'pot-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']">
<div class="production-orders-template-data"> <div class="production-orders-template-data">
<div class="client-ID"> <div class="customer-ID">
<div class="data-field" id="client"> <div class="data-field" id="customer">
<pre :class="['label', darkMode ? 'div-darkmode' : 'div-lightmode']">Customer:</pre> <pre :class="['label', darkMode ? 'div-darkmode' : 'div-lightmode']">Customer:</pre>
<pre v-if="!editable" <pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']"> {{ pot.customer }}</pre> :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']"> {{ pot.customer }}</pre>
@ -56,8 +56,8 @@
<input v-model="newName" @change="updateProductionOrder()" <input v-model="newName" @change="updateProductionOrder()"
:class="['data', 'production-orders-template-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']"> :class="['data', 'production-orders-template-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']">
<div class="production-orders-template-data"> <div class="production-orders-template-data">
<div class="client-ID"> <div class="customer-ID">
<div class="data-field" id="client"> <div class="data-field" id="customer">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre>
<select id="customersDropDownChosenCI" v-model="newCustomer" @change="updateNewCustomerID()" <select id="customersDropDownChosenCI" v-model="newCustomer" @change="updateNewCustomerID()"
:class="[darkMode ? 'select-darkmode' : 'select-lightmode']"> :class="[darkMode ? 'select-darkmode' : 'select-lightmode']">
@ -109,12 +109,14 @@ import { useStore } from 'vuex';
import { computed } from 'vue'; import { computed } from 'vue';
const store = useStore(); const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const editable = computed(() => store.state.editable); const editable = computed(() => store.state.editable);
const chosenPOTId = computed(() => store.state.chosenPOTId); const chosenPOTId = computed(() => store.state.chosenPOTId);
const deleteBool = computed(() => store.state.deleteBool); const deleteBool = computed(() => store.state.deleteBool);
const addBool = computed(() => store.state.new); const addBool = computed(() => store.state.new);
const darkMode = ref(true); const darkMode = ref('');
const pot = ref({}); const pot = ref({});
const customers = ref([]); const customers = ref([]);
const customer = ref({}); const customer = ref({});
@ -143,8 +145,6 @@ const confirmDeletePOT = async () => {
if (confirm("Do you really want to delete this production order template? It cannot be undone!")) { if (confirm("Do you really want to delete this production order template? It cannot be undone!")) {
try { try {
await Axios.delete(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/deleteProductionOrderTemplate/${chosenPOTId.value}`); await Axios.delete(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/deleteProductionOrderTemplate/${chosenPOTId.value}`);
store.commit('undoDelete');
store.commit('changeToTemplatelist');
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
@ -153,6 +153,9 @@ const confirmDeletePOT = async () => {
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
store.commit('undoDelete');
store.commit('resetStore');
store.commit('changeToTemplatelist');
} else { } else {
store.commit('undoDelete'); store.commit('undoDelete');
} }
@ -214,8 +217,8 @@ const updateCustomerID = async () => {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCustomerByName/${pot.value.customer}`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCustomerByName/${pot.value.customer}`);
customer.value = response.data; customer.value = response.data;
pot.value.customerID = customer.value.customerID; pot.value.customerID = customer.value.customerID;
store.commit('toggleClientChanged'); store.commit('toggleCustomerChanged');
store.commit('toggleClientId', pot.value.customerID); store.commit('toggleCustomerId', pot.value.customerID);
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
@ -241,8 +244,8 @@ const updateNewCustomerID = async () => {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCustomerByName/${newCustomer.value}`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCustomerByName/${newCustomer.value}`);
newCustomerID.value = response.data.customerID; newCustomerID.value = response.data.customerID;
store.commit('toggleClientChanged'); store.commit('toggleCustomerChanged');
store.commit('toggleClientId', newCustomerID.value) store.commit('toggleCustomerId', newCustomerID.value)
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
@ -269,11 +272,30 @@ const triggerBackendCallsWithDelay = async (fetchDataFunc) => {
}, 1500); }, 1500);
} }
watch(deleteBool, confirmDeletePOT); const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
onMounted(() => { function getItem(item) {
getPOTById(); if (process.client) {
getProductionOrderTemplates(); return localStorage.getItem(item)
} else {
return undefined
}
}
watch(deleteBool, confirmDeletePOT);
watch(modeChanged, getSession)
onMounted(async () => {
getSession();
await getPOTById();
await getProductionOrderTemplates();
triggerBackendCallsWithDelay(getCustomers); triggerBackendCallsWithDelay(getCustomers);
}); });
</script> </script>
@ -423,7 +445,23 @@ export default {
border-radius: 0.3125rem; border-radius: 0.3125rem;
} }
.client-ID, .select-darkmode {
border: none;
color: white;
background: #212121;
padding: 0.4rem;
border-radius: 0.3125rem;
}
.select-lightmode {
border: none;
color: black;
background: #EBEBEB;
padding: 0.4rem;
border-radius: 0.3125rem;
}
.customer-ID,
.user { .user {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@ -1,6 +1,6 @@
<template> <template>
<section v-if="searchable" :class="['pot-search', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section v-if="searchable" :class="['pot-search', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['clientLabel', darkMode ? 'label-darkmode' : 'label-lightmode']">Template:</div> <div :class="['customerLabel', darkMode ? 'label-darkmode' : 'label-lightmode']">Template:</div>
<input v-model="potSearchFilter" @change="searchPOT()" <input v-model="potSearchFilter" @change="searchPOT()"
:class="['dataInput', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']"> :class="['dataInput', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</section> </section>
@ -10,7 +10,7 @@
<tbody> <tbody>
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head"> <tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th <th
:class="['Client', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Client-darkmode' : 'Client-lightmode']"> :class="['Customer', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Customer-darkmode' : 'Customer-lightmode']">
Customer</th> Customer</th>
<th <th
:class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']"> :class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
@ -24,12 +24,12 @@
<tr v-for="template in productionOrderTemplates" :key="template.templateID" <tr v-for="template in productionOrderTemplates" :key="template.templateID"
:class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1"> :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td <td
:class="['Client', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Client-darkmode' : 'Client-lightmode']"> :class="['Customer', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Customer-darkmode' : 'Customer-lightmode']">
{{ template.customer }}</td> {{ template.customer }}</td>
<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="/productionOrders" id="nuxt-link" class="button" <nuxt-link to="/productionOrders" id="nuxt-link" class="button"
:class="[darkMode ? 'button-darkmode' : 'button-lightmode']" :class="[darkMode ? 'button-darkmode' : 'button-lightmode', darkMode ? 'nuxt-link-darkmode' : 'nuxt-link-lightmode']"
@click="goToChosenPOT(template.templateID)"> @click="goToChosenPOT(template.templateID)">
{{ template.name }} {{ template.name }}
</nuxt-link> </nuxt-link>
@ -54,22 +54,24 @@ import { computed } from 'vue';
// get accesss to the store // get accesss to the store
const store = useStore() const store = useStore()
const modeChanged = computed(() => store.state.updateDarkMode);
const goToChosenPOT = (id) => { const goToChosenPOT = (id) => {
store.commit('setChosenPOT', id); store.commit('setChosenPOT', id);
store.commit('changeToTemplate'); store.commit('changeToTemplate');
}; };
const clientFilter = computed(() => store.state.filteredByClient); const customerFilter = computed(() => store.state.filteredByCustomer);
const searchable = computed(() => store.state.searchable); const searchable = computed(() => store.state.searchable);
const potSearchFilter = ref(''); const potSearchFilter = ref('');
const darkMode = ref(true); const darkMode = ref('');
const productionOrderTemplates = ref([]); const productionOrderTemplates = ref([]);
//get all productionOrder templates //get all productionOrder templates
const getProductionOrderTemplates = async () => { const getProductionOrderTemplates = async () => {
if (!(clientFilter.value === '')) { if (!(customerFilter.value === '')) {
await getFilteredPOTByClient(); await getFilteredPOTByCustomer();
} else { } else {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllProductionOrderTemplates`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllProductionOrderTemplates`);
@ -100,20 +102,39 @@ const updateSearchTerm = async () => {
await getProductionOrderTemplates(); await getProductionOrderTemplates();
} }
//get all productionOrder templates based on the searched client //get all productionOrder templates based on the searched customer
const getFilteredPOTByClient = async () => { const getFilteredPOTByCustomer = async () => {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getSelectedPOTsByClient/${clientFilter.value}`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getSelectedPOTsByCustomer/${customerFilter.value}`);
productionOrderTemplates.value = response.data; productionOrderTemplates.value = response.data;
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
} }
watch(clientFilter, getProductionOrderTemplates); const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(customerFilter, getProductionOrderTemplates);
watch(searchable, updateSearchTerm); watch(searchable, updateSearchTerm);
watch(modeChanged, getSession)
onMounted(async () => { onMounted(async () => {
getSession();
await getProductionOrderTemplates(); await getProductionOrderTemplates();
}); });
</script> </script>
@ -179,9 +200,16 @@ export default {
#nuxt-link { #nuxt-link {
text-decoration: none; text-decoration: none;
}
.nuxt-link-darkmode {
color: white; color: white;
} }
.nuxt-link-lightmode {
color: #000;
}
.table-row { .table-row {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@ -255,15 +283,15 @@ th {
font: 700 0.875rem/1.875rem Overpass, sans-serif; font: 700 0.875rem/1.875rem Overpass, sans-serif;
} }
.Client { .Customer {
width: 33.3%; width: 33.3%;
} }
.Client-darkmode { .Customer-darkmode {
border-right: 0.0625rem solid #000000; border-right: 0.0625rem solid #000000;
} }
.Client-lightmode { .Customer-lightmode {
border-right: 0.0625rem solid #8e8e8e; border-right: 0.0625rem solid #8e8e8e;
} }
@ -314,7 +342,7 @@ th {
color: #000; color: #000;
} }
.clientLabel { .customerLabel {
width: 5.5625em; width: 5.5625em;
height: 1.875em; height: 1.875em;
font-family: "Overpass"; font-family: "Overpass";

View File

@ -1,168 +0,0 @@
<template>
<div :class="['data', darkMode ? 'div-darkmode' : 'div-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Templates:</div>
<table class="data-table" id="production-orders-template-table-no-client">
<tbody>
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th
:class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
Name</th>
<th
:class="['ID', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']">
ID
</th>
<th :class="['User', darkMode ? 'th-darkmode' : 'th-lightmode']">User</th>
</tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td
:class="['Name', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
...</td>
<td
:class="['ID', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'ID-darkmode' : 'ID-lightmode']">
...</td>
<td :class="['User', darkMode ? 'td-darkmode' : 'td-lightmode']">...</td>
</tr>
</tbody>
</table>
</div>
</template>
<script setup>
import { ref } from 'vue';
const darkMode = ref(true)
</script>
<script>
export default {
name: "ProductionOrdersTemplateTableNoClient",
};
</script>
<style scoped>
.data {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
align-self: stretch;
width: 100%;
padding: 1.25rem 1.875rem;
gap: 1.25rem;
border-radius: 0.625rem;
box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25);
}
.div-darkmode {
background-color: #2c2c2c;
}
.div-lightmode {
background-color: #fff;
}
.data-table {
width: 100%;
padding: 0 0.625rem;
table-layout: fixed;
border-collapse: collapse;
}
.table-row {
display: flex;
flex-direction: row;
align-items: center;
height: 3.125rem;
padding: 0.625rem;
gap: 0.625rem;
}
.tr-head-darkmode {
border-top: none;
border-bottom: 0.0625rem solid #000000;
}
.tr-head-lightmode {
border-top: none;
border-bottom: 0.0625rem solid #8e8e8e;
}
.tr-darkmode {
border-top: 0.0625rem solid #000000;
}
.tr-lightmode {
border-top: 0.0625rem solid #8e8e8e;
}
th,
td {
height: 1.875rem;
text-align: left;
padding: 0;
letter-spacing: 5%;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
}
.th-darkmode,
.td-darkmode {
color: #ffffff;
}
.th-lightmode,
.td-lightmode {
color: #000;
}
th {
font: 700 0.875rem/1.875rem Overpass, sans-serif;
}
.Name {
width: 50%;
}
.Name-darkmode {
border-right: 0.0625rem solid #000000;
}
.Name-lightmode {
border-right: 0.0625rem solid #8e8e8e;
}
.ID {
width: 40%;
}
.ID-darkmode {
border-right: 0.0625rem solid #000000;
}
.ID-lightmode {
border-right: 0.0625rem solid #8e8e8e;
}
.User {
width: 10%;
}
.label {
width: 6.0625em;
height: 1.875em;
font-family: 'Overpass';
font-style: normal;
font-weight: 400;
font-size: 1em;
line-height: 1.875em;
letter-spacing: 0.05em;
}
.label-darkmode {
color: #FFFFFF;
}
.label-lightmode {
color: #000;
}</style>

View File

@ -3,7 +3,7 @@
:class="['software-information', darkMode ? 'section-darkmode' : 'section-lightmode']"> :class="['software-information', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']" id="software">Software specifications: <div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']" id="software">Software specifications:
<div class="asset-data"> <div class="asset-data">
<table class="data-table" id="asset-table-no-client"> <table class="data-table" id="asset-table-no-customer">
<tbody> <tbody>
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head"> <tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th <th
@ -14,7 +14,8 @@
Version</th> Version</th>
<th :class="['License', darkMode ? 'th-darkmode' : 'th-lightmode']">License</th> <th :class="['License', darkMode ? 'th-darkmode' : 'th-lightmode']">License</th>
</tr> </tr>
<tr v-if="editable" :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1"> <tr v-if="editable" :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']"
id="row-1">
<td <td
:class="['Software', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Software-darkmode' : 'Software-lightmode']"> :class="['Software', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Software-darkmode' : 'Software-lightmode']">
<input type="text" v-model="item.software" @change="updateConfigItem()" <input type="text" v-model="item.software" @change="updateConfigItem()"
@ -30,7 +31,8 @@
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']"> :class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td> </td>
</tr> </tr>
<tr v-if="!editable" :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1"> <tr v-if="!editable" :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']"
id="row-1">
<td <td
:class="['Software', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Software-darkmode' : 'Software-lightmode']"> :class="['Software', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Software-darkmode' : 'Software-lightmode']">
{{ item.software }}</td> {{ item.software }}</td>
@ -47,7 +49,7 @@
<section v-if="addBool" :class="['software-information', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section v-if="addBool" :class="['software-information', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']" id="software">Software specifications: <div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']" id="software">Software specifications:
<div class="asset-data"> <div class="asset-data">
<table class="data-table" id="asset-table-no-client"> <table class="data-table" id="asset-table-no-customer">
<tbody> <tbody>
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head"> <tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th <th
@ -82,13 +84,15 @@
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from 'vue'; import { ref, onMounted, watch } 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'; import { useStore } from 'vuex';
import { computed } from 'vue'; import { computed } from 'vue';
const store = useStore(); const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const editable = computed(() => store.state.editable); const editable = computed(() => store.state.editable);
const chosenAssetId = computed(() => store.state.chosenAssetId); const chosenAssetId = computed(() => store.state.chosenAssetId);
const addBool = computed(() => store.state.new); const addBool = computed(() => store.state.new);
@ -98,7 +102,7 @@ const newSoftware = ref('');
const newVersion = ref(''); const newVersion = ref('');
const newLicense = ref(''); const newLicense = ref('');
const darkMode = ref(true) const darkMode = ref('');
const item = ref({}); const item = ref({});
const softwareBoolean = ref(false) const softwareBoolean = ref(false)
@ -176,8 +180,28 @@ const updateConfigItem = async () => {
} }
} }
onMounted(() => { const getSession = async () => {
getItemById(); const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
getSession();
await getItemById();
}); });
</script> </script>

View File

@ -5,8 +5,8 @@
<input v-if="editable" v-model="sol.solutionName" @change="updateSolution()" <input v-if="editable" v-model="sol.solutionName" @change="updateSolution()"
:class="['data', 'solution-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']"> :class="['data', 'solution-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']">
<div class="solution-data"> <div class="solution-data">
<div class="client-asset"> <div class="customer-asset">
<div class="data-field" id="client"> <div class="data-field" id="customer">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre>
<pre v-if="!editable" <pre v-if="!editable"
:class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ sol.customer }}</pre> :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">{{ sol.customer }}</pre>
@ -73,8 +73,8 @@
<input v-model="newSolutionName" @change="updateSol()" <input v-model="newSolutionName" @change="updateSol()"
:class="['data', 'solution-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']"> :class="['data', 'solution-name-input', darkMode ? 'h2-darkmode' : 'h2-lightmode', darkMode ? 'h2-input-darkmode' : 'h2-input-lightmode', 'input']">
<div class="solution-data"> <div class="solution-data">
<div class="client-asset"> <div class="customer-asset">
<div class="data-field" id="client"> <div class="data-field" id="customer">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre> <pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Customer:</pre>
<select id="customersDropDownChosenCI" v-model="newCustomer" @change="updateNewCustomerID()" <select id="customersDropDownChosenCI" v-model="newCustomer" @change="updateNewCustomerID()"
:class="[darkMode ? 'select-darkmode' : 'select-lightmode']"> :class="[darkMode ? 'select-darkmode' : 'select-lightmode']">
@ -142,12 +142,14 @@ import { useStore } from 'vuex';
import { computed } from 'vue'; import { computed } from 'vue';
const store = useStore(); const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const editable = computed(() => store.state.editable); const editable = computed(() => store.state.editable);
const chosenSolutionId = computed(() => store.state.chosenSolutionId); const chosenSolutionId = computed(() => store.state.chosenSolutionId);
const deleteBool = computed(() => store.state.deleteBool); const deleteBool = computed(() => store.state.deleteBool);
const addBool = computed(() => store.state.new); const addBool = computed(() => store.state.new);
const darkMode = ref(true); const darkMode = ref('');
const sol = ref({}); const sol = ref({});
const customer = ref({}); const customer = ref({});
const solutions = ref([]); const solutions = ref([]);
@ -163,8 +165,8 @@ const newDescription = ref('');
const newNotes = ref(''); const newNotes = ref('');
const newLastView = ref(''); const newLastView = ref('');
const newUser = ref(''); const newUser = ref('');
const changedClientId = computed(() => store.state.changedClientId); const changedCustomerId = computed(() => store.state.changedCustomerId);
const clientChanged = computed(() => store.state.clientChanged); const customerChanged = computed(() => store.state.customerChanged);
// get solution from id // get solution from id
const getSolutionById = async () => { const getSolutionById = async () => {
@ -178,28 +180,28 @@ const getSolutionById = async () => {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
} }
await getConfigItemsFromClient(); await getConfigItemsFromCustomer();
} }
//get all config items from the selected client //get all config items from the selected customer
const getConfigItemsFromClient = async () => { const getConfigItemsFromCustomer = async () => {
if (!addBool.value) { if (!addBool.value) {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCIFromClient/${sol.value.customerID}`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCIFromCustomer/${sol.value.customerID}`);
configItems.value = response.data; configItems.value = response.data;
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
} else { } else {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCIFromClient/${changedClientId.value}`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCIFromCustomer/${changedCustomerId.value}`);
configItems.value = response.data; configItems.value = response.data;
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
} }
if (clientChanged.value) { if (customerChanged.value) {
store.commit('toggleClientChanged'); store.commit('toggleCustomerChanged');
} }
} }
@ -232,7 +234,7 @@ const updateSolution = async () => {
counter += 1; counter += 1;
} }
}); });
if (counter == 1) { if (counter == 2) {
alert("This solution name already exists. Please choose an unique solution name or modify respectively delete the old one!"); alert("This solution name already exists. Please choose an unique solution name or modify respectively delete the old one!");
sol.value.solutionName = ''; sol.value.solutionName = '';
return; return;
@ -276,8 +278,6 @@ const confirmDeleteSolution = async () => {
if (confirm("Do you really want to delete this solution? It cannot be undone!")) { if (confirm("Do you really want to delete this solution? It cannot be undone!")) {
try { try {
await Axios.delete(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/deleteSolution/${chosenSolutionId.value}`); await Axios.delete(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/deleteSolution/${chosenSolutionId.value}`);
store.commit('undoDelete');
store.commit('changeToSolutionlist');
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
@ -286,6 +286,9 @@ const confirmDeleteSolution = async () => {
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
store.commit('undoDelete');
store.commit('resetStore');
store.commit('changeToSolutionlist');
} else { } else {
store.commit('undoDelete'); store.commit('undoDelete');
} }
@ -308,8 +311,8 @@ const updateCustomerID = async () => {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCustomerByName/${sol.value.customer}`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCustomerByName/${sol.value.customer}`);
customer.value = response.data; customer.value = response.data;
sol.value.customerID = customer.value.customerID; sol.value.customerID = customer.value.customerID;
store.commit('toggleClientChanged'); store.commit('toggleCustomerChanged');
store.commit('toggleClientId', sol.value.customerID); store.commit('toggleCustomerId', sol.value.customerID);
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
@ -321,13 +324,13 @@ const updateNewCustomerID = async () => {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCustomerByName/${newCustomer.value}`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCustomerByName/${newCustomer.value}`);
newCustomerID.value = response.data.customerID; newCustomerID.value = response.data.customerID;
store.commit('toggleClientChanged'); store.commit('toggleCustomerChanged');
store.commit('toggleClientId', newCustomerID.value); store.commit('toggleCustomerId', newCustomerID.value);
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
updateSol(); updateSol();
await getConfigItemsFromClient(); await getConfigItemsFromCustomer();
} }
// include delay to avoid 503 error // include delay to avoid 503 error
@ -337,12 +340,31 @@ const triggerBackendCallsWithDelay = async (fetchDataFunc) => {
}, 1500); }, 1500);
} }
watch(deleteBool, confirmDeleteSolution); const getSession = async () => {
watch(clientChanged, getSolutionById); const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
onMounted(() => { function getItem(item) {
getSolutionById(); if (process.client) {
getSolutions(); return localStorage.getItem(item)
} else {
return undefined
}
}
watch(deleteBool, confirmDeleteSolution);
watch(customerChanged, getSolutionById);
watch(modeChanged, getSession)
onMounted(async () => {
getSession();
await getSolutionById();
await getSolutions();
triggerBackendCallsWithDelay(getCustomers); triggerBackendCallsWithDelay(getCustomers);
}); });
</script> </script>
@ -486,7 +508,7 @@ export default {
align-self: stretch; align-self: stretch;
} }
.client-asset, .customer-asset,
.info { .info {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@ -137,7 +137,7 @@
@click="addRowForNewSol()">+</button> @click="addRowForNewSol()">+</button>
</section> </section>
<section v-if="addBool" id="saveNewSol"> <section v-if="addBool" id="saveNewSol">
<button :class="[darkMode ? 'saveNewSol-darkmode' : 'saveNewSol-lightmode']" @click="addSol()">Safe</button> <button :class="[darkMode ? 'saveNewSol-darkmode' : 'saveNewSol-lightmode']" @click="addSol()">Save</button>
</section> </section>
</template> </template>
@ -150,6 +150,8 @@ import { useStore } from 'vuex';
import { computed } from 'vue'; import { computed } from 'vue';
const store = useStore(); const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const addBool = computed(() => store.state.new); const addBool = computed(() => store.state.new);
const editable = computed(() => store.state.editable); const editable = computed(() => store.state.editable);
@ -165,10 +167,10 @@ const newDescriptionSol = computed(() => store.state.newDescriptionSol);
const newStepTodo = computed(() => solTodos.value.length); const newStepTodo = computed(() => solTodos.value.length);
const chosenSolId = computed(() => store.state.chosenSolutionId); const chosenSolId = computed(() => store.state.chosenSolutionId);
const clientChanged = computed(() => store.state.clientChanged); const customerChanged = computed(() => store.state.customerChanged);
const changedClientId = computed(() => store.state.changedClientId); const changedCustomerId = computed(() => store.state.changedCustomerId);
const darkMode = ref(true) const darkMode = ref('');
const addRow = ref(false); const addRow = ref(false);
const configItemList = ref([]); const configItemList = ref([]);
const solutions = ref([]); const solutions = ref([]);
@ -217,7 +219,7 @@ const addSol = async () => {
} }
} }
if (newCustomerSol.value.length === 0) { if (newCustomerSol.value.length === 0) {
alert("Please choose a client!"); alert("Please choose a customer!");
return; return;
} }
let allFine = true; let allFine = true;
@ -267,10 +269,10 @@ const addSol = async () => {
// add new row of todo for the new solution // add new row of todo for the new solution
const addRowForNewSol = async () => { const addRowForNewSol = async () => {
if (newCustomerSol.value.length === 0) { if (newCustomerSol.value.length === 0) {
alert("Please choose a client first!"); alert("Please choose a customer first!");
return; return;
} }
await getConfigItemsFromClient(); await getConfigItemsFromCustomer();
newTodos.push({ newTodos.push({
solutionID: chosenSolId.value, solutionID: chosenSolId.value,
step: newRowId.value, step: newRowId.value,
@ -332,7 +334,7 @@ const addSolTodo = async () => {
// add new row for the template // add new row for the template
const addChecklistRow = async () => { const addChecklistRow = async () => {
await getConfigItemsFromClient(); await getConfigItemsFromCustomer();
if (addRow.value) { if (addRow.value) {
alert('Please confirm the last added row first.') alert('Please confirm the last added row first.')
return return
@ -371,25 +373,25 @@ const getSolutionTodosById = async () => {
} }
} }
//get all config items from the selected client //get all config items from the selected customer
const getConfigItemsFromClient = async () => { const getConfigItemsFromCustomer = async () => {
if (!addBool.value) { if (!addBool.value) {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCIFromClient/${sol.value.customerID}`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCIFromCustomer/${sol.value.customerID}`);
configItemList.value = response.data; configItemList.value = response.data;
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
} else { } else {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCIFromClient/${changedClientId.value}`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCIFromCustomer/${changedCustomerId.value}`);
configItemList.value = response.data; configItemList.value = response.data;
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
} }
if (clientChanged.value) { if (customerChanged.value) {
store.commit('toggleClientChanged'); store.commit('toggleCustomerChanged');
} }
} }
@ -405,7 +407,7 @@ const getSolutionById = async () => {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
} }
await getConfigItemsFromClient(); await getConfigItemsFromCustomer();
} }
const deleteSolTodo = async (id) => { const deleteSolTodo = async (id) => {
@ -419,11 +421,30 @@ const deleteSolTodo = async (id) => {
await getSolutionTodosById(); await getSolutionTodosById();
} }
watch(clientChanged, getSolutionById); const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
onMounted(() => { function getItem(item) {
getSolutionTodosById(); if (process.client) {
getSolutionById(); return localStorage.getItem(item)
} else {
return undefined
}
}
watch(customerChanged, getSolutionById);
watch(modeChanged, getSession)
onMounted(async () => {
getSession();
await getSolutionTodosById();
await getSolutionById();
triggerBackendCallsWithDelay(getAllSolutions); triggerBackendCallsWithDelay(getAllSolutions);
}); });
</script> </script>

View File

@ -1,6 +1,6 @@
<template> <template>
<section v-if="searchable" :class="['solution-search', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section v-if="searchable" :class="['solution-search', darkMode ? 'section-darkmode' : 'section-lightmode']">
<div :class="['clientLabel', darkMode ? 'label-darkmode' : 'label-lightmode']">Solution</div> <div :class="['customerLabel', darkMode ? 'label-darkmode' : 'label-lightmode']">Solution</div>
<input v-model="solutionSearchFilter" @change="searchSolution()" <input v-model="solutionSearchFilter" @change="searchSolution()"
:class="['dataInput', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']"> :class="['dataInput', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</section> </section>
@ -10,7 +10,7 @@
<tbody> <tbody>
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head"> <tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th <th
:class="['Client', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Client-darkmode' : 'Client-lightmode']"> :class="['Customer', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Customer-darkmode' : 'Customer-lightmode']">
Customer</th> Customer</th>
<th <th
:class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']"> :class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
@ -26,12 +26,12 @@
<tr v-for="sol in solutions" :key="sol.primaryID" <tr v-for="sol in solutions" :key="sol.primaryID"
:class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1"> :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td <td
:class="['Client', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Client-darkmode' : 'Client-lightmode']"> :class="['Customer', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Customer-darkmode' : 'Customer-lightmode']">
{{ sol.customer }}</td> {{ sol.customer }}</td>
<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="/solutions" id="nuxt-link" class="button" <nuxt-link to="/solutions" id="nuxt-link" class="button"
:class="[darkMode ? 'button-darkmode' : 'button-lightmode']" :class="[darkMode ? 'button-darkmode' : 'button-lightmode', darkMode ? 'nuxt-link-darkmode' : 'nuxt-link-lightmode']"
@click="goToChosenSolution(sol.primaryID)"> @click="goToChosenSolution(sol.primaryID)">
{{ sol.solutionName }} {{ sol.solutionName }}
</nuxt-link> </nuxt-link>
@ -51,7 +51,7 @@
<script setup> <script setup>
import { ref, onMounted } from 'vue'; import { ref, onMounted, watch } 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'; import { useStore } from 'vuex';
@ -59,16 +59,18 @@ import { computed } from 'vue';
// get accesss to the store // get accesss to the store
const store = useStore() const store = useStore()
const modeChanged = computed(() => store.state.updateDarkMode);
const goToChosenSolution = (id) => { const goToChosenSolution = (id) => {
store.commit('setChosenSolution', id); store.commit('setChosenSolution', id);
store.commit('changeToSolution'); store.commit('changeToSolution');
}; };
const clientFilter = computed(() => store.state.filteredByClient); const customerFilter = computed(() => store.state.filteredByCustomer);
const searchable = computed(() => store.state.searchable); const searchable = computed(() => store.state.searchable);
const solutionSearchFilter = ref(''); const solutionSearchFilter = ref('');
const darkMode = ref(true) const darkMode = ref('');
const solutions = ref([]); const solutions = ref([]);
// update search term // update search term
@ -79,8 +81,8 @@ const updateSearchTerm = async () => {
//get all solutions //get all solutions
const getSolutions = async () => { const getSolutions = async () => {
if (!(clientFilter.value === '')) { if (!(customerFilter.value === '')) {
await getFilteredSolutionsByClient(); await getFilteredSolutionsByCustomer();
} else { } else {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllSolutions`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getAllSolutions`);
@ -91,10 +93,10 @@ const getSolutions = async () => {
} }
} }
//get all solutions based on the searched client //get all solutions based on the searched customer
const getFilteredSolutionsByClient = async () => { const getFilteredSolutionsByCustomer = async () => {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getSelectedSolutionsByClient/${clientFilter.value}`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getSelectedSolutionsByCustomer/${customerFilter.value}`);
solutions.value = response.data; solutions.value = response.data;
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
@ -115,11 +117,29 @@ const searchSolution = async () => {
} }
} }
watch(clientFilter, getSolutions); const getSession = async () => {
watch(searchable, updateSearchTerm); const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(customerFilter, getSolutions);
watch(searchable, updateSearchTerm);
watch(modeChanged, getSession)
onMounted(async () => { onMounted(async () => {
getSession();
await getSolutions(); await getSolutions();
}); });
</script> </script>
@ -256,10 +276,17 @@ th {
#nuxt-link { #nuxt-link {
text-decoration: none; text-decoration: none;
}
.nuxt-link-darkmode {
color: white; color: white;
} }
.clientLabel { .nuxt-link-lightmode {
color: #000;
}
.customerLabel {
width: 5.5625em; width: 5.5625em;
height: 1.875em; height: 1.875em;
font-family: "Overpass"; font-family: "Overpass";
@ -270,15 +297,15 @@ th {
letter-spacing: 0.05em; letter-spacing: 0.05em;
} }
.Client { .Customer {
width: 33.3%; width: 33.3%;
} }
.Client-darkmode { .Customer-darkmode {
border-right: 0.0625rem solid #000000; border-right: 0.0625rem solid #000000;
} }
.Client-lightmode { .Customer-lightmode {
border-right: 0.0625rem solid #8e8e8e; border-right: 0.0625rem solid #8e8e8e;
} }

View File

@ -1,186 +0,0 @@
<template>
<div :class="['data', darkMode ? 'div-darkmode' : 'div-lightmode']">
<div :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Solutions:</div>
<table class="data-table" id="solution-table">
<tbody>
<tr :class="['table-row', darkMode ? 'tr-head-darkmode' : 'tr-head-lightmode']" id="table-head">
<th
:class="['Name', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
Name</th>
<th
:class="['Asset', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Asset-darkmode' : 'Asset-lightmode']">
Asset</th>
<th
:class="['Type', darkMode ? 'th-darkmode' : 'th-lightmode', darkMode ? 'Type-darkmode' : 'Type-lightmode']">
Type</th>
<th :class="['User', darkMode ? 'th-darkmode' : 'th-lightmode']">User</th>
</tr>
<tr :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1">
<td
:class="['Name', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Name-darkmode' : 'Name-lightmode']">
...</td>
<td
:class="['Asset', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Asset-darkmode' : 'Asset-lightmode']">
...</td>
<td
:class="['Type', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Type-darkmode' : 'Type-lightmode']">
...</td>
<td :class="['User', darkMode ? 'td-darkmode' : 'td-lightmode']">...</td>
</tr>
</tbody>
</table>
</div>
</template>
<script setup>
import { ref } from 'vue';
const darkMode = ref(true)
</script>
<script>
export default {
name: "SolutionTableNoClient",
};
</script>
<style scoped>
.data {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
align-self: stretch;
width: 100%;
padding: 1.25rem 1.875rem;
gap: 1.25rem;
border-radius: 0.625rem;
box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25);
}
.div-darkmode {
background-color: #2c2c2c;
}
.div-lightmode {
background-color: #fff;
}
.data-table {
width: 100%;
padding: 0 0.625rem;
table-layout: fixed;
border-collapse: collapse;
}
.table-row {
display: flex;
flex-direction: row;
align-items: center;
height: 3.125rem;
padding: 0.625rem;
gap: 0.625rem;
}
.tr-head-darkmode {
border-top: none;
border-bottom: 0.0625rem solid #000000;
}
.tr-head-lightmode {
border-top: none;
border-bottom: 0.0625rem solid #8e8e8e;
}
.tr-darkmode {
border-top: 0.0625rem solid #000000;
}
.tr-lightmode {
border-top: 0.0625rem solid #8e8e8e;
}
th,
td {
height: 1.875rem;
text-align: left;
padding: 0;
letter-spacing: 5%;
font: 400 0.875rem/1.875rem Overpass, sans-serif;
}
th {
font: 700 0.875rem/1.875rem Overpass, sans-serif;
}
.th-darkmode,
.td-darkmode {
color: #ffffff;
}
.th-lightmode,
.td-lightmode {
color: #000;
}
.Name {
width: 45%;
}
.Name-darkmode {
border-right: 0.0625rem solid #000000;
}
.Name-lightmode {
border-right: 0.0625rem solid #8e8e8e;
}
.Asset {
width: 22.5%;
}
.Asset-darkmode {
border-right: 0.0625rem solid #000000;
}
.Asset-lightmode {
border-right: 0.0625rem solid #8e8e8e;
}
.Type {
width: 22.5%;
}
.Type-darkmode {
border-right: 0.0625rem solid #000000;
}
.Type-lightmode {
border-right: 0.0625rem solid #8e8e8e;
}
.User {
width: 10%;
}
.label {
width: 6.0625em;
height: 1.875em;
font-family: 'Overpass';
font-style: normal;
font-weight: 400;
font-size: 1em;
line-height: 1.875em;
letter-spacing: 0.05em;
}
.label-darkmode {
color: #FFFFFF;
}
.label-lightmode {
color: #000;
}
</style>

View File

@ -42,16 +42,18 @@
<input type="text" v-model="todo.task" @change="updatePOTTodo(todo)" <input type="text" v-model="todo.task" @change="updatePOTTodo(todo)"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']"> :class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td> </td>
<td v-if="!editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']"> {{ todo.comments <td v-if="!editable" :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']"> {{
todo.comments
}}</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
v-model="todo.comments" @change="updatePOTTodo(todo)" type="text" v-model="todo.comments" @change="updatePOTTodo(todo)"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']"> <button :class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']"> <button
:class="[darkMode ? 'deletePOTTodos-darkmode' : 'deletePOTTodos-lightmode']" :class="[darkMode ? 'deletePOTTodos-darkmode' : 'deletePOTTodos-lightmode']"
@click="deletePOTTodo(todo.primaryID)">-</button> @click="deletePOTTodo(todo.primaryID)">-</button>
</td> </td>
</tr> </tr>
<tr v-if="editable && addRow" :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1"> <tr v-if="editable && addRow" :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']"
id="row-1">
<td <td
:class="['Step', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Step-darkmode' : 'Step-lightmode']"> :class="['Step', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Step-darkmode' : 'Step-lightmode']">
{{ newStepTodo }} {{ newStepTodo }}
@ -126,7 +128,7 @@
<td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']"> <input type="text" <td :class="['Comments', darkMode ? 'td-darkmode' : 'td-lightmode']"> <input type="text"
v-model="newT.comments" v-model="newT.comments"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']"> <button :class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']"> <button
:class="[darkMode ? 'deletePOTTodos-darkmode' : 'deleteLastPOTTodos-lightmode']" :class="[darkMode ? 'deleteLastPOTTodos-darkmode' : 'deleteLastPOTTodos-lightmode']"
@click="deletePOTTodoFromNewTodos(index)">-</button> @click="deletePOTTodoFromNewTodos(index)">-</button>
</td> </td>
</tr> </tr>
@ -138,7 +140,7 @@
@click="addRowForNewPOT()">+</button> @click="addRowForNewPOT()">+</button>
</section> </section>
<section v-if="addBool" id="saveNewPOT"> <section v-if="addBool" id="saveNewPOT">
<button :class="[darkMode ? 'saveNewPOT-darkmode' : 'saveNewPOT-lightmode']" @click="addPOT()">Safe</button> <button :class="[darkMode ? 'saveNewPOT-darkmode' : 'saveNewPOT-lightmode']" @click="addPOT()">Save</button>
</section> </section>
</template> </template>
@ -151,6 +153,8 @@ import { useStore } from 'vuex';
import { computed } from 'vue'; import { computed } from 'vue';
const store = useStore(); const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const addBool = computed(() => store.state.new); const addBool = computed(() => store.state.new);
const editable = computed(() => store.state.editable); const editable = computed(() => store.state.editable);
@ -163,10 +167,10 @@ const newDescriptionPOT = computed(() => store.state.newDescriptionPOT);
const newNotesPOT = computed(() => store.state.newNotesPOT); const newNotesPOT = computed(() => store.state.newNotesPOT);
const newStepTodo = computed(() => potTodos.value.length); const newStepTodo = computed(() => potTodos.value.length);
const chosenPOTId = computed(() => store.state.chosenPOTId); const chosenPOTId = computed(() => store.state.chosenPOTId);
const clientChanged = computed(() => store.state.clientChanged); const customerChanged = computed(() => store.state.customerChanged);
const changedClientId = computed(() => store.state.changedClientId); const changedCustomerId = computed(() => store.state.changedCustomerId);
const darkMode = ref(true) const darkMode = ref('');
const addRow = ref(false); const addRow = ref(false);
const configItemList = ref([]); const configItemList = ref([]);
const productionOrderTemplates = ref([]); const productionOrderTemplates = ref([]);
@ -215,7 +219,7 @@ const addPOT = async () => {
} }
} }
if (newCustomerPOT.value.length === 0) { if (newCustomerPOT.value.length === 0) {
alert("Please choose a client!"); alert("Please choose a customer!");
return; return;
} }
let allFine = true; let allFine = true;
@ -263,10 +267,10 @@ const addPOT = async () => {
// add new row of todo for the new pot // add new row of todo for the new pot
const addRowForNewPOT = async () => { const addRowForNewPOT = async () => {
if (newCustomerPOT.value.length === 0) { if (newCustomerPOT.value.length === 0) {
alert("Please choose a client first!"); alert("Please choose a customer first!");
return; return;
} }
await getConfigItemsFromClient(); await getConfigItemsFromCustomer();
newTodos.push({ newTodos.push({
templateID: chosenPOTId.value, templateID: chosenPOTId.value,
rowID: newRowId.value, rowID: newRowId.value,
@ -328,7 +332,7 @@ const addPOTTodo = async () => {
// add new row for the template checklist // add new row for the template checklist
const addChecklistRow = async () => { const addChecklistRow = async () => {
await getConfigItemsFromClient(); await getConfigItemsFromCustomer();
if (addRow.value) { if (addRow.value) {
alert('Please confirm the last added row first.') alert('Please confirm the last added row first.')
return return
@ -367,25 +371,25 @@ const getPOTTodosById = async () => {
} }
} }
//get all config items from the selected client //get all config items from the selected customer
const getConfigItemsFromClient = async () => { const getConfigItemsFromCustomer = async () => {
if (!addBool.value) { if (!addBool.value) {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCIFromClient/${pot.value.customerID}`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCIFromCustomer/${pot.value.customerID}`);
configItemList.value = response.data; configItemList.value = response.data;
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
} else { } else {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCIFromClient/${changedClientId.value}`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCIFromCustomer/${changedCustomerId.value}`);
configItemList.value = response.data; configItemList.value = response.data;
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
} }
if (clientChanged.value) { if (customerChanged.value) {
store.commit('toggleClientChanged'); store.commit('toggleCustomerChanged');
} }
} }
@ -401,7 +405,7 @@ const getPOTById = async () => {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
} }
await getConfigItemsFromClient(); await getConfigItemsFromCustomer();
} }
const deletePOTTodo = async (id) => { const deletePOTTodo = async (id) => {
@ -415,11 +419,30 @@ const deletePOTTodo = async (id) => {
await getPOTTodosById(); await getPOTTodosById();
} }
watch(clientChanged, getPOTById); const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
onMounted(() => { function getItem(item) {
getPOTTodosById(); if (process.client) {
getPOTById(); return localStorage.getItem(item)
} else {
return undefined
}
}
watch(customerChanged, getPOTById);
watch(modeChanged, getSession)
onMounted(async () => {
getSession();
await getPOTTodosById();
await getPOTById();
triggerBackendCallsWithDelay(getProductionOrderTemplates); triggerBackendCallsWithDelay(getProductionOrderTemplates);
}); });
</script> </script>
@ -619,7 +642,6 @@ th {
box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25); box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25);
} }
.savePOTTodos-darkmode { .savePOTTodos-darkmode {
background: #212121; background: #212121;
color: #fff; color: #fff;
@ -659,7 +681,7 @@ th {
font: 400 0.875rem/1.875rem Overpass, sans-serif; font: 400 0.875rem/1.875rem Overpass, sans-serif;
border: none; border: none;
border-radius: 0.625rem; border-radius: 0.625rem;
margin-left: 2rem; margin-left: 15.8rem;
padding-left: 0.9rem; padding-left: 0.9rem;
padding-right: 0.9rem; padding-right: 0.9rem;
} }

View File

@ -42,16 +42,18 @@
<input type="text" v-model="todo.task" @change="updateMVTTodo(todo)" <input type="text" v-model="todo.task" @change="updateMVTTodo(todo)"
:class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']"> :class="['data', 'input', darkMode ? 'data-darkmode' : 'data-lightmode']">
</td> </td>
<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
v-model="todo.commets" @change="updateMVTTodo(todo)" type="text" 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>
</td> </td>
</tr> </tr>
<tr v-if="editable && addRow" :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']" id="row-1"> <tr v-if="editable && addRow" :class="['table-row', darkMode ? 'tr-darkmode' : 'tr-lightmode']"
id="row-1">
<td <td
:class="['Step', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Step-darkmode' : 'Step-lightmode']"> :class="['Step', darkMode ? 'td-darkmode' : 'td-lightmode', darkMode ? 'Step-darkmode' : 'Step-lightmode']">
{{ newStepTodo }} {{ newStepTodo }}
@ -138,7 +140,7 @@
@click="addRowForNewMVT()">+</button> @click="addRowForNewMVT()">+</button>
</section> </section>
<section v-if="addBool" id="saveNewMVT"> <section v-if="addBool" id="saveNewMVT">
<button :class="[darkMode ? 'saveNewMVT-darkmode' : 'saveNewMVT-lightmode']" @click="addMVT()">Safe</button> <button :class="[darkMode ? 'saveNewMVT-darkmode' : 'saveNewMVT-lightmode']" @click="addMVT()">Save</button>
</section> </section>
</template> </template>
@ -149,8 +151,12 @@ 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 modeChanged = computed(() => store.state.updateDarkMode);
const addBool = computed(() => store.state.new); const addBool = computed(() => store.state.new);
const editable = computed(() => store.state.editable); const editable = computed(() => store.state.editable);
@ -163,10 +169,10 @@ const newTypeMVT = computed(() => store.state.newTypeMVT);
const newNotesMVT = computed(() => store.state.newNotesMVT); const newNotesMVT = computed(() => store.state.newNotesMVT);
const newStepTodo = computed(() => mvtTodos.value.length); const newStepTodo = computed(() => mvtTodos.value.length);
const chosenMVTId = computed(() => store.state.chosenMVTId); const chosenMVTId = computed(() => store.state.chosenMVTId);
const clientChanged = computed(() => store.state.clientChanged); const customerChanged = computed(() => store.state.customerChanged);
const changedClientId = computed(() => store.state.changedClientId); const changedCustomerId = computed(() => store.state.changedCustomerId);
const darkMode = ref(true) const darkMode = ref('');
const addRow = ref(false); const addRow = ref(false);
const configItemList = ref([]); const configItemList = ref([]);
const maintenanceVisitTemplates = ref([]); const maintenanceVisitTemplates = ref([]);
@ -215,7 +221,7 @@ const addMVT = async () => {
} }
} }
if (newCustomerMVT.value.length === 0) { if (newCustomerMVT.value.length === 0) {
alert("Please choose a client!"); alert("Please choose a customer!");
return; return;
} }
let allFine = true; let allFine = true;
@ -263,10 +269,10 @@ const addMVT = async () => {
// add new row of todo for the new MVT // add new row of todo for the new MVT
const addRowForNewMVT = async () => { const addRowForNewMVT = async () => {
if (newCustomerMVT.value.length === 0) { if (newCustomerMVT.value.length === 0) {
alert("Please choose a client first!"); alert("Please choose a customer first!");
return; return;
} }
await getConfigItemsFromClient(); await getConfigItemsFromCustomer();
newTodos.push({ newTodos.push({
templateID: chosenMVTId.value, templateID: chosenMVTId.value,
rowID: newRowId.value, rowID: newRowId.value,
@ -328,7 +334,7 @@ const addMVTTodo = async () => {
// add new row for the template checklist // add new row for the template checklist
const addChecklistRow = async () => { const addChecklistRow = async () => {
await getConfigItemsFromClient(); await getConfigItemsFromCustomer();
if (addRow.value) { if (addRow.value) {
alert('Please confirm the last added row first.') alert('Please confirm the last added row first.')
return return
@ -367,25 +373,25 @@ const getMvtTodosById = async () => {
} }
} }
//get all config items from the selected client //get all config items from the selected customer
const getConfigItemsFromClient = async () => { const getConfigItemsFromCustomer = async () => {
if (!addBool.value) { if (!addBool.value) {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCIFromClient/${MVT.value.customerID}`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCIFromCustomer/${MVT.value.customerID}`);
configItemList.value = response.data; configItemList.value = response.data;
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
} else { } else {
try { try {
const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCIFromClient/${changedClientId.value}`); const response = await Axios.get(`https://${clientsideConfig.url}:${clientsideConfig.port}/api/getCIFromCustomer/${changedCustomerId.value}`);
configItemList.value = response.data; configItemList.value = response.data;
} catch (err) { } catch (err) {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
} }
if (clientChanged.value) { if (customerChanged.value) {
store.commit('toggleClientChanged'); store.commit('toggleCustomerChanged');
} }
} }
@ -401,7 +407,7 @@ const getMVTById = async () => {
console.log(err.response.statusText); console.log(err.response.statusText);
} }
} }
await getConfigItemsFromClient(); await getConfigItemsFromCustomer();
} }
const deleteMVTTodo = async (id) => { const deleteMVTTodo = async (id) => {
@ -415,11 +421,30 @@ const deleteMVTTodo = async (id) => {
await getMvtTodosById(); await getMvtTodosById();
} }
watch(clientChanged, getMVTById); const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
}
onMounted(() => { function getItem(item) {
getMvtTodosById(); if (process.client) {
getMVTById(); return localStorage.getItem(item)
} else {
return undefined
}
}
watch(customerChanged, getMVTById);
watch(modeChanged, getSession)
onMounted(async () => {
getSession();
await getMvtTodosById();
await getMVTById();
triggerBackendCallsWithDelay(getMaintenanceVisitTemplates); triggerBackendCallsWithDelay(getMaintenanceVisitTemplates);
}); });
</script> </script>

View File

@ -1,14 +1,43 @@
<template> <template>
<section :class="['userAccount', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section :class="['userAccount', loggedInUserDarkModeBoolean ? 'section-darkmode' : 'section-lightmode']">
<h2 :class="['heading', darkMode ? 'heading-darkmode' : 'heading-lightmode']">Account:</h2> <h2 :class="['heading', loggedInUserDarkModeBoolean ? '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', loggedInUserDarkModeBoolean ? 'pre-darkmode' : 'pre-lightmode']">Username:</pre>
<pre v-if="!editable"
:class="['data', loggedInUserDarkModeBoolean ? 'data-darkmode' : 'data-lightmode']">{{ loggedInUserUsername }}</pre>
<input v-if="editable" v-model="loggedInUserUsername" @change="updateUsername()"
:class="['data', 'input', loggedInUserDarkModeBoolean ? 'data-darkmode' : 'data-lightmode']">
</div> </div>
<div class="data-field" id="email">
<pre :class="['label', loggedInUserDarkModeBoolean ? 'pre-darkmode' : 'pre-lightmode']">Email:</pre>
<pre v-if="!editable"
:class="['data', loggedInUserDarkModeBoolean ? 'data-darkmode' : 'data-lightmode']">{{ loggedInUserEmail }}</pre>
<input v-if="editable" v-model="loggedInUserEmail" @change="updateUser()"
:class="['data', 'input', loggedInUserDarkModeBoolean ? 'data-darkmode' : 'data-lightmode']">
</div>
<input v-if="editable"
:class="[loggedInUserDarkModeBoolean ? 'input-darkmode' : '', !loggedInUserDarkModeBoolean ? 'input-lightmode' : '',]"
type="button" id="changePassword" value="Change Password" @click="changePassword">
</div>
<div v-if="changePasswordBool && editable" class="password">
<div class="data-field" id="password"> <div class="data-field" id="password">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Password:</pre> <pre
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">*******</pre> :class="['label', loggedInUserDarkModeBoolean ? 'pre-darkmode' : 'pre-lightmode']">New Password:</pre>
<input v-if="editable" v-model="loggedInUserNewPassword"
:class="['data', 'input', loggedInUserDarkModeBoolean ? 'data-darkmode' : 'data-lightmode']">
</div>
<div class="data-field" id="passwordRepeated">
<pre
:class="['label', loggedInUserDarkModeBoolean ? 'pre-darkmode' : 'pre-lightmode']">Repeat:</pre>
<input v-if="editable" v-model="loggedInUserNewPasswordRepeated"
:class="['data', 'input', loggedInUserDarkModeBoolean ? 'data-darkmode' : 'data-lightmode']">
</div>
<input
:class="[loggedInUserDarkModeBoolean ? 'input-darkmode' : '', !loggedInUserDarkModeBoolean ? 'input-lightmode' : '',]"
type="button" id="savePassword" value="Save Password" @click="savePassword">
</div> </div>
</div> </div>
</section> </section>
@ -16,9 +45,214 @@
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
import Axios from '../axios.config.js';
import clientsideConfig from '../../clientsideConfig.js';
const darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
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 loggedInUserDarkModeBool = ref('');
const loggedInUserDarkModeBoolean = ref('');
const employees = ref([]);
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');
loggedInUserDarkModeBool.value = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool.value == 1) {
loggedInUserDarkModeBoolean.value = true;
} else {
loggedInUserDarkModeBoolean.value = false;
}
}
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,
darkModeBool: loggedInUserDarkModeBoolean.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)
if (loggedInUserDarkModeBoolean.value) {
loggedInUserDarkModeBool.value = 1;
} else {
loggedInUserDarkModeBool.value = 0;
}
setItem('logged-in-user-darkMode', loggedInUserDarkModeBool.value)
getSession();
store.commit('setLocalStorageChanged');
store.commit('toggleUpdateDarkMode');
} 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);
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
await triggerBackendCallsWithDelay(getEmployees);
});
</script> </script>
<script> <script>
@ -53,6 +287,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 +341,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
} }
@ -99,7 +386,7 @@ export default {
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
width: 100%; width: 100%;
padding: 0 1.875rem; padding: 0.8rem 1.875rem;
border-radius: 0.625rem; border-radius: 0.625rem;
gap: 1.25rem; gap: 1.25rem;
} }
@ -137,4 +424,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

@ -1,26 +1,132 @@
<template> <template>
<section :class="['userAppearance', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section :class="['userAppearance', loggedInUserDarkModeBoolean ? 'section-darkmode' : 'section-lightmode']">
<div class="userData"> <div class="userData">
<div class="data-field" id="mode"> <div class="data-field" id="mode">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Mode:</pre> <pre :class="['label', loggedInUserDarkModeBoolean ? 'pre-darkmode' : 'pre-lightmode']">Mode:</pre>
<pre :class="['smallLabel', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Lightmode</pre> <pre
<Toggle v-model="darkMode" id="toggleAppearance" /> :class="['smallLabel', loggedInUserDarkModeBoolean ? 'pre-darkmode' : 'pre-lightmode']">Lightmode</pre>
<pre :class="['smallLabel', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Darkmode</pre> <Toggle v-model="loggedInUserDarkModeBoolean" id="toggleAppearance" />
<pre
:class="['smallLabel', loggedInUserDarkModeBoolean ? 'pre-darkmode' : 'pre-lightmode']">Darkmode</pre>
</div> </div>
<div class="data-field" id="language"> <div class="data-field" id="language">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Language:</pre> <pre :class="['label', loggedInUserDarkModeBoolean ? 'pre-darkmode' : 'pre-lightmode']">Language:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre> <pre :class="['data', loggedInUserDarkModeBoolean ? 'data-darkmode' : 'data-lightmode']">...</pre>
</div> </div>
</div> </div>
</section> </section>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import Toggle from '@vueform/toggle' import Toggle from '@vueform/toggle';
import { useStore } from 'vuex';
import Axios from '../axios.config.js';
import clientsideConfig from '../../clientsideConfig.js'
const darkMode = ref(true) const store = useStore();
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 loggedInUserDarkModeBool = ref('');
const loggedInUserDarkModeBoolean = ref(true);
function setItem(item, value) {
if (process.client) {
localStorage.setItem(item, value)
return true
} else {
return false
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
//update data
const updateUser = async () => {
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,
darkModeBool: loggedInUserDarkModeBoolean.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)
if (loggedInUserDarkModeBoolean.value) {
loggedInUserDarkModeBool.value = 1;
} else {
loggedInUserDarkModeBool.value = 0;
}
setItem('logged-in-user-darkMode', loggedInUserDarkModeBool.value)
getSession();
store.commit('setLocalStorageChanged');
store.commit('toggleUpdateDarkMode');
} catch (err) {
console.log(err.response.statusText);
}
}
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');
loggedInUserDarkModeBool.value = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool.value == 1) {
loggedInUserDarkModeBoolean.value = true;
} else {
loggedInUserDarkModeBoolean.value = false;
}
}
watch(loggedInUserDarkModeBoolean, updateUser)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>
@ -70,7 +176,7 @@ export default {
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
width: 100%; width: 100%;
padding: 0 1.875rem; padding: 0.8rem 1.875rem;
border-radius: 0.625rem; border-radius: 0.625rem;
gap: 1.25rem; gap: 1.25rem;
} }

View File

@ -1,13 +1,70 @@
<template> <template>
<section :class="['userProfile', darkMode ? 'section-darkmode' : 'section-lightmode']"> <section :class="['userProfile', loggedInUserDarkModeBoolean ? 'section-darkmode' : 'section-lightmode']">
<h2 :class="['heading', darkMode ? 'heading-darkmode' : 'heading-lightmode']">Profile:</h2> <h2 :class="['heading', loggedInUserDarkModeBoolean ? 'heading-darkmode' : 'heading-lightmode']">Profile:</h2>
<div class="userData"> <div class="userData">
<div class="rectangle-container"> <div class="rectangle-container">
<div :class="['rectangle', darkMode ? 'rectangle-darkmode' : 'rectangle-lightmode']"></div> <div :class="['rectangle', loggedInUserDarkModeBoolean ? 'rectangle-darkmode' : 'rectangle-lightmode']">
</div>
</div>
<div class="fullname-registered-lastLogin">
<div class="data-field" id="fullName">
<pre
:class="['label', loggedInUserDarkModeBoolean ? 'pre-darkmode' : 'pre-lightmode']">Full name:</pre>
<pre v-if="!editable"
:class="['data', loggedInUserDarkModeBoolean ? 'data-darkmode' : 'data-lightmode']">{{ loggedInUserFullName }}</pre>
<input v-if="editable" v-model="loggedInUserFullName" @change="updateUser()"
:class="['data', 'input', loggedInUserDarkModeBoolean ? 'data-darkmode' : 'data-lightmode']">
</div>
<div class="data-field" id="registered">
<pre
:class="['label', loggedInUserDarkModeBoolean ? 'pre-darkmode' : 'pre-lightmode']">Registered:</pre>
<pre
:class="['data', loggedInUserDarkModeBoolean ? 'data-darkmode' : 'data-lightmode']"> {{ loggedInUserRegistered }}</pre>
</div>
<div class="data-field" id="lastLogin">
<pre
:class="['label', loggedInUserDarkModeBoolean ? 'pre-darkmode' : 'pre-lightmode']">Last login:</pre>
<pre
:class="['data', loggedInUserDarkModeBoolean ? 'data-darkmode' : 'data-lightmode']"> {{ loggedInUserLastLogin }}</pre>
</div>
</div>
<div class="info">
<div class="city-phonenumber">
<div class="data-field" id="city">
<pre
:class="['label', loggedInUserDarkModeBoolean ? 'pre-darkmode' : 'pre-lightmode']">City:</pre>
<pre v-if="!editable"
:class="['data', loggedInUserDarkModeBoolean ? 'data-darkmode' : 'data-lightmode']">{{ loggedInUserCity }}</pre>
<input v-if="editable" v-model="loggedInUserCity" @change="updateUser()"
:class="['data', 'input', loggedInUserDarkModeBoolean ? 'data-darkmode' : 'data-lightmode']">
</div>
<div class="data-field" id="phonenumber">
<pre
:class="['label', loggedInUserDarkModeBoolean ? 'pre-darkmode' : 'pre-lightmode']">Phonenumber:</pre>
<pre v-if="!editable"
:class="['data', loggedInUserDarkModeBoolean ? 'data-darkmode' : 'data-lightmode']">{{ loggedInUserPhonenumber }}</pre>
<input v-if="editable" v-model="loggedInUserPhonenumber" @change="updateUser()"
:class="['data', 'input', loggedInUserDarkModeBoolean ? 'data-darkmode' : 'data-lightmode']">
</div>
</div>
<div class="postcode-address">
<div class="data-field" id="postcode">
<pre
:class="['label', loggedInUserDarkModeBoolean ? 'pre-darkmode' : 'pre-lightmode']">Postcode:</pre>
<pre v-if="!editable"
:class="['data', loggedInUserDarkModeBoolean ? 'data-darkmode' : 'data-lightmode']">{{ loggedInUserPostcode }}</pre>
<input v-if="editable" v-model="loggedInUserPostcode" @change="updateUser()"
:class="['data', 'input', loggedInUserDarkModeBoolean ? 'data-darkmode' : 'data-lightmode']">
</div>
<div class="data-field" id="address">
<pre
:class="['label', loggedInUserDarkModeBoolean ? 'pre-darkmode' : 'pre-lightmode']">Address:</pre>
<pre v-if="!editable"
:class="['data', loggedInUserDarkModeBoolean ? 'data-darkmode' : 'data-lightmode']">{{ loggedInUserAddress }}</pre>
<input v-if="editable" v-model="loggedInUserAddress" @change="updateUser()"
:class="['data', 'input', loggedInUserDarkModeBoolean ? 'data-darkmode' : 'data-lightmode']">
</div>
</div> </div>
<div class="data-field" id="username">
<pre :class="['label', darkMode ? 'pre-darkmode' : 'pre-lightmode']">Username:</pre>
<pre :class="['data', darkMode ? 'data-darkmode' : 'data-lightmode']">...</pre>
</div> </div>
</div> </div>
</section> </section>
@ -15,9 +72,170 @@
<script setup> <script setup>
import { ref } from 'vue'; import { ref, watch, onMounted } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
import Axios from '../axios.config.js';
import clientsideConfig from '../../clientsideConfig.js';
const darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
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('');
const loggedInUserDarkModeBool = ref('');
const loggedInUserDarkModeBoolean = 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');
loggedInUserDarkModeBool.value = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool.value == 1) {
loggedInUserDarkModeBoolean.value = true;
} else {
loggedInUserDarkModeBoolean.value = false;
}
}
//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,
darkModeBool: loggedInUserDarkModeBoolean.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)
if (loggedInUserDarkModeBoolean.value) {
loggedInUserDarkModeBool.value = 1;
} else {
loggedInUserDarkModeBool.value = 0;
}
setItem('logged-in-user-darkMode', loggedInUserDarkModeBool.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);
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>
@ -52,11 +270,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 +291,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 +312,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;
} }
@ -100,7 +358,7 @@ export default {
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
width: 100%; width: 100%;
padding: 0 1.875rem; padding: 0.8rem 1.875rem;
border-radius: 0.625rem; border-radius: 0.625rem;
gap: 1.25rem; gap: 1.25rem;
} }

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

39
composables/UserObject.ts Normal file
View File

@ -0,0 +1,39 @@
export var UserObjectDefinition: {
id: string;
username: string;
password: string;
registered: string;
lastLogin: string;
fullName: string;
email: string;
phonenumber: string;
address: string;
city: string;
postcode: string;
adminBool: boolean;
technician1Bool: boolean;
technician2Bool: boolean;
technicianMonitoringBool: boolean;
merchantBool: boolean;
internBool: boolean;
}
export interface UserObject {
id: string;
username: string;
password: string;
registered: string;
lastLogin: string;
fullName: string;
email: string;
phonenumber: string;
address: string;
city: string;
postcode: string;
adminBool: boolean;
technician1Bool: boolean;
technician2Bool: boolean;
technicianMonitoringBool: boolean;
merchantBool: boolean;
internBool: boolean;
}

View File

@ -1,6 +1,6 @@
<mxfile host="Electron" modified="2024-02-14T10:28:35.536Z" 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="_zOGEdVgp7g5JHBy-mYE" version="22.0.3" type="device" pages="2"> <mxfile host="Electron" modified="2024-03-11T18:43:59.748Z" 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="Ub9Iakw2VLrdzjhM2iAH" version="22.0.3" type="device" pages="2">
<diagram name="Seite-1" id="VLuSDTVFFHJCdRpH-1WC"> <diagram name="Seite-1" id="VLuSDTVFFHJCdRpH-1WC">
<mxGraphModel dx="393" dy="2849" 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="409" 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>
<mxCell id="0" /> <mxCell id="0" />
<mxCell id="1" parent="0" /> <mxCell id="1" parent="0" />
@ -395,7 +395,7 @@
<mxGeometry y="510" width="150" height="30" as="geometry" /> <mxGeometry y="510" width="150" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-15" value="issueSlips" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#00CC00;" parent="1" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-15" value="issueSlips" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#00CC00;" parent="1" vertex="1">
<mxGeometry x="2040" y="-560" width="140" height="540" as="geometry" /> <mxGeometry x="2040" y="-560" width="140" height="840" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-16" value="primaryID*" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-16" value="primaryID*" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="30" width="140" height="30" as="geometry" /> <mxGeometry y="30" width="140" height="30" as="geometry" />
@ -421,33 +421,63 @@
<mxCell id="WukdXvazNq34soQIU5Al-21" value="notes" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-21" value="notes" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="240" width="140" height="30" as="geometry" /> <mxGeometry y="240" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-23" value="supplierRequest" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="6nz9YpIofWTpyD1iDkT1-14" value="deliveryAddress" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="270" width="140" height="30" as="geometry" /> <mxGeometry y="270" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-32" value="supplierOffer" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-23" value="supplierRequestDate" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="300" width="140" height="30" as="geometry" /> <mxGeometry y="300" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-33" value="clientOffer" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="6nz9YpIofWTpyD1iDkT1-5" value="supplierRequest" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="330" width="140" height="30" as="geometry" /> <mxGeometry y="330" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-34" value="clientOrder" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-32" value="supplierOfferDate" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="360" width="140" height="30" as="geometry" /> <mxGeometry y="360" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-35" value="supplierOrder" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="6nz9YpIofWTpyD1iDkT1-6" value="supplierOffer" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="390" width="140" height="30" as="geometry" /> <mxGeometry y="390" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-36" value="ingress" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-33" value="clientOfferDate" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="420" width="140" height="30" as="geometry" /> <mxGeometry y="420" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-37" value="egress" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="6nz9YpIofWTpyD1iDkT1-7" value="clientOffer" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="450" width="140" height="30" as="geometry" /> <mxGeometry y="450" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-38" value="ingressBill" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-34" value="clientOrderDate" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="480" width="140" height="30" as="geometry" /> <mxGeometry y="480" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-39" value="egressBill" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="6nz9YpIofWTpyD1iDkT1-8" value="clientOrder" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="510" width="140" height="30" as="geometry" /> <mxGeometry y="510" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-35" value="supplierOrderDate" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="540" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="6nz9YpIofWTpyD1iDkT1-9" value="supplierOrder" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="570" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-36" value="ingressDate" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="600" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="6nz9YpIofWTpyD1iDkT1-10" value="ingress" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="630" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="6nz9YpIofWTpyD1iDkT1-11" value="egressDate" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="660" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-37" value="egress" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="690" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="6nz9YpIofWTpyD1iDkT1-12" value="ingressBillDate" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="720" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-38" value="ingressBill" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="750" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="6nz9YpIofWTpyD1iDkT1-13" value="egressBillDate" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="780" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-39" value="egressBill" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="810" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-40" value="orderingInfoIssueSlips" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#00CC00;" parent="1" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-40" value="orderingInfoIssueSlips" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#00CC00;" parent="1" vertex="1">
<mxGeometry x="2220" y="-440" width="140" height="210" as="geometry" /> <mxGeometry x="2220" y="-440" width="140" height="210" as="geometry" />
</mxCell> </mxCell>
@ -470,7 +500,7 @@
<mxGeometry y="180" width="140" height="30" as="geometry" /> <mxGeometry y="180" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-48" value="issues" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#00CC00;" parent="1" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-48" value="issues" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#00CC00;" parent="1" vertex="1">
<mxGeometry x="2040" y="120" width="140" height="210" as="geometry" /> <mxGeometry x="2040" y="400" width="140" height="210" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-49" value="primaryID*" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-48" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-49" value="primaryID*" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-48" vertex="1">
<mxGeometry y="30" width="140" height="30" as="geometry" /> <mxGeometry y="30" width="140" height="30" as="geometry" />
@ -491,7 +521,7 @@
<mxGeometry y="180" width="140" height="30" as="geometry" /> <mxGeometry y="180" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-56" value="issueVariants" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#00CC00;" parent="1" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-56" value="issueVariants" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#00CC00;" parent="1" vertex="1">
<mxGeometry x="2220" y="180" width="140" height="240" as="geometry" /> <mxGeometry x="2220" y="460" width="140" height="240" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-57" value="primaryID*" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-56" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-57" value="primaryID*" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-56" vertex="1">
<mxGeometry y="30" width="140" height="30" as="geometry" /> <mxGeometry y="30" width="140" height="30" as="geometry" />
@ -580,7 +610,7 @@
<mxCell id="WukdXvazNq34soQIU5Al-108" value="task" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-103" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-108" value="task" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-103" vertex="1">
<mxGeometry y="150" width="140" height="30" as="geometry" /> <mxGeometry y="150" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-109" value="comment" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-103" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-109" value="comments" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-103" vertex="1">
<mxGeometry y="180" width="140" height="30" as="geometry" /> <mxGeometry y="180" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-128" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="WukdXvazNq34soQIU5Al-126" target="DauqCNUrC7Z9yIe88X-r-22" edge="1"> <mxCell id="WukdXvazNq34soQIU5Al-128" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="WukdXvazNq34soQIU5Al-126" target="DauqCNUrC7Z9yIe88X-r-22" edge="1">

View File

@ -1,11 +1,11 @@
<mxfile host="Electron" modified="2024-02-27T19:18:30.556Z" 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="pTIMz7977P7LLgTl7RJZ" version="22.0.3" type="device" pages="2"> <mxfile host="Electron" modified="2024-03-26T21:49:41.086Z" 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="AqTSSHc8H4ak1GACwEHF" version="22.0.3" type="device" pages="2">
<diagram name="Seite-1" id="VLuSDTVFFHJCdRpH-1WC"> <diagram name="Seite-1" id="VLuSDTVFFHJCdRpH-1WC">
<mxGraphModel dx="395" 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="411" 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>
<mxCell id="0" /> <mxCell id="0" />
<mxCell id="1" parent="0" /> <mxCell id="1" parent="0" />
<mxCell id="DauqCNUrC7Z9yIe88X-r-1" value="customers" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#94FF4D;" parent="1" vertex="1"> <mxCell id="DauqCNUrC7Z9yIe88X-r-1" value="customers" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#94FF4D;" parent="1" vertex="1">
<mxGeometry x="1060" y="-1240" width="120" height="300" as="geometry" /> <mxGeometry x="1060" y="-1240" width="120" height="600" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-126" value="customerID*" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-126" value="customerID*" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1">
<mxGeometry y="30" width="120" height="30" as="geometry" /> <mxGeometry y="30" width="120" height="30" as="geometry" />
@ -19,21 +19,51 @@
<mxCell id="g533v6kp8f2wI3S2lvbX-2" value="EMail" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1"> <mxCell id="g533v6kp8f2wI3S2lvbX-2" value="EMail" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1">
<mxGeometry y="120" width="120" height="30" as="geometry" /> <mxGeometry y="120" width="120" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="g533v6kp8f2wI3S2lvbX-1" value="phonenumber" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1"> <mxCell id="EQ1vHiXafF4bEUqPIK37-7" value="secondEMail" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1">
<mxGeometry y="150" width="120" height="30" as="geometry" /> <mxGeometry y="150" width="120" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="DauqCNUrC7Z9yIe88X-r-4" value="&lt;div&gt;address&lt;/div&gt;" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1"> <mxCell id="EQ1vHiXafF4bEUqPIK37-8" value="thirdEMail" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1">
<mxGeometry y="180" width="120" height="30" as="geometry" /> <mxGeometry y="180" width="120" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="DauqCNUrC7Z9yIe88X-r-16" value="postcode" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1"> <mxCell id="g533v6kp8f2wI3S2lvbX-1" value="phonenumber" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1">
<mxGeometry y="210" width="120" height="30" as="geometry" /> <mxGeometry y="210" width="120" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="DauqCNUrC7Z9yIe88X-r-15" value="city" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1"> <mxCell id="EQ1vHiXafF4bEUqPIK37-10" value="secondPhonenumber" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1">
<mxGeometry y="240" width="120" height="30" as="geometry" /> <mxGeometry y="240" width="120" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="jym2pQnfcZ--NBFUidHV-1" value="notes" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1"> <mxCell id="EQ1vHiXafF4bEUqPIK37-9" value="thirdPhonenumber" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1">
<mxGeometry y="270" width="120" height="30" as="geometry" /> <mxGeometry y="270" width="120" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="DauqCNUrC7Z9yIe88X-r-4" value="&lt;div&gt;address&lt;/div&gt;" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1">
<mxGeometry y="300" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="DauqCNUrC7Z9yIe88X-r-16" value="postcode" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1">
<mxGeometry y="330" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="DauqCNUrC7Z9yIe88X-r-15" value="city" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1">
<mxGeometry y="360" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="jym2pQnfcZ--NBFUidHV-1" value="notes" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1">
<mxGeometry y="390" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="EQ1vHiXafF4bEUqPIK37-1" value="&lt;div&gt;secondAddress&lt;/div&gt;" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1">
<mxGeometry y="420" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="EQ1vHiXafF4bEUqPIK37-2" value="&lt;div&gt;secondPostcode&lt;/div&gt;" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1">
<mxGeometry y="450" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="EQ1vHiXafF4bEUqPIK37-3" value="&lt;div&gt;secondCity&lt;/div&gt;" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1">
<mxGeometry y="480" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="EQ1vHiXafF4bEUqPIK37-4" value="thirdAddress" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1">
<mxGeometry y="510" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="EQ1vHiXafF4bEUqPIK37-5" value="&lt;div&gt;thirdPostcode&lt;/div&gt;" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1">
<mxGeometry y="540" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="EQ1vHiXafF4bEUqPIK37-6" value="&lt;div&gt;thirdCity&lt;/div&gt;" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="DauqCNUrC7Z9yIe88X-r-1" vertex="1">
<mxGeometry y="570" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="DauqCNUrC7Z9yIe88X-r-18" value="masterMaintenanceVisits" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#00CC00;" parent="1" vertex="1"> <mxCell id="DauqCNUrC7Z9yIe88X-r-18" value="masterMaintenanceVisits" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#00CC00;" parent="1" vertex="1">
<mxGeometry x="470" y="-560" width="140" height="270" as="geometry" /> <mxGeometry x="470" y="-560" width="140" height="270" as="geometry" />
</mxCell> </mxCell>
@ -341,7 +371,7 @@
<mxGeometry y="300" width="140" height="30" as="geometry" /> <mxGeometry y="300" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="-K6vikdffkJQkB35vOLp-1" value="users" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" parent="1" vertex="1"> <mxCell id="-K6vikdffkJQkB35vOLp-1" value="users" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry y="-1570" width="150" height="540" as="geometry" /> <mxGeometry y="-1570" width="150" height="510" as="geometry" />
</mxCell> </mxCell>
<mxCell id="-K6vikdffkJQkB35vOLp-2" value="id" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="-K6vikdffkJQkB35vOLp-1" vertex="1"> <mxCell id="-K6vikdffkJQkB35vOLp-2" value="id" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="-K6vikdffkJQkB35vOLp-1" vertex="1">
<mxGeometry y="30" width="150" height="30" as="geometry" /> <mxGeometry y="30" width="150" height="30" as="geometry" />
@ -379,23 +409,20 @@
<mxCell id="ioDwbpDVXUhE7vu6D29p-8" value="adminBool" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="-K6vikdffkJQkB35vOLp-1" vertex="1"> <mxCell id="ioDwbpDVXUhE7vu6D29p-8" value="adminBool" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="-K6vikdffkJQkB35vOLp-1" vertex="1">
<mxGeometry y="360" width="150" height="30" as="geometry" /> <mxGeometry y="360" width="150" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="ioDwbpDVXUhE7vu6D29p-9" value="technician1Bool" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="-K6vikdffkJQkB35vOLp-1" vertex="1"> <mxCell id="ioDwbpDVXUhE7vu6D29p-10" value="technicianBool" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="-K6vikdffkJQkB35vOLp-1" vertex="1">
<mxGeometry y="390" width="150" height="30" as="geometry" /> <mxGeometry y="390" width="150" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="ioDwbpDVXUhE7vu6D29p-10" value="technician2Bool" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="-K6vikdffkJQkB35vOLp-1" vertex="1"> <mxCell id="ioDwbpDVXUhE7vu6D29p-12" value="readerBool" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="-K6vikdffkJQkB35vOLp-1" vertex="1">
<mxGeometry y="420" width="150" height="30" as="geometry" /> <mxGeometry y="420" width="150" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="ioDwbpDVXUhE7vu6D29p-11" value="technicianMonitoringBool" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="-K6vikdffkJQkB35vOLp-1" vertex="1"> <mxCell id="YxEx8JsSJKZlR_KfoIc3-1" value="darkModeBool" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="-K6vikdffkJQkB35vOLp-1" vertex="1">
<mxGeometry y="450" width="150" height="30" as="geometry" /> <mxGeometry y="450" width="150" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="ioDwbpDVXUhE7vu6D29p-12" value="merchantBool" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="-K6vikdffkJQkB35vOLp-1" vertex="1"> <mxCell id="ESQ1TkVnqClHsEl95Prr-1" value="language" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="-K6vikdffkJQkB35vOLp-1">
<mxGeometry y="480" width="150" height="30" as="geometry" /> <mxGeometry y="480" width="150" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="UjUgOsnL5tA5fsC7Xk2_-1" value="internBool" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="-K6vikdffkJQkB35vOLp-1" vertex="1">
<mxGeometry y="510" width="150" height="30" as="geometry" />
</mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-15" value="issueSlips" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#00CC00;" parent="1" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-15" value="issueSlips" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#00CC00;" parent="1" vertex="1">
<mxGeometry x="2040" y="-560" width="140" height="540" as="geometry" /> <mxGeometry x="2040" y="-560" width="140" height="840" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-16" value="primaryID*" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-16" value="primaryID*" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="30" width="140" height="30" as="geometry" /> <mxGeometry y="30" width="140" height="30" as="geometry" />
@ -421,33 +448,63 @@
<mxCell id="WukdXvazNq34soQIU5Al-21" value="notes" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-21" value="notes" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="240" width="140" height="30" as="geometry" /> <mxGeometry y="240" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-23" value="supplierRequest" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="6nz9YpIofWTpyD1iDkT1-14" value="deliveryAddress" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="270" width="140" height="30" as="geometry" /> <mxGeometry y="270" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-32" value="supplierOffer" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-23" value="supplierRequestDate" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="300" width="140" height="30" as="geometry" /> <mxGeometry y="300" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-33" value="clientOffer" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="6nz9YpIofWTpyD1iDkT1-5" value="supplierRequest" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="330" width="140" height="30" as="geometry" /> <mxGeometry y="330" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-34" value="clientOrder" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-32" value="supplierOfferDate" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="360" width="140" height="30" as="geometry" /> <mxGeometry y="360" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-35" value="supplierOrder" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="6nz9YpIofWTpyD1iDkT1-6" value="supplierOffer" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="390" width="140" height="30" as="geometry" /> <mxGeometry y="390" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-36" value="ingress" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-33" value="clientOfferDate" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="420" width="140" height="30" as="geometry" /> <mxGeometry y="420" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-37" value="egress" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="6nz9YpIofWTpyD1iDkT1-7" value="clientOffer" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="450" width="140" height="30" as="geometry" /> <mxGeometry y="450" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-38" value="ingressBill" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-34" value="clientOrderDate" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="480" width="140" height="30" as="geometry" /> <mxGeometry y="480" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-39" value="egressBill" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1"> <mxCell id="6nz9YpIofWTpyD1iDkT1-8" value="clientOrder" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="510" width="140" height="30" as="geometry" /> <mxGeometry y="510" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-35" value="supplierOrderDate" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="540" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="6nz9YpIofWTpyD1iDkT1-9" value="supplierOrder" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="570" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-36" value="ingressDate" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="600" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="6nz9YpIofWTpyD1iDkT1-10" value="ingress" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="630" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="6nz9YpIofWTpyD1iDkT1-11" value="egressDate" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="660" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-37" value="egress" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="690" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="6nz9YpIofWTpyD1iDkT1-12" value="ingressBillDate" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="720" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-38" value="ingressBill" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="750" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="6nz9YpIofWTpyD1iDkT1-13" value="egressBillDate" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="780" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-39" value="egressBill" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-15" vertex="1">
<mxGeometry y="810" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-40" value="orderingInfoIssueSlips" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#00CC00;" parent="1" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-40" value="orderingInfoIssueSlips" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#00CC00;" parent="1" vertex="1">
<mxGeometry x="2220" y="-440" width="140" height="210" as="geometry" /> <mxGeometry x="2220" y="-440" width="140" height="210" as="geometry" />
</mxCell> </mxCell>
@ -470,7 +527,7 @@
<mxGeometry y="180" width="140" height="30" as="geometry" /> <mxGeometry y="180" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-48" value="issues" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#00CC00;" parent="1" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-48" value="issues" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#00CC00;" parent="1" vertex="1">
<mxGeometry x="2040" y="120" width="140" height="210" as="geometry" /> <mxGeometry x="2040" y="400" width="140" height="210" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-49" value="primaryID*" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-48" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-49" value="primaryID*" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-48" vertex="1">
<mxGeometry y="30" width="140" height="30" as="geometry" /> <mxGeometry y="30" width="140" height="30" as="geometry" />
@ -491,7 +548,7 @@
<mxGeometry y="180" width="140" height="30" as="geometry" /> <mxGeometry y="180" width="140" height="30" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-56" value="issueVariants" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#00CC00;" parent="1" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-56" value="issueVariants" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#00CC00;" parent="1" vertex="1">
<mxGeometry x="2220" y="180" width="140" height="240" as="geometry" /> <mxGeometry x="2220" y="460" width="140" height="240" as="geometry" />
</mxCell> </mxCell>
<mxCell id="WukdXvazNq34soQIU5Al-57" value="primaryID*" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-56" vertex="1"> <mxCell id="WukdXvazNq34soQIU5Al-57" value="primaryID*" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" parent="WukdXvazNq34soQIU5Al-56" vertex="1">
<mxGeometry y="30" width="140" height="30" as="geometry" /> <mxGeometry y="30" width="140" height="30" as="geometry" />

View File

@ -1,91 +1,145 @@
<template> <template>
<aside <aside
:class="['actionbar', darkMode ? 'actionbar-darkmode' : 'actionbar-lightmode', isExpanded ? 'is-expanded' : 'is-not-expanded']"> :class="['actionbar', loggedInUserDarkModeBoolean ? 'actionbar-darkmode' : 'actionbar-lightmode', isExpanded ? 'is-expanded' : 'is-not-expanded']">
<div :class="['icon', darkMode ? 'indicator-darkmode' : 'indicator-lightmode']" id="indicator-icon" <div :class="['icon', loggedInUserDarkModeBoolean ? 'indicator-darkmode' : 'indicator-lightmode']"
@click="toggleActionbar"> id="indicator-icon" @click="toggleActionbar">
<img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy" <img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="../icons/actionbar-icons/Indicator-Icon-Opened.svg" /> src="/icons/actionbar-icons/Indicator-Icon-Opened.svg" />
</div> </div>
<nav class="actions"> <nav class="actions">
<button :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="search" @click="toggleSearched"> <button v-if="searchIcon" :class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']"
id="search" @click="toggleSearched">
<div class="icon" id="search-icon"> <div class="icon" id="search-icon">
<img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy" <img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="../icons/actionbar-icons/Search-Icon.svg" /> src="/icons/actionbar-icons/Search-Icon.svg" />
</div> </div>
<Transition name="fade"> <Transition name="fade">
<pre v-if="isExpanded" :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Search</pre> <pre v-if="isExpanded"
:class="['label', loggedInUserDarkModeBoolean ? 'label-darkmode' : 'label-lightmode']">Search</pre>
</Transition> </Transition>
</button> </button>
<button :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="filter" @click="toggleFiltered"> <button v-if="filterIcon" :class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']"
id="filter" @click="toggleFiltered">
<div class="icon" id="filter-icon"> <div class="icon" id="filter-icon">
<img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy" <img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="../icons/actionbar-icons/Filter-Icon.svg" /> src="/icons/actionbar-icons/Filter-Icon.svg" />
</div> </div>
<Transition name="fade"> <Transition name="fade">
<pre v-if="isExpanded" :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Filter</pre> <pre v-if="isExpanded"
:class="['label', loggedInUserDarkModeBoolean ? 'label-darkmode' : 'label-lightmode']">Filter</pre>
</Transition> </Transition>
</button> </button>
<button :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="instances"> <button v-if="instancesIcon" :class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']"
id="instances">
<div class="icon" id="instances-icon"> <div class="icon" id="instances-icon">
<img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy" <img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="../icons/actionbar-icons/Instances-Icon.svg" /> src="/icons/actionbar-icons/Instances-Icon.svg" />
</div> </div>
<Transition name="fade"> <Transition name="fade">
<pre v-if="isExpanded" :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Instances</pre> <pre v-if="isExpanded"
:class="['label', loggedInUserDarkModeBoolean ? 'label-darkmode' : 'label-lightmode']">Instances</pre>
</Transition> </Transition>
</button> </button>
<button :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="attachments"> <button v-if="solutionIcon" :class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']"
id="solutions" @click="changeToSolutions">
<div class="icon" id="instances-icon">
<img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="/icons/actionbar-icons/Instances-Icon.svg" />
</div>
<Transition name="fade">
<pre v-if="isExpanded"
:class="['label', loggedInUserDarkModeBoolean ? 'label-darkmode' : 'label-lightmode']">Solutions</pre>
</Transition>
</button>
<button v-if="attachmentsIcon" :class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']"
id="attachments">
<div class="icon" id="attachments-icon"> <div class="icon" id="attachments-icon">
<img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy" <img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="../icons/actionbar-icons/Attachments-Icon.svg" /> src="/icons/actionbar-icons/Attachments-Icon.svg" />
</div> </div>
<Transition name="fade"> <Transition name="fade">
<pre v-if="isExpanded" :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Attachments</pre> <pre v-if="isExpanded"
:class="['label', loggedInUserDarkModeBoolean ? 'label-darkmode' : 'label-lightmode']">Attachments</pre>
</Transition> </Transition>
</button> </button>
<button :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="sell"> <button v-if="sellIcon" :class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']" id="sell">
<div class="icon" id="sell-icon"> <div class="icon" id="sell-icon">
<img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy" <img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="../icons/actionbar-icons/Sell-Icon.svg" /> src="/icons/actionbar-icons/Sell-Icon.svg" />
</div> </div>
<Transition name="fade"> <Transition name="fade">
<pre v-if="isExpanded" :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Sell</pre> <pre v-if="isExpanded"
:class="['label', loggedInUserDarkModeBoolean ? 'label-darkmode' : 'label-lightmode']">Sell</pre>
</Transition> </Transition>
</button> </button>
<button :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="archive"> <button v-if="archiveIcon" :class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']"
id="archive">
<div class="icon" id="archive-icon"> <div class="icon" id="archive-icon">
<img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy" <img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="../icons/actionbar-icons/Archive-Icon.svg" /> src="/icons/actionbar-icons/Archive-Icon.svg" />
</div> </div>
<Transition name="fade"> <Transition name="fade">
<pre v-if="isExpanded" :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Archive</pre> <pre v-if="isExpanded"
:class="['label', loggedInUserDarkModeBoolean ? 'label-darkmode' : 'label-lightmode']">Archive</pre>
</Transition> </Transition>
</button> </button>
<button :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="new" @click="add"> <button v-if="addIcon && !loggedInUserReaderBool"
:class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']" id="new" @click="add">
<div class="icon" id="new-icon"> <div class="icon" id="new-icon">
<img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy" <img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="../icons/actionbar-icons/Add-New-Icon.svg" /> src="/icons/actionbar-icons/Add-New-Icon.svg" />
</div> </div>
<Transition name="fade"> <Transition name="fade">
<pre v-if="isExpanded" :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">New</pre> <pre v-if="isExpanded"
:class="['label', loggedInUserDarkModeBoolean ? 'label-darkmode' : 'label-lightmode']">New</pre>
</Transition> </Transition>
</button> </button>
<button :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="edit" @click="toggleEditable"> <button v-if="addInstanceIcon && !loggedInUserReaderBool"
:class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']" id="new-instance">
<div class="icon" id="new-icon">
<img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="/icons/actionbar-icons/Add-New-Icon.svg" />
</div>
<Transition name="fade">
<pre v-if="isExpanded"
:class="['label', loggedInUserDarkModeBoolean ? 'label-darkmode' : 'label-lightmode']">Instance</pre>
</Transition>
</button>
<router-link v-if="addSolutionIcon && !loggedInUserReaderBool" to="/solutions" class="button"
:class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']" id="solutions-button">
<button :class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']" id="new-solution"
@click="addSolution">
<div class="icon" id="new-icon">
<img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="/icons/actionbar-icons/Add-New-Icon.svg" />
</div>
<Transition name="fade">
<pre v-if="isExpanded"
:class="['label', loggedInUserDarkModeBoolean ? 'label-darkmode' : 'label-lightmode']">Solution</pre>
</Transition>
</button>
</router-link>
<button v-if="editIcon && !loggedInUserReaderBool"
:class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']" id="edit"
@click="toggleEditable">
<div class="icon" id="edit-icon"> <div class="icon" id="edit-icon">
<img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy" <img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="../icons/actionbar-icons/Edit-Icon.svg" /> src="/icons/actionbar-icons/Edit-Icon.svg" />
</div> </div>
<Transition name="fade"> <Transition name="fade">
<pre v-if="isExpanded" :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Edit</pre> <pre v-if="isExpanded"
:class="['label', loggedInUserDarkModeBoolean ? 'label-darkmode' : 'label-lightmode']">Edit</pre>
</Transition> </Transition>
</button> </button>
<button :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="delete" @click="deleteFunc"> <button v-if="deleteIcon && !loggedInUserReaderBool"
:class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']" id="delete" @click="deleteFunc">
<div class="icon" id="delete-icon"> <div class="icon" id="delete-icon">
<img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy" <img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="../icons/actionbar-icons/Delete-Icon.svg" /> src="/icons/actionbar-icons/Delete-Icon.svg" />
</div> </div>
<Transition name="fade"> <Transition name="fade">
<pre v-if="isExpanded" :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Delete</pre> <pre v-if="isExpanded"
:class="['label', loggedInUserDarkModeBoolean ? 'label-darkmode' : 'label-lightmode']">Delete</pre>
</Transition> </Transition>
</button> </button>
</nav> </nav>
@ -93,11 +147,28 @@
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { computed } from 'vue';
const darkMode = ref(true) const changeToSet = computed(() => store.state.changeToSet);
const isExpanded = ref(true) const addIcon = computed(() => store.state.addIcon);
const addInstanceIcon = computed(() => store.state.addInstanceIcon);
const addSolutionIcon = computed(() => store.state.addSolutionIcon);
const solutionIcon = computed(() => store.state.solutionIcon);
const filterIcon = computed(() => store.state.filterIcon);
const searchIcon = computed(() => store.state.searchIcon);
const instancesIcon = computed(() => store.state.instancesIcon);
const attachmentsIcon = computed(() => store.state.attachmentsIcon);
const sellIcon = computed(() => store.state.sellIcon);
const archiveIcon = computed(() => store.state.archiveIcon);
const editIcon = computed(() => store.state.editIcon);
const deleteIcon = computed(() => store.state.deleteIcon);
const loggedInUserDarkModeBoolean = ref('');
const isExpanded = ref(true);
const modeChanged = computed(() => store.state.updateDarkMode);
const loggedInUserReaderBool = ref(true);
// get accesss to the store // get accesss to the store
const store = useStore() const store = useStore()
@ -120,6 +191,58 @@ const toggleSearched = () => {
const add = () => { const add = () => {
store.commit('add'); store.commit('add');
}; };
const addSolution = () => {
store.commit('add');
};
const changeToSolutions = () => {
store.commit('changeToSolutionlistAsset');
}
// const changeToSettingsPage = () => {
// store.commit('changeToSettings');
// if (changeToSet.value) {
// store.commit('toggleChangeToSet');
// }
// console.log('set')
// }
// watch(changeToSet, changeToSettingsPage)
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
loggedInUserDarkModeBoolean.value = true;
} else {
loggedInUserDarkModeBoolean.value = false;
}
const readerBool = getItem('logged-in-user-readerBool');
if (readerBool == 1) {
loggedInUserReaderBool.value = true;
} else {
loggedInUserReaderBool.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
store.commit('changeToAssetlist')
if (changeToSet.value) {
store.commit('toggleChangeToSet');
store.commit('changeToSettings');
}
});
</script> </script>
@ -141,7 +264,7 @@ aside.actionbar {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: sticky; position: sticky;
top: 5rem; top: 3.75rem;
height: fit-content; height: fit-content;
width: fit-content; width: fit-content;
inline-size: fit-content; inline-size: fit-content;
@ -357,4 +480,5 @@ img {
max-width: 0; max-width: 0;
max-inline-size: 0; max-inline-size: 0;
} }
}</style> }
</style>

View File

@ -1,63 +1,102 @@
<template> <template>
<aside :class="['navbar', darkMode ? 'navbar-darkmode' : 'navbar-lightmode', isExpanded ? 'is-expanded' : 'is-not-expanded']"> <aside
:class="['navbar', loggedInUserDarkModeBoolean ? 'navbar-darkmode' : 'navbar-lightmode', isExpanded ? 'is-expanded' : 'is-not-expanded']">
<div class="toggleNavbar"> <div class="toggleNavbar">
<div v-if="isExpanded" :class="['icon', darkMode ? 'back-darkmode' : 'back-lightmode']" id="back-icon"> <div v-if="isExpanded" :class="['icon', loggedInUserDarkModeBoolean ? 'back-darkmode' : 'back-lightmode']"
<img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy" src="../icons/Back-Icon.svg" /> id="back-icon">
<img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="/icons/Back-Icon.svg" />
</div> </div>
<div :class="['icon', darkMode ? 'indicator-darkmode' : 'indicator-lightmode']" id="indicator-icon" @click="ToggleSidebar"> <div :class="['icon', loggedInUserDarkModeBoolean ? 'indicator-darkmode' : 'indicator-lightmode']"
<img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy" src="../icons/navbar-icons/Nav-Indicator-Icon-Opened.svg" /> id="indicator-icon" @click="ToggleSidebar">
<img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="/icons/navbar-icons/Nav-Indicator-Icon-Opened.svg" />
</div> </div>
</div> </div>
<div class="menus"> <div class="menus">
<nav id="home-menu" :class="[darkMode ? 'menu-darkmode' : 'menu-lightmode']"> <nav id="home-menu" :class="[loggedInUserDarkModeBoolean ? 'menu-darkmode' : 'menu-lightmode']">
<router-link to="/home" class="button" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="home-button"> <router-link to="/home" class="button"
:class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']" id="home-button">
<div class="icon" id="home-icon"> <div class="icon" id="home-icon">
<img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy" src="../icons/navbar-icons/Home-Icon.svg" /> <img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="/icons/navbar-icons/Home-Icon.svg" />
</div> </div>
<Transition name="fade"> <Transition name="fade">
<pre v-if="isExpanded" :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Home</pre> <pre v-if="isExpanded"
:class="['label', loggedInUserDarkModeBoolean ? 'label-darkmode' : 'label-lightmode']">Home</pre>
</Transition> </Transition>
</router-link> </router-link>
</nav> </nav>
<nav id="site-menu"> <nav id="site-menu">
<router-link to="/maintenanceVisits" class="button" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" @click="defaultMasterChecklistPage()" id="checklists-button"> <router-link to="/maintenanceVisits" class="button"
:class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']"
@click="defaultMasterChecklistPage()" id="checklists-button">
<div class="icon" id="checklists-icon"> <div class="icon" id="checklists-icon">
<img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy" src="../icons/navbar-icons/Checklists-Icon.svg" /> <img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="/icons/navbar-icons/Checklists-Icon.svg" />
</div> </div>
<Transition name="fade"> <Transition name="fade">
<pre v-if="isExpanded" :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Checklists</pre> <pre v-if="isExpanded"
:class="['label', loggedInUserDarkModeBoolean ? 'label-darkmode' : 'label-lightmode']">Checklists</pre>
</Transition> </Transition>
</router-link> </router-link>
<nuxt-link to="/assets" class="button" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" @click="defaultAssetPage()" id="assets-button"> <nuxt-link to="/assets" class="button"
:class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']" @click="defaultAssetPage()"
id="assets-button">
<div class="icon" id="assets-icon"> <div class="icon" id="assets-icon">
<img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy" src="../icons/navbar-icons/Assets-Icon.svg" /> <img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="/icons/navbar-icons/Assets-Icon.svg" />
</div> </div>
<Transition name="fade"> <Transition name="fade">
<pre v-if="isExpanded" :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Assets</pre> <pre v-if="isExpanded"
:class="['label', loggedInUserDarkModeBoolean ? 'label-darkmode' : 'label-lightmode']">Assets</pre>
</Transition> </Transition>
</nuxt-link> </nuxt-link>
<router-link to="/solutions" class="button" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" @click="defaultSolutionPage()" id="solutions-button"> <router-link to="/solutions" class="button"
:class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']" @click="defaultSolutionPage()"
id="solutions-button">
<div class="icon" id="solutions-icon"> <div class="icon" id="solutions-icon">
<img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy" src="../icons/navbar-icons/Solutions-Icon.svg" /> <img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="/icons/navbar-icons/Solutions-Icon.svg" />
</div> </div>
<Transition name="fade"> <Transition name="fade">
<pre v-if="isExpanded" :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Solutions</pre> <pre v-if="isExpanded"
:class="['label', loggedInUserDarkModeBoolean ? 'label-darkmode' : 'label-lightmode']">Solutions</pre>
</Transition> </Transition>
</router-link> </router-link>
<router-link to="/issueSlips" class="button" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="accounting-button"> <router-link to="/issueSlips" class="button"
:class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']"
@click="defaultIssueSlipPage()" id="accounting-button">
<div class="icon" id="accounting-icon"> <div class="icon" id="accounting-icon">
<img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy" src="../icons/navbar-icons/Accounting-Icon.svg" /> <img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="/icons/navbar-icons/Accounting-Icon.svg" />
</div> </div>
<Transition name="fade"> <Transition name="fade">
<pre v-if="isExpanded" :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Accounting</pre> <pre v-if="isExpanded"
:class="['label', loggedInUserDarkModeBoolean ? 'label-darkmode' : 'label-lightmode']">Accounting</pre>
</Transition> </Transition>
</router-link> </router-link>
<router-link to="/clients" class="button" :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" id="clients-button"> <router-link to="/customers" class="button"
<div class="icon" id="clients-icon"> :class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']" id="customers-button">
<img :class="[darkMode ? 'img-darkmode' : 'img-lightmode']" loading="lazy" src="../icons/navbar-icons/Clients-Icon.svg" /> <div class="icon" id="customers-icon">
<img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="/icons/navbar-icons/Customers-Icon.svg" />
</div> </div>
<Transition name="fade"> <Transition name="fade">
<pre v-if="isExpanded" :class="['label', darkMode ? 'label-darkmode' : 'label-lightmode']">Customers</pre> <pre v-if="isExpanded"
:class="['label', loggedInUserDarkModeBoolean ? 'label-darkmode' : 'label-lightmode']">Customers</pre>
</Transition>
</router-link>
<router-link v-if="loggedInUserAdminBool" to="/employees" class="button"
:class="[loggedInUserDarkModeBoolean ? 'button-darkmode' : 'button-lightmode']"
@click="defaultEmployeesPage()" id="employees-button">
<div class="icon" id="customers-icon">
<img :class="[loggedInUserDarkModeBoolean ? 'img-darkmode' : 'img-lightmode']" loading="lazy"
src="/icons/navbar-icons/Customers-Icon.svg" />
</div>
<Transition name="fade">
<pre v-if="isExpanded"
:class="['label', loggedInUserDarkModeBoolean ? 'label-darkmode' : 'label-lightmode']">Employees</pre>
</Transition> </Transition>
</router-link> </router-link>
</nav> </nav>
@ -65,17 +104,20 @@
</aside> </aside>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { computed } from 'vue';
const darkMode = ref(true) const store = useStore();
const isExpanded = ref(true) const modeChanged = computed(() => store.state.updateDarkMode);
const modeChangedLocalstorage = computed(() => store.state.modeNavbar);
const loggedInUserDarkModeBoolean = ref('');
const isExpanded = ref(true);
const loggedInUserAdminBool = ref(false);
// get accesss to the store // get accesss to the store
const store = useStore()
const defaultAssetPage = () => { const defaultAssetPage = () => {
store.commit('resetStore'); store.commit('resetStore');
store.commit('changeToAssetlist'); store.commit('changeToAssetlist');
@ -91,9 +133,52 @@ const defaultSolutionPage = () => {
store.commit('changeToSolutionlist') store.commit('changeToSolutionlist')
} }
const defaultIssueSlipPage = () => {
store.commit('resetStore');
store.commit('changeToIssueSliplist')
}
const defaultEmployeesPage = () => {
store.commit('resetStore');
store.commit('changeToEmployeelist')
}
const ToggleSidebar = () => { const ToggleSidebar = () => {
isExpanded.value = !isExpanded.value; isExpanded.value = !isExpanded.value;
}; };
const getSession = async () => {
if (modeChangedLocalstorage.value) {
store.commit('resetModeNavbarChanged');
}
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
loggedInUserDarkModeBoolean.value = true;
} else {
loggedInUserDarkModeBoolean.value = false;
}
const adminBool = getItem('logged-in-user-adminBool');
if (adminBool == 1) {
loggedInUserAdminBool.value = true;
} else {
loggedInUserAdminBool.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
watch(modeChangedLocalstorage, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>
@ -113,7 +198,7 @@ aside.navbar {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: sticky; position: sticky;
top: 5rem; top: 3.75rem;
height: fit-content; height: fit-content;
width: fit-content; width: fit-content;
inline-size: fit-content; inline-size: fit-content;
@ -126,20 +211,25 @@ aside.navbar {
overflow: clip; overflow: clip;
overflow-clip-margin: 0.625rem; overflow-clip-margin: 0.625rem;
} }
aside.is-expanded { aside.is-expanded {
animation: expand 0.5s linear both; animation: expand 0.5s linear both;
} }
aside.is-not-expanded { aside.is-not-expanded {
animation: contract 0.5s linear both; animation: contract 0.5s linear both;
} }
.is-not-expanded #indicator-icon { .is-not-expanded #indicator-icon {
transform: rotate(180deg); transform: rotate(180deg);
transition: 0.5s ease-in-out; transition: 0.5s ease-in-out;
} }
.navbar-darkmode { .navbar-darkmode {
box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25); box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25);
background-color: #2C2C2C; background-color: #2C2C2C;
} }
.navbar-lightmode { .navbar-lightmode {
box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25); box-shadow: 0.25rem 0.25rem 0.25rem 0rem rgba(0, 0, 0, 0.25);
background-color: #FFFFFF; background-color: #FFFFFF;
@ -181,8 +271,13 @@ nav {
overflow-clip-margin: 0.625rem; overflow-clip-margin: 0.625rem;
} }
.menu-darkmode { border-bottom: 0.0625rem solid #8E8E8E; } .menu-darkmode {
.menu-lightmode { border-bottom: 0.0625rem solid #BABABA; } border-bottom: 0.0625rem solid #8E8E8E;
}
.menu-lightmode {
border-bottom: 0.0625rem solid #BABABA;
}
.button, .button,
@ -200,18 +295,30 @@ a {
overflow: clip; overflow: clip;
overflow-clip-margin: 0.625rem; overflow-clip-margin: 0.625rem;
} }
.button-darkmode { background-color: #2C2C2C; }
.button-lightmode { background-color: #FFFFFF; } .button-darkmode {
background-color: #2C2C2C;
}
.button-lightmode {
background-color: #FFFFFF;
}
.button-darkmode:hover, .button-darkmode:hover,
.indicator-darkmode:hover, .indicator-darkmode:hover,
.back-darkmode:hover { background-color: #444444; } .back-darkmode:hover {
background-color: #444444;
}
.button-lightmode:hover, .button-lightmode:hover,
.indicator-lightmode:hover, .indicator-lightmode:hover,
.back-lightmode:hover { background-color: #ACACAC; } .back-lightmode:hover {
background-color: #ACACAC;
}
.is-not-expanded>button { align-self: center; } .is-not-expanded>button {
align-self: center;
}
.icon { .icon {
@ -222,6 +329,7 @@ a {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
#back-icon, #back-icon,
#indicator-icon { #indicator-icon {
width: 2.5rem; width: 2.5rem;
@ -229,10 +337,13 @@ a {
border-radius: 0.3125rem; border-radius: 0.3125rem;
transition: 0.2s ease-in-out; transition: 0.2s ease-in-out;
} }
.back-darkmode:hover, .back-darkmode:hover,
.back-lightmode:hover, .back-lightmode:hover,
.indicator-darkmode:hover, .indicator-darkmode:hover,
.indicator-lightmode:hover { cursor: pointer; } .indicator-lightmode:hover {
cursor: pointer;
}
img { img {
@ -242,7 +353,10 @@ img {
object-position: center; object-position: center;
overflow: hidden; overflow: hidden;
} }
.img-darkmode { filter: invert(100%); }
.img-darkmode {
filter: invert(100%);
}
.label { .label {
@ -254,8 +368,14 @@ img {
white-space: nowrap; white-space: nowrap;
font: 600 0.875rem/1.25rem Overpass, sans-serif; font: 600 0.875rem/1.25rem Overpass, sans-serif;
} }
.label-darkmode { color: #FFFFFF; }
.label-lightmode { color: #000000; } .label-darkmode {
color: #FFFFFF;
}
.label-lightmode {
color: #000000;
}

View File

@ -1,30 +1,118 @@
<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"
<div :class="['username', darkMode ? 'username-darkmode' : 'username-lightmode']">username</div> :class="[darkMode ? 'button-darkmode' : 'button-lightmode']" @click="goToSettings">
<div :class="['picture', darkMode ? 'picture-darkmode' : 'picture-lightmode']"> <div v-if="visibilityBool" class="profile">
<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="" /> <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';
import { computed } from 'vue';
const darkMode = ref(true) const store = useStore();
// const modeChanged = computed(() => store.state.updateDarkMode);
// watch(modeChanged, getSession)
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('')
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 () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
darkMode.value = true;
} else {
darkMode.value = false;
}
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');
}
if (id.value.fullPath == '/login') {
darkMode.value = true;
}
}
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');
localStorage.removeItem('logged-in-user-darkMode');
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>
<style scoped> <style scoped>
* { * {
box-sizing: border-box; box-sizing: border-box;
@ -36,28 +124,28 @@ header {
position: sticky; position: sticky;
top: 0; top: 0;
width: 100%; width: 100%;
height: 4.375rem; height: 3.125rem;
align-self: stretch; align-self: stretch;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 0.625rem 1.25rem; padding: 0.375rem 1.875rem;
} }
.header-darkmode { .header-darkmode {
background-color: #212121; background-color: #212121;
border-bottom: 0.125em solid #000; border-bottom: 0.125em solid #000000;
} }
.header-lightmode { .header-lightmode {
background-color: #EBEBEB; background-color: #ebebeb;
border-bottom: 0.125em solid #8e8e8e61; border-bottom: 0.125em solid #8e8e8e;
} }
#header-logo { #header-logo {
object-fit: contain; object-fit: contain;
object-position: center; object-position: center;
width: 5rem; width: 4rem;
height: 2.5rem; height: 2rem;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
overflow: hidden; overflow: hidden;
@ -68,37 +156,48 @@ header {
flex-direction: row; flex-direction: row;
align-items: flex-end; align-items: flex-end;
gap: 0.625rem; gap: 0.625rem;
padding: 0 0.625rem; padding: 0 0.375rem;
} }
.username { .username {
align-self: center; align-self: center;
margin: auto 0;
text-align: right; text-align: right;
font: 200 0.875rem Overpass, sans-serif; font: 200 0.75rem/1.25rem Overpass, sans-serif;
letter-spacing: 5%; letter-spacing: 0.01rem;
} }
.username-darkmode { .username-darkmode {
color: #fff; color: #ffffff;
} }
.username-lightmode { .username-lightmode {
color: #000; color: #000000;
}
.pre#username {
text-decoration: none;
} }
.picture { .picture {
display: flex; display: flex;
width: 2.5rem; width: 1.875rem;
height: 2.5rem; height: 1.875rem;
border-radius: 50%; border-radius: 50%;
} }
.picture-darkmode { .picture-loggedin-darkmode {
background-color: #fff; background-color: #ffffff;
} }
.picture-lightmode { .picture-not-loggedin-darkmode {
background-color: #000; background-color: #212121;
}
.picture-loggedin-lightmode {
background-color: #000000;
}
.picture-not-loggedin-lightmode {
background-color: #ebebeb;
} }
</style> </style>

View File

@ -1,6 +1,6 @@
<template> <template>
<PageHeader /> <PageHeader />
<main :class="[darkMode ? 'main-darkmode' : 'main-lightmode']"> <main :class="[loggedInUserDarkModeBoolean ? 'main-darkmode' : 'main-lightmode']">
<Navigationbar /> <Navigationbar />
<slot /> <slot />
<Actionbar /> <Actionbar />
@ -9,14 +9,41 @@
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import PageHeader from "./PageHeader.vue"; import PageHeader from "./PageHeader.vue";
import Navigationbar from "./Navigationbar.vue"; import Navigationbar from "./Navigationbar.vue";
import Actionbar from "./Actionbar.vue"; import Actionbar from "./Actionbar.vue";
import { useStore } from 'vuex';
import { computed } from 'vue';
const darkMode = ref(true) const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const loggedInUserDarkModeBoolean = ref('');
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
loggedInUserDarkModeBoolean.value = true;
} else {
loggedInUserDarkModeBoolean.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>

View File

@ -1,16 +1,54 @@
<template> <template>
<PageHeader /> <PageHeader />
<main :class="[darkMode ? 'main-darkmode' : 'main-lightmode']"> <main :class="[loggedInUserDarkModeBoolean ? 'main-darkmode' : 'main-lightmode']">
<slot /> <slot />
</main> </main>
</template> </template>
<script setup> <script setup>
import { ref, onMounted, watch } from 'vue';
import PageHeader from "../layouts/PageHeader.vue"; import PageHeader from "../layouts/PageHeader.vue";
import { useStore } from 'vuex';
import { computed } from 'vue';
const darkMode = ref(true) const route = useRoute()
const id = computed(() => route)
const store = useStore();
const modeChangedLocalstorage = computed(() => store.state.modeLayout);
const loggedInUserDarkModeBoolean = ref('');
const getSession = async () => {
if (modeChangedLocalstorage.value) {
store.commit('resetModeLayoutChanged');
}
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
loggedInUserDarkModeBoolean.value = true;
} else {
loggedInUserDarkModeBoolean.value = false;
}
if (id.value.fullPath == '/login') {
loggedInUserDarkModeBoolean.value = true;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChangedLocalstorage, getSession);
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>

24
nuxt-app/.gitignore vendored Normal file
View File

@ -0,0 +1,24 @@
# Nuxt dev/build outputs
.output
.data
.nuxt
.nitro
.cache
dist
# Node dependencies
node_modules
# Logs
logs
*.log
# Misc
.DS_Store
.fleet
.idea
# Local env files
.env
.env.*
!.env.example

75
nuxt-app/README.md Normal file
View File

@ -0,0 +1,75 @@
# Nuxt 3 Minimal Starter
Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
## Setup
Make sure to install the dependencies:
```bash
# npm
npm install
# pnpm
pnpm install
# yarn
yarn install
# bun
bun install
```
## Development Server
Start the development server on `http://localhost:3000`:
```bash
# npm
npm run dev
# pnpm
pnpm run dev
# yarn
yarn dev
# bun
bun run dev
```
## Production
Build the application for production:
```bash
# npm
npm run build
# pnpm
pnpm run build
# yarn
yarn build
# bun
bun run build
```
Locally preview production build:
```bash
# npm
npm run preview
# pnpm
pnpm run preview
# yarn
yarn preview
# bun
bun run preview
```
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.

5
nuxt-app/app.vue Normal file
View File

@ -0,0 +1,5 @@
<template>
<div>
<NuxtWelcome />
</div>
</template>

4
nuxt-app/nuxt.config.ts Normal file
View File

@ -0,0 +1,4 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
devtools: { enabled: true }
})

9593
nuxt-app/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

17
nuxt-app/package.json Normal file
View File

@ -0,0 +1,17 @@
{
"name": "nuxt-app",
"private": true,
"type": "module",
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
"dependencies": {
"nuxt": "^3.10.3",
"vue": "^3.4.19",
"vue-router": "^4.3.0"
}
}

BIN
nuxt-app/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -0,0 +1,3 @@
{
"extends": "../.nuxt/tsconfig.server.json"
}

4
nuxt-app/tsconfig.json Normal file
View File

@ -0,0 +1,4 @@
{
// https://nuxt.com/docs/guide/concepts/typescript
"extends": "./.nuxt/tsconfig.json"
}

View File

@ -1,10 +1,54 @@
// https://nuxt.com/docs/api/configuration/nuxt-config // https://nuxt.com/docs/api/configuration/nuxt-config
import type { import type { NuxtPage } from 'nuxt/schema'
NuxtPage import clientsideConfig from './clientsideConfig'
} from 'nuxt/schema' import { UserObjectDefinition } from './composables/UserObject'
export default defineNuxtConfig({ export default defineNuxtConfig({
devtools: { enabled: true }, devtools: { enabled: true },
modules: [
'@pinia/nuxt',
'@sidebase/nuxt-auth',
],
auth: {
//baseURL: `https://${clientsideConfig.url}:${clientsideConfig.port}/.output/server/chunks/routes/api/auth`,
computed: {
origin: `https://${clientsideConfig.url}:${clientsideConfig.port}/`,
//pathname: '/server/chunks/routes/api/auth/',
//fullBaseUrl: `https://${clientsideConfig.url}:${clientsideConfig.port}/server/chunks/routes/api/auth/`,
},
//baseUrl: `https://${clientsideConfig.url}:${clientsideConfig.port}/server/chunks/routes/api/auth/`,
provider: {
type: 'refresh',
endpoints: {
signIn: { path: '/login', method: 'post' },
signOut: { path: '/logout', method: 'get' },
signUp: { path: '/signup', method: 'post' },
getSession: { path: '/session', method: 'get' },
refresh: { path: '/refresh', method: 'post' }
},
token: {
signInResponseTokenPointer: '/token/authToken',
maxAgeInSeconds: 300, // 5 min
sameSiteAttribute: 'lax'
},
refreshToken: {
signInResponseRefreshTokenPointer: '/token/refreshToken',
maxAgeInSeconds: 604800, // 7 days
sameSiteAttribute: 'lax'
},
// TODO: define UserObject
//sessionDataType: UserObjectDefinition,
},
session: {
enableRefreshPeriodically: false,
enableRefreshOnWindowFocus: true,
},
globalAppMiddleware: true,
},
/*buildModules: [
//'@nuxtjs/composition-api/module',
['@pinia/nuxt', { disableVuex: false }],
],*/
devServer: { devServer: {
https: { https: {
key: './certs/privkey.pem', key: './certs/privkey.pem',
@ -15,10 +59,24 @@ export default defineNuxtConfig({
server: { server: {
cors: { cors: {
origin: true, origin: true,
credentials: true,
optionsSuccessStatus: 204, optionsSuccessStatus: 204,
}, },
} }
}, },
runtimeConfig: {
public: {
apiBase: `https://${clientsideConfig.url}:${clientsideConfig.port}/server/chunks/routes/api`,
axios: {
browserBaseURL: `https://${clientsideConfig.url}:${clientsideConfig.port}/`,
},
},
private: {
axios: {
baseURL: `https://${clientsideConfig.url}:${clientsideConfig.port}/`,
}
}
},
// hooks: { // hooks: {
// 'pages:extend'(pages) { // 'pages:extend'(pages) {
// function setMiddleware(pages: NuxtPage[]) { // function setMiddleware(pages: NuxtPage[]) {

4682
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -7,25 +7,38 @@
"dev": "nuxt dev", "dev": "nuxt dev",
"generate": "nuxt generate", "generate": "nuxt generate",
"preview": "nuxt preview", "preview": "nuxt preview",
"postinstall": "nuxt prepare" "prepare": "nuxt prepare",
"cleanup": "nuxt cleanup"
}, },
"devDependencies": { "devDependencies": {
"@nuxt/devtools": "latest", "@nuxt/devtools": "latest",
"nuxt": "^3.8.0", "@pinia/nuxt": "^0.5.1",
"@sidebase/nuxt-auth": "^0.6.7",
"nuxt": "^3.10.3",
"pinia": "^2.1.7",
"vue": "^3.3.7", "vue": "^3.3.7",
"vue-router": "^4.2.5" "vue-router": "^4.2.5"
}, },
"dependencies": { "dependencies": {
"@nuxt/module-builder": "^0.5.5",
"@types/jsonwebtoken": "^9.0.6",
"@types/node": "^20.11.24",
"@vueform/toggle": "^2.1.4", "@vueform/toggle": "^2.1.4",
"axios": "^1.6.7", "axios": "^1.6.7",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^4.18.2", "express": "^4.18.2",
"h3": "^1.11.1",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
"leading-trim": "^1.0.2", "leading-trim": "^1.0.2",
"mariadb": "^3.2.3", "mariadb": "^3.2.3",
"nuxi": "^3.10.1",
"pinia-plugin-persistedstate": "^3.2.1",
"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",
"vuex": "^4.1.0" "vuex": "^4.1.0"
} }
} }

View File

@ -2,13 +2,12 @@
<section id="content"> <section id="content">
<div id="content-header"> <div id="content-header">
<router-link to="/assets" class="button" id="assets-button" @click="defaultAssetPage()"> <router-link to="/assets" class="button" id="assets-button" @click="defaultAssetPage()">
<h1 :class="[darkMode ? 'h1-darkmode' : 'h1-lightmode']" id="page-name">Assets</h1> <h1 :class="[loggedInUserDarkModeBoolean ? 'h1-darkmode' : 'h1-lightmode']" id="page-name">Assets</h1>
</router-link> </router-link>
</div> </div>
<div id="content-body"> <div id="content-body">
<ClientSearch v-if="onAssetlist || onCustomerAssetlist" /> <CustomerSearch v-if="onAssetlist" />
<AssetTable v-if="onAssetlist" /> <AssetTable v-if="onAssetlist" />
<AssetTableNoClient v-if="onCustomerAssetlist" />
<Asset v-if="onAsset" /> <Asset v-if="onAsset" />
<HardwareSpecifications v-if="onAsset" /> <HardwareSpecifications v-if="onAsset" />
<SoftwareSpecifications v-if="onAsset" /> <SoftwareSpecifications v-if="onAsset" />
@ -21,11 +20,9 @@
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import CustomerSearch from "../components/CustomerSearch.vue";
import ClientSearch from "../components/ClientSearch.vue";
import AssetTable from "../components/server/AssetTable.vue"; import AssetTable from "../components/server/AssetTable.vue";
import AssetTableNoClient from "../components/server/AssetTableNoClient.vue";
import Asset from "../components/server/Asset.vue"; import Asset from "../components/server/Asset.vue";
import HardwareSpecifications from "../components/server/HardwareSpecifications.vue"; import HardwareSpecifications from "../components/server/HardwareSpecifications.vue";
import SoftwareSpecifications from "../components/server/SoftwareSpecifications.vue"; import SoftwareSpecifications from "../components/server/SoftwareSpecifications.vue";
@ -37,12 +34,14 @@ import { computed } from 'vue';
const store = useStore(); const store = useStore();
const onAssetlist = computed(() => store.state.onAssetlist); const onAssetlist = computed(() => store.state.onAssetlist);
const onCustomerAssetlist = computed(() => store.state.onCustomerAssetlist);
const onAsset = computed(() => store.state.onAsset); const onAsset = computed(() => store.state.onAsset);
const onSolutionlistAsset = computed(() => store.state.onSolutionlistAsset); const onSolutionlistAsset = computed(() => store.state.onSolutionlistAsset);
const modeChanged = computed(() => store.state.updateDarkMode);
const loggedInUserDarkModeBoolean = ref('');
definePageMeta({ definePageMeta({
layout: 'default' layout: 'default',
title: 'Assets'
}) })
const defaultAssetPage = () => { const defaultAssetPage = () => {
@ -50,7 +49,28 @@ const defaultAssetPage = () => {
store.commit('changeToAssetlist') store.commit('changeToAssetlist')
} }
const darkMode = ref(true) const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
loggedInUserDarkModeBoolean.value = true;
} else {
loggedInUserDarkModeBoolean.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>

View File

@ -1,101 +0,0 @@
<template>
<section id="content">
<div id="content-header">
<h1 :class="[darkMode ? 'h1-darkmode' : 'h1-lightmode']" id="page-name">Clients</h1>
</div>
<div id="content-body">
<ClientTable v-if="onCustomerlist"/>
<Client v-if="onCustomer"/>
<ClientQuickAccess v-if="onCustomer"/>
<ClientEmployeeList v-if="onEmployeelist"/>
<ClientEmployee v-if="onEmployee"/>
<ClientDepartmentList v-if="onDepartmentlist"/>
<ClientDepartment v-if="onDepartment"/>
<ClientDepartmentEmployeeList v-if="onDepartment"/>
</div>
</section>
</template>
<script setup>
import { ref } from 'vue';
import ClientTable from "../components/server/ClientTable.vue";
import Client from "../components/server/Client.vue";
import ClientQuickAccess from "../components/server/ClientQuickAccess.vue";
import ClientEmployeeList from "../components/server/ClientEmployeeList.vue";
import ClientEmployee from "../components/server/ClientEmployee.vue";
import ClientDepartmentList from '~/components/server/ClientDepartmentList.vue';
import ClientDepartment from '~/components/server/ClientDepartment.vue';
import ClientDepartmentEmployeeList from '~/components/server/ClientDepartmentEmployeeList.vue';
definePageMeta({
layout: 'default'
})
const darkMode = ref(true)
// to render the right components
const onCustomerlist = ref(true)
const onCustomer = ref(true)
const onEmployeelist = ref(true)
const onEmployee = ref(true)
const onDepartmentlist = ref(true)
const onDepartment = ref(true)
</script>
<script>
export default {
name: "ClientsPage",
}
</script>
<style scoped>
* {
box-sizing: border-box;
}
#content {
display: flex;
flex-direction: column;
float: left;
justify-content: stretch;
align-items: stretch;
width: 100%;
flex-grow: 1;
gap: 0.625rem;
padding: 0 1.25rem;
}
#content-header {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
width: 100%;
height: 3.125rem;
}
#page-name {
letter-spacing: 5%;
font: 400 1.5rem/125% Overpass, -apple-system, Roboto, Helvetica, sans-serif;
}
.h1-darkmode {
color: #fff;
}
.h1-lightmode {
color: #000;
}
#content-body {
display: flex;
flex-direction: column;
width: 100%;
gap: 1.25rem;
margin-bottom: 0.625rem;
border-radius: 0.625rem;
}
</style>

130
pages/customers.vue Normal file
View File

@ -0,0 +1,130 @@
<template>
<section id="content">
<div id="content-header">
<h1 :class="[loggedInUserDarkModeBoolean ? 'h1-darkmode' : 'h1-lightmode']" id="page-name">Customers</h1>
</div>
<div id="content-body">
<CustomerTable v-if="onCustomerlist" />
<Customer v-if="onCustomer" />
<CustomerQuickAccess v-if="onCustomer" />
<CustomerEmployeeList v-if="onEmployeelist" />
<CustomerEmployee v-if="onEmployee" />
<CustomerDepartmentList v-if="onDepartmentlist" />
<CustomerDepartment v-if="onDepartment" />
<CustomerDepartmentEmployeeList v-if="onDepartment" />
</div>
</section>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue';
import CustomerTable from "../components/server/CustomerTable.vue";
import Customer from "../components/server/Customer.vue";
import CustomerQuickAccess from "../components/server/CustomerQuickAccess.vue";
import CustomerEmployeeList from "../components/server/CustomerEmployeeList.vue";
import CustomerEmployee from "../components/server/CustomerEmployee.vue";
import CustomerDepartmentList from '~/components/server/CustomerDepartmentList.vue';
import CustomerDepartment from '~/components/server/CustomerDepartment.vue';
import CustomerDepartmentEmployeeList from '~/components/server/CustomerDepartmentEmployeeList.vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
definePageMeta({
layout: 'default',
title: 'Customers'
})
const loggedInUserDarkModeBoolean = ref('');
// to render the right components
const onCustomerlist = ref(true)
const onCustomer = ref(true)
const onEmployeelist = ref(true)
const onEmployee = ref(true)
const onDepartmentlist = ref(true)
const onDepartment = ref(true)
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
loggedInUserDarkModeBoolean.value = true;
} else {
loggedInUserDarkModeBoolean.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script>
<script>
export default {
name: "CustomersPage",
}
</script>
<style scoped>
* {
box-sizing: border-box;
}
#content {
display: flex;
flex-direction: column;
float: left;
justify-content: stretch;
align-items: stretch;
width: 100%;
flex-grow: 1;
gap: 0.625rem;
padding: 0 1.25rem;
}
#content-header {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
width: 100%;
height: 3.125rem;
}
#page-name {
letter-spacing: 5%;
font: 400 1.5rem/125% Overpass, -apple-system, Roboto, Helvetica, sans-serif;
}
.h1-darkmode {
color: #fff;
}
.h1-lightmode {
color: #000;
}
#content-body {
display: flex;
flex-direction: column;
width: 100%;
gap: 1.25rem;
margin-bottom: 0.625rem;
border-radius: 0.625rem;
}
</style>

134
pages/employees.vue Normal file
View File

@ -0,0 +1,134 @@
<template>
<section id="content">
<div id="content-header">
<router-link to="/employees" class="button" id="employees-button" @click="defaultEmployeePage()">
<h1 :class="[loggedInUserDarkModeBoolean ? 'h1-darkmode' : 'h1-lightmode']" id="page-name">Employees</h1>
</router-link>
</div>
<div id="content-body">
<EmployeeSearch v-if="onEmployeelist" />
<Employeetable v-if="onEmployeelist" />
<Employee v-if="onEmployee" />
<EmployeeGroups v-if="onEmployee" />
</div>
</section>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue';
import EmployeeSearch from "../components/EmployeeSearch.vue";
import Employeetable from "../components/server/EmployeeTable.vue";
import Employee from "../components/server/Employee.vue";
import EmployeeGroups from "../components/server/EmployeeGroups.vue";
import { useStore } from 'vuex';
import { computed } from 'vue';
const router = useRouter()
const store = useStore();
const onEmployeelist = computed(() => store.state.onEmployeelist);
const onEmployee = computed(() => store.state.onEmployee);
const loggedInUserDarkModeBoolean = ref('');
const modeChanged = computed(() => store.state.updateDarkMode);
definePageMeta({
layout: 'default',
title: 'Employees'
})
const defaultEmployeePage = () => {
store.commit('resetStore');
store.commit('changeToEmployeelist')
}
const getSession = async () => {
const loggedInUserAdminBool = getItem('logged-in-user-adminBool');
if (loggedInUserAdminBool == 0) {
router.push('/home');
};
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
loggedInUserDarkModeBoolean.value = true;
} else {
loggedInUserDarkModeBoolean.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script>
<script>
export default {
name: "EmployeePage",
}
</script>
<style scoped>
* {
box-sizing: border-box;
}
#content {
display: flex;
flex-direction: column;
float: left;
justify-content: stretch;
align-items: stretch;
width: 100%;
flex-grow: 1;
gap: 0.625rem;
padding: 0 1.25rem;
}
#content-header {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
width: 100%;
height: 3.125rem;
}
#page-name {
letter-spacing: 5%;
font: 400 1.5rem/125% Overpass, -apple-system, Roboto, Helvetica,
sans-serif;
text-decoration: underline;
}
.h1-darkmode {
color: #fff;
}
.h1-lightmode {
color: #000;
}
#content-body {
display: flex;
flex-direction: column;
width: 100%;
gap: 1.25rem;
margin-bottom: 0.625rem;
border-radius: 0.625rem;
}
.button {
text-decoration: none;
}
</style>

View File

@ -2,7 +2,7 @@
<Navigationbar /> <Navigationbar />
<section id="content"> <section id="content">
<div id="content-header"> <div id="content-header">
<pre :class="[darkMode ? 'pre-darkmode' : 'pre-lightmode']" id="page-name">Home</pre> <pre :class="[loggedInUserDarkModeBoolean ? 'pre-darkmode' : 'pre-lightmode']" id="page-name">Home</pre>
</div> </div>
<div id="content-body"> <div id="content-body">
<Dashboard /> <Dashboard />
@ -13,17 +13,51 @@
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import Navigationbar from "../layouts/Navigationbar.vue"; import Navigationbar from "../layouts/Navigationbar.vue";
import Dashboard from "../components/Dashboard.vue"; import Dashboard from "../components/Dashboard.vue";
import QuickAccess from "../components/QuickAccess.vue"; import QuickAccess from "../components/QuickAccess.vue";
import { useStore } from 'vuex';
import { computed } from 'vue';
const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const modeChangedLocalstorage = computed(() => store.state.mode);
definePageMeta({ definePageMeta({
layout: 'empty' layout: 'empty',
title: 'Home'
}) })
const darkMode = ref(true) const loggedInUserDarkModeBoolean = ref('');
const getSession = async () => {
if (modeChangedLocalstorage.value) {
store.commit('resetModeChanged');
}
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
loggedInUserDarkModeBoolean.value = true;
} else {
loggedInUserDarkModeBoolean.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
watch(modeChangedLocalstorage, getSession)
onMounted(() => {
getSession();
});
</script> </script>
<script> <script>

View File

@ -1,23 +1,52 @@
<template> <template>
<section id="content"> <section id="content">
<div id="content-header"> <div id="content-header">
<h1 :class="[darkMode ? 'h1-darkmode' : 'h1-lightmode']" id="page-name">Pagename</h1> <h1 :class="[loggedInUserDarkModeBoolean ? 'h1-darkmode' : 'h1-lightmode']" id="page-name">Pagename</h1>
</div> </div>
<div id="content-body"> <div id="content-body">
<section :class="[darkMode ? 'stuff-darkmode' : 'stuff-lightmode']" id="stuff"></section> <section :class="[loggedInUserDarkModeBoolean ? 'stuff-darkmode' : 'stuff-lightmode']" id="stuff"></section>
</div> </div>
</section> </section>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useStore } from 'vuex';
import { computed } from 'vue';
const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
definePageMeta({ definePageMeta({
layout: 'default' layout: 'default',
title: 'Test'
}) })
const darkMode = ref(true) const loggedInUserDarkModeBoolean = ref('');
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
loggedInUserDarkModeBoolean.value = true;
} else {
loggedInUserDarkModeBoolean.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>

166
pages/issueItems.vue Normal file
View File

@ -0,0 +1,166 @@
<template>
<section id="content">
<div id="content-header">
<router-link to="/issueSlips" class="button" id="issueSlips-button" @click="defaultIssueSlipPage()">
<h1 :class="[loggedInUserDarkModeBoolean ? 'h1-darkmode' : 'h1-lightmode']" id="page-name">Issue slips
</h1>
</router-link>
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
<router-link to="/issueItems" class="button" id="issues-button" @click="defaultIssuePage()">
<h1 :class="[loggedInUserDarkModeBoolean ? 'h1-darkmode' : 'h1-lightmode']" id="active-page-name">Issues
</h1>
</router-link>
</div>
<div id="content-body">
<IssueStateSearch v-if="onIssueItemList" />
<IssueTable v-if="onIssueItemList" />
<Issue v-if="onIssueItem" />
<IssueVariants v-if="onIssueItem" />
<IssueVariant v-if="onIssueItemVariant" />
</div>
</section>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue';
import IssueStateSearch from "../components/IssueStateSearch.vue";
import IssueTable from "../components/server/IssueTable.vue";
import Issue from "../components/server/Issue.vue";
import IssueVariants from "../components/server/IssueVariants.vue";
import IssueVariant from "../components/server/IssueVariant.vue";
import { useStore } from 'vuex';
import { computed } from 'vue';
const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const onIssueItemList = computed(() => store.state.onIssueItemList);
const onIssueItem = computed(() => store.state.onIssueItem);
const onIssueItemVariant = computed(() => store.state.onIssueItemVariant);
definePageMeta({
layout: 'default',
title: 'Issue Items'
})
const loggedInUserDarkModeBoolean = ref('');
const defaultIssueSlipPage = () => {
store.commit('resetStore');
store.commit('changeToIssueSliplist')
}
const defaultIssuePage = () => {
store.commit('resetStore');
store.commit('changeToIssueItemList')
}
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
loggedInUserDarkModeBoolean.value = true;
} else {
loggedInUserDarkModeBoolean.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script>
<script>
export default {
name: "IssueItemsPage",
}
</script>
<style scoped>
* {
box-sizing: border-box;
}
#content {
display: flex;
flex-direction: column;
float: left;
justify-content: stretch;
align-items: stretch;
width: 100%;
flex-grow: 1;
gap: 0.625rem;
padding: 0 1.25rem;
}
#content-header {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
width: 100%;
height: 3.125rem;
}
#page-name {
letter-spacing: 5%;
font: 400 1.5rem/125% Overpass, -apple-system, Roboto, Helvetica,
sans-serif;
text-decoration: none;
}
#active-page-name {
letter-spacing: 5%;
font: 400 1.5rem/125% Overpass, -apple-system, Roboto, Helvetica,
sans-serif;
text-decoration: underline;
}
.button {
text-decoration: none;
}
.h1-darkmode {
color: #fff;
}
.h1-lightmode {
color: #000;
}
#content-body {
display: flex;
flex-direction: column;
width: 100%;
gap: 1.25rem;
margin-bottom: 0.625rem;
border-radius: 0.625rem;
}
</style>../components/IssueStateSearch.vue

View File

@ -1,8 +1,9 @@
<template> <template>
<section id="content"> <section id="content">
<div id="content-header"> <div id="content-header">
<router-link to="/issueSlips" class="button" id="issueSlips-button"> <router-link to="/issueSlips" class="button" id="issueSlips-button" @click="defaultIssueSlipPage()">
<h1 :class="[darkMode ? 'h1-darkmode' : 'h1-lightmode']" id="active-page-name">Issue slips</h1> <h1 :class="[loggedInUserDarkModeBoolean ? 'h1-darkmode' : 'h1-lightmode']" id="active-page-name">Issue slips
</h1>
</router-link> </router-link>
&nbsp; &nbsp;
&nbsp; &nbsp;
@ -20,42 +21,74 @@
&nbsp; &nbsp;
&nbsp; &nbsp;
&nbsp; &nbsp;
<router-link to="/issues" class="button" id="issues-button"> <router-link to="/issueItems" class="button" id="issues-button" @click="defaultIssuePage()">
<h1 :class="[darkMode ? 'h1-darkmode' : 'h1-lightmode']" id="page-name">Issues</h1> <h1 :class="[loggedInUserDarkModeBoolean ? 'h1-darkmode' : 'h1-lightmode']" id="page-name">Issues</h1>
</router-link> </router-link>
</div> </div>
<div id="content-body"> <div id="content-body">
<ClientSearch v-if="onIssueSliplist || onCustomerIssueSliplist"/> <CustomerSearch v-if="onIssueSliplist" />
<IssueSlipTable v-if="onIssueSliplist"/> <IssueSlipTable v-if="onIssueSliplist" />
<IssueSlipTableNoClient v-if="onCustomerIssueSliplist"/> <IssueSlip v-if="onIssueSlip" />
<IssueSlip v-if="onIssueSlip"/> <OrderingInformation v-if="onIssueSlip" />
<OrderingInformation v-if="onIssueSlip"/> <Accounting v-if="onIssueSlip" />
<Accounting v-if="onIssueSlip"/>
</div> </div>
</section> </section>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import CustomerSearch from "../components/CustomerSearch.vue";
import ClientSearch from "../components/ClientSearch.vue";
import IssueSlipTable from "../components/server/IssueSlipTable.vue"; import IssueSlipTable from "../components/server/IssueSlipTable.vue";
import IssueSlipTableNoClient from "../components/server/IssueSlipTableNoClient.vue";
import IssueSlip from "../components/server/IssueSlip.vue"; import IssueSlip from "../components/server/IssueSlip.vue";
import OrderingInformation from "../components/server/OrderingInformation.vue"; import OrderingInformation from "../components/server/OrderingInformation.vue";
import Accounting from "../components/server/Accounting.vue"; import Accounting from "../components/server/Accounting.vue";
import { useStore } from 'vuex';
import { computed } from 'vue';
const store = useStore();
const modeChanged = computed(() => store.state.updateDarkMode);
const onIssueSliplist = computed(() => store.state.onIssueSliplist);
const onIssueSlip = computed(() => store.state.onIssueSlip);
const loggedInUserDarkModeBoolean = ref('');
definePageMeta({ definePageMeta({
layout: 'default' layout: 'default',
title: 'Issue Slips'
}) })
const darkMode = ref(true) const defaultIssueSlipPage = () => {
store.commit('resetStore');
store.commit('changeToIssueSliplist')
}
// to render the right components const defaultIssuePage = () => {
const onIssueSliplist = ref(true) store.commit('resetStore');
const onCustomerIssueSliplist = ref(false) store.commit('changeToIssueItemList')
const onIssueSlip = ref(false) }
const getSession = async () => {
const loggedInUserDarkModeBool = getItem('logged-in-user-darkMode');
if (loggedInUserDarkModeBool == 1) {
loggedInUserDarkModeBoolean.value = true;
} else {
loggedInUserDarkModeBoolean.value = false;
}
}
function getItem(item) {
if (process.client) {
return localStorage.getItem(item)
} else {
return undefined
}
}
watch(modeChanged, getSession)
onMounted(async () => {
await getSession();
});
</script> </script>
<script> <script>

View File

@ -1,126 +0,0 @@
<template>
<section id="content">
<div id="content-header">
<router-link to="/issueSlips" class="button" id="issueSlips-button">
<h1 :class="[darkMode ? 'h1-darkmode' : 'h1-lightmode']" id="page-name">Issue slips</h1>
</router-link>
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
<router-link to="/issues" class="button" id="issues-button">
<h1 :class="[darkMode ? 'h1-darkmode' : 'h1-lightmode']" id="active-page-name">Issues</h1>
</router-link>
</div>
<div id="content-body">
<IssueTable v-if="onIssueItemList"/>
<Issue v-if="onIssueItem"/>
<IssueVariants v-if="onIssueItem"/>
<IssueVariant v-if="onIssueItemVariant"/>
</div>
</section>
</template>
<script setup>
import { ref } from 'vue';
import IssueTable from "../components/server/IssueTable.vue";
import Issue from "../components/server/Issue.vue";
import IssueVariants from "../components/server/IssueVariants.vue";
import IssueVariant from "../components/server/IssueVariant.vue";
definePageMeta({
layout: 'default'
})
const darkMode = ref(true)
// to render the right components
const onIssueItem = ref(false)
const onIssueItemList = ref(true)
const onIssueItemVariant = ref(false)
</script>
<script>
export default {
name: "IssuePage",
}
</script>
<style scoped>
* {
box-sizing: border-box;
}
#content {
display: flex;
flex-direction: column;
float: left;
justify-content: stretch;
align-items: stretch;
width: 100%;
flex-grow: 1;
gap: 0.625rem;
padding: 0 1.25rem;
}
#content-header {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
width: 100%;
height: 3.125rem;
}
#page-name {
letter-spacing: 5%;
font: 400 1.5rem/125% Overpass, -apple-system, Roboto, Helvetica,
sans-serif;
text-decoration: none;
}
#active-page-name {
letter-spacing: 5%;
font: 400 1.5rem/125% Overpass, -apple-system, Roboto, Helvetica,
sans-serif;
text-decoration: underline;
}
.button {
text-decoration: none;
}
.h1-darkmode {
color: #fff;
}
.h1-lightmode {
color: #000;
}
#content-body {
display: flex;
flex-direction: column;
width: 100%;
gap: 1.25rem;
margin-bottom: 0.625rem;
border-radius: 0.625rem;
}
</style>

Some files were not shown because too many files have changed in this diff Show More