import { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { validateCharacter } from '../lib/SchemaValidator'; const STORAGE_KEY = 'homeai_characters'; const ACTIVE_KEY = 'homeai_active_character'; function loadProfiles() { try { const raw = localStorage.getItem(STORAGE_KEY); return raw ? JSON.parse(raw) : []; } catch { return []; } } function saveProfiles(profiles) { localStorage.setItem(STORAGE_KEY, JSON.stringify(profiles)); } function getActiveId() { return localStorage.getItem(ACTIVE_KEY) || null; } function setActiveId(id) { localStorage.setItem(ACTIVE_KEY, id); } export default function Characters() { const [profiles, setProfiles] = useState(loadProfiles); const [activeId, setActive] = useState(getActiveId); const [error, setError] = useState(null); const [dragOver, setDragOver] = useState(false); const navigate = useNavigate(); useEffect(() => { saveProfiles(profiles); }, [profiles]); const handleImport = (e) => { const files = Array.from(e.target?.files || []); importFiles(files); if (e.target) e.target.value = ''; }; const importFiles = (files) => { files.forEach(file => { if (!file.name.endsWith('.json')) return; const reader = new FileReader(); reader.onload = (ev) => { try { const data = JSON.parse(ev.target.result); validateCharacter(data); const id = data.name + '_' + Date.now(); setProfiles(prev => [...prev, { id, data, image: null, addedAt: new Date().toISOString() }]); setError(null); } catch (err) { setError(`Import failed for ${file.name}: ${err.message}`); } }; reader.readAsText(file); }); }; const handleDrop = (e) => { e.preventDefault(); setDragOver(false); const files = Array.from(e.dataTransfer.files); importFiles(files); }; const handleImageUpload = (profileId, e) => { const file = e.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = (ev) => { setProfiles(prev => prev.map(p => p.id === profileId ? { ...p, image: ev.target.result } : p) ); }; reader.readAsDataURL(file); }; const removeProfile = (id) => { setProfiles(prev => prev.filter(p => p.id !== id)); if (activeId === id) { setActive(null); localStorage.removeItem(ACTIVE_KEY); } }; const activateProfile = (id) => { setActive(id); setActiveId(id); }; const exportProfile = (profile) => { const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(profile.data, null, 2)); const a = document.createElement('a'); a.href = dataStr; a.download = `${profile.data.name || 'character'}.json`; a.click(); }; const editProfile = (profile) => { sessionStorage.setItem('edit_character', JSON.stringify(profile.data)); sessionStorage.setItem('edit_character_profile_id', profile.id); navigate('/editor'); }; const activeProfile = profiles.find(p => p.id === activeId); return (
{profiles.length} profile{profiles.length !== 1 ? 's' : ''} stored {activeProfile && ( Active: {activeProfile.data.display_name || activeProfile.data.name} )}
Drop character JSON files here to import
No character profiles yet. Import a JSON file to get started.
{char.description}