- Introduced color, font, border, shadow, and transition variables. - Styled nav tabs, tab content, buttons, form elements, and status bar. - Added tabs for config, CSV management, and email ops. - Implemented tab switching and config load/save functions. - Added status message display functionality.
311 lines
11 KiB
HTML
311 lines
11 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Invoice Email Sender</title>
|
|
<link href="https://fonts.googleapis.com/css2?family=Lora:wght@400;700&display=swap" rel="stylesheet">
|
|
<style>
|
|
/* Global styles */
|
|
:root {
|
|
/* Color scheme variables */
|
|
--primary-color: #007bff;
|
|
--primary-dark: #0056b3;
|
|
--secondary-color: #333;
|
|
--light-color: #f4f7fa;
|
|
--lighter-color: #f8f9fa;
|
|
--error-color: #ee5555;
|
|
/* Font, border, shadow, and transition variables */
|
|
--font-family: 'Lora', serif;
|
|
--border-radius: 10px;
|
|
--border-color: #ccc;
|
|
--border-focus-color: #007bff;
|
|
--box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
|
|
--transition-speed: 0.3s;
|
|
}
|
|
|
|
body {
|
|
font-family: var(--font-family);
|
|
background-color: var(--light-color);
|
|
color: var(--secondary-color);
|
|
margin: 0;
|
|
padding: 20px;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.container {
|
|
max-width: 850px;
|
|
margin: auto;
|
|
padding: 20px;
|
|
background: #fff;
|
|
border-radius: var(--border-radius);
|
|
box-shadow: var(--box-shadow);
|
|
text-align: center;
|
|
}
|
|
|
|
/* Navigation tab styling */
|
|
.nav-tab {
|
|
display: inline-block;
|
|
margin-right: 15px;
|
|
padding: 10px;
|
|
cursor: pointer;
|
|
color: var(--primary-color);
|
|
transition: color var(--transition-speed);
|
|
}
|
|
|
|
.nav-tab:hover, .nav-tab.active {
|
|
color: var(--primary-dark);
|
|
border-bottom: 3px solid var(--primary-color);
|
|
}
|
|
|
|
/* Tab content area styling */
|
|
.tab-content {
|
|
display: none; /* Hide all tab content by default */
|
|
}
|
|
|
|
.tab-content.active {
|
|
display: block; /* Display active tab content */
|
|
padding: 20px;
|
|
text-align: left;
|
|
border-top: 1px solid #eee;
|
|
}
|
|
|
|
/* Button styling */
|
|
.button {
|
|
background: var(--primary-color);
|
|
color: #fff;
|
|
border: none;
|
|
padding: 10px 20px;
|
|
margin: 10px 5px;
|
|
border-radius: var(--border-radius);
|
|
cursor: pointer;
|
|
transition: background-color var(--transition-speed);
|
|
font-weight: 500;
|
|
font-size: 1rem;
|
|
}
|
|
|
|
.button:hover {
|
|
background-color: var(--primary-dark);
|
|
}
|
|
|
|
/* Form element styling */
|
|
input[type="text"], input[type="password"], textarea {
|
|
width: calc(100% - 20px);
|
|
padding: 10px;
|
|
border: 1px solid var(--border-color);
|
|
border-radius: var(--border-radius);
|
|
margin-top: 10px;
|
|
display: block;
|
|
margin-bottom: 20px;
|
|
line-height: 1.4;
|
|
background: var(--lighter-color);
|
|
}
|
|
|
|
input[type="text"]:focus, input[type="password"]:focus, textarea:focus {
|
|
border-color: var(--border-focus-color);
|
|
box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
|
|
}
|
|
|
|
label {
|
|
display: block;
|
|
margin-bottom: 5px;
|
|
font-weight: bold;
|
|
color: var(--secondary-color);
|
|
text-align: left;
|
|
}
|
|
|
|
/* Status bar styling */
|
|
.status-bar {
|
|
padding: 10px;
|
|
margin-top: 20px;
|
|
text-align: left;
|
|
font-size: .9rem;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container" id="appContainer">
|
|
<!-- Navigation Tabs -->
|
|
<nav>
|
|
<div class="nav-tab active" data-target="config">Configuration</div>
|
|
<div class="nav-tab" data-target="csv">CSV Management</div>
|
|
<div class="nav-tab" data-target="email">Email Operations</div>
|
|
</nav>
|
|
<!-- Configuration Form -->
|
|
<section id="config" class="tab-content active">
|
|
<form id="configForm">
|
|
<!-- Configuration Fields -->
|
|
<div class="form-group">
|
|
<label for="user">User:</label>
|
|
<input type="text" id="user" name="user">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="password">Password:</label>
|
|
<input type="password" id="password" name="password">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="ccEmail">CC Email:</label>
|
|
<input type="text" id="ccEmail" name="ccEmail">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="bccEmail">BCC Email:</label>
|
|
<input type="text" id="bccEmail" name="bccEmail">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="emailTemplate">Email Template:</label>
|
|
<textarea id="emailTemplate" rows="6"></textarea>
|
|
</div>
|
|
<!-- Form Action Buttons -->
|
|
<div class="form-actions">
|
|
<button class="button" type="button" id="loadConfigBtn">Load Config</button>
|
|
<button class="button" type="button" id="saveConfigBtn">Save Config</button>
|
|
</div>
|
|
</form>
|
|
</section>
|
|
<!-- CSV Management Form -->
|
|
<section id="csv" class="tab-content">
|
|
<form id="csvForm">
|
|
<div class="form-group">
|
|
<label for="csvPath">CSV Path:</label>
|
|
<input type="text" id="csvPath" name="csvPath">
|
|
</div>
|
|
<div class="form-actions">
|
|
<button class="button" type="button">Load CSV</button>
|
|
</div>
|
|
</form>
|
|
</section>
|
|
<!-- Email Operations Form -->
|
|
<section id="email" class="tab-content">
|
|
<form id="emailForm">
|
|
<div class="form-actions">
|
|
<button class="button" type="button">Send Emails</button>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="emailLogs">Email Logs:</label>
|
|
<textarea id="emailLogs" rows="10">Log output here...</textarea>
|
|
</div>
|
|
</form>
|
|
</section>
|
|
<!-- Status Bar -->
|
|
<div class="status-bar" id="statusMessage">Status: Ready</div>
|
|
</div>
|
|
<script>
|
|
// Page Initialization
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
document.querySelectorAll('.nav-tab').forEach(tab => {
|
|
tab.addEventListener('click', function () {
|
|
changeTab(this.getAttribute('data-target'));
|
|
});
|
|
});
|
|
|
|
document.getElementById('loadConfigBtn').addEventListener('click', loadConfig);
|
|
document.getElementById('saveConfigBtn').addEventListener('click', saveConfig);
|
|
});
|
|
|
|
// Tab change function
|
|
function changeTab(targetId) {
|
|
const tabContents = document.querySelectorAll(".tab-content");
|
|
const tabs = document.querySelectorAll(".nav-tab");
|
|
|
|
tabContents.forEach(tab => {
|
|
tab.style.display = "none";
|
|
tab.classList.remove("active");
|
|
});
|
|
|
|
tabs.forEach(tab => tab.classList.remove("active"));
|
|
|
|
const targetTabContent = document.getElementById(targetId);
|
|
const targetTab = document.querySelector(`.nav-tab[data-target="${targetId}"]`);
|
|
|
|
if (targetTabContent) {
|
|
targetTabContent.style.display = "block";
|
|
targetTabContent.classList.add("active");
|
|
}
|
|
|
|
if (targetTab) {
|
|
targetTab.classList.add("active");
|
|
}
|
|
}
|
|
|
|
// Configuration load function
|
|
function loadConfig() {
|
|
fetch('/data')
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error('Network response was not ok: ' + response.statusText);
|
|
}
|
|
return response.json();
|
|
})
|
|
.then(data => {
|
|
if (!data.email || typeof data.email_template !== 'string') {
|
|
throw new Error('Incorrect data structure from server');
|
|
}
|
|
document.getElementById('user').value = data.email.user || '';
|
|
document.getElementById('password').value = data.email.password || '';
|
|
document.getElementById('ccEmail').value = data.email.cc_email || '';
|
|
document.getElementById('bccEmail').value = data.email.bcc_email || '';
|
|
document.getElementById('emailTemplate').textContent = data.email_template || '';
|
|
updateStatusBar("Configuration Loaded Successfully");
|
|
})
|
|
.catch(error => {
|
|
console.error('Error loading configuration:', error);
|
|
updateStatusBar(`Error loading configuration: ${error}`, true);
|
|
});
|
|
}
|
|
|
|
// Configuration save function
|
|
function saveConfig() {
|
|
const emailData = {
|
|
user: document.getElementById('user').value,
|
|
password: document.getElementById('password').value,
|
|
cc_email: document.getElementById('ccEmail').value,
|
|
bcc_email: document.getElementById('bccEmail').value
|
|
};
|
|
|
|
const emailTemplateData = document.getElementById('emailTemplate').value;
|
|
|
|
fetch('/data', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
email: emailData,
|
|
email_template: emailTemplateData
|
|
}),
|
|
})
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error('Network response was not ok: ' + response.statusText);
|
|
}
|
|
return response.json();
|
|
})
|
|
.then(data => {
|
|
if (data.success) {
|
|
alert("Configuration Saved Successfully");
|
|
updateStatusBar("Configuration Saved Successfully");
|
|
} else {
|
|
throw new Error("Failed to save configuration: " + data.message);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error saving configuration:', error);
|
|
updateStatusBar(`Error saving configuration: ${error}`, true);
|
|
});
|
|
}
|
|
|
|
// Status bar update function
|
|
function updateStatusBar(message, isError = false) {
|
|
const statusBar = document.getElementById('statusMessage');
|
|
statusBar.textContent = message;
|
|
if (isError) {
|
|
statusBar.style.color = 'var(--error-color)';
|
|
} else {
|
|
statusBar.style.color = 'initial';
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|