- 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
35 lines
1.1 KiB
TypeScript
35 lines
1.1 KiB
TypeScript
import { useAppConfigStore } from '../stores/appConfig'
|
|
import { useWizardStore } from '../stores/wizard'
|
|
|
|
/**
|
|
* Gate the entire app behind /setup until wizard_complete is true.
|
|
*
|
|
* Rules:
|
|
* - Any non-/setup route while wizard is incomplete → redirect to /setup
|
|
* - /setup/* while wizard is complete → redirect to /
|
|
* - /setup with no step suffix → redirect to the current step route
|
|
*
|
|
* Must run AFTER appConfig.load() has resolved (called from router.beforeEach).
|
|
*/
|
|
export async function wizardGuard(
|
|
to: { path: string },
|
|
_from: unknown,
|
|
next: (to?: string | { path: string }) => void,
|
|
): Promise<void> {
|
|
const config = useAppConfigStore()
|
|
|
|
// Ensure config is loaded before inspecting wizardComplete
|
|
if (!config.loaded) await config.load()
|
|
|
|
const onSetup = to.path.startsWith('/setup')
|
|
const complete = config.wizardComplete
|
|
|
|
// Wizard done — keep user out of /setup
|
|
if (complete && onSetup) return next('/')
|
|
|
|
// Wizard not done — redirect to setup
|
|
if (!complete && !onSetup) return next('/setup')
|
|
|
|
// On /setup exactly (no step) — delegate to WizardLayout which loads status
|
|
next()
|
|
}
|