- WizardLayout.vue: full-page card, progress bar, crash-recovery via loadStatus(isCloud); auto-skips steps 1/2/5 in cloud mode - wizard.css: shared step styles (headings, banners, radio cards, chip lists, form fields, expandables, nav buttons) - Step 1 — Hardware: GPU detection, profile select, mismatch warning - Step 2 — Tier: Free/Paid/Premium radio cards - Step 3 — Resume: upload (PDF/DOCX/ODT) or manual experience builder; pre-fills identity fields from parsed resume data - Step 4 — Identity: name/email/phone/LinkedIn/career summary; full validation before saveStep - Step 5 — Inference: remote API keys vs local Ollama; advanced service-host/port expandable; soft-fail connection test - Step 6 — Search: chip-style job title + location input with comma/Enter commit; remote-only checkbox - Step 7 — Integrations: optional tile-grid (Notion/Calendar/Slack/ Discord/Drive); paid-tier badge for gated items; calls wizard.complete() on Finish - wizard.ts Pinia store: loadStatus, detectHardware, saveStep, testInference, complete; cloud auto-skip logic - wizardGuard.ts: gates all routes behind /setup until wizard_complete; redirects complete users away from /setup - router/index.ts: /setup nested route tree; unified beforeEach guard (wizard gate → setup branch → settings tier gate) - App.vue: hide AppNav + strip sidebar margin on /setup routes
47 lines
1.7 KiB
TypeScript
47 lines
1.7 KiB
TypeScript
import { ref } from 'vue'
|
|
import { defineStore } from 'pinia'
|
|
import { useApiFetch } from '../composables/useApi'
|
|
|
|
export type Tier = 'free' | 'paid' | 'premium' | 'ultra'
|
|
export type InferenceProfile = 'remote' | 'cpu' | 'single-gpu' | 'dual-gpu'
|
|
|
|
export const useAppConfigStore = defineStore('appConfig', () => {
|
|
const isCloud = ref(false)
|
|
const isDevMode = ref(false)
|
|
const tier = ref<Tier>('free')
|
|
const contractedClient = ref(false)
|
|
const inferenceProfile = ref<InferenceProfile>('cpu')
|
|
const isDemo = ref(false)
|
|
const wizardComplete = ref(true) // optimistic default — guard corrects on load
|
|
const loaded = ref(false)
|
|
const devTierOverride = ref(localStorage.getItem('dev_tier_override') ?? '')
|
|
|
|
async function load() {
|
|
const { data } = await useApiFetch<{
|
|
isCloud: boolean; isDemo: boolean; isDevMode: boolean; tier: Tier
|
|
contractedClient: boolean; inferenceProfile: InferenceProfile
|
|
wizardComplete: boolean
|
|
}>('/api/config/app')
|
|
if (!data) return
|
|
isCloud.value = data.isCloud
|
|
isDemo.value = data.isDemo ?? false
|
|
isDevMode.value = data.isDevMode
|
|
tier.value = data.tier
|
|
contractedClient.value = data.contractedClient
|
|
inferenceProfile.value = data.inferenceProfile
|
|
wizardComplete.value = data.wizardComplete ?? true
|
|
loaded.value = true
|
|
}
|
|
|
|
function setDevTierOverride(value: string | null) {
|
|
if (value) {
|
|
localStorage.setItem('dev_tier_override', value)
|
|
devTierOverride.value = value
|
|
} else {
|
|
localStorage.removeItem('dev_tier_override')
|
|
devTierOverride.value = ''
|
|
}
|
|
}
|
|
|
|
return { isCloud, isDemo, isDevMode, wizardComplete, tier, contractedClient, inferenceProfile, loaded, load, devTierOverride, setDevTierOverride }
|
|
})
|