Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>KaizenGO AI - Ollama Powered Task Coach</title> | |
| <!-- Font Awesome for Icons --> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| :root { | |
| --bg-color: #1E1E1E; | |
| --text-color: #E0E0E0; | |
| --ai-color: #569CD6; | |
| --done-color: #6A9955; | |
| --button-bg: #2D2D30; | |
| --accent-color: #007ACC; | |
| --input-bg: #3C3C3C; | |
| --list-bg: #252526; | |
| --border-color: #3E3E42; | |
| --font-main: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| --font-code: 'Consolas', 'Courier New', monospace; | |
| } | |
| * { | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| } | |
| body { | |
| background-color: var(--bg-color); | |
| color: var(--text-color); | |
| font-family: var(--font-main); | |
| height: 100vh; | |
| display: flex; | |
| flex-direction: column; | |
| overflow: hidden; | |
| } | |
| /* Header */ | |
| header { | |
| background-color: #252526; | |
| padding: 15px 20px; | |
| border-bottom: 1px solid var(--border-color); | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| } | |
| h1 { | |
| font-size: 1.2rem; | |
| color: var(--accent-color); | |
| font-weight: 600; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .status-bar { | |
| display: flex; | |
| gap: 15px; | |
| font-size: 0.85rem; | |
| } | |
| .status-item { | |
| display: flex; | |
| align-items: center; | |
| gap: 6px; | |
| } | |
| .status-active { color: #4CAF50; } | |
| .status-offline { color: #FF5252; } | |
| .status-checking { color: #FFC107; } | |
| .anycoder-link { | |
| font-size: 0.75rem; | |
| color: #858585; | |
| text-decoration: none; | |
| opacity: 0.8; | |
| } | |
| .anycoder-link:hover { opacity: 1; color: var(--accent-color); } | |
| /* Main Layout */ | |
| .container { | |
| display: flex; | |
| flex: 1; | |
| overflow: hidden; | |
| } | |
| /* Sidebar (Task List) */ | |
| .sidebar { | |
| width: 320px; | |
| background-color: var(--bg-color); | |
| border-right: 1px solid var(--border-color); | |
| display: flex; | |
| flex-direction: column; | |
| padding: 10px; | |
| flex-shrink: 0; | |
| } | |
| .section-title { | |
| font-size: 1.1rem; | |
| color: var(--accent-color); | |
| margin-bottom: 10px; | |
| font-weight: 600; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| } | |
| .stats-bar { | |
| font-size: 0.8rem; | |
| color: #858585; | |
| margin-bottom: 15px; | |
| padding-bottom: 10px; | |
| border-bottom: 1px solid var(--border-color); | |
| } | |
| .task-list-container { | |
| flex: 1; | |
| background-color: var(--list-bg); | |
| border-radius: 4px; | |
| overflow-y: auto; | |
| padding: 5px; | |
| margin-bottom: 15px; | |
| border: 1px solid var(--border-color); | |
| } | |
| .task-item { | |
| padding: 10px; | |
| margin-bottom: 5px; | |
| background-color: var(--button-bg); | |
| border-radius: 4px; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| border-left: 3px solid transparent; | |
| } | |
| .task-item:hover { | |
| background-color: #3a3a3c; | |
| } | |
| .task-item.selected { | |
| border-left: 3px solid var(--accent-color); | |
| background-color: #2D2D30; | |
| box-shadow: 0 2px 4px rgba(0,0,0,0.3); | |
| } | |
| .task-item.done { | |
| opacity: 0.6; | |
| text-decoration: line-through; | |
| border-left-color: var(--done-color); | |
| } | |
| .task-title { | |
| font-size: 0.95rem; | |
| font-weight: 500; | |
| } | |
| .task-meta { | |
| font-size: 0.75rem; | |
| color: #999; | |
| margin-top: 4px; | |
| display: flex; | |
| gap: 10px; | |
| } | |
| /* Quick Actions */ | |
| .quick-actions { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 10px; | |
| margin-bottom: 15px; | |
| } | |
| .action-btn { | |
| padding: 8px; | |
| background-color: var(--button-bg); | |
| color: var(--text-color); | |
| border: 1px solid var(--border-color); | |
| border-radius: 4px; | |
| cursor: pointer; | |
| font-size: 0.85rem; | |
| transition: background 0.2s; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 6px; | |
| } | |
| .action-btn:hover { | |
| background-color: #3E3E42; | |
| border-color: var(--accent-color); | |
| } | |
| /* Task Management Buttons */ | |
| .task-controls { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr 1fr; | |
| gap: 5px; | |
| margin-bottom: 15px; | |
| } | |
| .control-btn { | |
| padding: 6px; | |
| background-color: var(--button-bg); | |
| color: var(--text-color); | |
| border: 1px solid var(--border-color); | |
| border-radius: 3px; | |
| cursor: pointer; | |
| font-size: 0.8rem; | |
| } | |
| .control-btn:hover { | |
| background-color: #3E3E42; | |
| } | |
| /* Main Chat Area */ | |
| .main-area { | |
| flex: 1; | |
| display: flex; | |
| flex-direction: column; | |
| padding: 20px; | |
| overflow: hidden; | |
| background-color: var(--bg-color); | |
| } | |
| .chat-header { | |
| margin-bottom: 15px; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| } | |
| .chat-display { | |
| flex: 1; | |
| background-color: var(--list-bg); | |
| border-radius: 8px; | |
| padding: 20px; | |
| overflow-y: auto; | |
| margin-bottom: 20px; | |
| border: 1px solid var(--border-color); | |
| font-family: var(--font-code); | |
| font-size: 0.95rem; | |
| line-height: 1.5; | |
| box-shadow: inset 0 0 10px rgba(0,0,0,0.5); | |
| } | |
| .message { | |
| margin-bottom: 15px; | |
| padding: 10px 15px; | |
| border-radius: 8px; | |
| max-width: 90%; | |
| animation: fadeIn 0.3s ease; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(5px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .msg-ai { | |
| background-color: #252526; | |
| border-left: 4px solid var(--ai-color); | |
| align-self: flex-start; | |
| } | |
| .msg-system { | |
| background-color: #2D2D30; | |
| color: #ccc; | |
| font-style: italic; | |
| font-size: 0.85rem; | |
| align-self: center; | |
| text-align: center; | |
| max-width: 100%; | |
| border-radius: 20px; | |
| width: fit-content; | |
| } | |
| .msg-user { | |
| background-color: var(--accent-color); | |
| color: white; | |
| align-self: flex-end; | |
| margin-left: auto; | |
| border-radius: 8px 8px 0 8px; | |
| } | |
| .msg-steps { | |
| background-color: #1a2e1a; | |
| border-left: 4px solid var(--done-color); | |
| color: #b8e0b8; | |
| font-family: var(--font-code); | |
| } | |
| .chat-input-area { | |
| display: flex; | |
| gap: 10px; | |
| background-color: var(--button-bg); | |
| padding: 10px; | |
| border-radius: 8px; | |
| border: 1px solid var(--border-color); | |
| } | |
| .chat-input { | |
| flex: 1; | |
| background-color: var(--input-bg); | |
| color: var(--text-color); | |
| border: 1px solid var(--border-color); | |
| border-radius: 4px; | |
| padding: 10px; | |
| font-family: var(--font-main); | |
| font-size: 1rem; | |
| outline: none; | |
| } | |
| .chat-input:focus { | |
| border-color: var(--accent-color); | |
| } | |
| .send-btn { | |
| background-color: var(--accent-color); | |
| color: white; | |
| border: none; | |
| border-radius: 4px; | |
| padding: 0 20px; | |
| cursor: pointer; | |
| font-weight: 600; | |
| transition: background 0.2s; | |
| } | |
| .send-btn:hover { | |
| background-color: #0062a3; | |
| } | |
| /* Settings Row */ | |
| .settings-row { | |
| margin-top: 15px; | |
| display: flex; | |
| gap: 10px; | |
| align-items: center; | |
| flex-wrap: wrap; | |
| } | |
| .setting-item { | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| background-color: var(--button-bg); | |
| padding: 5px 10px; | |
| border-radius: 4px; | |
| border: 1px solid var(--border-color); | |
| } | |
| select, input[type="text"] { | |
| background-color: var(--input-bg); | |
| color: var(--text-color); | |
| border: none; | |
| padding: 5px; | |
| border-radius: 3px; | |
| font-family: var(--font-main); | |
| } | |
| .search-btn { | |
| background-color: var(--accent-color); | |
| color: white; | |
| border: none; | |
| padding: 5px 10px; | |
| border-radius: 3px; | |
| cursor: pointer; | |
| } | |
| .tool-btn { | |
| background-color: var(--button-bg); | |
| color: var(--text-color); | |
| border: 1px solid var(--border-color); | |
| padding: 5px 10px; | |
| border-radius: 3px; | |
| cursor: pointer; | |
| } | |
| .tool-btn:hover { | |
| background-color: #3E3E42; | |
| } | |
| /* Responsive */ | |
| @media (max-width: 768px) { | |
| .container { | |
| flex-direction: column; | |
| } | |
| .sidebar { | |
| width: 100%; | |
| height: 30%; | |
| border-right: none; | |
| border-bottom: 1px solid var(--border-color); | |
| } | |
| .main-area { | |
| height: 70%; | |
| } | |
| .task-controls { | |
| grid-template-columns: 1fr 1fr; | |
| } | |
| .control-btn:last-child { | |
| grid-column: span 2; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <header> | |
| <h1><i class="fa-solid fa-robot"></i> KaizenGO AI <span style="font-size: 0.8em; opacity: 0.7;">- Ollama Powered</span></h1> | |
| <div class="status-bar"> | |
| <div class="status-item" id="ollamaStatus"> | |
| <i class="fa-solid fa-wifi"></i> <span id="statusText">Checking...</span> | |
| </div> | |
| <div class="status-item"> | |
| <i class="fa-solid fa-list"></i> <span id="totalTasksDisplay">0 Tasks</span> | |
| </div> | |
| </div> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" class="anycoder-link" target="_blank"> | |
| Built with anycoder | |
| </a> | |
| </header> | |
| <div class="container"> | |
| <!-- Sidebar --> | |
| <aside class="sidebar"> | |
| <div class="section-title"><i class="fa-solid fa-clipboard-list"></i> Your Tasks</div> | |
| <div class="stats-bar" id="taskStats"> | |
| Total: 0 | Pending: 0 | Done: 0 | |
| </div> | |
| <div class="task-list-container" id="taskList"> | |
| <!-- Tasks will be injected here --> | |
| <div style="text-align: center; color: #555; margin-top: 20px; font-style: italic;"> | |
| No tasks yet.<br>Click "New Task" to start. | |
| </div> | |
| </div> | |
| <div class="section-title" style="font-size: 1rem; margin-top: 10px;"><i class="fa-solid fa-bolt"></i> Quick Actions</div> | |
| <div class="quick-actions"> | |
| <button class="action-btn" onclick="app.startTaskCreation()"> | |
| <i class="fa-solid fa-plus"></i> New Task | |
| </button> | |
| <button class="action-btn" onclick="app.startDailyCheckin()"> | |
| <i class="fa-solid fa-sun"></i> Daily Check-in | |
| </button> | |
| </div> | |
| <div class="section-title" style="font-size: 1rem; margin-top: 10px;"><i class="fa-solid fa-gear"></i> Task Controls</div> | |
| <div class="task-controls"> | |
| <button class="control-btn" onclick="app.analyzeSelected()"><i class="fa-solid fa-magnifying-glass"></i> Analyze</button> | |
| <button class="control-btn" onclick="app.toggleDone()"><i class="fa-solid fa-check-circle"></i> Done</button> | |
| <button class="control-btn" onclick="app.editTask()"><i class="fa-solid fa-pen-to-square"></i> Edit</button> | |
| <button class="control-btn" onclick="app.deleteTask()"><i class="fa-solid fa-trash"></i> Delete</button> | |
| <button class="control-btn" onclick="app.viewSteps()"><i class="fa-solid fa-list-ol"></i> Steps</button> | |
| <button class="control-btn" onclick="app.exportTasks()"><i class="fa-solid fa-file-arrow-down"></i> Export</button> | |
| </div> | |
| <div style="margin-top: auto; padding-top: 15px; border-top: 1px solid var(--border-color);"> | |
| <button class="action-btn" style="width: 100%; justify-content: center;" onclick="app.testOllama()"> | |
| <i class="fa-solid fa-wrench"></i> Test AI Connection | |
| </button> | |
| </div> | |
| </aside> | |
| <!-- Main Chat Area --> | |
| <main class="main-area"> | |
| <div class="chat-header"> | |
| <div> | |
| <div class="section-title" style="margin:0;"><i class="fa-solid fa-comments"></i> AI Assistant</div> | |
| <div style="font-size: 0.8rem; color: #858585;">Powered by Ollama (Simulated Model: exaone3.5:2.4b)</div> | |
| </div> | |
| <button class="tool-btn" onclick="app.clearChat()"><i class="fa-solid fa-rotate-right"></i> Clear Chat</button> | |
| </div> | |
| <div class="chat-display" id="chatDisplay"> | |
| <!-- Chat history goes here --> | |
| </div> | |
| <div class="chat-input-area"> | |
| <input type="text" id="chatInput" class="chat-input" placeholder="Type your message here..." autocomplete="off"> | |
| <button class="send-btn" onclick="app.processUserResponse()"> | |
| <i class="fa-solid fa-paper-plane"></i> Send | |
| </button> | |
| </div> | |
| <div class="settings-row"> | |
| <div class="setting-item"> | |
| <label>Font Size:</label> | |
| <select id="fontSizeSelector" onchange="app.changeFontSize(this.value)"> | |
| <option value="10">10</option> | |
| <option value="12" selected>12</option> | |
| <option value="14">14</option> | |
| <option value="16">16</option> | |
| </select> | |
| </div> | |
| <div class="setting-item" style="flex-direction: row;"> | |
| <i class="fa-solid fa-search"></i> | |
| <input type="text" id="searchInput" placeholder="Filter tasks..." oninput="app.searchTasks(this.value)"> | |
| <button class="search-btn" onclick="app.searchTasks(document.getElementById('searchInput').value)">Filter</button> | |
| <button class="tool-btn" onclick="app.resetSearch()"><i class="fa-solid fa-xmark"></i></button> | |
| </div> | |
| <div class="setting-item"> | |
| <button class="tool-btn" onclick="app.showHelp()"><i class="fa-solid fa-circle-question"></i> Help</button> | |
| <button class="tool-btn" onclick="app.showSettings()"><i class="fa-solid fa-sliders"></i> Settings</button> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <script> | |
| // --- Application Logic --- | |
| class KaizenGOApp { | |
| constructor() { | |
| this.tasks = []; | |
| this.config = { | |
| fontSize: 12, | |
| ollamaUrl: "http://localhost:11434/api/generate", | |
| ollamaModel: "exaone3.5:2.4b" | |
| }; | |
| this.conversation = { | |
| mode: '', // '', 'task_creation', 'task_breakdown', 'daily_checkin' | |
| step: 0, | |
| context: {}, | |
| answers: [] | |
| }; | |
| this.selectedTaskId = null; | |
| // Initialize | |
| this.init(); | |
| } | |
| init() { | |
| this.loadFromStorage(); | |
| this.renderTasks(); | |
| this.updateStats(); | |
| this.addSystemMessage("Welcome to KaizenGO AI! I'm ready to help you organize your tasks."); | |
| this.addSystemMessage("Click 'New Task' to start a guided conversation with the AI."); | |
| // Setup Enter key for chat | |
| document.getElementById('chatInput').addEventListener('keypress', (e) => { | |
| if (e.key === 'Enter') this.processUserResponse(); | |
| }); | |
| } | |
| // --- Storage Management --- | |
| loadFromStorage() { | |
| const storedTasks = localStorage.getItem('kaizenTasks'); | |
| const storedConfig = localStorage.getItem('kaizenConfig'); | |
| if (storedTasks) this.tasks = JSON.parse(storedTasks); | |
| if (storedConfig) this.config = { ...this.config, ...JSON.parse(storedConfig) }; | |
| // Apply font | |
| document.getElementById('fontSizeSelector').value = this.config.fontSize; | |
| this.changeFontSize(this.config.fontSize); | |
| } | |
| saveToStorage() { | |
| localStorage.setItem('kaizenTasks', JSON.stringify(this.tasks)); | |
| localStorage.setItem('kaizenConfig', JSON.stringify(this.config)); | |
| } | |
| // --- Task Management --- | |
| renderTasks(filterText = "") { | |
| const listContainer = document.getElementById('taskList'); | |
| listContainer.innerHTML = ''; | |
| let filteredTasks = this.tasks; | |
| if (filterText) { | |
| filteredTasks = this.tasks.filter(t => t.title.toLowerCase().includes(filterText.toLowerCase())); | |
| } | |
| if (filteredTasks.length === 0) { | |
| listContainer.innerHTML = '<div style="text-align: center; color: #555; margin-top: 20px; font-style: italic;">No tasks found.</div>'; | |
| } else { | |
| filteredTasks.forEach(task => { | |
| const taskEl = document.createElement('div'); | |
| taskEl.className = `task-item ${task.done ? 'done' : ''} ${this.selectedTaskId === task.id ? 'selected' : ''}`; | |
| taskEl.onclick = () => this.selectTask(task.id); | |
| taskEl.innerHTML = ` | |
| <div class="task-title">${task.title} ${task.done ? '<i class="fa-solid fa-check" style="float:right; color:var(--done-color)"></i>' : ''}</div> | |
| <div class="task-meta"> | |
| <span>${task.done ? 'Completed' : 'Pending'}</span> | |
| <span>${task.created}</span> | |
| </div> | |
| `; | |
| listContainer.appendChild(taskEl); | |
| }); | |
| } | |
| this.updateStats(); | |
| } | |
| updateStats() { | |
| const total = this.tasks.length; | |
| const done = this.tasks.filter(t => t.done).length; | |
| const pending = total - done; | |
| document.getElementById('taskStats').innerText = `Total: ${total} | Pending: ${pending} | Done: ${done}`; | |
| document.getElementById('totalTasksDisplay').innerText = `${total} Tasks`; | |
| } | |
| selectTask(id) { | |
| this.selectedTaskId = id; | |
| this.renderTasks(document.getElementById('searchInput').value); | |
| } | |
| getSelectedTask() { | |
| return this.tasks.find(t => t.id === this.selectedTaskId); | |
| } | |
| generateId() { | |
| return 'TASK_' + Math.floor(Math.random() * 100000).toString().padStart(5, '0'); | |
| } | |
| addTask(title, details = {}) { | |
| const newTask = { | |
| id: this.generateId(), | |
| title: title, | |
| done: false, | |
| created: new Date().toLocaleDateString(), | |
| ...details, | |
| steps: details.steps || [] | |
| }; | |
| this.tasks.push(newTask); | |
| this.saveToStorage(); | |
| this.renderTasks(); | |
| this.addSystemMessage(`✅ Task created: ${title}`); | |
| } | |
| deleteTask() { | |
| if (!this.selectedTaskId) { | |
| this.addSystemMessage("⚠️ Please select a task to delete."); | |
| return; | |
| } | |
| if (confirm("Are you sure you want to delete this task?")) { | |
| this.tasks = this.tasks.filter(t => t.id !== this.selectedTaskId); | |
| this.selectedTaskId = null; | |
| this.saveToStorage(); | |
| this.renderTasks(); | |
| this.addSystemMessage("Task deleted."); | |
| } | |
| } | |
| editTask() { | |
| const task = this.getSelectedTask(); | |
| if (!task) { | |
| this.addSystemMessage("⚠️ Please select a task to edit."); | |
| return; | |
| } | |
| const newTitle = prompt("Edit task title:", task.title); | |
| if (newTitle && newTitle.trim() !== "") { | |
| task.title = newTitle.trim(); | |
| this.saveToStorage(); | |
| this.renderTasks(); | |
| this.addSystemMessage("Task updated."); | |
| } | |
| } | |
| toggleDone() { | |
| const task = this.getSelectedTask(); | |
| if (!task) { | |
| this.addSystemMessage("⚠️ Please select a task."); | |
| return; | |
| } | |
| task.done = !task.done; | |
| if (task.done) { | |
| task.completed = new Date().toLocaleDateString(); | |
| this.addSystemMessage(`🎉 Task marked as done: ${task.title}`); | |
| } else { | |
| this.addSystemMessage(`🔄 Task reopened: ${task.title}`); | |
| } | |
| this.saveToStorage(); | |
| this.renderTasks(); | |
| } | |
| exportTasks() { | |
| if (this.tasks.length === 0) { | |
| this.addSystemMessage("No tasks to export."); | |
| return; | |
| } | |
| let content = "KAIZENG EXPORT\n\n"; | |
| this.tasks.forEach(t => { | |
| content += `[${t.done ? 'DONE' : 'PENDING'}] ${t.title}\n`; | |
| if (t.steps.length > 0) { | |
| t.steps.forEach((s, i) => content += ` ${i+1}. ${s}\n`); | |
| } | |
| content += "\n"; | |
| }); | |
| const blob = new Blob([content], { type: 'text/plain' }); | |
| const url = window.URL.createObjectURL(blob); | |
| const a = document.createElement('a'); | |
| a.href = url; | |
| a.download = 'kaizeng_tasks.txt'; | |
| a.click(); | |
| window.URL.revokeObjectURL(url); | |
| this.addSystemMessage("💾 Tasks exported successfully."); | |
| } | |
| searchTasks(filter) { | |
| this.renderTasks(filter); | |
| } | |
| resetSearch() { | |
| document.getElementById('searchInput').value = ""; | |
| this.renderTasks(); | |
| } | |
| // --- Chat & AI Logic (Simulated) --- | |
| addMessage(sender, text, type = 'text') { | |
| const chatDisplay = document.getElementById('chatDisplay'); | |
| const msgDiv = document.createElement('div'); | |
| let senderClass = 'msg-system'; | |
| let senderIcon = 'ℹ️'; | |
| if (sender === 'AI') { | |
| senderClass = 'msg-ai'; | |
| senderIcon = '🤖 AI:'; | |
| } else if (sender === 'You') { | |
| senderClass = 'msg-user'; | |
| senderIcon = '👤 You:'; | |
| } else if (sender === 'Steps') { | |
| senderClass = 'msg-steps'; | |
| senderIcon = '📋 Plan:'; | |
| } | |
| // Format text (convert newlines to <br>) | |
| const formattedText = text.replace(/\n/g, '<br>'); | |
| msgDiv.className = `message ${senderClass}`; | |
| msgDiv.innerHTML = `<strong>${senderIcon}</strong> ${formattedText}`; | |
| chatDisplay.appendChild(msgDiv); | |
| chatDisplay.scrollTop = chatDisplay.scrollHeight; | |
| } | |
| addSystemMessage(text) { | |
| this.addMessage('System', text); | |
| } | |
| clearChat() { | |
| document.getElementById('chatDisplay').innerHTML = ''; | |
| this.conversation.mode = ''; | |
| this.conversation.step = 0; | |
| this.conversation.answers = []; | |
| this.addSystemMessage("Chat cleared. How can I help you?"); | |
| } | |
| processUserResponse() { | |
| const inputEl = document.getElementById('chatInput'); | |
| const message = inputEl.value.trim(); | |
| if (!message) return; | |
| this.addMessage('You', message); | |
| inputEl.value = ''; | |
| // Handle based on mode | |
| if (this.conversation.mode === 'task_creation') { | |
| this.handleTaskCreationFlow(message); | |
| } else if (this.conversation.mode === 'task_breakdown') { | |
| this.handleTaskBreakdownFlow(message); | |
| } else if (this.conversation.mode === 'daily_checkin') { | |
| this.handleDailyCheckinFlow(message); | |
| } else { | |
| this.handleGeneralChat(message); | |
| } | |
| } | |
| // --- AI Conversation Flows (Simulating Ollama) --- | |
| startTaskCreation() { | |
| this.conversation.mode = 'task_creation'; | |
| this.conversation.step = 0; | |
| this.conversation.answers = []; | |
| this.conversation.context = {}; | |
| this.addSystemMessage("Starting New Task Creation Wizard..."); | |
| this.simulateAiThinking(() => { | |
| this.conversation.step = 1; | |
| this.addMessage('AI', "Hello! I'm here to help you create a clear, actionable task. 🌟\n\nWhat would you like to accomplish? Keep it friendly and specific."); | |
| }); | |
| } | |
| handleTaskCreationFlow(response) { | |
| this.conversation.answers.push(response); | |
| if (this.conversation.step === 1) { | |
| this.simulateAiThinking(() => { | |
| this.conversation.step = 2; | |
| this.addMessage('AI', `Got it! You want to "${response}".\n\nWhy is this important to you right now? What will completing this enable or give you?`); | |
| }); | |
| } else if (this.conversation.step === 2) { | |
| this.simulateAiThinking(() => { | |
| this.conversation.step = 3; | |
| this.addMessage('AI', `That's a great motivation: "${response}".\n\nWhen would you like this completed? (e.g., By Friday, End of month)`); | |
| }); | |
| } else if (this.conversation.step === 3) { | |
| this.simulateAiThinking(() => { | |
| this.conversation.step = 4; | |
| this.addMessage('AI', `Deadline set: "${response}".\n\nWhat challenges or obstacles might make this difficult for you?`); | |
| }); | |
| } else if (this.conversation.step === 4) { | |
| this.simulateAiThinking(() => { | |
| this.conversation.step = 5; | |
| this.addMessage('AI', `Obstacles noted: "${response}".\n\nFinally, on a scale of 1-10, how clear are you on your FIRST step? (1=Unclear, 10=Crystal clear)`); | |
| }); | |
| } else if (this.conversation.step === 5) { | |
| this.simulateAiThinking(() => { | |
| this.conversation.mode = ''; | |
| this.conversation.step = 0; | |
| // Generate Final Task | |
| const taskTitle = this.conversation.answers[0]; | |
| const taskWhy = this.conversation.answers[1]; | |
| const taskDeadline = this.conversation.answers[2]; | |
| const taskObstacles = this.conversation.answers[3]; | |
| const taskClarity = this.conversation.answers[4]; | |
| // Generate "AI" Steps | |
| let steps = []; | |
| if (parseInt(taskClarity) < 5) { | |
| steps = [ | |
| "Research information related to the task", | |
| "Break the main goal into smaller sub-goals", | |
| "Identify resources needed", | |
| "Draft a preliminary plan", | |
| "Review and refine the plan" | |
| ]; | |
| } else { | |
| steps = [ | |
| "Start with the most critical sub-task immediately", | |
| "Gather any missing tools or resources", | |
| "Execute Step 1 of the main plan", | |
| "Review progress at the end of the day", | |
| "Adjust plan based on initial results" | |
| ]; | |
| } | |
| this.addTask(taskTitle, { | |
| why: taskWhy, | |
| deadline: taskDeadline, | |
| obstacles: taskObstacles, | |
| steps: steps | |
| }); | |
| this.addMessage('AI', `🎉 Task Created Successfully! "${taskTitle}" is now in your list.\n\nI've generated a plan based on your inputs. Remember your "Why": ${taskWhy}.\n\nGood luck!`); | |
| }); | |
| } | |
| } | |
| startDailyCheckin() { | |
| this.conversation.mode = 'daily_checkin'; | |
| this.conversation.step = 0; | |
| this.conversation.answers = []; | |
| this.addSystemMessage("Starting Daily Check-in..."); | |
| this.simulateAiThinking(() => { | |
| this.conversation.step = 1; | |
| this.addMessage('AI', "Good morning! 👋\n\nHow are you feeling about your tasks today? Are you feeling:\n1. Energized\n2. Overwhelmed\n3. Unsure where to start\n4. Procrastinating"); | |
| }); | |
| } | |
| handleDailyCheckinFlow(response) { | |
| this.conversation.answers.push(response); | |
| if (this.conversation.step === 1) { | |
| this.simulateAiThinking(() => { | |
| this.conversation.step = 2; | |
| this.conversation.mode = ''; | |
| let guidance = ""; | |
| if (response.toLowerCase().includes("energized")) { | |
| guidance = "That's fantastic! Use this energy to tackle the most challenging task on your list first."; | |
| } else if (response.toLowerCase().includes("overwhelmed")) { | |
| guidance = "Take a deep breath. Let's break down your biggest task into a 5-minute action step. What's the very first physical movement needed?"; | |
| } else if (response.toLowerCase().includes("unsure")) { | |
| guidance = "It's okay. Let's look at your task list. Pick ONE task that takes less than 15 minutes. Completing small wins builds momentum."; | |
| } else { | |
| guidance = "We've all been there. Set a timer for 25 minutes (Pomodoro). Just focus on opening the file or logging in. Action precedes motivation."; | |
| } | |
| this.addMessage('AI', `I understand you're feeling "${response}".\n\n${guidance}`); | |
| }); | |
| } | |
| } | |
| analyzeSelected() { | |
| const task = this.getSelectedTask(); | |
| if (!task) { | |
| this.addSystemMessage("⚠️ Please select a task to analyze."); | |
| return; | |
| } | |
| this.conversation.mode = 'task_breakdown'; | |
| this.conversation.step = 0; | |
| this.conversation.answers = []; | |
| this.conversation.currentTaskId = task.id; | |
| this.addSystemMessage(`Analyzing: "${task.title}"...`); | |
| this.simulateAiThinking(() => { | |
| this.conversation.step = 1; | |
| this.addMessage('AI', `I see the task: "${task.title}".\n\nTo help you break this down, can you tell me WHY completing this task is important to you? What will it give you?`); | |
| }); | |
| } | |
| handleTaskBreakdownFlow(response) { | |
| this.conversation.answers.push(response); | |
| if (this.conversation.step === 1) { | |
| this.simulateAiThinking(() => { | |
| this.conversation.step = 2; | |
| this.addMessage('AI', `Understood: "${response}".\n\nOkay, for the task "${this.tasks.find(t=>t.id === this.conversation.currentTaskId)?.title}", what are the 3-5 smallest chunks you can imagine? Don't worry about order yet.`); | |
| }); | |
| } else if (this.conversation.step === 2) { | |
| this.simulateAiThinking(() => { | |
| this.conversation.step = 3; | |
| this.addMessage('AI', `Chunks noted: "${response}".\n\nIf you had to do ONE of these chunks right now (next 2 hours), which one would it be?`); | |
| }); | |
| } else if (this.conversation.step === 3) { | |
| this.simulateAiThinking(() => { | |
| this.conversation.mode = ''; | |
| this.conversation.step = 0; | |
| const task = this.tasks.find(t => t.id === this.conversation.currentTaskId); | |
| if (task) { | |
| task.steps = [ | |
| `Start with: "${response}" (Quick Win)`, | |
| "Gather resources needed for other chunks", | |
| "Execute Chunk 2", | |
| "Execute Chunk 3", | |
| "Review and Integrate results" | |
| ]; | |
| this.saveToStorage(); | |
| this.renderTasks(); | |
| this.addMessage('AI', "✅ Action Plan Generated!\n\nI've updated your task with a step-by-step plan. Start with your 'Quick Win' to build momentum!"); | |
| this.viewSteps(); | |
| } | |
| }); | |
| } | |
| } | |
| handleGeneralChat(message) { | |
| this.simulateAiThinking(() => { | |
| let response = "I'm here to help with task management! \n\nTry:\n• 'Create a new task'\n• 'Check my stats'\n• 'Help'\n• Analyze a selected task"; | |
| const lowerMsg = message.toLowerCase(); | |
| if (lowerMsg.includes("help")) { | |
| response = "📖 HELP\n\nSETUP: If Ollama is offline, you can still use the app for basic task management.\n\nFEATURES:\n• 'New Task' - Guided AI creation\n• 'Analyze' - Deep dive into selected task\n• Chat - Ask for motivation or tips"; | |
| } else if (lowerMsg.includes("stats") || lowerMsg.includes("statistics")) { | |
| const total = this.tasks.length; | |
| const done = this.tasks.filter(t => t.done).length; | |
| response = `📊 CURRENT STATUS\nTotal Tasks: ${total}\nCompleted: ${done}\nPending: ${total - done}`; | |
| } else if (lowerMsg.includes("hello") || lowerMsg.includes("hi")) { | |
| response = "Hello there! Ready to be productive today? ☀️"; | |
| } | |
| this.addMessage('AI', response); | |
| }); | |
| } | |
| viewSteps() { | |
| const task = this.getSelectedTask(); | |
| if (!task) { | |
| this.addSystemMessage("⚠️ Please select a task to view steps."); | |
| return; | |
| } | |
| if (!task.steps || task.steps.length === 0) { | |
| this.addSystemMessage("No steps defined for this task. Try clicking 'Analyze' first!"); | |
| return; | |
| } | |
| let stepsText = `📋 Action Plan for: ${task.title}\n`; | |
| if (task.why) stepsText += `🎯 Purpose: ${task.why}\n`; | |
| stepsText += "\n"; | |
| task.steps.forEach((step, index) => { | |
| stepsText += `${index + 1}. ${step}\n`; | |
| }); | |
| this.addMessage('Steps', stepsText); | |
| } | |
| testOllamaConnection() { | |
| this.addSystemMessage("Testing AI Connection..."); | |
| const statusEl = document.getElementById('ollamaStatus'); | |
| const statusText = document.getElementById('statusText'); | |
| statusEl.className = "status-item status-checking"; | |
| statusText.innerText = "Testing..."; | |
| setTimeout(() => { | |
| // In a real app, this would be an API call. | |
| // Here we simulate success because we are in a browser. | |
| statusEl.className = "status-item status-active"; | |
| statusText.innerText = "Online (Simulated)"; | |
| this.addSystemMessage("✅ Connection Test Successful! (Simulated Mode)\n\n*Note: Real Ollama connection requires a backend server due to browser CORS policies."); | |
| }, 1500); | |
| } | |
| changeFontSize(size) { | |
| document.body.style.fontSize = `${size}px`; | |
| this.config.fontSize = size; | |
| this.saveToStorage(); | |
| } | |
| showHelp() { | |
| this.addMessage('AI', "📖 HELP\n\n1. New Task: Use the AI to guide you through creating a plan.\n2. Analyze: Deep dive into an existing task to break it down.\n3. Daily Check-in: Start your day with a focused mindset.\n4. Filter: Use the search bar to find tasks quickly.\n\nNeed more? Ask me 'Help' anytime!"); | |
| } | |
| showSettings() { | |
| const newUrl = prompt("Ollama API URL:", this.config.ollamaUrl); | |
| if (newUrl) { | |
| this.config.ollamaUrl = newUrl; | |
| this.saveToStorage(); | |
| this.addSystemMessage("Settings saved."); | |
| } | |
| } | |
| simulateAiThinking(callback) { | |
| // Visual feedback | |
| const input = document.getElementById('chatInput'); | |
| const originalPlaceholder = input.placeholder; | |
| input.placeholder = "AI is thinking..."; | |
| input.disabled = true; | |
| setTimeout(() => { | |
| input.placeholder = originalPlaceholder; | |
| input.disabled = false; | |
| input.focus(); | |
| if (callback) callback(); | |
| }, 1000 + Math.random() * 500); // Random delay 1-1.5s | |
| } | |
| } | |
| // Start the App | |
| const app = new KaizenGOApp(); | |
| </script> | |
| </body> | |
| </html> |