<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Artist Backoffice OS & Voice Portal</title>
<style>
:root {
--bg-dark: #0d0d0d;
--panel-bg: #141414;
--accent-gold: #d4af37;
--text-white: #ffffff;
--text-gray: #a3a3a3;
--border-dark: #262626;
--state-recording: #ea4335;
}
.bb-dashboard-container {
background-color: var(--bg-dark);
color: var(--text-white);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
max-width: 900px;
margin: 30px auto;
padding: 24px;
border-radius: 12px;
border: 1px solid var(--border-dark);
}
/* Top Layout Bar */
.bb-dash-header {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid var(--border-dark);
padding-bottom: 20px;
margin-bottom: 24px;
}
.bb-dash-header h2 {
margin: 0;
font-size: 1.5rem;
letter-spacing: -0.5px;
}
.bb-pro-badge {
background-color: #1a1a1a;
border: 1px solid var(--accent-gold);
color: var(--accent-gold);
padding: 6px 12px;
border-radius: 20px;
font-size: 0.85rem;
font-weight: 600;
text-transform: uppercase;
}
/* Split-Screen Workspace Grid */
.bb-dash-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
}
@media (max-width: 768px) {
.bb-dash-grid {
grid-template-columns: 1fr;
}
}
.bb-panel {
background-color: var(--panel-bg);
border: 1px solid var(--border-dark);
border-radius: 8px;
padding: 20px;
}
.bb-panel h4 {
margin-top: 0;
margin-bottom: 16px;
font-size: 1.1rem;
border-bottom: 1px solid var(--border-dark);
padding-bottom: 8px;
color: var(--accent-gold);
}
/* Proprietary Voice Controller Interface */
.bb-voice-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40px 20px;
text-align: center;
}
.bb-mic-button {
width: 90px;
height: 90px;
border-radius: 50%;
background-color: #1a1a1a;
border: 2px solid var(--border-dark);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20px;
transition: all 0.3s ease;
box-shadow: 0 0 0 0 rgba(212, 175, 55, 0.4);
}
.bb-mic-button:hover {
border-color: var(--accent-gold);
transform: scale(1.03);
}
.bb-mic-button svg {
width: 36px;
height: 36px;
fill: var(--text-gray);
transition: fill 0.2s ease;
}
/* Dynamic Recording State Modifiers */
.bb-mic-button.recording {
background-color: var(--state-recording);
border-color: var(--state-recording);
animation: bb-pulse 1.5s infinite;
}
.bb-mic-button.recording svg {
fill: var(--text-white);
}
@keyframes bb-pulse {
0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(234, 67, 53, 0.5); }
70% { transform: scale(1.05); box-shadow: 0 0 0 15px rgba(234, 67, 53, 0); }
100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(234, 67, 53, 0); }
}
.bb-voice-status {
font-size: 1rem;
font-weight: 500;
color: var(--text-gray);
margin-bottom: 4px;
}
.bb-voice-subtext {
font-size: 0.85rem;
color: #666666;
}
/* Queue / Appointment Listing Card Templates */
.bb-appt-card {
background-color: #1a1a1a;
border: 1px solid var(--border-dark);
border-radius: 6px;
padding: 14px;
margin-bottom: 12px;
position: relative;
}
.bb-appt-card.active-now {
border-left: 3px solid var(--accent-gold);
}
.bb-appt-time {
font-size: 0.8rem;
color: var(--accent-gold);
font-weight: 600;
text-transform: uppercase;
}
.bb-appt-name {
font-size: 1.05rem;
font-weight: 600;
margin: 4px 0;
}
.bb-appt-details {
font-size: 0.85rem;
color: var(--text-gray);
}
.bb-live-indicator {
position: absolute;
top: 14px;
right: 14px;
font-size: 0.75rem;
background-color: rgba(212, 175, 55, 0.15);
color: var(--accent-gold);
padding: 2px 8px;
border-radius: 4px;
font-weight: 600;
text-transform: uppercase;
}
</style>
</head>
<body>
<div class="bb-dashboard-container">
<!-- Dashboard Control Bar Layout -->
<div class="bb-dash-header">
<div>
<h2>Beauty Business OS Dashboard</h2>
<p style="color: var(--text-gray); font-size: 0.9rem; margin: 4px 0 0 0;">Studio Session Control & AI Engine Room</p>
</div>
<div class="bb-pro-badge" id="bb-pro-tag">Artist Console #001</div>
</div>
<div class="bb-dash-grid">
<!-- LEFT COLUMN PANEL: THE LIVE CHAIR CONTEXT -->
<div class="bb-panel">
<h4>Active Schedule Queue</h4>
<!-- Simulated Live Contextual Appointment Mapping Block -->
<div class="bb-appt-card active-now">
<span class="bb-live-indicator">Active in Chair</span>
<div class="bb-appt-time">11:00 AM — 12:30 PM</div>
<div class="bb-appt-name">Jessica Miller (Maid of Honor)</div>
<div class="bb-appt-details">Service: Full Bridal Event Glam Portfolio</div>
</div>
<div class="bb-appt-card">
<div class="bb-appt-time">01:00 PM — 01:45 PM</div>
<div class="bb-appt-name">Sarah Jenkins (The Bride)</div>
<div class="bb-appt-details">Service: Master Bridal Consultation Sequence</div>
</div>
</div>
<!-- RIGHT COLUMN PANEL: THE HANDS-FREE VOICE RECORDER CONTROLLER -->
<div class="bb-panel" style="display: flex; align-items: center; justify-content: center;">
<div class="bb-voice-container">
<button class="bb-mic-button" id="bb-mic-trigger" onclick="toggleVoiceSession()">
<!-- Modern Microphone Icon Vector Graphic -->
<svg viewBox="0 0 24 24">
<path d="M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z"/>
</svg>
</button>
<div class="bb-voice-status" id="bb-voice-status-text">System Standby</div>
<div class="bb-voice-subtext" id="bb-voice-subtext-text">Tap mic container to capture technical formula logs mid-service.</div>
</div>
</div>
</div>
</div>
<script>
// GLOBAL CONFIGURATION MATRIX: Map to your personal instances
const CONFIG_PRO_ID = 1;
const CONFIG_XANO_API_ENDPOINT = "https://YOUR_XANO_BASE_URL/api:v1/voice-entry";
let mediaRecorder;
let audioChunks = [];
let isRecording = false;
async function toggleVoiceSession() {
const micBtn = document.getElementById('bb-mic-trigger');
const statusTxt = document.getElementById('bb-voice-status-text');
const subTxt = document.getElementById('bb-voice-subtext-text');
if (!isRecording) {
// Initialize clean web audio binary hardware streaming pipeline natively
audioChunks = [];
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm' });
mediaRecorder.ondataavailable = event => {
audioChunks.push(event.data);
};
mediaRecorder.onstop = async () => {
statusTxt.innerText = "Processing Data...";
subTxt.innerText = "Streaming secure audio matrix payloads cleanly to Xano...";
const audioBlob = new Blob(audioChunks, { type: 'audio/webm' });
const formData = new FormData();
formData.append('pro_id', CONFIG_PRO_ID);
formData.append('audio_file', audioBlob, 'dictation.webm');
// Execute standard direct decoupled fetch call straight to your server container
try {
const response = await fetch(CONFIG_XANO_API_ENDPOINT, {
method: 'POST',
body: formData
});
if (response.ok) {
statusTxt.innerText = "Vault Updated Successfully";
subTxt.innerText = "OpenAI Whisper and GPT-4o successfully saved formula maps directly to the client file.";
} else {
statusTxt.innerText = "Server Error Encounted";
subTxt.innerText = "Check your Xano execution debugger log channels.";
}
} catch (err) {
statusTxt.innerText = "Connection Failure Route";
subTxt.innerText = "Unable to connect to Xano endpoint. Retrying cache...";
}
setTimeout(() => {
if(!isRecording) {
statusTxt.innerText = "System Standby";
subTxt.innerText = "Tap mic container to capture technical formula logs mid-service.";
}
}, 5000);
};
mediaRecorder.start();
isRecording = true;
micBtn.classList.add('recording');
statusTxt.innerText = "Listening Live...";
statusTxt.style.color = "#ea4335";
subTxt.innerText = "Dictate look formulas naturally now. Tap icon box again to close and parse.";
} catch (err) {
alert("Microphone connection access denied or hardware channel absent.");
console.error(err);
}
} else {
// Engage execution finalization step loop parameters
mediaRecorder.stop();
isRecording = false;
micBtn.classList.remove('recording');
statusTxt.style.color = "var(--text-white)";
}
}
</script>
</body>
</html>