import { useState, useEffect } from 'react'; import ConfigurationModal from './components/ConfigurationModal'; import ServerWidget from './components/ServerWidget'; import { DEFAULT_CATEGORIES } from './constants'; import { Category, Website, Config } from './types'; import WebsiteEditModal from './components/WebsiteEditModal'; import CategoryEditModal from './components/CategoryEditModal'; import Header from './components/layout/Header'; import EditButton from './components/layout/EditButton'; import ConfigurationButton from './components/layout/ConfigurationButton'; import CategoryGroup from './components/layout/CategoryGroup'; import Wallpaper from './components/Wallpaper'; const defaultConfig: Config = { title: 'Vision Start', subtitle: 'Your personal portal to the web.', currentWallpapers: ['Abstract'], wallpaperFrequency: '1d', wallpaperBlur: 0, wallpaperBrightness: 100, wallpaperOpacity: 100, titleSize: 'medium', subtitleSize: 'medium', alignment: 'middle', horizontalAlignment: 'middle', clock: { enabled: true, size: 'medium', font: 'Helvetica', format: 'h:mm A', }, serverWidget: { enabled: false, pingFrequency: 15, servers: [], }, }; const App: React.FC = () => { const [categories, setCategories] = useState(() => { try { const storedCategories = localStorage.getItem('categories'); if (storedCategories) { return JSON.parse(storedCategories); } } catch (error) { console.error('Error parsing categories from localStorage', error); } return DEFAULT_CATEGORIES; }); const [isEditing, setIsEditing] = useState(false); const [isConfigModalOpen, setIsConfigModalOpen] = useState(false); const [editingWebsite, setEditingWebsite] = useState(null); const [addingWebsite, setAddingWebsite] = useState(null); const [editingCategory, setEditingCategory] = useState(null); const [isCategoryModalOpen, setIsCategoryModalOpen] = useState(false); const [config, setConfig] = useState(() => { try { const storedConfig = localStorage.getItem('config'); if (storedConfig) { const parsedConfig = JSON.parse(storedConfig); return { ...defaultConfig, ...parsedConfig }; } } catch (error) { console.error('Error parsing config from localStorage', error); } return { ...defaultConfig }; }); useEffect(() => { localStorage.setItem('config', JSON.stringify(config)); }, [config]); const handleSaveConfig = (newConfig: Config) => { setConfig(newConfig); setIsConfigModalOpen(false); }; const handleWallpaperChange = (newConfig: Partial) => { setConfig(prev => ({ ...prev, ...newConfig })); }; const handleSaveWebsite = (website: Partial) => { if (editingWebsite) { const newCategories = categories.map(category => ({ ...category, websites: category.websites.map(w => w.id === website.id ? { ...w, ...website } : w ), })); setCategories(newCategories); setEditingWebsite(null); } else if (addingWebsite) { const newWebsite: Website = { id: Date.now().toString(), name: website.name || '', url: website.url || '', icon: website.icon || '', categoryId: addingWebsite.id, }; const newCategories = categories.map(category => category.id === addingWebsite.id ? { ...category, websites: [...category.websites, newWebsite] } : category ); setCategories(newCategories); setAddingWebsite(null); } }; const handleSaveCategory = (name: string) => { if (editingCategory) { const newCategories = categories.map(category => category.id === editingCategory.id ? { ...category, name } : category ); setCategories(newCategories); } else { const newCategory: Category = { id: Date.now().toString(), name, websites: [], }; setCategories([...categories, newCategory]); } setEditingCategory(null); setIsCategoryModalOpen(false); }; const handleDeleteWebsite = () => { if (!editingWebsite) return; const newCategories = categories.map(category => ({ ...category, websites: category.websites.filter(w => w.id !== editingWebsite.id), })); setCategories(newCategories); setEditingWebsite(null); }; const handleDeleteCategory = () => { if (!editingCategory) return; const newCategories = categories.filter(c => c.id !== editingCategory.id); setCategories(newCategories); setEditingCategory(null); setIsCategoryModalOpen(false); }; const handleMoveWebsite = (website: Website, direction: 'left' | 'right') => { if (categoryIndex === -1) return; const category = categories[categoryIndex]; const websiteIndex = category.websites.findIndex(w => w.id === website.id); if (websiteIndex === -1) return; const newCategories = [...categories]; const newWebsites = [...category.websites]; const [movedWebsite] = newWebsites.splice(websiteIndex, 1); if (direction === 'left') { const newCategoryIndex = (categoryIndex - 1 + categories.length) % categories.length; newCategories[categoryIndex] = { ...category, websites: newWebsites }; const destCategory = newCategories[newCategoryIndex]; const destWebsites = [...destCategory.websites, { ...movedWebsite, categoryId: destCategory.id }]; newCategories[newCategoryIndex] = { ...destCategory, websites: destWebsites }; } else { const newCategoryIndex = (categoryIndex + 1) % categories.length; newCategories[categoryIndex] = { ...category, websites: newWebsites }; const destCategory = newCategories[newCategoryIndex]; const destWebsites = [...destCategory.websites, { ...movedWebsite, categoryId: destCategory.id }]; newCategories[newCategoryIndex] = { ...destCategory, websites: destWebsites }; } setCategories(newCategories); }; const getAlignmentClass = (alignment: string) => { switch (alignment) { case 'top': return 'justify-start'; case 'middle': return 'justify-center'; case 'bottom': return 'justify-end'; default: return 'justify-center'; } }; const getHorizontalAlignmentClass = (alignment: string) => { switch (alignment) { case 'left': return 'justify-start'; case 'middle': return 'justify-center'; case 'right': return 'justify-end'; default: return 'justify-center'; } }; return (
setIsEditing(!isEditing)} /> setIsConfigModalOpen(true)} />
{categories.map((category) => ( ))} {isEditing && (
)}
{config.serverWidget.enabled && } {(editingWebsite || addingWebsite) && ( { setEditingWebsite(null); setAddingWebsite(null); }} onSave={handleSaveWebsite} onDelete={handleDeleteWebsite} /> )} {isCategoryModalOpen && ( { setEditingCategory(null); setIsCategoryModalOpen(false); }} onSave={handleSaveCategory} onDelete={handleDeleteCategory} /> )} {isConfigModalOpen && ( setIsConfigModalOpen(false)} onSave={handleSaveConfig} onWallpaperChange={handleWallpaperChange} /> )}
); } export default App;