UNPKG

@bigdigital/kiosk-content-sdk

Version:

A Firebase-powered Content Management System SDK optimized for kiosks with offline support, template management, and real-time connection monitoring

358 lines (300 loc) 8.8 kB
# Kiosk Content SDK ```bash npm install @bigdigital/kiosk-content-sdk ``` ## Content Management Features - Offline-first content storage - Dynamic template support - Real-time content updates - Type-safe content validation - Automatic content synchronization - Rich media support - Kiosk monitoring and status tracking ## Comprehensive Example Here's a complete example showing content management with template support and kiosk monitoring: ```typescript import { useContentWithTemplate, kioskSDK } from '@bigdigital/kiosk-content-sdk'; import { useEffect, useState } from 'react'; import { Badge } from './ui/badge'; import { Wifi, WifiOff } from 'lucide-react'; interface ContentViewProps { contentId: string; } function ContentView({ contentId }: ContentViewProps) { const [kioskStatus, setKioskStatus] = useState<'connected' | 'disconnected'>('disconnected'); // Content management configuration const config = { projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID, apiKey: import.meta.env.VITE_FIREBASE_API_KEY, offlineSupport: true, // Enable offline support cacheStrategy: "local", // Use local storage for caching syncInterval: 300000, // Sync every 5 minutes cacheMaxAge: 600000 // Cache expires after 10 minutes }; // Initialize content with template const { content, template, loading, error, isOnline, refresh } = useContentWithTemplate(config, contentId); // Initialize kiosk monitoring useEffect(() => { const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; const wsHost = window.location.host; const wsUrl = `${protocol}//${wsHost}/api/ws/kiosk`; const connection = kioskSDK.initializeMonitoring({ url: wsUrl, onConnectionUpdate: (isConnected) => { setKioskStatus(isConnected ? 'connected' : 'disconnected'); } }); // Handle connection events connection.on('error', (error) => { console.error('Kiosk connection error:', error); }); connection.on('disconnected', () => { console.log('Kiosk disconnected, attempting to reconnect...'); }); // Cleanup on unmount return () => { connection.disconnect(); }; }, []); // Loading state if (loading) { return ( <div className="flex items-center justify-center p-8"> <div className="animate-spin h-8 w-8 border-4 border-primary border-t-transparent rounded-full" /> </div> ); } // Error state if (error) { return ( <div className="p-4 bg-destructive/15 text-destructive rounded-md"> <h2 className="font-semibold mb-2">Error</h2> <p>{error.message}</p> <button onClick={refresh} className="mt-4 px-4 py-2 bg-primary text-white rounded-md" > Retry </button> </div> ); } // Content not found if (!content) { return ( <div className="p-4 text-muted-foreground"> Content not found </div> ); } return ( <div className="space-y-6"> {/* Connection status indicator */} <div className="fixed bottom-4 right-4"> <Badge variant={kioskStatus === 'connected' ? 'default' : 'destructive'} className="flex items-center gap-2" > {kioskStatus === 'connected' ? ( <> <Wifi className="h-3 w-3" /> <span>Connected</span> </> ) : ( <> <WifiOff className="h-3 w-3" /> <span>Offline</span> </> )} </Badge> </div> {/* Content display */} <div className="space-y-4"> <h1 className="text-2xl font-bold">{content.title}</h1> <p className="text-muted-foreground">{content.description}</p> {/* Template-specific content */} {template && ( <div className="mt-8"> <h2 className="text-xl font-semibold mb-4"> Template: {template.name} </h2> {template.fields.map(field => ( <div key={field.id} className="mb-4"> <h3 className="font-medium">{field.label}</h3> {/* Render field based on type */} {field.type === 'text' && ( <p>{content.data[field.id]}</p> )} {field.type === 'image' && ( <img src={content.data[field.id]} alt={field.label} className="rounded-lg max-w-full h-auto" /> )} </div> ))} </div> )} {/* Offline indicator */} {!isOnline && ( <div className="mt-4 p-2 bg-yellow-50 text-yellow-600 rounded-md text-sm"> Working offline - Changes will sync when connection is restored </div> )} <button onClick={refresh} className="mt-6 px-4 py-2 bg-primary text-white rounded-md" > Refresh Content </button> </div> </div> ); } export default ContentView; ``` ## Quick Start ### Basic Content Management ```typescript import { useKioskContent } from '@bigdigital/kiosk-content-sdk'; function ContentDisplay() { const { content, isLoading } = useKioskContent({ projectId: 'your-project-id', offlineSupport: true }); if (isLoading) return <div>Loading...</div>; return ( <div> {content.map(item => ( <div key={item.id}> <h2>{item.title}</h2> <p>{item.description}</p> </div> ))} </div> ); } ``` ### Managing Templates ```typescript import { useTemplate } from '@bigdigital/kiosk-content-sdk'; function TemplateEditor() { const { template } = useTemplate('template-id'); return ( <div> <h1>{template.name}</h1> {template.fields.map(field => ( <div key={field.id}> {/* Render appropriate field editor based on type */} {field.type === 'text' && <input type="text" />} {field.type === 'image' && <ImageUploader />} </div> ))} </div> ); } ``` ## Content Types ```typescript // Content item structure interface Content { id: string; title: string; description: string; data: Record<string, any>; template?: string; metadata: { createdAt: string; updatedAt: string; version: number; }; } // Template structure interface Template { id: string; name: string; fields: Field[]; } // Field definitions interface Field { id: string; type: 'text' | 'image' | 'video' | 'rich-text'; required: boolean; label: string; settings?: Record<string, any>; } ``` ## Hooks Reference ### Content Management - `useKioskContent`: Fetch and manage content items - `useProjectContent`: Get content for specific project - `useContentWithTemplate`: Get content with template data - `useOfflineContent`: Access offline-stored content ### Template Management - `useTemplate`: Manage single template - `useTemplates`: List all available templates - `useTemplateContent`: Get content for specific template ### Synchronization - `useContentSync`: Handle content synchronization ## Type Safety The SDK provides TypeScript support out of the box: ```typescript import { Content, Template } from '@bigdigital/kiosk-content-sdk'; // Your content is fully typed const content: Content = { id: 'unique-id', title: 'My Content', description: 'Description', data: { // Your content data } }; ``` ## Error Handling ```typescript import { useKioskContent } from '@bigdigital/kiosk-content-sdk'; function ContentWithErrorHandling() { const { content, error, retry } = useKioskContent({ onError: (error) => { console.error('Content error:', error); } }); if (error) { return ( <div> <p>Error: {error.message}</p> <button onClick={retry}>Retry</button> </div> ); } return <ContentDisplay content={content} />; } ``` ## Key Features for Content Management - Automatic offline storage - Template-based content validation - Real-time content updates - Rich media support - Type-safe content handling - Automatic content synchronization - Error recovery and retry mechanisms - Kiosk status monitoring and management For more detailed documentation and advanced features, visit our [documentation](https://github.com/bigdigital/kiosk-content-sdk/docs). ## Testing The SDK includes testing utilities for mocking content and connection behavior: ```typescript import { MockKioskConnection } from '@bigdigital/kiosk-content-sdk/testing'; const mockConnection = new MockKioskConnection({ mockResponses: { 'content-1': { /* mock content */ } } }); ```