From 905b05e3433ce8ee56cd694ec7e7a46492351f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Henrique?= Date: Sun, 27 Jul 2025 18:13:43 -0300 Subject: [PATCH] refactors! --- App.tsx | 172 ++++------------------ components/layout/CategoryGroup.tsx | 76 ++++++++++ components/layout/ConfigurationButton.tsx | 22 +++ components/layout/EditButton.tsx | 25 ++++ components/layout/Header.tsx | 84 +++++++++++ types.ts | 27 +++- 6 files changed, 260 insertions(+), 146 deletions(-) create mode 100644 components/layout/CategoryGroup.tsx create mode 100644 components/layout/ConfigurationButton.tsx create mode 100644 components/layout/EditButton.tsx create mode 100644 components/layout/Header.tsx diff --git a/App.tsx b/App.tsx index 338790e..6c76a7e 100755 --- a/App.tsx +++ b/App.tsx @@ -1,17 +1,18 @@ import React, { useState, useEffect } from 'react'; -import WebsiteTile from './components/WebsiteTile'; import ConfigurationModal from './components/ConfigurationModal'; -import Clock from './components/Clock'; import ServerWidget from './components/ServerWidget'; import { DEFAULT_CATEGORIES } from './constants'; -import { Category, Website, Wallpaper } from './types'; -import Dropdown from './components/Dropdown'; +import { Category, Website, Wallpaper, 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 { baseWallpapers } from './components/utils/baseWallpapers'; -const defaultConfig = { +const defaultConfig: Config = { title: 'Vision Start', subtitle: 'Your personal portal to the web.', backgroundUrls: ['https://i.imgur.com/C6ynAtX.jpeg'], @@ -54,7 +55,7 @@ const App: React.FC = () => { const [addingWebsite, setAddingWebsite] = useState(null); const [editingCategory, setEditingCategory] = useState(null); const [isCategoryModalOpen, setIsCategoryModalOpen] = useState(false); - const [config, setConfig] = useState(() => { + const [config, setConfig] = useState(() => { try { const storedConfig = localStorage.getItem('config'); if (storedConfig) { @@ -240,51 +241,6 @@ const App: React.FC = () => { } }; - const getClockSizeClass = (size: string) => { - switch (size) { - case 'tiny': - return 'text-3xl'; - case 'small': - return 'text-4xl'; - case 'medium': - return 'text-5xl'; - case 'large': - return 'text-6xl'; - default: - return 'text-5xl'; - } - }; - - const getTitleSizeClass = (size: string) => { - switch (size) { - case 'tiny': - return 'text-4xl'; - case 'small': - return 'text-5xl'; - case 'medium': - return 'text-6xl'; - case 'large': - return 'text-7xl'; - default: - return 'text-6xl'; - } - }; - - const getSubtitleSizeClass = (size: string) => { - switch (size) { - case 'tiny': - return 'text-lg'; - case 'small': - return 'text-xl'; - case 'medium': - return 'text-2xl'; - case 'large': - return 'text-3xl'; - default: - return 'text-2xl'; - } - }; - const getHorizontalAlignmentClass = (alignment: string) => { switch (alignment) { case 'left': @@ -299,7 +255,6 @@ const App: React.FC = () => { }; return ( -
@@ -311,98 +266,25 @@ const App: React.FC = () => { opacity: `${config.wallpaperOpacity}%`, }} > -
- -
-
- -
+ setIsEditing(!isEditing)} /> + setIsConfigModalOpen(true)} /> - {/* Absolute top-center Clock */} - {config.clock.enabled && ( -
- -
- )} - -
- {(config.title || config.subtitle) && ( -
-

- {config.title} -

-

- {config.subtitle} -

-
- )} -
+
{categories.map((category) => ( -
-
-

{category.name}

- {isEditing && ( - - )} -
-
- {category.websites.map((website) => ( - - ))} - {isEditing && ( - - )} -
-
+ ))} {isEditing && (
@@ -413,10 +295,10 @@ const App: React.FC = () => { }} className="text-white/50 hover:text-white transition-colors" > - - - - + + + +
)} @@ -465,4 +347,4 @@ const App: React.FC = () => { ); } -export default App; \ No newline at end of file +export default App; diff --git a/components/layout/CategoryGroup.tsx b/components/layout/CategoryGroup.tsx new file mode 100644 index 0000000..8753131 --- /dev/null +++ b/components/layout/CategoryGroup.tsx @@ -0,0 +1,76 @@ +import React from 'react'; +import WebsiteTile from '../WebsiteTile'; +import { Category, Website } from '../../types'; + +interface CategoryGroupProps { + category: Category; + isEditing: boolean; + setEditingCategory: (category: Category) => void; + setIsCategoryModalOpen: (isOpen: boolean) => void; + setAddingWebsite: (category: Category) => void; + setEditingWebsite: (website: Website) => void; + handleMoveWebsite: (website: Website, direction: 'left' | 'right') => void; + getHorizontalAlignmentClass: (alignment: string) => string; + config: { + horizontalAlignment: string; + tileSize?: string; + }; +} + +const CategoryGroup: React.FC = ({ + category, + isEditing, + setEditingCategory, + setIsCategoryModalOpen, + setAddingWebsite, + setEditingWebsite, + handleMoveWebsite, + getHorizontalAlignmentClass, + config, +}) => { + return ( +
+
+

{category.name}

+ {isEditing && ( + + )} +
+
+ {category.websites.map((website) => ( + + ))} + {isEditing && ( + + )} +
+
+ ); +}; + +export default CategoryGroup; diff --git a/components/layout/ConfigurationButton.tsx b/components/layout/ConfigurationButton.tsx new file mode 100644 index 0000000..06dd404 --- /dev/null +++ b/components/layout/ConfigurationButton.tsx @@ -0,0 +1,22 @@ +import React from 'react'; + +interface ConfigurationButtonProps { + onClick: () => void; +} + +const ConfigurationButton: React.FC = ({ onClick }) => { + return ( +
+ +
+ ); +}; + +export default ConfigurationButton; diff --git a/components/layout/EditButton.tsx b/components/layout/EditButton.tsx new file mode 100644 index 0000000..41506f8 --- /dev/null +++ b/components/layout/EditButton.tsx @@ -0,0 +1,25 @@ +import React from 'react'; + +interface EditButtonProps { + isEditing: boolean; + onClick: () => void; +} + +const EditButton: React.FC = ({ isEditing, onClick }) => { + return ( +
+ +
+ ); +}; + +export default EditButton; diff --git a/components/layout/Header.tsx b/components/layout/Header.tsx new file mode 100644 index 0000000..e67dcd9 --- /dev/null +++ b/components/layout/Header.tsx @@ -0,0 +1,84 @@ +import React from 'react'; +import Clock from '../Clock'; +import { Config } from '../../types'; + +interface HeaderProps { + config: Config; +} + +const getClockSizeClass = (size: string) => { + switch (size) { + case 'tiny': + return 'text-3xl'; + case 'small': + return 'text-4xl'; + case 'medium': + return 'text-5xl'; + case 'large': + return 'text-6xl'; + default: + return 'text-5xl'; + } +}; + +const getTitleSizeClass = (size: string) => { + switch (size) { + case 'tiny': + return 'text-4xl'; + case 'small': + return 'text-5xl'; + case 'medium': + return 'text-6xl'; + case 'large': + return 'text-7xl'; + default: + return 'text-6xl'; + } +}; + +const getSubtitleSizeClass = (size: string) => { + switch (size) { + case 'tiny': + return 'text-lg'; + case 'small': + return 'text-xl'; + case 'medium': + return 'text-2xl'; + case 'large': + return 'text-3xl'; + default: + return 'text-2xl'; + } +}; + +const Header: React.FC = ({ config }) => { + return ( + <> + {config.clock.enabled && ( +
+ +
+ )} +
+ {(config.title || config.subtitle) && ( +
+

+ {config.title} +

+

+ {config.subtitle} +

+
+ )} +
+ + ); +}; + +export default Header; diff --git a/types.ts b/types.ts index 8640da5..ecc3f1f 100755 --- a/types.ts +++ b/types.ts @@ -1,4 +1,3 @@ - export interface Website { id: string; name: string; @@ -24,3 +23,29 @@ export interface Wallpaper { url?: string; base64?: string; } + +export interface Config { + title: string; + subtitle: string; + backgroundUrls: string[]; + wallpaperFrequency: string; + wallpaperBlur: number; + wallpaperBrightness: number; + wallpaperOpacity: number; + titleSize: string; + subtitleSize: string; + alignment: string; + horizontalAlignment: string; + clock: { + enabled: boolean; + size: string; + font: string; + format: string; + }; + serverWidget: { + enabled: boolean; + pingFrequency: number; + servers: Server[]; + }; + tileSize?: string; +} \ No newline at end of file