Explorar o código

introduce vanila components

Daniel Bohry hai 1 mes
pai
achega
6e2c75dc5c

+ 18 - 96
src/main/resources/static/404.html

@@ -10,16 +10,11 @@
     <meta name="mobile-web-app-capable" content="yes">
     <meta name="application-name" content="kNotes">
     <title>Page Not Found - kNotes</title>
-    <link rel="stylesheet" href="style.css">
+    <link rel="stylesheet" href="css/style.css">
+    <link rel="icon" type="image/x-icon" href="img/favicon.ico">
 </head>
 <body>
-<div class="header">
-    <div class="title" onclick="window.location.href='/'" style="cursor: pointer;"><img src="logo.png" alt="kNotes logo"/> kNotes</div>
-    <div class="header-right">
-        <div class="theme-switch" id="themeSwitch" onclick="toggleTheme()" title="Toggle dark/light theme"></div>
-        <button class="new-btn" onclick="window.location.href='/'">Home</button>
-    </div>
-</div>
+<div id="headerContainer"></div>
 
 <div class="content">
     <div class="error-content">
@@ -29,98 +24,25 @@
             The page you're looking for doesn't exist. It might have been moved, deleted,
             or you entered the wrong URL.
         </p>
+        <div class="error-actions">
+            <button class="dialog-btn primary" onclick="window.location.href='/'">
+                Go Home
+            </button>
+            <button class="dialog-btn secondary" onclick="showIdInput()">
+                Open Note
+            </button>
+        </div>
     </div>
 </div>
 
-<script>
-    function initializeTheme() {
-        const savedTheme = localStorage.getItem('theme') || 'light';
-        const body = document.body;
-        const themeSwitch = document.getElementById('themeSwitch');
-
-        if (!themeSwitch) return;
-
-        if (savedTheme === 'dark') {
-            body.setAttribute('data-theme', 'dark');
-            themeSwitch.classList.add('dark');
-        } else {
-            body.removeAttribute('data-theme');
-            themeSwitch.classList.remove('dark');
-        }
-
-        updateThemeColor();
-    }
-
-    function toggleTheme() {
-        const body = document.body;
-        const themeSwitch = document.getElementById('themeSwitch');
-
-        if (!themeSwitch) return;
-
-        const currentTheme = body.getAttribute('data-theme');
-
-        if (currentTheme === 'dark') {
-            body.removeAttribute('data-theme');
-            themeSwitch.classList.remove('dark');
-            localStorage.setItem('theme', 'light');
-        } else {
-            body.setAttribute('data-theme', 'dark');
-            themeSwitch.classList.add('dark');
-            localStorage.setItem('theme', 'dark');
-        }
+<div id="modalContainer"></div>
 
-        updateThemeColor();
-    }
-
-    function updateThemeColor() {
-        const themeColorMeta = document.querySelector('meta[name="theme-color"]');
-        const currentTheme = document.body.getAttribute('data-theme');
-
-        if (themeColorMeta) {
-            if (currentTheme === 'dark') {
-                themeColorMeta.setAttribute('content', '#2d2d2d');
-            } else {
-                themeColorMeta.setAttribute('content', '#007bff');
-            }
-        }
-    }
-
-    function hideIdInput() {
-        const idInputOverlay = document.getElementById('idInputOverlay');
-        const noteIdInput = document.getElementById('noteIdInput');
-
-        if (idInputOverlay) {
-            idInputOverlay.classList.add('hidden');
-        }
-
-        if (noteIdInput) {
-            noteIdInput.value = '';
-        }
-    }
-
-    function loadNoteFromInput() {
-        const noteIdInput = document.getElementById('noteIdInput');
-        if (!noteIdInput) return;
-
-        const id = noteIdInput.value.trim();
-        if (id) {
-            hideIdInput();
-            window.location.href = `/${id}`;
-        }
-    }
-
-    document.addEventListener('DOMContentLoaded', function () {
-        initializeTheme();
-
-        const noteIdInput = document.getElementById('noteIdInput');
-        if (noteIdInput) {
-            noteIdInput.addEventListener('keypress', function (e) {
-                if (e.key === 'Enter') {
-                    loadNoteFromInput();
-                }
-            });
-        }
-    });
+<script src="js/components.js"></script>
+<script src="js/script.js"></script>
+<script>
+document.addEventListener('DOMContentLoaded', async () => {
+    await initPage('error');
+});
 </script>
 </body>
 </html>

+ 23 - 0
src/main/resources/static/components/base.html

@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
+    <meta name="theme-color" content="#007bff">
+    <meta name="apple-mobile-web-app-capable" content="yes">
+    <meta name="apple-mobile-web-app-status-bar-style" content="default">
+    <meta name="apple-mobile-web-app-title" content="kNotes">
+    <meta name="mobile-web-app-capable" content="yes">
+    <meta name="application-name" content="kNotes">
+    <title>{{PAGE_TITLE}}</title>
+    <link rel="stylesheet" href="css/style.css">
+    <link rel="icon" type="image/x-icon" href="img/favicon.ico">
+</head>
+<body>
+{{PAGE_CONTENT}}
+
+<script src="js/components.js"></script>
+<script src="js/script.js"></script>
+{{PAGE_SCRIPT}}
+</body>
+</html>

+ 8 - 0
src/main/resources/static/components/header.html

@@ -0,0 +1,8 @@
+<div class="header">
+    <div class="title" onclick="window.location.href='/'" style="cursor: pointer;">
+        <img src="img/logo.png" alt="kNotes logo"/> kNotes
+    </div>
+    <div class="header-right">
+        {{HEADER_CONTENT}}
+    </div>
+</div>

+ 10 - 0
src/main/resources/static/components/modal.html

@@ -0,0 +1,10 @@
+<div id="idInputOverlay" class="id-input-overlay hidden">
+    <div class="id-input-dialog">
+        <h3>Open Note</h3>
+        <input type="text" id="noteIdInput" class="id-input" placeholder="Enter note ID"/>
+        <div class="dialog-buttons">
+            <button class="dialog-btn secondary" onclick="hideIdInput()">Cancel</button>
+            <button class="dialog-btn primary" onclick="loadNoteFromInput()">Open</button>
+        </div>
+    </div>
+</div>

+ 0 - 0
src/main/resources/static/style.css → src/main/resources/static/css/style.css


+ 12 - 63
src/main/resources/static/home.html

@@ -10,86 +10,35 @@
     <meta name="mobile-web-app-capable" content="yes">
     <meta name="application-name" content="kNotes">
     <title>kNotes - Simple Note Taking</title>
-    <link rel="stylesheet" href="style.css">
+    <link rel="stylesheet" href="css/style.css">
+    <link rel="icon" type="image/x-icon" href="img/favicon.ico">
 </head>
 <body>
-<div class="header">
-    <div class="title" onclick="window.location.href='/'" style="cursor: pointer;"><img src="logo.png"
-                                                                                        alt="kNotes logo"/> kNotes
-    </div>
-    <div class="header-right">
-        <div class="theme-switch" id="themeSwitch" onclick="toggleTheme()" title="Toggle dark/light theme"></div>
-    </div>
-</div>
+<div id="headerContainer"></div>
 
 <div class="content">
     <div class="error-content">
         <div class="error-icon">📝</div>
         <h1 class="error-title">Welcome to kNotes</h1>
         <div class="error-actions">
-            <button class="dialog-btn primary" onclick="createNewNote()">
-                Create New
+            <button class="dialog-btn primary" onclick="window.location.href='/index.html'">
+                Create New Note
             </button>
             <button class="dialog-btn secondary" onclick="showIdInput()">
-                Open Existing
+                Open Existing Note
             </button>
         </div>
     </div>
 </div>
 
-<div id="idInputOverlay" class="id-input-overlay hidden">
-    <div class="id-input-dialog">
-        <h3>Open Note</h3>
-        <input type="text" id="noteIdInput" class="id-input" placeholder="Enter note ID"/>
-        <div class="dialog-buttons">
-            <button class="dialog-btn secondary" onclick="hideIdInput()">Cancel</button>
-            <button class="dialog-btn primary" onclick="loadNoteFromInput()">Open</button>
-        </div>
-    </div>
-</div>
+<div id="modalContainer"></div>
 
-<script src="script.js"></script>
+<script src="js/components.js"></script>
+<script src="js/script.js"></script>
 <script>
-    function createNewNote() {
-        window.location.href = '/index.html';
-    }
-
-    function hideIdInput() {
-        const idInputOverlay = document.getElementById('idInputOverlay');
-        const noteIdInput = document.getElementById('noteIdInput');
-
-        if (idInputOverlay) {
-            idInputOverlay.classList.add('hidden');
-        }
-
-        if (noteIdInput) {
-            noteIdInput.value = '';
-        }
-    }
-
-    function loadNoteFromInput() {
-        const noteIdInput = document.getElementById('noteIdInput');
-        if (!noteIdInput) return;
-
-        const id = noteIdInput.value.trim();
-        if (id) {
-            hideIdInput();
-            window.location.href = `/${id}`;
-        }
-    }
-
-    document.addEventListener('DOMContentLoaded', function () {
-        initializeTheme();
-
-        const noteIdInput = document.getElementById('noteIdInput');
-        if (noteIdInput) {
-            noteIdInput.addEventListener('keypress', function (e) {
-                if (e.key === 'Enter') {
-                    loadNoteFromInput();
-                }
-            });
-        }
-    });
+document.addEventListener('DOMContentLoaded', async () => {
+    await initPage('home');
+});
 </script>
 </body>
 </html>

+ 0 - 0
src/main/resources/static/favicon.ico → src/main/resources/static/img/favicon.ico


+ 0 - 0
src/main/resources/static/logo.png → src/main/resources/static/img/logo.png


+ 12 - 22
src/main/resources/static/index.html

@@ -10,38 +10,28 @@
     <meta name="mobile-web-app-capable" content="yes">
     <meta name="application-name" content="kNotes">
     <title>kNotes</title>
-    <link rel="stylesheet" href="style.css">
+    <link rel="stylesheet" href="css/style.css">
+    <link rel="icon" type="image/x-icon" href="img/favicon.ico">
 </head>
 <body>
-<div class="header">
-    <div class="title" onclick="window.location.href='/'" style="cursor: pointer;"><img src="logo.png" alt="kNotes logo"/> kNotes</div>
-    <div class="header-right">
-        <span class="note-id" id="noteIdDisplay" style="display: none; cursor: pointer;" onclick="copyNoteLink()" title="Click to copy note link"></span>
-        <div class="theme-switch" id="themeSwitch" onclick="toggleTheme()" title="Toggle dark/light theme"></div>
-        <button class="new-btn" onclick="showIdInput()">Open</button>
-        <button class="new-btn" onclick="newNote()">New</button>
-    </div>
-</div>
+<div id="headerContainer"></div>
 
 <div id="updateToast" class="update-toast hidden">
-    Note was updated
+    📄 Note was updated
 </div>
 
 <div class="content">
     <textarea class="note-area" id="noteContent" placeholder="Start typing your note..."></textarea>
 </div>
 
-<div id="idInputOverlay" class="id-input-overlay hidden">
-    <div class="id-input-dialog">
-        <h3>Open Note</h3>
-        <input type="text" id="noteIdInput" class="id-input" placeholder="Enter note ID"/>
-        <div class="dialog-buttons">
-            <button class="dialog-btn secondary" onclick="hideIdInput()">Cancel</button>
-            <button class="dialog-btn primary" onclick="loadNoteFromInput()">Open</button>
-        </div>
-    </div>
-</div>
+<div id="modalContainer"></div>
 
-<script src="script.js"></script>
+<script src="js/components.js"></script>
+<script src="js/script.js"></script>
+<script>
+document.addEventListener('DOMContentLoaded', async () => {
+    await initPage('editor');
+});
+</script>
 </body>
 </html>

+ 74 - 0
src/main/resources/static/js/components.js

@@ -0,0 +1,74 @@
+// Enhanced component loader
+async function loadComponent(componentPath, targetId, customizations = {}) {
+    try {
+        const response = await fetch(componentPath);
+        if (!response.ok) throw new Error(`Failed to load ${componentPath}`);
+
+        let html = await response.text();
+
+        // Apply customizations
+        Object.entries(customizations).forEach(([placeholder, value]) => {
+            html = html.replace(new RegExp(`{{${placeholder}}}`, 'g'), value);
+        });
+
+        const targetElement = document.getElementById(targetId);
+        if (targetElement) {
+            targetElement.innerHTML = html;
+        }
+    } catch (error) {
+        console.error('Component loading failed:', error);
+    }
+}
+
+// Page configurations
+const PAGE_CONFIGS = {
+    editor: {
+        header: `
+            <span class="note-id" id="noteIdDisplay" style="display: none; cursor: pointer;" onclick="copyNoteLink()" title="Click to copy note link"></span>
+            <div class="theme-switch" id="themeSwitch" onclick="toggleTheme()" title="Toggle dark/light theme"></div>
+            <button class="new-btn" onclick="showIdInput()">Open</button>
+            <button class="new-btn" onclick="newNote()">New</button>
+        `,
+        needsModal: true,
+        needsToast: true
+    },
+    home: {
+        header: `
+            <div class="theme-switch" id="themeSwitch" onclick="toggleTheme()" title="Toggle dark/light theme"></div>
+        `,
+        needsModal: true,
+        needsToast: false
+    },
+    error: {
+        header: `
+            <div class="theme-switch" id="themeSwitch" onclick="toggleTheme()" title="Toggle dark/light theme"></div>
+            <button class="new-btn" onclick="window.location.href='/'">Home</button>
+        `,
+        needsModal: true,
+        needsToast: false
+    }
+};
+
+// Initialize page components
+async function initPage(pageType) {
+    const config = PAGE_CONFIGS[pageType];
+    if (!config) {
+        console.error('Unknown page type:', pageType);
+        return;
+    }
+
+    // Load header
+    await loadComponent('/components/header.html', 'headerContainer', {
+        HEADER_CONTENT: config.header
+    });
+
+    // Load modal if needed
+    if (config.needsModal) {
+        await loadComponent('/components/modal.html', 'modalContainer');
+    }
+
+    // Initialize theme
+    if (typeof initializeTheme === 'function') {
+        initializeTheme();
+    }
+}

+ 4 - 8
src/main/resources/static/script.js → src/main/resources/static/js/script.js

@@ -13,10 +13,7 @@ function initializeTheme() {
     const body = document.body;
     const themeSwitch = document.getElementById('themeSwitch');
 
-    if (!themeSwitch) {
-        console.error('Theme switch element not found');
-        return;
-    }
+    if (!themeSwitch) return;
 
     // Apply the theme
     if (savedTheme === 'dark') {
@@ -26,16 +23,15 @@ function initializeTheme() {
         body.removeAttribute('data-theme');
         themeSwitch.classList.remove('dark');
     }
+
+    updateThemeColor();
 }
 
 function toggleTheme() {
     const body = document.body;
     const themeSwitch = document.getElementById('themeSwitch');
 
-    if (!themeSwitch) {
-        console.error('Theme switch element not found');
-        return;
-    }
+    if (!themeSwitch) return;
 
     // Toggle between light and dark themes
     const currentTheme = body.getAttribute('data-theme');