feat: implement three-mode UI system (Easy / Pro / Chat)

Add switchable UI modes with conditional rendering:
- Easy mode: goal-based interface with 7 guided workflows
- Pro mode: current technical interface preserved with Quick Start Goals
- Chat mode: AIUI placeholder for future integration

New components: ModeSwitcher, EasyHome, GoalDetail wizard, Chat placeholder
New stores: uiMode (mode persistence), goals (progress tracking)
New data: goal definitions catalog, helpTree goals section
Modified: Dashboard (reactive nav), Home (mode dispatcher), Settings (mode picker),
Router (goal/chat routes), Spotlight (goal search integration)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-04 07:09:31 +00:00
co-authored by Claude Opus 4.6
parent 486fc39249
commit 7b044d22ef
17 changed files with 1108 additions and 103 deletions
+55
View File
@@ -186,6 +186,37 @@
</button>
</div>
<!-- Interface Mode Section -->
<div class="path-option-card cursor-default px-6 py-6 mb-6">
<h2 class="text-xl font-semibold text-white/96 mb-2">Interface Mode</h2>
<p class="text-sm text-white/60 mb-6">Choose how you want to interact with your node.</p>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<button
v-for="m in interfaceModes"
:key="m.id"
@click="uiMode.setMode(m.id)"
class="path-option-card text-left p-5"
:class="{ 'path-option-card--selected': uiMode.mode === m.id }"
>
<div class="flex items-center gap-3 mb-3">
<svg class="w-6 h-6 text-white/70" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
v-for="(path, index) in m.iconPaths"
:key="index"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
:d="path"
/>
</svg>
<h3 class="text-lg font-semibold text-white/96">{{ m.label }}</h3>
</div>
<p class="text-sm text-white/60 leading-relaxed">{{ m.description }}</p>
</button>
</div>
</div>
<!-- System Section -->
<div class="path-option-card cursor-default px-6 py-6">
<h2 class="text-xl font-semibold text-white/96 mb-4">System</h2>
@@ -204,12 +235,36 @@
import { computed, ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { useAppStore } from '../stores/app'
import { useUIModeStore } from '@/stores/uiMode'
import ControllerIndicator from '@/components/ControllerIndicator.vue'
import { rpcClient } from '@/api/rpc-client'
import { useModalKeyboard } from '@/composables/useModalKeyboard'
import type { UIMode } from '@/types/api'
const router = useRouter()
const store = useAppStore()
const uiMode = useUIModeStore()
const interfaceModes: { id: UIMode; label: string; description: string; iconPaths: string[] }[] = [
{
id: 'easy',
label: 'Easy',
description: 'Goal-based interface. Choose what you want to do, and the system handles the rest.',
iconPaths: ['M14.828 14.828a4 4 0 01-5.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z'],
},
{
id: 'gamer',
label: 'Pro',
description: 'Full control over all services. Configure everything manually with all technical details.',
iconPaths: ['M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z', 'M15 12a3 3 0 11-6 0 3 3 0 016 0z'],
},
{
id: 'chat',
label: 'Chat',
description: 'Conversational AI interface. Manage your node through natural language. Coming soon.',
iconPaths: ['M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z'],
},
]
const serverName = computed(() => store.serverName)
const version = computed(() => store.serverInfo?.version || '0.0.0')