commit 45da69700cf91d861f5f684b21b2a551612ec035 Author: Alomairi Date: Thu Aug 29 11:42:20 2024 +0000 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0b8c862 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# config/db.config.js +node_modules +upload/* +stuff-expermental +package-lock.json +config/db.config.js diff --git a/README.md b/README.md new file mode 100644 index 0000000..c1ed90a --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# Terminal Diagnostic Helper + +## Overview + +**Terminal Diagnostic Helper** is an application designed to assist engineers in diagnosing and resolving issues with POS terminals. Users can view terminal images, select problems, record fixes, and generate reports in Excel format, while also sending data to a server for storage. + +## Features + +- **Terminal Image View:** Display images of POS terminals for easier diagnosis. +- **Problem Selection:** Choose from a list of common terminal problems. +- **Fix Logging:** Record the fixes applied to each issue. +- **Excel Export:** Copy diagnostic and repair data to an Excel spreadsheet. +- **Server Storage:** Automatically save diagnostic data to a server. + +## Installation + +1. **Clone the Repository:** + ```bash + git clone https://github.com/yourusername/your-repository.git + ``` \ No newline at end of file diff --git a/config/db.config_example.js b/config/db.config_example.js new file mode 100644 index 0000000..bf47d17 --- /dev/null +++ b/config/db.config_example.js @@ -0,0 +1,6 @@ +module.exports = { + host: 'database or ip', + user: 'user', + password: 'pass', + database: 'dbname' + } \ No newline at end of file diff --git a/login.html b/login.html new file mode 100644 index 0000000..07ffe49 --- /dev/null +++ b/login.html @@ -0,0 +1,30 @@ +HTML + + + + + + Login + + + + + + +
+

Login

+
+ + + + + +
+
+ + \ No newline at end of file diff --git a/main.js b/main.js new file mode 100644 index 0000000..2419100 --- /dev/null +++ b/main.js @@ -0,0 +1,162 @@ +const express = require('express'); +const fs = require('fs'); +const path = require('path'); +const mysql = require("mysql2/promise"); +const config = require("./config/db.config.js"); +const session = require('express-session'); + +const PORT = process.env.PORT || 5000; // Default port is 5000 + +const log = { + yellow: '\x1b[33m%s\x1b[0m', //yellow + cyan: '\x1b[36m%s\x1b[0m',//cyan + red: '\x1b[31m%s\x1b[0m', //red + green: '\x1b[32m%s\x1b[0m', //green + black: '\x1b[30m%s\x1b[0m', //black + blue: '\x1b[34m%s\x1b[0m', //blue + gray: '\x1b[90m%s\x1b[0m' //gray +} + + +// Create a connection pool +const pool = mysql.createPool({ + host: config.host, + user: config.user, + password: config.password, + database: config.database, + waitForConnections: true, + connectionLimit: 10, + queueLimit: 0 +}); + + + +const app = express(); + +app.set('view engine', 'ejs'); +app.set('views', path.join(__dirname, 'views')); + +app.use(session({ + secret: config.secret, + resave: true, + saveUninitialized: true +})); +app.use(express.json()); +app.use(express.urlencoded({ extended: true })); +app.use(express.static(path.join(__dirname, 'static'))); + + + +app.get('/', function(request, response) { + if (request.session.loggedin) { + // Output username + // response.send('Welcome back, ' + request.session.username + '!'); +console.log(request.session.username , 'open main page'); + // Render home page with username + response.render('home', { username: request.session.username }); + + + + } else { + // Not logged in + // response.send('Please login to view this page!'); + response.redirect('/login'); + } +}); + +app.get('/login', function(request, response) { + /// Render login template with any message from query parameters + console.log('Message:', request.query.message); // Log the message + response.render('login', { message: request.query.message || '' }); + + + + // response.sendFile(path.join(__dirname + '/login.html')); +}); + + +app.post('/auth', async function(request, response) { + // Capture the input fields + const { login, password } = request.body; + + // Ensure the input fields exist and are not empty + if (login && password) { + try { + // Get a connection from the pool + const connection = await pool.getConnection(); + + // Execute SQL query + // const [rows] = await connection.execute( + // 'SELECT * FROM accounts WHERE username = ? AND password = ?', + // [username, password] + // ); + + const [rows] = await connection.execute( + 'SELECT * FROM accounts WHERE (username = ? OR email = ?) AND password = ?', + [login, login, password] + ); + + // console.log(rows); + + + // Release the connection back to the pool + connection.release(); + + // If the account exists + if (rows.length > 0) { + // Authenticate the user + request.session.loggedin = true; + request.session.username = rows[0].username; + // request.session.username = username; + // Redirect to home page + response.redirect('/'); + } else { + response.redirect('/login?message=Incorrect Username and/or Password!'); + } + } catch (error) { + console.error('Database query error:', error); + response.status(500).send('An error occurred while processing your request.'); + } + } else { + // response.send('Please enter Username and Password!'); + response.redirect('/login?message=Please enter Username and Password!'); + } + +}); + + +// http://localhost:3000/home +app.get('/home', function(request, response) { + // If the user is loggedin + if (request.session.loggedin) { + // Output username + // response.send('Welcome back, ' + request.session.username + '!'); + + // Render home page with username + response.render('home', { username: request.session.username }); + + } else { + // Not logged in + // response.send('Please login to view this page!'); + response.redirect('/login'); + } + response.end(); +}); + + + + +// http://localhost:3000/logout +app.get('/logout', function(request, response) { + request.session.destroy((err) => { + if (err) { + return response.status(500).send('Failed to logout'); + } + response.redirect('/'); + }); +}); + + +app.listen(PORT, () => { + console.info(`Listening on http://0.0.0.0:${PORT}/`); +}); \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..8fff1b8 --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "Terminal Diagnostic Helper", + "version": "1.0.0", + "description": "POS Terminal Diagnostic Helper by Ahmed Alomairi", + "main": "index.js", + "scripts": { + "test": "node main.js test", + "start": "node main.js", + "clean": "rm -f /app/service-upload/upload/* && node main.js clean", + "reset": "rm -f /app/service-upload/upload/* && node main.js", + "dev": "npm install nodemon --save-dev && node main.js development --port 3000" + }, + "author": "Ahmed Alomairi", + "license": "ISC", + "dependencies": { + "ejs": "^3.1.10", + "express": "^4.18.3", + "express-session": "^1.18.0", + "mysql2": "^3.6.5" + }, + "devDependencies": { + "nodemon": "^3.1.0" + } +} diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..f72aa34 --- /dev/null +++ b/public/index.html @@ -0,0 +1,111 @@ + + + + + + + + Загрузчик файлов + + + + + + + + + + + + + + + + +

+ Загрузчик инженерных файлов +
+ + Загружаемый файл Excel инженера из папка "Перевод в платные" должен содержать заголовок
( Модель, Сер.номер, Заявленная неисправность, Произведенная работа )
+

+ +
+

Перетащите файлы сюда или нажмите, чтобы выбрать

+
+ + +
+ + + +
+ + + + +
+ + + +
+ +
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/public/js.js b/public/js.js new file mode 100644 index 0000000..83c4621 --- /dev/null +++ b/public/js.js @@ -0,0 +1,288 @@ +const fileInput = document.getElementById('fileInput'); +const selectedFilesDiv = document.getElementById('selectedFiles'); + +let repeatedList = [] +fileInput.addEventListener('change', function () { + + populateFileTable(Array.from(fileInput.files)); + console.log('fileInput.files on change', fileInput.files); getFileListFromServer(fileInput.files); +}); + +async function getFileListFromServer(fileInput) { + + const fileUpload = document.getElementById('fileUpload'); +fileUpload.style.color = 'white'; + + await fetch('/getfilenames') + .then(response => response.json()) + .then(data => { + // Call populateFileTable() with the retrieved file list + compareFilelist(fileInput , data); + }) + .catch(error => console.error('Error getting file list from server:', error)); +} +function compareFilelist(fileInput , data) { + // console.log("resultes :"); + console.log(fileInput); + // console.log(data); //array + + Array.from(fileInput).forEach(selectedfile => { + console.log(selectedfile.name); + data.forEach(filename => { + if (filename === selectedfile.name){ + const repeatedFileName = selectedfile.name + console.log( repeatedFileName, 'is repeated '); + repeatedList.push(repeatedFileName); + + Array.from(selectedFilesDiv.children[0].rows).forEach((row, index) => { + const fileNameCell = row.cells[0]; + const fileStateCell = row.cells[2]; + + const fileName = fileNameCell.textContent; + if (fileName == repeatedFileName) { + row.style.backgroundColor = 'rgb(254 255 82)'; + fileStateCell.innerText = 'Repeated file!'; + } + }); + + } // repeat function + }); + + }); + + +} + + +async function handleFormSubmit(event) { + event.preventDefault(); + + const getFileStateBtn = document.getElementById('getFileStateBtn'); +getFileStateBtn.disabled = false; + +const fileUpload = document.getElementById('fileUpload'); +fileUpload.style.color = 'grey'; + + const formData = new FormData(this); + + // Get the file input element + const fileInput = document.getElementById('fileInput'); + const fileList = fileInput.files; + + + + // Filter out files based on repeatedList before upload + const filteredFiles = Array.from(fileList).filter(file => { + return !repeatedList.includes(file.name); + }); + + if (filteredFiles.length > 0) { + + // Replace the original files with the modified file list + formData.delete('uploaded'); // Delete the existing files + filteredFiles.forEach(file => formData.append('uploaded', file)); // Add modified files + + + try { + const response = await fetch('/upload', { + method: 'POST', + body: formData + }); + + // Handle response as needed + + + const data = await response.json(); + console.log(data); + const fileStates = data.states; + const filelist = data.files; + const fileErrors = data.errors; + + const resultDiv = document.getElementById('result'); + // createTable(resultDiv, data.files); + + + Array.from(selectedFilesDiv.children[0].rows).forEach((row, index) => { + const fileNameCell = row.cells[0]; + const fileSizeCell = row.cells[1]; + const fileStateCell = row.cells[2]; + + const fileName = fileNameCell.textContent; + const fileSize = fileSizeCell.textContent; + + filelist.forEach(element => { + if (element.originalFilename === fileName) { + console.log('found file name similar'); + console.log('element.size', element.size); + console.log('fileName', fileSize); + + if (element.size == fileSize) { + row.style.fontWeight = 'bold'; + row.style.backgroundImage = 'radial-gradient(farthest-corner at 50% 50%, skyblue, transparent)'; + fileStateCell.innerText = 'uploaded'; + } else { + row.style.backgroundColor = 'pink'; + fileStateCell.innerText = 'error upload'; + + } + } + + }); + // const fileState = filelist.find(file => file.originalFilename === fileName); + // if (fileState) { + // fileSizeCell.textContent = fileState.size; + // if (fileState.size === 'Bad') { + // row.style.backgroundColor = 'red'; + // } else { + // row.style.backgroundColor = 'transparent'; + // } + // } + + }); + +} catch (error) { + console.error('Error uploading files:', error); + // Handle errors during upload + alert('Error uploading files:', error); +} +} else { + console.log("No valid files selected for upload."); + alert('Допустимые файлы не выбраны или уже загружены.'); +} + + +} + + + +// Function to populate the file table with selected files +function populateFileTable(fileList) { + const table = document.createElement('table'); + + const headerRow = table.insertRow(); + // headerRow.style.background = '#121212'; + headerRow.style.background = ' linear-gradient(90deg, rgba(28,28,28,0.8379726890756303) 0%, rgba(24,23,23,0.9556197478991597) 51%, rgba(29,29,29,0.8715861344537815) 100%)'; + headerRow.style.color = 'white'; + const filenameHeader = headerRow.insertCell(); + filenameHeader.textContent = 'Filename'; + const sizeHeader = headerRow.insertCell(); + sizeHeader.textContent = 'Size'; + const stateHeader = headerRow.insertCell(); + stateHeader.textContent = 'State'; + + + fileList.forEach(fileData => { + const row = table.insertRow(); + const filenameCell = row.insertCell(); + if (fileData.originalFilename) { + filenameCell.textContent = fileData.originalFilename; + } else if (fileData.name) { + filenameCell.textContent = fileData.name; + } + + const sizeCell = row.insertCell(); + sizeCell.textContent = fileData.size; + const stateCell = row.insertCell(); + stateCell.textContent = '---'; + }); + + // Replace the existing content with the new table + selectedFilesDiv.innerHTML = ''; + selectedFilesDiv.appendChild(table); +} + + + +document.querySelector('form').addEventListener('submit', handleFormSubmit); + +document.getElementById("getFileStateBtn").addEventListener("click", async function () { + + const getFileStateBtn = document.getElementById('getFileStateBtn'); + getFileStateBtn.disabled = true; // Disable the button + const fileUpload = document.getElementById('fileUpload'); +fileUpload.style.color = 'white'; + + const response = await fetch('/getState'); + const data = await response.json(); + console.log(data); + // const stateDiv = document.getElementById('state'); + // createTable(stateDiv, data.states); + + const fileStates = data.states; + const fileErrors = data.errors; + + // const resultDiv = document.getElementById('result'); + // createTable(resultDiv, data.files); + + + Array.from(selectedFilesDiv.children[0].rows).forEach((row, index) => { + const fileNameCell = row.cells[0]; + const fileSizeCell = row.cells[1]; + const fileStateCell = row.cells[2]; + + const fileName = fileNameCell.textContent; + + const fileState = fileStates.find(file => file.name === fileName); + if (fileState) { + fileStateCell.innerText = fileState.size; + if (fileState.size === 'Bad') { + row.style.backgroundImage = 'radial-gradient(farthest-corner at 50% 50%, orangered, transparent)'; + } else { + row.style.backgroundImage = 'radial-gradient(farthest-corner at 50% 50%, lightgreen, transparent)'; + } + } + + }); + +}); + + +const dropZone = document.getElementById('dropZone'); + +// Prevent default behavior for drag events +['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { + dropZone.addEventListener(eventName, preventDefault, false); +}); + +function preventDefault(event) { + event.preventDefault(); + event.stopPropagation(); +} + +// Handle file drop event +dropZone.addEventListener('drop', handleDrop, false); + +function handleDrop(event) { + event.preventDefault(); + event.stopPropagation(); + + const fileList = event.dataTransfer.files; + + // const repeatedList = ['avoid_uploading_this_file.txt', 'another_filename_to_avoid.txt']; // Example repeatedList + + // Filter out files based on repeatedList before upload + const filteredFiles = Array.from(fileList).filter(file => { + return !repeatedList.includes(file.name); + }); + + // Replace the original files with the modified file list + const formData = new FormData(); + filteredFiles.forEach(file => formData.append('uploaded', file)); // Add modified files + + // Update the file input field with dropped files + const fileInput = document.getElementById('fileInput'); + fileInput.files = fileList; + + // Submit the form or call handleFormSubmit function here with formData + + populateFileTable(Array.from(fileInput.files)); + console.log('dragdrop', fileInput.files); + getFileListFromServer(fileInput.files); + +} + +// Allow users to trigger file selection by clicking the drop zone +dropZone.addEventListener('click', () => { + const fileInput = document.getElementById('fileInput'); + fileInput.click(); +}); \ No newline at end of file diff --git a/public/style.css b/public/style.css new file mode 100644 index 0000000..d83dd6d --- /dev/null +++ b/public/style.css @@ -0,0 +1,320 @@ +body { + background-color: #262626; +} + +/* .title { + color: #6dabf1; + text-align: center; +} */ + +.filesList { + display: flex; + gap: 10px; + justify-content: center; +} + +table { + display: table; + width: 68vw; + max-width: 1140px; + border-collapse: separate; + box-sizing: border-box; + text-indent: initial; + /* border-spacing: 2px; */ + border-spacing: initial; + /* border-color: gray; */ +} + +td { + padding: 10px; + border-bottom: solid; + /* border-style: solid; */ +} + +td:first-child{ + border-top: solid; +border-top-style: none !important; + border-top-left-radius: 15px; +} +td:last-child{ + border-top: solid; + border-top-style: none !important; + border-top-right-radius: 15px; + } + +tr:last-child td { + border: none; +} + +.container { + display: flex; + margin: 10px; + justify-content: center; +} + +#selectedFiles { + + text-align: -webkit-center; + max-width: 1140px; + background-color: lavender; + border-radius: 20px; + /* padding-bottom: 10px; */ + border-style: outset; +} + + +body { + /* color: #fff; */ + font-family: 'Rubik', sans-serif; + /* margin:0; */ + max-width: 1140px; + margin: 0 auto; +} + +.logo { + display: flex; + align-items: center; +} + +.flex { + display: flex; + justify-content: space-between; + align-items: center; +} + +.nav-bar { + padding: 3px 10px 3px 20px; + background-color: rgb(0, 0, 0); +} + +.nav-bar a { + color: #fff; + cursor: pointer; +} + +.nav-bar .hm { + font-size: 20px; +} + +#m-bar { + display: none; + font-size: 20px; +} + +#menu-links ul { + margin: 0; + padding: 0; +} + +#menu-links ul li { + display: inline-block; + margin: 0 35px; + list-style-type: none; +} + +#menu-links a { + text-decoration: none; + font-weight: 500; + font-size: 15px; + text-transform: uppercase; +} + +.nav-btn { + padding: 3px 15px; + background-color: #868686; + text-decoration: none; + color: black; + border-radius: 35px; +} + +.nav-btn:hover { + background-color: #6791e0 !important; +} + +.active { + color: #2d6cdf !important; +} + +#menu-links a:hover { + color: #6dabf1 !important; +} + +@media only screen and (max-width: 900px) { + #btn { + display: none; + } +} + +@media only screen and (max-width: 880px) { + .nav-bar { + display: block; + text-align: center; + background-color: rgba(0, 0, 0, .4); + } + + #menu-links ul li { + display: block; + margin: 25px 0; + } + + #btn { + display: block; + } + + #m-bar { + display: block; + } + + .hidden { + display: none !important; + } + + .not-hidden { + display: block !important; + } +} + +.bg-tarakan { + display: none; + position: absolute; + max-width: 1140px; + width: -webkit-fill-available; +} + +.show-tarakan { + display: block; +} + +.control { + display: flex; + gap: 20px; + margin: auto; + text-align-last: center; + justify-content: center; +} + +/* #getFileStateBtn { + padding: 10px; + } */ +.btn { + padding: 12px; + border-radius: 10px; + color: #f5f5f5; + /* background-color: #2d6cdf; */ + background: linear-gradient(40deg, #000000, #698ed1); + font-size: 16px; + cursor: pointer; + align-self: center; + box-shadow: 0 4px 7px rgb(99 139 255 / 40%); + border-style: hidden; +} + +.upload-section { + display: flex; + gap: 30px; + align-content: center; + justify-content: center; +} + +#fileInput { + opacity: 0; + width: 0.1px; + height: 0.1px; + position: absolute; +} + +.upload-section input[type=submit] { + /* padding: 12px 30px; */ + border: none; + /* background-color: #333333; */ + /* color: #ffffff; */ + font-size: 16px; +} + +.btn:hover , +.btn:focus { + transform: scale(1.09); +} + +form { + /* width: 50%; */ + /* margin: auto; */ + /* background-color: #f5f5f5; */ + /* padding: 30px; */ + /* font-size: 20px; */ + /* padding: 10px; */ + /* border-radius: 10px; */ + /* color: #f5f5f5; */ + /* background-color: #2d6cdf; */ +} + +#dropZone { + background: repeating-linear-gradient(45deg, black, transparent 100px); + padding: 30px; + text-align: center; + margin-bottom: 10px; + color: white; +} + +/* Add a style for the disabled button */ +#getFileStateBtn[disabled] { + color: #ccc; /* Grey text color */ + cursor: not-allowed; /* Change cursor to 'not-allowed' */ +} + + + +.title { + color: #6dabf1; + display: flex; + align-items: center; + justify-content: center; +gap: 5px; + +} + +.tooltip { + position: relative; + display: inline-block; + cursor: help; /* Change cursor to pointer on hover */ +} + +.tooltip .tooltiptext { + visibility: hidden; + width: 327px; + background-color: #333; + color: #fff; + text-align: center; + border-radius: 9px; + padding: 5px; + position: absolute; + z-index: 1; + bottom: -87px; + /* left: 50%; */ + margin-left: -60px; + opacity: 0; + transition: opacity 0.3s; + font-size: 16px; +} + +.tooltip:hover .tooltiptext { + visibility: visible; + opacity: 1; +} + + +footer { + position: fixed; + left: 0; + bottom: 0; + width: 100%; + padding-top: 5px; + padding-bottom: 5px; + display: flex; + justify-content: center; + + background-color: #000000; + color: lightgray; + font-family: sans-serif; + text-decoration: none !important; +} \ No newline at end of file diff --git a/static/login-style.css b/static/login-style.css new file mode 100644 index 0000000..93b8e83 --- /dev/null +++ b/static/login-style.css @@ -0,0 +1,195 @@ +@import url('https://fonts.googleapis.com/css?family=Raleway:400,700'); + +* { + box-sizing: border-box; + margin: 0; + padding: 0; + font-family: Raleway, sans-serif; +} + +body { + background: linear-gradient(90deg, #C7C5F4, #776BCC); + overflow: hidden; +} + +.container { + display: flex; + align-items: center; + justify-content: center; + min-height: 100vh; +} + +.screen { + background: linear-gradient(90deg, #5D54A4, #7C78B8); + position: relative; + height: 600px; + width: 360px; + box-shadow: 0px 0px 24px #5C5696; +} + +.screen__content { + z-index: 1; + position: relative; + height: 100%; +} + +.screen__background { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 0; + -webkit-clip-path: inset(0 0 0 0); + clip-path: inset(0 0 0 0); +} + +.screen__background__shape { + transform: rotate(45deg); + position: absolute; +} + +.screen__background__shape1 { + height: 520px; + width: 520px; + background: #FFF; + top: -50px; + right: 120px; + border-radius: 0 72px 0 0; +} + +.screen__background__shape2 { + height: 220px; + width: 220px; + background: #6C63AC; + top: -172px; + right: 0; + border-radius: 32px; +} + +.screen__background__shape3 { + height: 540px; + width: 190px; + background: linear-gradient(270deg, #5D54A4, #6A679E); + top: -24px; + right: 0; + border-radius: 32px; +} + +.screen__background__shape4 { + height: 400px; + width: 200px; + background: #7E7BB9; + top: 420px; + right: 50px; + border-radius: 60px; +} + +.login { + width: 360px; + padding: 30px; + padding-top: 64px; +} + +.login__field { + padding: 20px 0px; + position: relative; +} + +.login__icon { + position: absolute; + top: 30px; + color: #7875B5; +} + +.login__input { + border: none; + border-bottom: 2px solid #D1D1D4; + background: none; + padding: 10px; + padding-left: 24px; + font-weight: 700; + width: 75%; + transition: .2s; +} + +.login__input:active, +.login__input:focus, +.login__input:hover { + outline: none; + border-bottom-color: #6A679E; +} + +.login__submit { + background: #fff; + font-size: 14px; + margin-top: 30px; + padding: 16px 20px; + border-radius: 26px; + border: 1px solid #D4D3E8; + text-transform: uppercase; + font-weight: 700; + display: flex; + align-items: center; + width: 100%; + color: #4C489D; + box-shadow: 0px 2px 2px #5C5696; + cursor: pointer; + transition: .2s; +} + +.login__submit:active, +.login__submit:focus, +.login__submit:hover { + border-color: #6A679E; + outline: none; +} + +.button__icon { + font-size: 24px; + margin-left: auto; + color: #7875B5; +} + +.social-login { + position: absolute; + height: 140px; + width: 160px; + text-align: center; + bottom: 0px; + right: 0px; + color: #fff; +} + +.social-icons { + display: flex; + align-items: center; + justify-content: center; +} + +.social-login__icon { + padding: 20px 10px; + color: #fff; + text-decoration: none; + text-shadow: 0px 0px 8px #7875B5; +} + +.social-login__icon:hover { + transform: scale(1.5); +} + +.login-title{ + font-size: large; + padding-left: 30px; + padding-top: 30px; +} +.error-message{ + font-size: small; + /* text-align: center; */ + color: coral; + font-weight: bold; +} + +.logo{ + width: 64px; +} \ No newline at end of file diff --git a/static/logo.png b/static/logo.png new file mode 100644 index 0000000..085d471 Binary files /dev/null and b/static/logo.png differ diff --git a/static/styles.css b/static/styles.css new file mode 100644 index 0000000..4db51a6 --- /dev/null +++ b/static/styles.css @@ -0,0 +1,71 @@ +body { + font-family: Arial, sans-serif; +} +nav ul { + list-style-type: none; + padding: 0; +} +nav ul li { + display: inline; + margin-right: 10px; +} + + +* { + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "segoe ui", roboto, oxygen, ubuntu, cantarell, "fira sans", "droid sans", "helvetica neue", Arial, sans-serif; + font-size: 16px; +} +body { + background-color: #435165; +} +.login { + width: 400px; + background-color: #ffffff; + box-shadow: 0 0 9px 0 rgba(0, 0, 0, 0.3); + margin: 100px auto; +} +.login h1 { + text-align: center; + color: #5b6574; + font-size: 24px; + padding: 20px 0 20px 0; + border-bottom: 1px solid #dee0e4; +} +.login form { + display: flex; + flex-wrap: wrap; + justify-content: center; + padding-top: 20px; +} +.login form label { + display: flex; + justify-content: center; + align-items: center; + width: 50px; + height: 50px; + background-color: #3274d6; + color: #ffffff; +} +.login form input[type="password"], .login form input[type="text"] { + width: 310px; + height: 50px; + border: 1px solid #dee0e4; + margin-bottom: 20px; + padding: 0 15px; +} +.login form input[type="submit"] { + width: 100%; + padding: 15px; + margin-top: 20px; + background-color: #3274d6; + border: 0; + cursor: pointer; + font-weight: bold; + color: #ffffff; + transition: background-color 0.2s; +} +.login form input[type="submit"]:hover { + background-color: #2868c7; + transition: background-color 0.2s; +} \ No newline at end of file diff --git a/views/home.ejs b/views/home.ejs new file mode 100644 index 0000000..0d27c0d --- /dev/null +++ b/views/home.ejs @@ -0,0 +1,21 @@ + + + + + + Home + + + + +

Welcome to the Home Page!

+ + diff --git a/views/login.ejs b/views/login.ejs new file mode 100644 index 0000000..88846e9 --- /dev/null +++ b/views/login.ejs @@ -0,0 +1,67 @@ + + + + + + Login + + + + + + +
+
+
+ + + + + + + + + + +
+
+ + + + +
+

© 2024 Ал Омаири Ахмед

+
+ +
+ + +