Complete admin dashboard with all pages: profile editor (cover photo, business hours, social links), settings (account, notifications, security), enhanced trades view with detail modal, and orders with status workflow. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
312 lines
13 KiB
HTML
312 lines
13 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Grubflip Admin — Settings</title>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Plus+Jakarta+Sans:wght@600;700;800&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="css/tokens.css">
|
|
<link rel="stylesheet" href="css/admin.css">
|
|
</head>
|
|
<body>
|
|
<div class="admin-layout">
|
|
<div class="sidebar-overlay" id="sidebarOverlay"></div>
|
|
|
|
<aside class="sidebar" id="sidebar" role="navigation" aria-label="Admin navigation">
|
|
<div class="sidebar-brand">
|
|
<div class="logo-icon">GF</div>
|
|
<span>Grubflip</span>
|
|
</div>
|
|
<nav class="sidebar-nav">
|
|
<div class="sidebar-section-title">Main</div>
|
|
<a href="dashboard.html" class="sidebar-link"><span class="icon">📊</span> Dashboard</a>
|
|
<a href="meals.html" class="sidebar-link"><span class="icon">🍔</span> Meals</a>
|
|
<a href="orders.html" class="sidebar-link"><span class="icon">📦</span> Orders</a>
|
|
<a href="trades.html" class="sidebar-link"><span class="icon">🔄</span> Trades</a>
|
|
<div class="sidebar-section-title">Settings</div>
|
|
<a href="profile.html" class="sidebar-link"><span class="icon">🏪</span> Restaurant Profile</a>
|
|
<a href="settings.html" class="sidebar-link active"><span class="icon">⚙️</span> Settings</a>
|
|
</nav>
|
|
<div class="sidebar-footer">
|
|
<div class="sidebar-user">
|
|
<div class="avatar" id="userAvatar">DR</div>
|
|
<div class="user-info">
|
|
<div class="user-name" id="userName">Demo Restaurant</div>
|
|
<div class="user-role" id="userRole">Owner</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
|
|
<main class="main-content">
|
|
<header class="topbar">
|
|
<div class="topbar-left">
|
|
<button class="menu-toggle" id="menuToggle" aria-label="Toggle menu">☰</button>
|
|
<h1 class="topbar-title">Settings</h1>
|
|
</div>
|
|
<div class="topbar-right">
|
|
<button class="topbar-btn" aria-label="Sign out" id="logoutBtn">⏻</button>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="page-content" style="max-width:48rem">
|
|
<div class="page-header">
|
|
<h1>Settings</h1>
|
|
<p class="subtitle">Manage your account and notification preferences.</p>
|
|
</div>
|
|
|
|
<!-- Tabs -->
|
|
<div class="tabs" id="settingsTabs">
|
|
<button class="tab active" data-tab="account">Account</button>
|
|
<button class="tab" data-tab="notifications">Notifications</button>
|
|
<button class="tab" data-tab="security">Security</button>
|
|
</div>
|
|
|
|
<!-- Account Tab -->
|
|
<div class="settings-panel" id="panel-account">
|
|
<div class="card mb-6">
|
|
<div class="card-header">
|
|
<h2>Account Information</h2>
|
|
</div>
|
|
<form id="accountForm">
|
|
<div class="form-group">
|
|
<label for="accName" class="form-label">Full Name</label>
|
|
<input type="text" id="accName" class="form-input" placeholder="Your name">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="accEmail" class="form-label">Email Address</label>
|
|
<input type="email" id="accEmail" class="form-input" placeholder="you@restaurant.com">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="accPhone" class="form-label">Phone Number</label>
|
|
<input type="tel" id="accPhone" class="form-input" placeholder="(555) 123-4567">
|
|
</div>
|
|
<button type="submit" class="btn btn-primary">Save Changes</button>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h2 style="color:var(--gf-error)">Danger Zone</h2>
|
|
</div>
|
|
<p class="text-sm text-muted mb-4">Permanently delete your account and all associated data. This action cannot be undone.</p>
|
|
<button class="btn btn-danger btn-sm" id="deleteAccountBtn">Delete Account</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Notifications Tab -->
|
|
<div class="settings-panel hidden" id="panel-notifications">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h2>Notification Preferences</h2>
|
|
</div>
|
|
|
|
<div class="setting-row">
|
|
<div class="setting-info">
|
|
<strong>New Trade Requests</strong>
|
|
<p class="text-sm text-muted">Get notified when someone proposes a trade for one of your meals.</p>
|
|
</div>
|
|
<label class="toggle">
|
|
<input type="checkbox" checked data-pref="trade_requests">
|
|
<span class="toggle-slider"></span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="setting-row">
|
|
<div class="setting-info">
|
|
<strong>Trade Completed</strong>
|
|
<p class="text-sm text-muted">Notification when a trade is successfully completed.</p>
|
|
</div>
|
|
<label class="toggle">
|
|
<input type="checkbox" checked data-pref="trade_completed">
|
|
<span class="toggle-slider"></span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="setting-row">
|
|
<div class="setting-info">
|
|
<strong>New Reviews</strong>
|
|
<p class="text-sm text-muted">Get notified when someone leaves a review on your meal.</p>
|
|
</div>
|
|
<label class="toggle">
|
|
<input type="checkbox" checked data-pref="new_reviews">
|
|
<span class="toggle-slider"></span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="setting-row">
|
|
<div class="setting-info">
|
|
<strong>Weekly Summary</strong>
|
|
<p class="text-sm text-muted">Receive a weekly email with your trade stats and popular meals.</p>
|
|
</div>
|
|
<label class="toggle">
|
|
<input type="checkbox" data-pref="weekly_summary">
|
|
<span class="toggle-slider"></span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="setting-row">
|
|
<div class="setting-info">
|
|
<strong>Marketing Emails</strong>
|
|
<p class="text-sm text-muted">Tips, feature updates, and promotional content.</p>
|
|
</div>
|
|
<label class="toggle">
|
|
<input type="checkbox" data-pref="marketing">
|
|
<span class="toggle-slider"></span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Security Tab -->
|
|
<div class="settings-panel hidden" id="panel-security">
|
|
<div class="card mb-6">
|
|
<div class="card-header">
|
|
<h2>Change Password</h2>
|
|
</div>
|
|
<form id="passwordForm">
|
|
<div class="form-group">
|
|
<label for="currentPass" class="form-label">Current Password</label>
|
|
<input type="password" id="currentPass" class="form-input" placeholder="Enter current password" autocomplete="current-password">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="newPass" class="form-label">New Password</label>
|
|
<input type="password" id="newPass" class="form-input" placeholder="Enter new password" autocomplete="new-password">
|
|
<span class="form-hint">At least 8 characters with a mix of letters and numbers.</span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="confirmPass" class="form-label">Confirm New Password</label>
|
|
<input type="password" id="confirmPass" class="form-input" placeholder="Confirm new password" autocomplete="new-password">
|
|
</div>
|
|
<button type="submit" class="btn btn-primary">Update Password</button>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h2>Active Sessions</h2>
|
|
</div>
|
|
<div class="setting-row">
|
|
<div class="setting-info">
|
|
<strong>Current Session</strong>
|
|
<p class="text-sm text-muted">This device · Last active now</p>
|
|
</div>
|
|
<span class="badge badge-success">Active</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
|
|
<div class="toast-container" id="toastContainer"></div>
|
|
|
|
<style>
|
|
.setting-row {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: var(--gf-space-4);
|
|
padding: var(--gf-space-4) 0;
|
|
border-bottom: 1px solid var(--gf-neutral-100);
|
|
}
|
|
.setting-row:last-child { border-bottom: none; }
|
|
.setting-info { flex: 1; }
|
|
.setting-info strong {
|
|
display: block;
|
|
font-size: var(--gf-text-sm);
|
|
font-weight: var(--gf-weight-semibold);
|
|
color: var(--gf-neutral-800);
|
|
margin-bottom: var(--gf-space-1);
|
|
}
|
|
.settings-panel { animation: fadeIn 0.2s ease; }
|
|
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
|
</style>
|
|
|
|
<script src="js/admin-app.js"></script>
|
|
<script>
|
|
if (!AdminApp.requireAuth()) throw new Error('Not authenticated');
|
|
const user = AdminApp.getUser();
|
|
if (user.name) {
|
|
document.getElementById('userName').textContent = user.name;
|
|
document.getElementById('userAvatar').textContent = user.name.split(' ').map(w => w[0]).join('').slice(0, 2).toUpperCase();
|
|
document.getElementById('accName').value = user.name;
|
|
}
|
|
if (user.email) document.getElementById('accEmail').value = user.email;
|
|
if (user.role) document.getElementById('userRole').textContent = user.role.charAt(0).toUpperCase() + user.role.slice(1);
|
|
|
|
AdminApp.initSidebar();
|
|
document.getElementById('logoutBtn').addEventListener('click', AdminApp.logout);
|
|
|
|
// --- Tabs ---
|
|
document.getElementById('settingsTabs').addEventListener('click', function(e) {
|
|
var tab = e.target.closest('.tab');
|
|
if (!tab) return;
|
|
document.querySelectorAll('.tab').forEach(function(t) { t.classList.remove('active'); });
|
|
tab.classList.add('active');
|
|
document.querySelectorAll('.settings-panel').forEach(function(p) { p.classList.add('hidden'); });
|
|
var panel = document.getElementById('panel-' + tab.dataset.tab);
|
|
if (panel) panel.classList.remove('hidden');
|
|
});
|
|
|
|
// --- Account Form ---
|
|
document.getElementById('accountForm').addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
var name = document.getElementById('accName').value.trim();
|
|
var email = document.getElementById('accEmail').value.trim();
|
|
if (!name || !email) {
|
|
AdminApp.toast('Please fill in all required fields', 'error');
|
|
return;
|
|
}
|
|
// Update local storage for demo
|
|
var u = AdminApp.getUser();
|
|
u.name = name;
|
|
u.email = email;
|
|
u.phone = document.getElementById('accPhone').value.trim();
|
|
localStorage.setItem('gf_user', JSON.stringify(u));
|
|
document.getElementById('userName').textContent = name;
|
|
document.getElementById('userAvatar').textContent = name.split(' ').map(function(w) { return w[0]; }).join('').slice(0, 2).toUpperCase();
|
|
AdminApp.toast('Account updated', 'success');
|
|
});
|
|
|
|
// --- Password Form ---
|
|
document.getElementById('passwordForm').addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
var current = document.getElementById('currentPass').value;
|
|
var newPass = document.getElementById('newPass').value;
|
|
var confirm = document.getElementById('confirmPass').value;
|
|
|
|
if (!current || !newPass || !confirm) {
|
|
AdminApp.toast('Please fill in all fields', 'error');
|
|
return;
|
|
}
|
|
if (newPass.length < 8) {
|
|
AdminApp.toast('Password must be at least 8 characters', 'error');
|
|
return;
|
|
}
|
|
if (newPass !== confirm) {
|
|
AdminApp.toast('Passwords do not match', 'error');
|
|
return;
|
|
}
|
|
AdminApp.toast('Password updated successfully', 'success');
|
|
document.getElementById('passwordForm').reset();
|
|
});
|
|
|
|
// --- Delete Account ---
|
|
document.getElementById('deleteAccountBtn').addEventListener('click', function() {
|
|
if (window.confirm('Are you sure? This will permanently delete your account.')) {
|
|
AdminApp.toast('Account deletion is not available in demo mode', 'warning');
|
|
}
|
|
});
|
|
|
|
// --- Notification Toggles ---
|
|
document.querySelectorAll('[data-pref]').forEach(function(toggle) {
|
|
toggle.addEventListener('change', function() {
|
|
AdminApp.toast('Preference updated', 'success');
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|