import { useState, useEffect } from 'react'; import { Link } from 'react-router-dom'; import { settingsProfilesApi } from '../services/apiClient'; import { SettingsProfile } from '../types/api'; import { APPS } from '../config/apps'; export function SettingsProfilesAdminPage() { const [profiles, setProfiles] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [showCreateModal, setShowCreateModal] = useState(false); const [editingProfile, setEditingProfile] = useState(null); useEffect(() => { loadProfiles(); }, []); const loadProfiles = async () => { try { setLoading(true); setError(null); const response: any = await settingsProfilesApi.getAll(); setProfiles(response.data); } catch (err: any) { setError(err.error?.message || 'Failed to load Magic Codes'); } finally { setLoading(false); } }; const handleDelete = async (profileId: number) => { if (!confirm('Are you sure you want to delete this magic code? The magic code will no longer work.')) { return; } try { await settingsProfilesApi.delete(profileId); await loadProfiles(); } catch (err: any) { alert(err.error?.message || 'Failed to delete magic code'); } }; const handleCopyCode = async (code: string) => { try { await navigator.clipboard.writeText(code); alert('Magic code copied to clipboard!'); } catch (err) { // Fallback for older browsers const textArea = document.createElement('textarea'); textArea.value = code; document.body.appendChild(textArea); textArea.select(); document.execCommand('copy'); document.body.removeChild(textArea); alert('Magic code copied to clipboard!'); } }; const handleRegenerateCode = async (profileId: number) => { if (!confirm('Are you sure you want to regenerate the magic code? The old code will stop working.')) { return; } try { const response: any = await settingsProfilesApi.regenerateCode(profileId); await loadProfiles(); alert(`New magic code: ${response.data.magicCode}`); } catch (err: any) { alert(err.error?.message || 'Failed to regenerate code'); } }; const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString(); }; if (loading) { return (

Loading magic codes...

); } return (
← Back to Admin

Magic Codes

Create magic codes to manage settings for children

{error && (
{error}
)} {profiles.length === 0 ? (

No magic codes yet.

) : (
{profiles.map((profile) => ( ))}
Name Magic Code Enabled Apps Status Created Actions
{profile.name}
{profile.magicCode}
{profile.enabledApps && profile.enabledApps.length > 0 ? (
{profile.enabledApps.map(appId => { const app = APPS.find(a => a.id === appId); return app ? ( {app.name} ) : null; })}
) : ( All apps )}
{profile.isActive ? 'Active' : 'Inactive'} {formatDate(profile.createdAt)}
)}
{showCreateModal && ( setShowCreateModal(false)} onSuccess={() => { setShowCreateModal(false); loadProfiles(); }} /> )} {editingProfile && ( setEditingProfile(null)} onSuccess={() => { setEditingProfile(null); loadProfiles(); }} /> )}
); } function SettingsProfileFormModal({ profile, onClose, onSuccess }: { profile?: SettingsProfile; onClose: () => void; onSuccess: () => void; }) { const [name, setName] = useState(profile?.name || ''); const [description, setDescription] = useState(profile?.description || ''); // Default enabled apps: speechsounds and tictactoe (videos is disabled by default) const defaultEnabledApps = APPS.filter(app => !app.disabled && app.id !== 'videos').map(app => app.id); const [enabledApps, setEnabledApps] = useState(profile?.enabledApps ?? defaultEnabledApps); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const toggleApp = (appId: string) => { setEnabledApps(prev => prev.includes(appId) ? prev.filter(id => id !== appId) : [...prev, appId] ); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(null); if (!name.trim()) { setError('Name is required'); return; } try { setLoading(true); if (profile) { // Update existing profile await settingsProfilesApi.update(profile.id, { name, description }); await settingsProfilesApi.updateSettings(profile.id, { enabledApps }); } else { // Create new profile await settingsProfilesApi.create({ name, description, enabledApps }); } onSuccess(); } catch (err: any) { setError(err.error?.message || 'Failed to save profile'); } finally { setLoading(false); } }; return (

{profile ? 'Edit Magic Code' : 'Create Magic Code'}

setName(e.target.value)} placeholder="e.g., Kid 1's iPad" className="w-full px-4 py-2 border border-border rounded-lg bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary" required />
setDescription(e.target.value)} placeholder="e.g., For daily use" className="w-full px-4 py-2 border border-border rounded-lg bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary" />

Select which apps children can access. Leave all unchecked to allow all apps (including videos).

{APPS.filter(app => !app.disabled).map(app => ( ))}
{profile && (
{profile.magicCode}

Share this code with your child to apply these settings

)} {error && (
{error}
)}
); }