grubflip/admin/settings.html
Sarah 960391c4f4 Add admin restaurant profile, settings, and update trades/orders pages
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>
2026-03-27 15:41:45 +00:00

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">&#x1f4ca;</span> Dashboard</a>
<a href="meals.html" class="sidebar-link"><span class="icon">&#x1f354;</span> Meals</a>
<a href="orders.html" class="sidebar-link"><span class="icon">&#x1f4e6;</span> Orders</a>
<a href="trades.html" class="sidebar-link"><span class="icon">&#x1f504;</span> Trades</a>
<div class="sidebar-section-title">Settings</div>
<a href="profile.html" class="sidebar-link"><span class="icon">&#x1f3ea;</span> Restaurant Profile</a>
<a href="settings.html" class="sidebar-link active"><span class="icon">&#x2699;&#xfe0f;</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">&#9776;</button>
<h1 class="topbar-title">Settings</h1>
</div>
<div class="topbar-right">
<button class="topbar-btn" aria-label="Sign out" id="logoutBtn">&#x23fb;</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 &middot; 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>