524 lines
23 KiB
Plaintext
524 lines
23 KiB
Plaintext
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Settings - Kitchen Agent</title>
|
||
<link rel="stylesheet" href="/public/css/style.css">
|
||
</head>
|
||
<body class="settings-page">
|
||
<header class="main-header">
|
||
<div class="header-content">
|
||
<h1>Settings</h1>
|
||
<div class="header-actions">
|
||
<a href="/dashboard" class="btn btn-secondary">Back to Dashboard</a>
|
||
<a href="/auth/logout" class="btn btn-secondary">Logout</a>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="settings-container">
|
||
<% if (message) { %>
|
||
<div class="alert alert-success">
|
||
<%= message %>
|
||
</div>
|
||
<% } %>
|
||
|
||
<% if (error) { %>
|
||
<div class="alert alert-error">
|
||
<%= error %>
|
||
</div>
|
||
<% } %>
|
||
|
||
<div class="tabs">
|
||
<button class="tab-btn active" data-tab="general">General</button>
|
||
<button class="tab-btn" data-tab="printer">Printer</button>
|
||
<button class="tab-btn" data-tab="template">Receipt Template</button>
|
||
</div>
|
||
|
||
<form action="/settings/save" method="POST" id="settingsForm">
|
||
|
||
<!-- General Settings Tab -->
|
||
<div class="tab-content active" id="general-tab">
|
||
<h2>General Settings</h2>
|
||
|
||
<div class="form-group">
|
||
<label for="selectedBotId">Select Bot/Assistant</label>
|
||
<select id="selectedBotId" name="selectedBotId" required>
|
||
<option value="">-- Select Bot --</option>
|
||
<% bots.forEach(bot => { %>
|
||
<% const botConfig = JSON.parse(bot.bot_config || '{}'); %>
|
||
<option value="<%= bot.id %>" <%= config.selectedBotId == bot.id ? 'selected' : '' %>>
|
||
<%= botConfig.name || 'Bot #' + bot.id %>
|
||
</option>
|
||
<% }); %>
|
||
</select>
|
||
<small>Select which bot's orders to display</small>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="pollingInterval">Order Polling Interval (milliseconds)</label>
|
||
<input type="number" id="pollingInterval" name="pollingInterval"
|
||
value="<%= config.pollingInterval || 15000 %>" min="5000" max="60000" step="1000">
|
||
<small>How often to check for new orders (default: 15000 = 15 seconds)</small>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="dashboardRefreshInterval">Dashboard Refresh Interval (milliseconds)</label>
|
||
<input type="number" id="dashboardRefreshInterval" name="dashboardRefreshInterval"
|
||
value="<%= config.dashboardRefreshInterval || 10000 %>" min="5000" max="60000" step="1000">
|
||
<small>How often to refresh the dashboard display (default: 10000 = 10 seconds)</small>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="checkbox-label">
|
||
<input type="checkbox" name="showOrderStats" <%= config.showOrderStats !== 'false' ? 'checked' : '' %>>
|
||
Show Order Statistics Bar
|
||
</label>
|
||
</div>
|
||
|
||
<h3 style="margin-top: 30px; margin-bottom: 15px; border-top: 2px solid #e0e0e0; padding-top: 20px;">Sound Notifications</h3>
|
||
|
||
<div class="form-group">
|
||
<label class="checkbox-label">
|
||
<input type="checkbox" id="soundNotificationsEnabled" name="soundNotificationsEnabled" <%= config.soundNotificationsEnabled !== 'false' ? 'checked' : '' %>>
|
||
Enable Sound Notifications
|
||
</label>
|
||
<small>Play sounds when new orders arrive or orders are canceled</small>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="soundVolume">Notification Volume</label>
|
||
<input type="range" id="soundVolume" name="soundVolume" min="0" max="100" value="<%= config.soundVolume || 80 %>" style="width: 100%;">
|
||
<small>Volume: <span id="volumeValue"><%= config.soundVolume || 80 %></span>%</small>
|
||
</div>
|
||
|
||
<div class="settings-section" style="background: #f9f9f9; padding: 20px; border-radius: 8px; margin-top: 20px;">
|
||
<h4 style="margin-top: 0;">New Order Sound</h4>
|
||
<div class="form-group">
|
||
<label>Current Sound File:</label>
|
||
<p style="font-size: 14px; color: #666;">
|
||
<%= config.newOrderSoundPath || '/public/sounds/new-order-notification.mp3' %>
|
||
</p>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>Upload Custom Sound (optional)</label>
|
||
<input type="file" id="newOrderSoundUpload" accept="audio/*">
|
||
<button type="button" class="btn btn-secondary" onclick="uploadSound('newOrder')">Upload New Order Sound</button>
|
||
<button type="button" class="btn btn-secondary" onclick="testSound('newOrder')">🔊 Test Sound</button>
|
||
<small>Supported formats: MP3, WAV, OGG</small>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="settings-section" style="background: #f9f9f9; padding: 20px; border-radius: 8px; margin-top: 20px;">
|
||
<h4 style="margin-top: 0;">Canceled Order Sound</h4>
|
||
<div class="form-group">
|
||
<label>Current Sound File:</label>
|
||
<p style="font-size: 14px; color: #666;">
|
||
<%= config.canceledOrderSoundPath || '/public/sounds/canceled-order-notification.mp3' %>
|
||
</p>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>Upload Custom Sound (optional)</label>
|
||
<input type="file" id="canceledOrderSoundUpload" accept="audio/*">
|
||
<button type="button" class="btn btn-secondary" onclick="uploadSound('canceled')">Upload Canceled Sound</button>
|
||
<button type="button" class="btn btn-secondary" onclick="testSound('canceled')">🔊 Test Sound</button>
|
||
<small>Supported formats: MP3, WAV, OGG</small>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Printer Management Tab -->
|
||
<div class="tab-content" id="printer-tab">
|
||
<h2>Printer Management</h2>
|
||
<p class="section-description">Configure individual printers with specific paper sizes, templates, and settings.</p>
|
||
|
||
<div class="settings-section">
|
||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
|
||
<h3 style="margin: 0;">Configured Printers</h3>
|
||
<button type="button" class="btn btn-primary" onclick="openAddPrinterModal()">+ Add Printer</button>
|
||
</div>
|
||
|
||
<div id="printer-cards-container" class="printer-cards-container">
|
||
<!-- Printer cards will be loaded here dynamically -->
|
||
<div class="loading">Loading printers...</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Receipt Template Tab -->
|
||
<div class="tab-content" id="template-tab">
|
||
<h2>Receipt Template</h2>
|
||
|
||
<div class="form-group">
|
||
<label for="headerText">Header Text</label>
|
||
<textarea id="headerText" name="headerText" rows="2" placeholder="KITCHEN ORDER"><%= typeof config.headerText !== 'undefined' ? config.headerText : '' %></textarea>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="footerText">Footer Text</label>
|
||
<textarea id="footerText" name="footerText" rows="2" placeholder="Thank you!"><%= typeof config.footerText !== 'undefined' ? config.footerText : '' %></textarea>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="checkbox-label">
|
||
<input type="checkbox" name="qrCodeEnabled" <%= config.qrCodeEnabled !== 'false' ? 'checked' : '' %>>
|
||
Print QR Code on Receipt
|
||
</label>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="qrCodeSize">QR Code Size</label>
|
||
<input type="number" id="qrCodeSize" name="qrCodeSize" min="2" max="8" value="<%= config.qrCodeSize || 3 %>">
|
||
<small>Cell size (2–8). Larger = bigger QR.</small>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="qrCodeCorrection">QR Error Correction</label>
|
||
<select id="qrCodeCorrection" name="qrCodeCorrection">
|
||
<option value="L" <%= (config.qrCodeCorrection || 'M') === 'L' ? 'selected' : '' %>>L (Low)</option>
|
||
<option value="M" <%= (config.qrCodeCorrection || 'M') === 'M' ? 'selected' : '' %>>M (Medium)</option>
|
||
<option value="Q" <%= (config.qrCodeCorrection || 'M') === 'Q' ? 'selected' : '' %>>Q (Quartile)</option>
|
||
<option value="H" <%= (config.qrCodeCorrection || 'M') === 'H' ? 'selected' : '' %>>H (High)</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="qrCodeContentTemplate">QR Content Template</label>
|
||
<input type="text" id="qrCodeContentTemplate" name="qrCodeContentTemplate" value="<%= config.qrCodeContentTemplate || 'ORDER-{id}' %>">
|
||
<small>Use placeholders: {id}, {total}, {type}, {createdAt}</small>
|
||
</div>
|
||
|
||
<h3>Show/Hide Sections</h3>
|
||
|
||
<div class="form-group">
|
||
<label class="checkbox-label">
|
||
<input type="checkbox" name="showCustomerInfo" <%= config.showCustomerInfo !== 'false' ? 'checked' : '' %>>
|
||
Show Customer Information
|
||
</label>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="checkbox-label">
|
||
<input type="checkbox" name="showOrderItems" <%= config.showOrderItems !== 'false' ? 'checked' : '' %>>
|
||
Show Order Items
|
||
</label>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="checkbox-label">
|
||
<input type="checkbox" name="showPrices" <%= config.showPrices !== 'false' ? 'checked' : '' %>>
|
||
Show Prices
|
||
</label>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="checkbox-label">
|
||
<input type="checkbox" name="showTimestamps" <%= config.showTimestamps !== 'false' ? 'checked' : '' %>>
|
||
Show Timestamps
|
||
</label>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>Logo Image (optional)</label>
|
||
<input type="file" id="logoUpload" accept="image/*">
|
||
<button type="button" class="btn btn-secondary" onclick="uploadLogo()">Upload Logo</button>
|
||
<small>Upload a logo image to print at the top of receipts</small>
|
||
<% if (config.logoPath) { %>
|
||
<div class="current-logo">
|
||
<p>Current logo: <%= config.logoPath %></p>
|
||
</div>
|
||
<% } %>
|
||
</div>
|
||
|
||
<h3>Business Information</h3>
|
||
<div class="form-group">
|
||
<label for="businessName">Business Name</label>
|
||
<input type="text" id="businessName" name="businessName" value="<%= config.businessName || '' %>">
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="businessAddress">Address</label>
|
||
<input type="text" id="businessAddress" name="businessAddress" value="<%= config.businessAddress || '' %>">
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="businessPhone">Phone</label>
|
||
<input type="text" id="businessPhone" name="businessPhone" value="<%= config.businessPhone || '' %>">
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="businessWebsite">Website</label>
|
||
<input type="text" id="businessWebsite" name="businessWebsite" value="<%= config.businessWebsite || '' %>">
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="businessEmail">Email</label>
|
||
<input type="text" id="businessEmail" name="businessEmail" value="<%= config.businessEmail || '' %>">
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="businessContactSize">Contact Font Size</label>
|
||
<select id="businessContactSize" name="businessContactSize">
|
||
<option value="normal" <%= (config.businessContactSize || 'normal') === 'normal' ? 'selected' : '' %>>Normal</option>
|
||
<option value="large" <%= (config.businessContactSize || 'normal') === 'large' ? 'selected' : '' %>>Large</option>
|
||
</select>
|
||
<small>Controls the size of address/phone/website/email in header.</small>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-actions">
|
||
<button type="submit" class="btn btn-primary btn-large">Save All Settings</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<!-- Printer Configuration Modal -->
|
||
<div class="modal" id="printerConfigModal">
|
||
<div class="modal-content modal-large">
|
||
<div class="modal-header">
|
||
<h2 id="printerModalTitle">Add Printer</h2>
|
||
<button class="close-btn" onclick="closePrinterModal()">×</button>
|
||
</div>
|
||
|
||
<div class="printer-modal-body">
|
||
<div class="printer-modal-tabs">
|
||
<button class="printer-modal-tab-btn active" data-tab="connection">Connection</button>
|
||
<button class="printer-modal-tab-btn" data-tab="paper">Paper & Format</button>
|
||
<button class="printer-modal-tab-btn" data-tab="template">Template</button>
|
||
<button class="printer-modal-tab-btn" data-tab="business">Business Info</button>
|
||
<button class="printer-modal-tab-btn" data-tab="logo">Logo & Branding</button>
|
||
<button class="printer-modal-tab-btn" data-tab="qrcode">QR Code</button>
|
||
</div>
|
||
|
||
<form id="printerConfigForm" onsubmit="return false;">
|
||
<input type="hidden" id="printer_id" name="id">
|
||
|
||
<!-- Connection Tab -->
|
||
<div class="printer-modal-tab-content active" id="connection-tab-content">
|
||
<div class="form-group">
|
||
<label for="printer_name">Printer Name *</label>
|
||
<input type="text" id="printer_name" name="name" required placeholder="e.g., Kitchen Printer - 80mm">
|
||
<small>Give this printer a descriptive name</small>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="printer_type_select">Connection Type *</label>
|
||
<select id="printer_type_select" name="type" required>
|
||
<option value="network">Network (TCP/IP)</option>
|
||
<option value="com">Serial Port (COM)</option>
|
||
<option value="usb">USB</option>
|
||
<option value="system">Windows System Printer</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="printer_interface">Connection Address *</label>
|
||
<input type="text" id="printer_interface" name="interface" required placeholder="e.g., 192.168.1.100:9100, COM1, /dev/usb/lp0">
|
||
<small id="interface_hint">Enter IP:Port for network printers</small>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<button type="button" class="btn btn-secondary" onclick="detectPrintersForModal()">Detect Available Printers</button>
|
||
<div id="detected-printers-list" style="margin-top: 10px;"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Paper & Format Tab -->
|
||
<div class="printer-modal-tab-content" id="paper-tab-content">
|
||
<div class="form-group">
|
||
<label for="paper_format">Paper Format *</label>
|
||
<select id="paper_format" name="paper_format" required>
|
||
<option value="58mm">58mm Thermal</option>
|
||
<option value="80mm" selected>80mm Thermal</option>
|
||
<option value="letter">Letter Size (8.5 x 11)</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="paper_width">Character Width *</label>
|
||
<input type="number" id="paper_width" name="paper_width" value="48" min="20" max="100" required>
|
||
<small>58mm: 32 chars | 80mm: 48 chars | Letter: 80+ chars</small>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="printer_type_model">Printer Model/Brand *</label>
|
||
<select id="printer_type_model" name="printer_type" required>
|
||
<option value="epson" selected>Epson</option>
|
||
<option value="star">Star</option>
|
||
<option value="tanca">Tanca</option>
|
||
<option value="brother">Brother</option>
|
||
<option value="custom">Custom</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="font_size">Font Size</label>
|
||
<select id="font_size" name="font_size">
|
||
<option value="small">Small</option>
|
||
<option value="normal" selected>Normal</option>
|
||
<option value="large">Large</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="line_style">Line Style</label>
|
||
<select id="line_style" name="line_style">
|
||
<option value="single" selected>Single (─)</option>
|
||
<option value="double">Double (═)</option>
|
||
<option value="dashed">Dashed (- -)</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Template Tab -->
|
||
<div class="printer-modal-tab-content" id="template-tab-content">
|
||
<div class="form-group">
|
||
<label for="header_text">Header Text</label>
|
||
<textarea id="header_text" name="header_text" rows="2" placeholder="KITCHEN ORDER"></textarea>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="footer_text">Footer Text</label>
|
||
<textarea id="footer_text" name="footer_text" rows="2" placeholder="Thank you!"></textarea>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="checkbox-label">
|
||
<input type="checkbox" id="show_customer_info" name="show_customer_info" checked>
|
||
Show Customer Information
|
||
</label>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="checkbox-label">
|
||
<input type="checkbox" id="show_order_items" name="show_order_items" checked>
|
||
Show Order Items
|
||
</label>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="checkbox-label">
|
||
<input type="checkbox" id="show_prices" name="show_prices" checked>
|
||
Show Prices
|
||
</label>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="checkbox-label">
|
||
<input type="checkbox" id="show_timestamps" name="show_timestamps" checked>
|
||
Show Timestamps
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Business Info Tab -->
|
||
<div class="printer-modal-tab-content" id="business-tab-content">
|
||
<div class="form-group">
|
||
<label for="business_name">Business Name</label>
|
||
<input type="text" id="business_name" name="business_name" placeholder="Your Business Name">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="business_address">Address</label>
|
||
<input type="text" id="business_address" name="business_address" placeholder="123 Main St, City, State ZIP">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="business_phone">Phone</label>
|
||
<input type="text" id="business_phone" name="business_phone" placeholder="(555) 123-4567">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="business_website">Website</label>
|
||
<input type="text" id="business_website" name="business_website" placeholder="www.example.com">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="business_email">Email</label>
|
||
<input type="email" id="business_email" name="business_email" placeholder="contact@example.com">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="business_contact_size">Contact Info Size</label>
|
||
<select id="business_contact_size" name="business_contact_size">
|
||
<option value="normal" selected>Normal</option>
|
||
<option value="large">Large</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Logo & Branding Tab -->
|
||
<div class="printer-modal-tab-content" id="logo-tab-content">
|
||
<div class="form-group">
|
||
<label>Logo Image</label>
|
||
<input type="file" id="logo_upload_modal" accept="image/*">
|
||
<button type="button" class="btn btn-secondary" onclick="uploadLogoForPrinter()" style="margin-top: 10px;">Upload Logo</button>
|
||
<small>Upload a logo for this specific printer</small>
|
||
<div id="logo_preview" style="margin-top: 10px;"></div>
|
||
<input type="hidden" id="logo_path" name="logo_path">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="logo_max_width_dots">Logo Max Width (dots)</label>
|
||
<input type="number" id="logo_max_width_dots" name="logo_max_width_dots" min="100" max="800" placeholder="Auto-detect based on paper width">
|
||
<small>58mm: ~384 dots | 80mm: ~576 dots | Leave empty for auto</small>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- QR Code Tab -->
|
||
<div class="printer-modal-tab-content" id="qrcode-tab-content">
|
||
<div class="form-group">
|
||
<label class="checkbox-label">
|
||
<input type="checkbox" id="qr_code_enabled" name="qr_code_enabled" checked>
|
||
Print QR Code on Receipt
|
||
</label>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="qr_code_size">QR Code Size</label>
|
||
<input type="number" id="qr_code_size" name="qr_code_size" value="3" min="2" max="8">
|
||
<small>Cell size (2-8). Larger = bigger QR code</small>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="qr_code_correction">Error Correction Level</label>
|
||
<select id="qr_code_correction" name="qr_code_correction">
|
||
<option value="L">L (Low - 7% recovery)</option>
|
||
<option value="M" selected>M (Medium - 15% recovery)</option>
|
||
<option value="Q">Q (Quartile - 25% recovery)</option>
|
||
<option value="H">H (High - 30% recovery)</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="qr_code_content_template">QR Content Template</label>
|
||
<input type="text" id="qr_code_content_template" name="qr_code_content_template" value="ORDER-{id}" placeholder="ORDER-{id}">
|
||
<small>Use: {id}, {total}, {type}, {createdAt}</small>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal-actions" style="margin-top: 30px; padding-top: 20px; border-top: 2px solid #e0e0e0;">
|
||
<div class="form-group">
|
||
<label class="checkbox-label">
|
||
<input type="checkbox" id="is_default" name="is_default">
|
||
Set as Default Printer
|
||
</label>
|
||
</div>
|
||
<div class="form-group">
|
||
<label class="checkbox-label">
|
||
<input type="checkbox" id="is_enabled" name="is_enabled" checked>
|
||
Enabled (Print to this printer)
|
||
</label>
|
||
</div>
|
||
<button type="button" class="btn btn-secondary" onclick="closePrinterModal()">Cancel</button>
|
||
<button type="submit" class="btn btn-primary" onclick="savePrinterConfig()">Save Printer</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="/public/js/common.js"></script>
|
||
<script src="/public/js/settings.js"></script>
|
||
</body>
|
||
</html>
|
||
|