UNPKG

voice-ai-workforce

Version:

Voice AI assistant for workforce management - hands-free task updates, time tracking, and team communication. Built by VenueBoost Inc.

1,029 lines (910 loc) 29.5 kB
# Examples ## Quick Start Examples ### Basic Voice Button by Mode #### End-User Mode (Customers, Employees) ```tsx import React from 'react'; import { VoiceButton } from '@voice-ai-workforce/react'; import { SpeechProvider, AIProvider, ResponseMode } from '@voice-ai-workforce/types'; const customerConfig = { speechToText: { provider: SpeechProvider.WEB_SPEECH }, textToSpeech: { provider: SpeechProvider.WEB_SPEECH }, aiProvider: { provider: AIProvider.OPENAI }, responseMode: ResponseMode.BOTH, interfaceMode: 'end-user' as const, }; function CustomerApp() { return ( <div> <h1>Welcome to Staffluent</h1> <VoiceButton config={customerConfig} customLabels={{ voiceButton: { startText: 'Ask Question', stopText: 'Stop', processingText: 'Thinking...' } }} onCommand={(command) => { // Command is filtered - only contains: intent, rawText, timestamp console.log('Customer said:', command.rawText); }} onError={(error) => { // Error message is user-friendly console.log('Simple error:', error.message); // "Voice assistant unavailable" }} /> {/* User sees: - "Ask Question" button (not "Start Listening") - No provider information - No confidence scores - No debug information - Friendly error messages */} </div> ); } ``` #### Project Mode (Business Administrators) ```tsx import React, { useState } from 'react'; import { VoiceButton, VoiceCommandCenter } from '@voice-ai-workforce/react'; const adminConfig = { speechToText: { provider: SpeechProvider.WEB_SPEECH }, textToSpeech: { provider: SpeechProvider.WEB_SPEECH }, aiProvider: { provider: AIProvider.OPENAI }, responseMode: ResponseMode.BOTH, interfaceMode: 'project' as const, }; function AdminDashboard() { const [centerOpen, setCenterOpen] = useState(false); return ( <div> <h1>Staffluent Admin Dashboard</h1> <VoiceButton config={adminConfig} showMiniCenter={true} onCommand={(command) => { // Command includes confidence scores and some debug info console.log('Admin command:', { intent: command.intent, confidence: command.confidence, // Available in project mode provider: command.provider // Available in project mode }); }} /> <button onClick={() => setCenterOpen(true)}> Open Voice Settings </button> <VoiceCommandCenter config={adminConfig} isOpen={centerOpen} onClose={() => setCenterOpen(false)} showCategories={true} showHistory={true} /> {/* Admin sees: - Provider information (OpenAI status) - Confidence scores - Command center with settings - Some analytics - Technical but not overwhelming */} </div> ); } ``` #### Developer Mode (Full Debug) ```tsx import React, { useState } from 'react'; import { VoiceButton, VoiceCommandCenter } from '@voice-ai-workforce/react'; const devConfig = { speechToText: { provider: SpeechProvider.WEB_SPEECH }, textToSpeech: { provider: SpeechProvider.WEB_SPEECH }, aiProvider: { provider: AIProvider.OPENAI }, responseMode: ResponseMode.BOTH, interfaceMode: 'developer' as const, visibility: { showDebugInfo: true, showProcessingTimes: true, showTechnicalErrors: true, } }; function DeveloperConsole() { const [centerOpen, setCenterOpen] = useState(true); return ( <div> <h1>Voice AI Development Console</h1> <VoiceButton config={devConfig} showMiniCenter={true} onCommand={(command) => { // Full command object with all debug information console.log('Full debug command:', { intent: command.intent, entities: command.entities, // Full entity extraction confidence: command.confidence, // Exact confidence score provider: command.provider, // Which AI provider responded rawText: command.rawText, timestamp: command.timestamp, processingTime: '245ms' // Processing time visible }); }} onResponse={(response) => { // Full response with metadata console.log('Full debug response:', { text: response.text, success: response.success, metadata: response.metadata // All technical details }); }} onError={(error) => { // Full technical error with stack trace console.error('Technical error:', error.details); }} /> <VoiceCommandCenter config={devConfig} isOpen={centerOpen} onClose={() => setCenterOpen(false)} width={400} showCategories={true} showHistory={true} /> {/* Developer sees: - Full provider status and switching - All confidence scores and processing times - Complete command history with metadata - Analytics and export options - Full error messages with stack traces - All debugging information */} </div> ); } ``` ## Real-World Use Cases ### Use Case 1: Staffluent Employee Mobile App ```tsx // Employee clocking in/out with simple voice interface import { VoiceButton } from '@voice-ai-workforce/react'; function EmployeeClockInApp() { const employeeConfig = { speechToText: { provider: SpeechProvider.WEB_SPEECH }, textToSpeech: { provider: SpeechProvider.WEB_SPEECH }, aiProvider: { provider: AIProvider.OPENAI }, responseMode: ResponseMode.BOTH, interfaceMode: 'end-user' as const, }; return ( <div className="mobile-app"> <header> <h1>Staffluent</h1> <div className="user-info">John Doe - Site Supervisor</div> </header> <main> <div className="clock-section"> <VoiceButton config={employeeConfig} size="xl" customLabels={{ voiceButton: { startText: 'Tap to Speak', stopText: 'Listening...', processingText: 'Processing...' } }} onCommand={(command) => { // Handle work commands if (command.intent === 'clock_in') { // Process clock in showNotification('Clocked in successfully'); } }} /> </div> <div className="quick-actions"> <p>Try saying:</p> <ul> <li>"Clock me in"</li> <li>"Start my break"</li> <li>"Report an issue"</li> <li>"Complete task"</li> </ul> </div> </main> {/* Employee experience: - Large, easy-to-tap voice button - Simple, clear feedback - No technical jargon - Works reliably without overwhelming options */} </div> ); } ``` ### Use Case 2: Business Admin Configuration Panel ```tsx // Business admins configuring voice AI features import { VoiceCommandCenter, VoiceButton } from '@voice-ai-workforce/react'; function AdminVoiceConfiguration() { const [settings, setSettings] = useState({ enableVoice: true, voiceMode: 'project' as const, customCommands: [] }); const adminConfig = { speechToText: { provider: SpeechProvider.WEB_SPEECH }, textToSpeech: { provider: SpeechProvider.WEB_SPEECH }, aiProvider: { provider: AIProvider.OPENAI }, responseMode: ResponseMode.BOTH, interfaceMode: settings.voiceMode, }; return ( <div className="admin-panel"> <h1>Voice AI Configuration</h1> <div className="config-section"> <h2>Voice Interface Mode</h2> <select value={settings.voiceMode} onChange={(e) => setSettings({ ...settings, voiceMode: e.target.value as any })} > <option value="end-user">End User (Simple)</option> <option value="project">Project (Balanced)</option> <option value="developer">Developer (Full Debug)</option> </select> </div> <div className="preview-section"> <h2>Preview</h2> <VoiceButton config={adminConfig} showMiniCenter={true} onCommand={(command) => { console.log('Preview command:', command); }} /> </div> <div className="analytics-section"> <h2>Voice Usage Analytics</h2> <VoiceCommandCenter config={{ ...adminConfig, interfaceMode: 'project' // Always show project mode for analytics }} isOpen={true} position="right" width={350} /> </div> {/* Admin experience: - Can switch between modes to see differences - Preview how employees will see the interface - Access to analytics and configuration - Balance between simplicity and control */} </div> ); } ``` ### Use Case 3: Customer Support Portal ```tsx // Customers getting help with minimal friction import { VoiceButton } from '@voice-ai-workforce/react'; function CustomerSupportPortal() { const supportConfig = { speechToText: { provider: SpeechProvider.WEB_SPEECH }, textToSpeech: { provider: SpeechProvider.WEB_SPEECH }, aiProvider: { provider: AIProvider.OPENAI }, responseMode: ResponseMode.BOTH, interfaceMode: 'end-user' as const, visibility: { useGenericLabels: true, showProviders: false, showDebugInfo: false, } }; const [conversation, setConversation] = useState([]); return ( <div className="support-portal"> <header> <h1>Need Help?</h1> <p>Ask questions about your service or report issues</p> </header> <div className="conversation"> {conversation.map((message, i) => ( <div key={i} className={`message ${message.type}`}> {message.text} </div> ))} </div> <div className="voice-input"> <VoiceButton config={supportConfig} size="lg" customLabels={{ voiceButton: { startText: 'Ask for Help', stopText: 'Listening...', processingText: 'Understanding...' }, errors: { generic: 'Having trouble hearing you. Please try again.', permission: 'Please allow microphone access to use voice.', connection: 'Check your internet connection.' } }} onCommand={(command) => { // Add user message to conversation setConversation(prev => [...prev, { type: 'user', text: command.rawText // Only rawText available in end-user mode }]); }} onResponse={(response) => { // Add AI response to conversation setConversation(prev => [...prev, { type: 'assistant', text: response.text }]); }} onError={(error) => { // User-friendly error handling setConversation(prev => [...prev, { type: 'error', text: error.message // Friendly message, no technical details }]); }} /> <p className="help-text"> Tap the button and say things like: <br /> "I need help with my account" <br /> "How do I change my schedule?" <br /> "Report a problem with the app" </p> </div> {/* Customer experience: - Clear, helpful interface - No technical distractions - Friendly error messages - Focus on getting help quickly */} </div> ); } ``` ## Mode Comparison Examples ### Visual Interface Differences ```tsx // Component showing all three modes side by side function ModeComparison() { const baseConfig = { speechToText: { provider: SpeechProvider.WEB_SPEECH }, textToSpeech: { provider: SpeechProvider.WEB_SPEECH }, aiProvider: { provider: AIProvider.OPENAI }, responseMode: ResponseMode.BOTH, }; return ( <div className="mode-comparison"> <div className="mode-column"> <h3>End-User Mode</h3> <div className="mode-demo"> <VoiceButton config={{ ...baseConfig, interfaceMode: 'end-user' }} customLabels={{ voiceButton: { startText: 'Ask Question' } }} /> <div className="mode-info"> <p>✅ Simple "Ask Question" button</p> <p>❌ No provider information</p> <p>❌ No confidence scores</p> <p>❌ No debug information</p> <p>✅ Friendly error messages</p> </div> </div> </div> <div className="mode-column"> <h3>Project Mode</h3> <div className="mode-demo"> <VoiceButton config={{ ...baseConfig, interfaceMode: 'project' }} showMiniCenter={true} /> <div className="mode-info"> <p>✅ "Start Listening" button</p> <p>✅ Provider status (OpenAI)</p> <p>✅ Confidence scores</p> <p>⚠️ Limited debug information</p> <p>✅ Technical but user-friendly errors</p> </div> </div> </div> <div className="mode-column"> <h3>Developer Mode</h3> <div className="mode-demo"> <VoiceButton config={{ ...baseConfig, interfaceMode: 'developer' }} showMiniCenter={true} /> <div className="mode-info"> <p>✅ Full debug interface</p> <p>✅ All provider information</p> <p>✅ Processing times</p> <p>✅ Full technical details</p> <p>✅ Complete error messages</p> </div> </div> </div> </div> ); } ``` ### Error Handling by Mode ```tsx function ErrorHandlingExample() { const [currentMode, setCurrentMode] = useState<'end-user' | 'project' | 'developer'>('end-user'); const [lastError, setLastError] = useState<string>(''); const config = { speechToText: { provider: SpeechProvider.WEB_SPEECH }, textToSpeech: { provider: SpeechProvider.WEB_SPEECH }, aiProvider: { provider: AIProvider.OPENAI }, responseMode: ResponseMode.BOTH, interfaceMode: currentMode, }; const simulateError = () => { // Simulate a network error const networkError = new Error('Failed to connect to OpenAI API'); networkError.stack = 'NetworkError: Failed to connect\n at ApiClient.request'; // Show how error is handled differently by mode const voiceError = { code: 'NETWORK_ERROR', message: getErrorMessage(networkError, currentMode), details: currentMode === 'developer' ? networkError.stack : undefined }; setLastError(voiceError.message); }; const getErrorMessage = (error: Error, mode: string) => { switch (mode) { case 'end-user': return 'Voice assistant is temporarily unavailable. Please try again.'; case 'project': return 'Connection failed. Check your internet connection.'; case 'developer': return `Network Error: ${error.message}`; default: return error.message; } }; return ( <div> <h3>Error Handling by Mode</h3> <div> <label>Select Mode: </label> <select value={currentMode} onChange={(e) => setCurrentMode(e.target.value as any)}> <option value="end-user">End User</option> <option value="project">Project</option> <option value="developer">Developer</option> </select> </div> <VoiceButton config={config} onError={(error) => setLastError(error.message)} /> <button onClick={simulateError}>Simulate Network Error</button> {lastError && ( <div className={`error-display mode-${currentMode}`}> <h4>Error in {currentMode} mode:</h4> <p>{lastError}</p> </div> )} <div className="error-examples"> <h4>Error Message Examples:</h4> <table> <thead> <tr> <th>Error Type</th> <th>End-User Mode</th> <th>Project Mode</th> <th>Developer Mode</th> </tr> </thead> <tbody> <tr> <td>Network Error</td> <td>"Voice assistant unavailable"</td> <td>"Connection failed"</td> <td>"NetworkError: Failed to connect to OpenAI API"</td> </tr> <tr> <td>Permission Denied</td> <td>"Microphone permission required"</td> <td>"Microphone access denied"</td> <td>"NotAllowedError: Permission denied by user"</td> </tr> <tr> <td>Invalid Command</td> <td>"I didn't understand that"</td> <td>"Command not recognized"</td> <td>"No matching intent found (confidence: 0.23)"</td> </tr> </tbody> </table> </div> </div> ); } ``` ## Advanced Examples ### Dynamic Mode Switching ```tsx // Switch modes based on user context or environment function DynamicModeExample() { const [user] = useUser(); // Your user hook const [isDevelopment] = useState(process.env.NODE_ENV === 'development'); // Determine mode based on context const getVoiceMode = (): VoiceInterfaceMode => { // Force developer mode in development if (isDevelopment && user.permissions.includes('debug')) { return 'developer'; } // Admin users get project mode if (user.role === 'admin' || user.role === 'manager') { return 'project'; } // Default to end-user mode return 'end-user'; }; const config = { speechToText: { provider: SpeechProvider.WEB_SPEECH }, textToSpeech: { provider: SpeechProvider.WEB_SPEECH }, aiProvider: { provider: AIProvider.OPENAI }, responseMode: ResponseMode.BOTH, interfaceMode: getVoiceMode(), }; return ( <div> <div className="user-context"> <p>User: {user.name} ({user.role})</p> <p>Environment: {isDevelopment ? 'Development' : 'Production'}</p> <p>Voice Mode: {getVoiceMode()}</p> </div> <VoiceButton config={config} // Mode-specific customizations customLabels={ getVoiceMode() === 'end-user' ? { voiceButton: { startText: 'Ask for Help' } } : undefined } showMiniCenter={getVoiceMode() !== 'end-user'} /> </div> ); } ``` ### Component-Level Mode Overrides ```tsx // Different components in the same app using different modes function MultiModeApp() { const globalConfig = { speechToText: { provider: SpeechProvider.WEB_SPEECH }, textToSpeech: { provider: SpeechProvider.WEB_SPEECH }, aiProvider: { provider: AIProvider.OPENAI }, responseMode: ResponseMode.BOTH, interfaceMode: 'project' as const, // Global default }; return ( <div className="app"> <header> <h1>Staffluent Dashboard</h1> {/* Admin section - override to developer mode */} <div className="admin-controls"> <VoiceCommandCenter config={globalConfig} mode="developer" // Component override isOpen={true} width={300} position="right" /> </div> </header> <main> {/* User help section - override to end-user mode */} <div className="help-section"> <h2>Need Help?</h2> <VoiceButton config={globalConfig} mode="end-user" // Component override customLabels={{ voiceButton: { startText: 'Ask Question' } }} /> </div> {/* Manager section - use global project mode */} <div className="manager-section"> <h2>Team Management</h2> <VoiceButton config={globalConfig} // Uses global 'project' mode showMiniCenter={true} /> </div> </main> </div> ); } ``` ### Custom Visibility Configuration ```tsx // Fine-tuned visibility control function CustomVisibilityExample() { const config = { speechToText: { provider: SpeechProvider.WEB_SPEECH }, textToSpeech: { provider: SpeechProvider.WEB_SPEECH }, aiProvider: { provider: AIProvider.OPENAI }, responseMode: ResponseMode.BOTH, interfaceMode: 'project' as const, }; return ( <div> <h2>Custom Visibility Examples</h2> {/* Show confidence but hide providers */} <div className="example"> <h3>Analytics Mode</h3> <VoiceButton config={config} visibilityOverrides={{ showConfidenceScores: true, showProviders: false, showDebugInfo: false, showMiniCenter: true, }} /> </div> {/* Minimal debugging mode */} <div className="example"> <h3>Light Debug Mode</h3> <VoiceButton config={config} visibilityOverrides={{ showProcessingTimes: true, showProviders: true, showTechnicalErrors: false, showAdvancedSettings: false, }} /> </div> {/* Customer service mode */} <div className="example"> <h3>Customer Service Mode</h3> <VoiceButton config={config} mode="end-user" visibilityOverrides={{ showCommandHistory: true, // Keep history for customer service showStatusIndicator: true, }} customLabels={{ voiceButton: { startText: 'Report Issue', stopText: 'Listening...', }, errors: { generic: 'Sorry, I could not process your request. Please try again or contact support.', } }} /> </div> </div> ); } ``` ## Integration Examples ### Using with useVoiceAI Hook ```tsx function CustomVoiceInterface() { const [selectedMode, setSelectedMode] = useState<VoiceInterfaceMode>('project'); const { isListening, isProcessing, startListening, stopListening, currentCommand, lastResponse, error, visibility, labels } = useVoiceAI({ config: { speechToText: { provider: SpeechProvider.WEB_SPEECH }, textToSpeech: { provider: SpeechProvider.WEB_SPEECH }, aiProvider: { provider: AIProvider.OPENAI }, responseMode: ResponseMode.BOTH, interfaceMode: selectedMode, }, onCommand: (command) => { console.log('Command received:', command); // Command content varies by mode }, onResponse: (response) => { console.log('Response:', response); // Response metadata varies by mode }, onError: (error) => { console.error('Error:', error); // Error detail varies by mode } }); return ( <div> <div className="mode-selector"> <label>Voice Mode: </label> <select value={selectedMode} onChange={(e) => setSelectedMode(e.target.value as any)}> <option value="end-user">End User</option> <option value="project">Project</option> <option value="developer">Developer</option> </select> </div> <div className="voice-interface"> <button onClick={isListening ? stopListening : startListening} disabled={!isAvailable} className={`voice-button ${isListening ? 'listening' : ''}`} > {isListening ? labels.voiceButton.stopText : labels.voiceButton.startText} </button> {isProcessing && <div>{labels.voiceButton.processingText}</div>} {error && <div className="error">{error}</div>} </div> {/* Conditionally show debug information based on visibility */} {visibility.showDebugInfo && currentCommand && ( <div className="debug-info"> <h4>Debug Information</h4> <pre>{JSON.stringify(currentCommand, null, 2)}</pre> </div> )} {/* Show confidence scores if visible */} {visibility.showConfidenceScores && currentCommand && ( <div className="confidence"> Confidence: {Math.round(currentCommand.confidence * 100)}% </div> )} {/* Show provider information if visible */} {visibility.showProviders && ( <div className="provider-info"> Provider: {labels.providers.generic} </div> )} </div> ); } ``` ### Testing Mode Behavior ```tsx // Test component to verify mode behavior function ModeTestSuite() { const [testResults, setTestResults] = useState<Record<string, any>>({}); const runModeTest = async (mode: VoiceInterfaceMode) => { const config = { speechToText: { provider: SpeechProvider.WEB_SPEECH }, textToSpeech: { provider: SpeechProvider.WEB_SPEECH }, aiProvider: { provider: AIProvider.OPENAI }, responseMode: ResponseMode.BOTH, interfaceMode: mode, }; const results = { mode, configResolved: !!config.interfaceMode, visibilityResolved: false, labelsResolved: false, errorHandling: 'not tested' }; // Test visibility resolution try { const { visibility, labels } = useVoiceVisibility(config); results.visibilityResolved = !!visibility; results.labelsResolved = !!labels; // Test mode-specific features results.features = { showProviders: visibility.showProviders, showDebugInfo: visibility.showDebugInfo, showConfidenceScores: visibility.showConfidenceScores, useGenericLabels: visibility.useGenericLabels, }; } catch (error) { results.errorHandling = error.message; } setTestResults(prev => ({ ...prev, [mode]: results })); }; return ( <div className="mode-test-suite"> <h2>Mode Test Suite</h2> <div className="test-controls"> <button onClick={() => runModeTest('end-user')}>Test End-User Mode</button> <button onClick={() => runModeTest('project')}>Test Project Mode</button> <button onClick={() => runModeTest('developer')}>Test Developer Mode</button> </div> <div className="test-results"> {Object.entries(testResults).map(([mode, results]) => ( <div key={mode} className="test-result"> <h3>{mode} Mode Results</h3> <pre>{JSON.stringify(results, null, 2)}</pre> </div> ))} </div> </div> ); } ``` ## Production Examples These examples show real-world implementations suitable for production use: ### Enterprise Admin Dashboard ```tsx // Full-featured admin interface with mode switching function EnterpriseAdminDashboard() { const [userRole] = useUserRole(); const [voiceMode, setVoiceMode] = useState<VoiceInterfaceMode>( userRole === 'super_admin' ? 'developer' : 'project' ); const config = { speechToText: { provider: SpeechProvider.WEB_SPEECH }, textToSpeech: { provider: SpeechProvider.WEB_SPEECH }, aiProvider: { provider: AIProvider.OPENAI }, responseMode: ResponseMode.BOTH, interfaceMode: voiceMode, }; return ( <div className="enterprise-dashboard"> <header className="dashboard-header"> <h1>Enterprise Voice AI Management</h1> {userRole === 'super_admin' && ( <div className="mode-switcher"> <label>Interface Mode:</label> <select value={voiceMode} onChange={(e) => setVoiceMode(e.target.value as any)}> <option value="developer">Developer (Full Debug)</option> <option value="project">Project (Standard)</option> <option value="end-user">End User (Preview)</option> </select> </div> )} </header> <div className="dashboard-content"> <aside className="voice-panel"> <VoiceCommandCenter config={config} isOpen={true} position="left" width={320} showCategories={true} showHistory={true} /> </aside> <main className="main-content"> <div className="voice-quick-actions"> <VoiceButton config={config} size="lg" showMiniCenter={false} /> </div> {/* Dashboard content */} </main> </div> </div> ); } ``` These examples demonstrate the flexibility and power of the 3-tier mode system, showing how the same voice AI components can serve different user types with appropriately tailored interfaces and functionality.