feat(pro): wire all 7 Pro components into app

- ProjectBox: 5 Pro tabs (Analytics, Budget, Export, Symbols, Agent Mem)
  with PERSISTED-LAZY mount, proStatus() feature gate, peach accent color
- SettingsPanel: Pro tab (Accounts + Marketplace) conditionally shown
- ProSettings.svelte: wrapper with sub-tabs for AccountSwitcher + PluginMarketplace
- Feature detection via dynamic import of pro-bridge + proStatus() call
- All tabs hidden when agor-pro plugin not loaded (community edition)
This commit is contained in:
Hibryda 2026-03-18 02:01:18 +01:00
parent 0953395423
commit d1463d4d1e
4 changed files with 102 additions and 4 deletions

View file

@ -9,13 +9,14 @@
import ProjectSettings from './categories/ProjectSettings.svelte';
import OrchestrationSettings from './categories/OrchestrationSettings.svelte';
import AdvancedSettings from './categories/AdvancedSettings.svelte';
import ProSettings from './categories/ProSettings.svelte';
interface Props {
onClose?: () => void;
}
let { onClose }: Props = $props();
const CATEGORIES: { id: SettingsCategory; label: string; icon: string }[] = [
const BASE_CATEGORIES: { id: SettingsCategory; label: string; icon: string }[] = [
{ id: 'appearance', label: 'Appearance', icon: '🎨' },
{ id: 'agents', label: 'Agents', icon: '🤖' },
{ id: 'security', label: 'Security', icon: '🛡' },
@ -24,6 +25,11 @@
{ id: 'advanced', label: 'Advanced', icon: '⚡' },
];
let proAvailable = $state(false);
let CATEGORIES = $derived(proAvailable
? [...BASE_CATEGORIES, { id: 'pro' as SettingsCategory, label: 'Pro', icon: '💎' }]
: BASE_CATEGORIES);
let activeCategory = $state<SettingsCategory>('appearance');
let searchQuery = $state('');
let searchResults = $derived(searchQuery.length >= 2
@ -78,7 +84,10 @@
}
let searchInput: HTMLInputElement | undefined = $state();
onMount(() => { searchInput?.focus(); });
onMount(() => {
searchInput?.focus();
import('../commercial/pro-bridge').then(m => m.proStatus()).then(() => { proAvailable = true; }).catch(() => {});
});
</script>
<div class="settings-panel" onkeydown={handleSidebarKeydown}>
@ -142,6 +151,8 @@
<OrchestrationSettings />
{:else if activeCategory === 'advanced'}
<AdvancedSettings />
{:else if activeCategory === 'pro'}
<ProSettings />
{/if}
</div>
</div>

View file

@ -0,0 +1,35 @@
<script lang="ts">
import AccountSwitcher from '../../commercial/AccountSwitcher.svelte';
import PluginMarketplace from '../../commercial/PluginMarketplace.svelte';
let activeSection = $state<'accounts' | 'marketplace'>('accounts');
</script>
<div class="pro-settings">
<div class="pro-tabs">
<button class="pro-tab" class:active={activeSection === 'accounts'} onclick={() => activeSection = 'accounts'}>
Accounts
</button>
<button class="pro-tab" class:active={activeSection === 'marketplace'} onclick={() => activeSection = 'marketplace'}>
Marketplace
</button>
</div>
<div class="pro-content">
{#if activeSection === 'accounts'}
<AccountSwitcher />
{:else}
<PluginMarketplace />
{/if}
</div>
</div>
<style>
.pro-settings { display: flex; flex-direction: column; gap: 0.5rem; }
.pro-tabs { display: flex; gap: 0.25rem; padding-bottom: 0.5rem; border-bottom: 1px solid var(--ctp-surface0); }
.pro-tab { padding: 0.3rem 0.75rem; background: none; border: none; border-radius: 0.25rem;
color: var(--ctp-subtext0); cursor: pointer; font-size: 0.8rem; }
.pro-tab:hover { background: var(--ctp-surface0); color: var(--ctp-text); }
.pro-tab.active { background: color-mix(in srgb, var(--ctp-peach) 15%, transparent); color: var(--ctp-peach); }
.pro-content { flex: 1; overflow-y: auto; }
</style>

View file

@ -9,7 +9,8 @@ export type SettingsCategory =
| 'security'
| 'projects'
| 'orchestration'
| 'advanced';
| 'advanced'
| 'pro';
export interface SettingEntry {
key: string;