- Add Quick Task Templates: admin creates task shortcuts, tap to create tasks instantly - Add Scheduled Tasks: admin defines recurring tasks with cron expressions - New API endpoints: /api/admin/quickTasks/* and /api/admin/scheduledTasks/* - New database tables: QuickTaskTemplates, ScheduledTaskDefinitions - Portal UI: Task Admin page with shortcut buttons and scheduled task management Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
595 lines
26 KiB
HTML
595 lines
26 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">
|
|
</head>
|
|
<body>
|
|
<div class="app">
|
|
<!-- Sidebar -->
|
|
<aside class="sidebar" id="sidebar">
|
|
<div class="sidebar-header">
|
|
<div class="logo">
|
|
<span class="logo-icon">P</span>
|
|
<span class="logo-text">Payfrit</span>
|
|
</div>
|
|
<button class="sidebar-toggle" id="sidebarToggle">
|
|
<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="#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="#beacons" class="nav-item" data-page="beacons">
|
|
<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>Beacons</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="#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>
|
|
|
|
<div class="sidebar-footer">
|
|
<div class="business-info">
|
|
<div class="business-avatar" id="businessAvatar">B</div>
|
|
<div class="business-details">
|
|
<div class="business-name" id="businessName">Loading...</div>
|
|
<div class="business-status online">Online</div>
|
|
</div>
|
|
</div>
|
|
<a href="#logout" class="nav-item logout" data-page="logout">
|
|
<svg class="nav-icon" width="20" height="20" 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>
|
|
<span>Logout</span>
|
|
</a>
|
|
</div>
|
|
</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">
|
|
<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">
|
|
<button class="user-btn" id="userBtn">
|
|
<span class="user-avatar" id="userAvatar">U</span>
|
|
</button>
|
|
</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.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>Status</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="teamTableBody">
|
|
<tr><td colspan="5" class="empty-state">Loading team...</td></tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Beacons Page -->
|
|
<section class="page" id="page-beacons">
|
|
<div class="beacons-layout">
|
|
<!-- Left side: 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>
|
|
|
|
<!-- Middle: 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>
|
|
|
|
<!-- Right side: 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>
|
|
</div>
|
|
</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 Task Templates 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 Template</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>
|
|
</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: #333; border-radius: 8px; margin-bottom: 8px; background-size: contain; background-position: center; background-repeat: no-repeat;"></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 Color</label>
|
|
<p style="color: #666; font-size: 13px; margin-bottom: 8px;">Used for accents and fallback backgrounds</p>
|
|
<div style="display: flex; gap: 12px; 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()"></span>
|
|
<button class="btn btn-secondary" onclick="Portal.showBrandColorPicker()" style="flex: 1;">
|
|
Change Color
|
|
</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>
|
|
</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()">×</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=6"></script>
|
|
</body>
|
|
</html>
|