FocusFlow / frontend /index.html
immortalindeed's picture
UI Refinement: Center video overlay, unify meeting metrics, and fix dashboard navigation
bb444b3
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FocusFlow | Real-Time Meeting Analytics</title>
<link rel="stylesheet" href="/static/style.css?v=1.3">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Playfair+Display:ital,wght@0,400;0,700;1,400&display=swap" rel="stylesheet">
<script src="https://unpkg.com/lucide@latest"></script>
</head>
<body>
<div class="ambient-glow top-right"></div>
<div class="ambient-glow bottom-left"></div>
<div class="app-container">
<!-- Sidebar -->
<aside class="sidebar">
<div class="logo">
<div class="logo-icon"><i data-lucide="target" style="width:28px; height:28px; stroke-width: 2;"></i></div>
<h1 >FocusFlow</h1>
</div>
<nav class="nav-menu">
<button class="nav-btn active" id="btn-dashboard">
<span class="icon"><i data-lucide="layout-dashboard"></i></span> Dashboard
</button>
<button class="nav-btn" id="btn-live">
<span class="icon"><i data-lucide="video"></i></span> Live Analysis
</button>
<button class="nav-btn" id="btn-meeting">
<span class="icon"><i data-lucide="users"></i></span> Meeting Intel
</button>
<button class="nav-btn" id="btn-history">
<span class="icon"><i data-lucide="history"></i></span> History
</button>
</nav>
<div class="tech-stack glass-panel">
<h3>TECH STACK</h3>
<ul>
<li><span class="icon"><i data-lucide="server" style="width:16px;height:16px;"></i></span> FastAPI Backend</li>
<li><span class="icon"><i data-lucide="eye" style="width:16px;height:16px;"></i></span> MediaPipe Vision</li>
<li><span class="icon"><i data-lucide="zap" style="width:16px;height:16px;"></i></span> C++ / PyBind11</li>
<li><span class="icon"><i data-lucide="database" style="width:16px;height:16px;"></i></span> SQLite Storage</li>
</ul>
</div>
</aside>
<!-- Main Content -->
<main class="main-content">
<!-- Header -->
<header class="top-header">
<div class="header-titles">
<h2 id="page-title">Live Analysis</h2>
<p id="page-subtitle">Real-Time Engagement Tracking</p>
</div>
<div class="session-controls">
<div id="status-indicator" class="status-indicator">
<div class="dot red"></div> <span id="recording-time">00:00</span>
</div>
<button class="btn btn-primary" id="btn-start"><i data-lucide="play" style="width: 16px; height: 16px;"></i> Start Session</button>
<button class="btn btn-danger hidden" id="btn-stop"><i data-lucide="square" style="width: 16px; height: 16px;"></i> Stop Session</button>
</div>
</header>
<!-- Dashboard View -->
<section id="view-dashboard" class="view hidden">
<div class="welcome-box glass-panel">
<h2>Welcome to FocusFlow</h2>
<p>FocusFlow is a real-time meeting analytics tool that tracks visual engagement during video calls. It uses advanced computer vision and C++ extensions to compute your focus score dynamically.</p>
</div>
<div class="dashboard-grid">
<div class="stat-card glass-panel highlight">
<span class="icon"><i data-lucide="check-circle"></i></span>
<div class="value" id="dash-total-sessions">0</div>
<div class="label">Total Sessions</div>
</div>
<div class="stat-card glass-panel highlight">
<span class="icon"><i data-lucide="trending-up"></i></span>
<div class="value" id="dash-avg-focus">0%</div>
<div class="label">Avg. Focus</div>
</div>
<div class="stat-card glass-panel highlight">
<span class="icon"><i data-lucide="clock"></i></span>
<div class="value" id="dash-focus-time">0m</div>
<div class="label">Focus Time</div>
</div>
</div>
<div class="quick-actions" style="display: flex; justify-content: center; margin-top: 24px;">
<button class="btn btn-primary" onclick="document.getElementById('btn-live').click()">Start New Session</button>
<button class="btn btn-secondary" onclick="document.getElementById('btn-meeting').click()" style="margin-left: 12px;">Meeting Intelligence</button>
</div>
</section>
<!-- Live Analysis View -->
<section id="view-live" class="view active">
<div class="grid-layout">
<!-- Video Section -->
<div class="video-section">
<div class="video-container glass-panel">
<video id="webcam" autoplay playsinline muted></video>
<canvas id="overlay"></canvas>
<div id="video-overlay" class="video-overlay">
<div class="icon"><i data-lucide="camera-off" style="width:40px;height:40px;stroke-width:1.5;"></i></div>
<p>Click Start Session to begin analyzing</p>
</div>
</div>
<!-- Alerts -->
<div id="alert-banner" class="alert-banner hidden">
⚠️ WAKE UP ALERT
</div>
</div>
<!-- Metrics Section -->
<div class="metrics-section">
<!-- Hero Score -->
<div class="hero-score-card glass-panel">
<h3 class="label">Engagement Score</h3>
<div class="score-value" id="engagement-score">--</div>
<div class="progress-bar">
<div class="progress-fill" id="engagement-bar" style="width: 0%"></div>
</div>
<p class="status-text" id="status-text">FOCUSED</p>
</div>
<!-- Quick Stats Grid -->
<div class="stats-grid mt-20">
<div class="stat-card glass-panel">
<span class="icon"><i data-lucide="activity"></i></span>
<div class="value" id="yawn-count">0</div>
<div class="label">Yawns</div>
</div>
<div class="stat-card glass-panel">
<span class="icon"><i data-lucide="moon"></i></span>
<div class="value" id="drowsy-count">0</div>
<div class="label">Sleep Events</div>
</div>
<div class="stat-card glass-panel">
<span class="icon"><i data-lucide="zap"></i></span>
<div class="value" id="ear-value">0.00</div>
<div class="label">EAR</div>
</div>
<div class="stat-card glass-panel">
<span class="icon" id="emotion-icon"><i data-lucide="smile"></i></span>
<div class="value emotion" id="emotion-label">Neutral</div>
<div class="label">Emotion</div>
</div>
</div>
<!-- Deep Metrics -->
<div class="deep-metrics glass-panel mt-20">
<h3>Face Analytics</h3>
<div class="metrics-list">
<div class="metric-item">
<span class="label">Gaze Score</span>
<span class="value" id="gaze-score">--%</span>
</div>
<div class="metric-item">
<span class="label">Head Stability</span>
<span class="value" id="stability-score">--%</span>
</div>
<div class="metric-item">
<span class="label">Face Quality</span>
<span class="value" id="quality-score">--%</span>
</div>
<div class="metric-item">
<span class="label">Attention</span>
<span class="value" id="attention-score">--%</span>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Meeting View -->
<section id="view-meeting" class="view hidden">
<div class="grid-layout">
<div class="video-section">
<div id="meeting-setup" class="welcome-box glass-panel">
<h3><i data-lucide="users" style="vertical-align: middle; margin-right: 8px;"></i> Meeting Intelligence</h3>
<p>Track aggregate engagement for professional meetings. This mode is optimized for multiple participants and provides group dynamics analysis.</p>
<div class="mt-20">
<label style="font-size: 14px; color: var(--text-muted);">Meeting Title</label>
<input type="text" id="meeting-title" placeholder="Project Sync..." style="width: 100%; padding: 12px; margin-top: 8px; border: 1px solid var(--border); border-radius: 8px; background: white; font-family: inherit;">
</div>
<div class="mt-20" style="display: flex; gap: 10px;">
<button class="btn btn-primary" id="btn-start-meeting">Start with Camera</button>
<button class="btn btn-secondary" id="btn-share-screen"><i data-lucide="monitor" style="width: 16px; height: 16px; vertical-align: middle; margin-right: 4px;"></i> Share Screen</button>
</div>
</div>
<!-- Video container for active meeting -->
<div id="meeting-active-video" class="video-container glass-panel hidden" style="height: 400px; position:relative;">
<video id="meeting-video" autoplay playsinline muted style="width: 100%; height: 100%; object-fit: cover; border-radius: 12px;"></video>
<div class="video-overlay" id="meeting-video-label" style="background: rgba(0,0,0,0.4); color: white; position: absolute; bottom: 10px; left: 10px; padding: 5px 10px; border-radius: 4px; font-size: 12px;">Active Meeting Feed</div>
</div>
</div>
<div class="metrics-section">
<div class="hero-score-card glass-panel">
<h3 class="label">Group Engagement</h3>
<div class="score-value" id="meeting-avg-score">--</div>
<div class="progress-bar">
<div class="progress-fill" id="meeting-engagement-bar" style="width: 0%"></div>
</div>
</div>
<!-- Same stats grid as Live view -->
<div class="stats-grid mt-20">
<div class="stat-card glass-panel">
<span class="icon"><i data-lucide="user-check"></i></span>
<div class="value" id="participant-count">0</div>
<div class="label">Participants</div>
</div>
<div class="stat-card glass-panel">
<span class="icon"><i data-lucide="alert-circle"></i></span>
<div class="value" id="meeting-warnings">0</div>
<div class="label">Distractions</div>
</div>
<div class="stat-card glass-panel">
<span class="icon"><i data-lucide="activity"></i></span>
<div class="value" id="meeting-yawn-count">0</div>
<div class="label">Yawns</div>
</div>
<div class="stat-card glass-panel">
<span class="icon"><i data-lucide="moon"></i></span>
<div class="value" id="meeting-drowsy-count">0</div>
<div class="label">Sleep</div>
</div>
</div>
<!-- Same deep metrics as Live view -->
<div class="deep-metrics glass-panel mt-20">
<h3>Meeting Analytics</h3>
<div class="metrics-list">
<div class="metric-item">
<span class="label">Group Gaze</span>
<span class="value" id="meeting-gaze-score">--%</span>
</div>
<div class="metric-item">
<span class="label">Avg Attention</span>
<span class="value" id="meeting-attention-score">--%</span>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- History View -->
<section id="view-history" class="view hidden">
<div class="history-container glass-panel">
<div class="history-header" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
<h2>Recent Sessions</h2>
<div class="tabs" style="display: flex; gap: 10px;">
<button class="btn btn-sm active" id="tab-individual">Individual</button>
<button class="btn btn-sm" id="tab-meetings">Meetings</button>
</div>
</div>
<div id="history-list" class="history-list">
<!-- Sessions inserted dynamically -->
<div class="text-center" style="padding: 40px; color: var(--text-muted)">
Loading sessions...
</div>
</div>
</div>
</section>
</main>
</div>
<script src="/static/script.js"></script>
</body>
</html>