This repository has been archived on 2026-03-21. You can view files and clone it, but cannot push or open issues or pull requests.
payfrit-biz/portal/index.html
John Mizerek 771f70f2f3 Add BrandColorLight to portal settings page
Updated the portal settings brand color picker to show both dark
and light colors. Light swatch shown alongside dark swatch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 15:09:30 -08:00

811 lines
41 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Payfrit Business Portal</title>
<link rel="stylesheet" href="portal.css">
<script>
// Auth check - redirect to signup if not logged in
(function() {
const token = localStorage.getItem('payfrit_portal_token');
if (!token) {
window.location.href = 'signup.html';
}
})();
</script>
</head>
<body>
<div class="app">
<!-- Sidebar -->
<aside class="sidebar" id="sidebar">
<!-- Business Card -->
<div class="business-info" style="padding: 12px 16px; border-bottom: 1px solid var(--gray-200); display: flex; align-items: center; gap: 12px;">
<div class="business-avatar" id="businessAvatar">B</div>
<div class="business-details" style="flex: 1;">
<div class="business-name" id="businessName">Loading...</div>
<div class="business-status online">Online</div>
</div>
<button class="sidebar-toggle" id="sidebarToggle" style="background: none; border: none; cursor: pointer; padding: 4px;">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M3 12h18M3 6h18M3 18h18"/>
</svg>
</button>
</div>
<nav class="sidebar-nav">
<a href="#dashboard" class="nav-item active" data-page="dashboard">
<svg class="nav-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/>
<rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/>
</svg>
<span>Dashboard</span>
</a>
<a href="#orders" class="nav-item" data-page="orders">
<svg class="nav-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2"/>
<rect x="9" y="3" width="6" height="4" rx="1"/>
<path d="M9 12h6M9 16h6"/>
</svg>
<span>Orders</span>
</a>
<a href="menu-builder.html" class="nav-item">
<svg class="nav-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M3 6h18M3 12h18M3 18h18"/>
</svg>
<span>Menu</span>
</a>
<a href="station-assignment.html" class="nav-item">
<svg class="nav-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="2" y="3" width="20" height="18" rx="2"/>
<path d="M2 9h20M9 21V9"/>
</svg>
<span>Stations</span>
</a>
<a href="#reports" class="nav-item" data-page="reports">
<svg class="nav-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M18 20V10M12 20V4M6 20v-6"/>
</svg>
<span>Reports</span>
</a>
<a href="#team" class="nav-item" data-page="team">
<svg class="nav-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"/>
<circle cx="9" cy="7" r="4"/>
<path d="M23 21v-2a4 4 0 00-3-3.87M16 3.13a4 4 0 010 7.75"/>
</svg>
<span>Team</span>
</a>
<a href="#services" class="nav-item" data-page="services">
<svg class="nav-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9"/>
<path d="M13.73 21a2 2 0 01-3.46 0"/>
</svg>
<span>Services</span>
</a>
<a href="#service-points" class="nav-item" data-page="service-points">
<svg class="nav-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="3"/>
<path d="M12 2v4M12 18v4M2 12h4M18 12h4"/>
<path d="M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/>
</svg>
<span>Service Points</span>
</a>
<a href="#admin-tasks" class="nav-item" data-page="admin-tasks">
<svg class="nav-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
<span>Task Admin</span>
</a>
<a href="#settings" class="nav-item" data-page="settings">
<svg class="nav-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="3"/>
<path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-2 2 2 2 0 01-2-2v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83 0 2 2 0 010-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H3a2 2 0 01-2-2 2 2 0 012-2h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 010-2.83 2 2 0 012.83 0l.06.06a1.65 1.65 0 001.82.33H9a1.65 1.65 0 001-1.51V3a2 2 0 012-2 2 2 0 012 2v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 0 2 2 0 010 2.83l-.06.06a1.65 1.65 0 00-.33 1.82V9a1.65 1.65 0 001.51 1H21a2 2 0 012 2 2 2 0 01-2 2h-.09a1.65 1.65 0 00-1.51 1z"/>
</svg>
<span>Settings</span>
</a>
</nav>
</aside>
<!-- Main Content -->
<main class="main-content">
<header class="top-bar">
<div class="page-title">
<h1 id="pageTitle">Dashboard</h1>
</div>
<div class="top-bar-actions">
<button class="btn btn-icon" id="refreshBtn" title="Refresh" onclick="Portal.loadPageData(Portal.currentPage)" style="display:flex;align-items:center;justify-content:center;cursor:pointer;">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M23 4v6h-6M1 20v-6h6"/>
<path d="M3.51 9a9 9 0 0114.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0020.49 15"/>
</svg>
</button>
<div class="user-menu" style="position: relative;">
<button class="user-btn" id="userBtn" onclick="document.getElementById('userDropdown').classList.toggle('show')">
<span class="user-avatar" id="userAvatar">B</span>
</button>
<div class="user-dropdown" id="userDropdown" style="display:none; position:absolute; right:0; top:100%; margin-top:8px; background:var(--bg-card); border:1px solid var(--border-color); border-radius:8px; min-width:200px; box-shadow:0 4px 12px rgba(0,0,0,0.3); z-index:1000; overflow:hidden;">
<a href="#settings" class="nav-item" data-page="settings" onclick="document.getElementById('userDropdown').classList.remove('show'); Portal.navigate('settings');" style="display:flex; align-items:center; gap:10px; padding:12px 16px; color:var(--text-primary); text-decoration:none; transition:background 0.15s;" onmouseover="this.style.background='var(--bg-secondary)'" onmouseout="this.style.background=''">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.6 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.6a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06a1.65 1.65 0 00-.33 1.82V9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z"/></svg>
Settings
</a>
<a href="#" onclick="Portal.switchBusiness(); document.getElementById('userDropdown').classList.remove('show'); return false;" style="display:flex; align-items:center; gap:10px; padding:12px 16px; color:var(--text-primary); text-decoration:none; transition:background 0.15s;" onmouseover="this.style.background='var(--bg-secondary)'" onmouseout="this.style.background=''">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M16 3h5v5M8 3H3v5M3 16v5h5M21 16v5h-5M7 12h10"/></svg>
Switch Business
</a>
<a href="#" onclick="Portal.addNewBusiness(); document.getElementById('userDropdown').classList.remove('show'); return false;" style="display:flex; align-items:center; gap:10px; padding:12px 16px; color:var(--text-primary); text-decoration:none; transition:background 0.15s;" onmouseover="this.style.background='var(--bg-secondary)'" onmouseout="this.style.background=''">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 5v14M5 12h14"/></svg>
Add New Business
</a>
<div style="border-top: 1px solid var(--border-color);"></div>
<a href="#" onclick="Portal.logout(); return false;" style="display:flex; align-items:center; gap:10px; padding:12px 16px; color:#ef4444; text-decoration:none; transition:background 0.15s;" onmouseover="this.style.background='var(--bg-secondary)'" onmouseout="this.style.background=''">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4M16 17l5-5-5-5M21 12H9"/></svg>
Logout
</a>
</div>
</div>
</div>
</header>
<!-- Page Container -->
<div class="page-container" id="pageContainer">
<!-- Dashboard Page -->
<section class="page active" id="page-dashboard">
<div class="stats-grid">
<div class="stat-card">
<div class="stat-icon orders">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2"/>
</svg>
</div>
<div class="stat-content">
<div class="stat-value" id="statOrdersToday">0</div>
<div class="stat-label">Orders Today</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon revenue">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 1v22M17 5H9.5a3.5 3.5 0 000 7h5a3.5 3.5 0 010 7H6"/>
</svg>
</div>
<div class="stat-content">
<div class="stat-value" id="statRevenueToday">$0</div>
<div class="stat-label">Revenue Today</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon pending">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/>
</svg>
</div>
<div class="stat-content">
<div class="stat-value" id="statPendingOrders">0</div>
<div class="stat-label">Pending Orders</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon items">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M3 6h18M3 12h18M3 18h18"/>
</svg>
</div>
<div class="stat-content">
<div class="stat-value" id="statMenuItems">0</div>
<div class="stat-label">Menu Items</div>
</div>
</div>
</div>
<div class="dashboard-grid">
<div class="card recent-orders">
<div class="card-header">
<h3>Recent Orders</h3>
<a href="#orders" class="link">View All</a>
</div>
<div class="card-body">
<div class="orders-list" id="recentOrdersList">
<div class="empty-state">No recent orders</div>
</div>
</div>
</div>
<div class="card quick-actions">
<div class="card-header">
<h3>Quick Actions</h3>
</div>
<div class="card-body">
<div class="action-grid">
<button class="action-btn" onclick="Portal.navigate('menu')">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 5v14M5 12h14"/>
</svg>
Add Menu Item
</button>
<button class="action-btn" onclick="window.open('/kds/index.html', '_blank')">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="2" y="3" width="20" height="14" rx="2"/>
<path d="M8 21h8M12 17v4"/>
</svg>
Open KDS
</button>
<button class="action-btn" onclick="Portal.openQuickTasks()">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/>
</svg>
Quick Tasks
</button>
<button class="action-btn" onclick="Portal.openHUD()">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M18 20V10M12 20V4M6 20v-6"/>
</svg>
Task HUD
</button>
<button class="action-btn" onclick="Portal.navigate('settings')">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="3"/>
</svg>
Settings
</button>
</div>
</div>
</div>
</div>
</section>
<!-- Orders Page -->
<section class="page" id="page-orders">
<div class="page-header">
<div class="filters">
<select id="orderStatusFilter" class="form-select">
<option value="">All Statuses</option>
<option value="1">Submitted</option>
<option value="2">Preparing</option>
<option value="3">Ready</option>
<option value="4">Completed</option>
</select>
<input type="date" id="orderDateFilter" class="form-input">
</div>
</div>
<div class="card">
<div class="table-container">
<table class="data-table">
<thead>
<tr>
<th>Order #</th>
<th>Customer</th>
<th>Items</th>
<th>Total</th>
<th>Status</th>
<th>Time</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="ordersTableBody">
<tr><td colspan="7" class="empty-state">Loading orders...</td></tr>
</tbody>
</table>
</div>
</div>
</section>
<!-- Menu Page -->
<section class="page" id="page-menu">
<div class="page-header">
<a href="setup-wizard.html" class="btn btn-secondary" style="margin-right: auto;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 2L2 7l10 5 10-5-10-5z"/>
<path d="M2 17l10 5 10-5"/>
<path d="M2 12l10 5 10-5"/>
</svg>
Setup Wizard
</a>
<button class="btn btn-primary" onclick="Portal.showAddCategoryModal()">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 5v14M5 12h14"/>
</svg>
Add Category
</button>
<button class="btn btn-primary" onclick="Portal.showAddItemModal()">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 5v14M5 12h14"/>
</svg>
Add Item
</button>
</div>
<div class="menu-grid" id="menuGrid">
<div class="empty-state">Loading menu...</div>
</div>
</section>
<!-- Reports Page -->
<section class="page" id="page-reports">
<div class="reports-grid">
<div class="card">
<div class="card-header">
<h3>Sales Overview</h3>
<select id="reportPeriod" class="form-select">
<option value="7">Last 7 Days</option>
<option value="30">Last 30 Days</option>
<option value="90">Last 90 Days</option>
</select>
</div>
<div class="card-body">
<div class="chart-placeholder" id="salesChart">
<p>Sales chart will appear here</p>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<h3>Top Selling Items</h3>
</div>
<div class="card-body">
<div id="topItemsList" class="top-items-list">
<div class="empty-state">No data available</div>
</div>
</div>
</div>
</div>
</section>
<!-- Team Page -->
<section class="page" id="page-team">
<div class="page-header">
<button class="btn btn-primary" onclick="Portal.showInviteModal()">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M16 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"/>
<circle cx="8.5" cy="7" r="4"/>
<path d="M20 8v6M23 11h-6"/>
</svg>
Invite Team Member
</button>
<div class="hiring-toggle">
<label class="toggle">
<input type="checkbox" id="hiringToggle">
<span class="toggle-slider"></span>
</label>
<span>Accepting Applications</span>
</div>
</div>
<div class="card">
<div class="table-container">
<table class="data-table">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th>Role</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="teamTableBody">
<tr><td colspan="6" class="empty-state">Loading team...</td></tr>
</tbody>
</table>
</div>
</div>
</section>
<!-- Service Points Page (combined: Service Points, Beacons, Sharing) -->
<section class="page" id="page-service-points">
<div class="service-points-layout">
<!-- Service Points list -->
<div class="card">
<div class="card-header" style="display:flex;justify-content:space-between;align-items:center;">
<h3>Service Points</h3>
<button class="btn btn-sm btn-primary" onclick="Portal.showServicePointModal()">+ Add Service Point</button>
</div>
<div class="card-body">
<div class="list-group" id="servicePointsList">
<div class="empty-state">Loading service points...</div>
</div>
</div>
</div>
<!-- Beacons list -->
<div class="card">
<div class="card-header" style="display:flex;justify-content:space-between;align-items:center;">
<h3>Beacons</h3>
<button class="btn btn-sm btn-primary" onclick="Portal.showBeaconModal()">+ Add Beacon</button>
</div>
<div class="card-body">
<div class="list-group" id="beaconsList">
<div class="empty-state">Loading beacons...</div>
</div>
</div>
</div>
<!-- Beacon Assignments -->
<div class="card">
<div class="card-header" style="display:flex;justify-content:space-between;align-items:center;">
<h3>Beacon Assignments</h3>
<button class="btn btn-sm btn-primary" onclick="Portal.showAssignmentModal()">+ Assign</button>
</div>
<div class="card-body">
<div class="list-group" id="assignmentsList">
<div class="empty-state">Loading assignments...</div>
</div>
</div>
</div>
<!-- COMMENTED OUT FOR LAUNCH - Service Point Marketing / Grants (coming soon)
<div class="card" id="spSharingOwnerCard">
<div class="card-header" style="display:flex;justify-content:space-between;align-items:center">
<h3>Grants You've Created</h3>
<button class="btn btn-primary btn-sm" onclick="Portal.showInviteBusinessModal()">Invite Business</button>
</div>
<div class="card-body" id="ownerGrantsList">
<div class="loading-text">Loading...</div>
</div>
</div>
<div class="card" id="spSharingGuestCard">
<div class="card-header">
<h3>Invites &amp; Active Grants</h3>
</div>
<div class="card-body" id="guestGrantsList">
<div class="loading-text">Loading...</div>
</div>
</div>
</div>
<div class="modal-overlay" id="inviteBusinessModal" style="display:none">
<div class="modal" style="max-width:500px">
<div class="modal-header">
<h3>Invite Business to Service Point</h3>
<button class="modal-close" onclick="Portal.closeInviteModal()">&times;</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>Search Business</label>
<input type="text" id="inviteBizSearch" class="form-input" placeholder="Business name or ID..." oninput="Portal.searchBusinessForInvite()">
<div id="inviteBizResults" style="margin-top:8px"></div>
</div>
<div class="form-group" id="inviteBizSelected" style="display:none">
<label>Selected Business</label>
<div id="inviteBizSelectedName" class="form-input" style="background:var(--bg-secondary)"></div>
</div>
<div class="form-group">
<label>Service Point</label>
<select id="inviteSPSelect" class="form-input"></select>
</div>
<div class="form-group">
<label>Economics</label>
<select id="inviteEconType" class="form-input" onchange="Portal.toggleEconValue()">
<option value="none">None</option>
<option value="flat_fee">Flat Fee ($/order)</option>
<option value="percent_of_orders">Percentage of Orders</option>
</select>
<input type="number" id="inviteEconValue" class="form-input" placeholder="0" step="0.01" min="0" style="display:none;margin-top:4px">
</div>
<div class="form-group">
<label>Eligibility</label>
<select id="inviteEligibility" class="form-input">
<option value="public">Public (anyone)</option>
<option value="employees">Employees only</option>
<option value="guests">Guests only</option>
<option value="internal">Internal (owner's employees)</option>
</select>
</div>
<div class="form-group">
<label>Time Policy</label>
<select id="inviteTimePolicy" class="form-input">
<option value="always">Always</option>
<option value="schedule">Schedule</option>
<option value="date_range">Date Range</option>
</select>
</div>
</div>
<div class="modal-footer">
<button class="btn" onclick="Portal.closeInviteModal()">Cancel</button>
<button class="btn btn-primary" onclick="Portal.submitGrantInvite()">Send Invite</button>
</div>
</div>
</div>
END COMMENTED OUT -->
</section>
<!-- Services Page (Task Types) -->
<section class="page" id="page-services">
<div class="card">
<div class="card-header" style="display:flex;justify-content:space-between;align-items:center;">
<h3>Bell Menu Services</h3>
<button class="btn btn-sm btn-primary" onclick="Portal.showAddServiceModal()">+ Add Service</button>
</div>
<div class="card-body">
<p style="color:#666;margin-bottom:16px;">These service options appear when customers tap the bell icon in the app. Customize the names, descriptions, and icons to match your business.</p>
<div class="list-group" id="servicesList">
<div class="empty-state">Loading...</div>
</div>
</div>
</div>
</section>
<!-- Admin Tasks Page -->
<section class="page" id="page-admin-tasks">
<div class="admin-tasks-layout">
<!-- Quick Tasks Section -->
<div class="card">
<div class="card-header" style="display:flex;justify-content:space-between;align-items:center;">
<h3>Quick Tasks</h3>
<button class="btn btn-sm btn-primary" onclick="Portal.showAddQuickTaskModal()">+ Add Quick Task</button>
</div>
<div class="card-body">
<p style="color:#666;margin-bottom:16px;">Create common tasks instantly with one tap.</p>
<div class="quick-tasks-grid" id="quickTasksGrid">
<div class="empty-state">Loading...</div>
</div>
<div id="quickTasksManageList" style="margin-top:24px;"></div>
</div>
</div>
<!-- Scheduled Tasks Section -->
<div class="card">
<div class="card-header" style="display:flex;justify-content:space-between;align-items:center;">
<h3>Scheduled Tasks</h3>
<button class="btn btn-sm btn-primary" onclick="Portal.showAddScheduledTaskModal()">+ Add Scheduled Task</button>
</div>
<div class="card-body">
<p style="color:#666;margin-bottom:16px;">Define recurring tasks that automatically create entries in the Tasks system.</p>
<div class="list-group" id="scheduledTasksList">
<div class="empty-state">Loading...</div>
</div>
</div>
</div>
<!-- Worker Ratings Section -->
<div class="card">
<div class="card-header" style="display:flex;justify-content:space-between;align-items:center;">
<h3>Worker Ratings</h3>
<button class="btn btn-sm btn-secondary" onclick="Portal.loadPendingRatings()">Refresh</button>
</div>
<div class="card-body">
<p style="color:#666;margin-bottom:16px;">Rate worker performance on recently completed tasks. These ratings help track performance over time.</p>
<div class="list-group" id="pendingRatingsList">
<div class="empty-state">Loading...</div>
</div>
</div>
</div>
</div>
</section>
<!-- Settings Page -->
<section class="page" id="page-settings">
<div class="settings-grid">
<div class="card">
<div class="card-header">
<h3>Business Information</h3>
</div>
<div class="card-body">
<form id="businessInfoForm" class="form" onsubmit="Portal.saveBusinessInfo(event)">
<div class="form-group">
<label>Business Name</label>
<input type="text" id="settingBusinessName" class="form-input" required>
</div>
<div class="form-group">
<label>Phone</label>
<input type="tel" id="settingPhone" class="form-input" placeholder="(555) 123-4567">
</div>
<div class="form-group">
<label>Sales Tax Rate (%)</label>
<input type="number" id="settingTaxRate" class="form-input" placeholder="8.25" step="0.01" min="0" max="25">
<small style="color:#666;font-size:12px;">Enter as percentage (e.g., 8.25 for 8.25%)</small>
</div>
<div class="form-group">
<label>Street Address</label>
<input type="text" id="settingAddressLine1" class="form-input" placeholder="123 Main St">
</div>
<div class="form-row" style="display:grid;grid-template-columns:2fr 1fr 1fr;gap:12px;">
<div class="form-group">
<label>City</label>
<input type="text" id="settingCity" class="form-input" placeholder="Los Angeles">
</div>
<div class="form-group">
<label>State</label>
<select id="settingState" class="form-input">
<option value="">--</option>
</select>
</div>
<div class="form-group">
<label>ZIP</label>
<input type="text" id="settingZip" class="form-input" placeholder="90001" maxlength="10">
</div>
</div>
<button type="submit" class="btn btn-primary" id="saveBusinessBtn">Save Changes</button>
</form>
</div>
</div>
<div class="card">
<div class="card-header" style="display:flex;justify-content:space-between;align-items:center;">
<h3>Business Hours</h3>
<button class="btn btn-sm btn-secondary" onclick="Portal.saveHours()">Save Hours</button>
</div>
<div class="card-body">
<div class="hours-list" id="hoursEditor">
<!-- Hours will be loaded here -->
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<h3>Branding</h3>
</div>
<div class="card-body">
<div style="display: flex; flex-direction: column; gap: 16px;">
<div>
<label style="display: block; margin-bottom: 8px; font-weight: 500;">Header Image</label>
<p style="color: #666; font-size: 13px; margin-bottom: 8px;">Displayed at the top of your menu. Recommended: 1200x400px</p>
<div id="headerPreview" style="width: 100%; height: 120px; background: #fff; border-radius: 8px; margin-bottom: 8px; background-size: cover; background-position: center; background-repeat: no-repeat; border: 1px solid #ddd;"></div>
<button class="btn btn-secondary" onclick="Portal.uploadHeader()" style="width: 100%;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 8px;">
<path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M17 8l-5-5-5 5M12 3v12"/>
</svg>
Upload Header
</button>
</div>
<div>
<label style="display: block; margin-bottom: 8px; font-weight: 500;">Brand Colors</label>
<p style="color: #666; font-size: 13px; margin-bottom: 8px;">Dark for accents/gradients, Light for card tinting</p>
<div style="display: flex; gap: 12px; align-items: center;">
<div style="display: flex; gap: 6px; align-items: center;">
<span id="brandColorSwatch" style="width: 40px; height: 40px; border-radius: 8px; background: #1B4D3E; border: 2px solid rgba(255,255,255,0.2); cursor: pointer;" onclick="Portal.showBrandColorPicker()" title="Dark"></span>
<span id="brandColorLightSwatch" style="width: 40px; height: 40px; border-radius: 8px; background: #fff; border: 2px solid rgba(255,255,255,0.2); cursor: pointer;" onclick="Portal.showBrandColorPicker()" title="Light"></span>
</div>
<button class="btn btn-secondary" onclick="Portal.showBrandColorPicker()" style="flex: 1;">
Change Colors
</button>
</div>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<h3>Payment Settings</h3>
</div>
<div class="card-body">
<div class="stripe-status" id="stripeStatus">
<div class="status-icon disconnected">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="10"/>
<path d="M15 9l-6 6M9 9l6 6"/>
</svg>
</div>
<div class="status-text">
<strong>Stripe Not Connected</strong>
<p>Connect your Stripe account to accept payments</p>
</div>
<button class="btn btn-primary" onclick="Portal.connectStripe()">
Connect Stripe
</button>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<h3>Tabs / Running Checks</h3>
</div>
<div class="card-body">
<p style="color: #666; font-size: 13px; margin-bottom: 16px;">Allow customers to open a tab, authorize their card, and order multiple rounds before closing out with a single charge.</p>
<div class="form-group" style="display: flex; align-items: center; gap: 12px; margin-bottom: 16px;">
<label class="toggle">
<input type="checkbox" id="tabsEnabled" onchange="Portal.saveTabSettings()">
<span class="toggle-slider"></span>
</label>
<span>Enable Tabs</span>
</div>
<div id="tabSettingsDetails" style="display: none;">
<div class="form-group">
<label>Tab Lock Duration (minutes)</label>
<input type="number" id="tabLockMinutes" class="form-input" value="30" min="5" max="480" style="width: 120px;">
<small style="color:#666;font-size:12px;display:block;margin-top:4px;">How long a tab stays open without activity before auto-closing</small>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px; margin-top: 12px;">
<div class="form-group">
<label>Min Auth Amount ($)</label>
<input type="number" id="tabMinAuthAmount" class="form-input" value="50" min="10" max="10000" step="10">
</div>
<div class="form-group">
<label>Default Auth Amount ($)</label>
<input type="number" id="tabDefaultAuthAmount" class="form-input" value="150" min="10" max="10000" step="10">
</div>
<div class="form-group">
<label>Max Auth Amount ($)</label>
<input type="number" id="tabMaxAuthAmount" class="form-input" value="1000" min="10" max="10000" step="10">
</div>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 12px;">
<div class="form-group">
<label>Max Members Per Tab</label>
<input type="number" id="tabMaxMembers" class="form-input" value="10" min="1" max="50">
</div>
<div class="form-group">
<label>Auto-Increase Threshold</label>
<input type="number" id="tabAutoIncreaseThreshold" class="form-input" value="0.80" min="0.5" max="1.0" step="0.05">
<small style="color:#666;font-size:12px;display:block;margin-top:4px;">Suggest auth increase when this % of limit is reached</small>
</div>
</div>
<div class="form-group" style="display: flex; align-items: center; gap: 12px; margin-top: 12px;">
<label class="toggle">
<input type="checkbox" id="tabApprovalRequired">
<span class="toggle-slider"></span>
</label>
<span>Require owner approval for member orders</span>
</div>
<button class="btn btn-primary" onclick="Portal.saveTabSettings()" style="margin-top: 16px;">Save Tab Settings</button>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<h3>Customer Preview</h3>
</div>
<div class="card-body">
<p style="color: #666; font-size: 13px; margin-bottom: 12px;">See how your business looks in the Payfrit app. Open this link on your phone to preview your menu as a customer would see it.</p>
<a id="previewAppLink" href="#" onclick="Portal.openCustomerPreview(); return false;" class="btn btn-primary" style="display: inline-flex; align-items: center; gap: 8px; width: 100%; justify-content: center;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M15 3h4a2 2 0 012 2v14a2 2 0 01-2 2h-4M10 17l5-5-5-5M13 12H3"/>
</svg>
Open in Payfrit App
</a>
</div>
</div>
</div>
</section>
</div>
</main>
</div>
<!-- Modal Container -->
<div class="modal-overlay" id="modalOverlay">
<div class="modal" id="modal">
<div class="modal-header">
<h3 id="modalTitle">Modal</h3>
<button class="modal-close" onclick="Portal.closeModal()">&times;</button>
</div>
<div class="modal-body" id="modalBody">
<!-- Modal content loaded dynamically -->
</div>
</div>
</div>
<!-- Toast Container -->
<div class="toast-container" id="toastContainer"></div>
<script src="portal.js?v=13"></script>
<!-- Close dropdown when clicking outside -->
<script>
document.addEventListener('click', function(e) {
const dropdown = document.getElementById('userDropdown');
const userBtn = document.getElementById('userBtn');
if (dropdown && !dropdown.contains(e.target) && !userBtn.contains(e.target)) {
dropdown.classList.remove('show');
dropdown.style.display = 'none';
}
});
// Toggle show/hide
const origBtn = document.getElementById('userBtn');
if (origBtn) {
origBtn.addEventListener('click', function(e) {
e.stopPropagation();
const dd = document.getElementById('userDropdown');
if (dd.style.display === 'none' || dd.style.display === '') {
dd.style.display = 'block';
} else {
dd.style.display = 'none';
}
});
}
</script>
</body>
</html>