feat(demo): wire DemoBanner, WelcomeModal, HintChip into app + views
This commit is contained in:
parent
51b7dbb29b
commit
cd5bd80a2a
6 changed files with 50 additions and 18 deletions
|
|
@ -7,10 +7,9 @@
|
||||||
<!-- Skip to main content link (screen reader / keyboard nav) -->
|
<!-- Skip to main content link (screen reader / keyboard nav) -->
|
||||||
<a href="#main-content" class="skip-link">Skip to main content</a>
|
<a href="#main-content" class="skip-link">Skip to main content</a>
|
||||||
|
|
||||||
<!-- Demo mode banner — sticky top bar, visible on all pages -->
|
<!-- Demo mode banner + welcome modal — rendered when isDemo -->
|
||||||
<div v-if="config.isDemo" class="demo-banner" role="status" aria-live="polite">
|
<DemoBanner v-if="config.isDemo" />
|
||||||
👁 Demo mode — changes are not saved and AI features are disabled.
|
<WelcomeModal v-if="config.isDemo" />
|
||||||
</div>
|
|
||||||
|
|
||||||
<RouterView />
|
<RouterView />
|
||||||
|
|
||||||
|
|
@ -32,6 +31,8 @@ import { useHackerMode, useKonamiCode } from './composables/useEasterEgg'
|
||||||
import { useTheme } from './composables/useTheme'
|
import { useTheme } from './composables/useTheme'
|
||||||
import { useToast } from './composables/useToast'
|
import { useToast } from './composables/useToast'
|
||||||
import AppNav from './components/AppNav.vue'
|
import AppNav from './components/AppNav.vue'
|
||||||
|
import DemoBanner from './components/DemoBanner.vue'
|
||||||
|
import WelcomeModal from './components/WelcomeModal.vue'
|
||||||
import { useAppConfigStore } from './stores/appConfig'
|
import { useAppConfigStore } from './stores/appConfig'
|
||||||
import { useDigestStore } from './stores/digest'
|
import { useDigestStore } from './stores/digest'
|
||||||
|
|
||||||
|
|
@ -128,20 +129,6 @@ body {
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Demo mode banner — sticky top bar */
|
|
||||||
.demo-banner {
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
z-index: 200;
|
|
||||||
background: var(--color-warning);
|
|
||||||
color: #1a1a1a; /* forced dark — warning bg is always light enough */
|
|
||||||
text-align: center;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
font-weight: 600;
|
|
||||||
padding: 6px var(--space-4, 16px);
|
|
||||||
letter-spacing: 0.01em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Global toast — bottom-center, above tab bar */
|
/* Global toast — bottom-center, above tab bar */
|
||||||
.global-toast {
|
.global-toast {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<!-- ── Mobile: full-width list ──────────────────────────────────── -->
|
<!-- ── Mobile: full-width list ──────────────────────────────────── -->
|
||||||
<div v-if="isMobile" class="apply-list">
|
<div v-if="isMobile" class="apply-list">
|
||||||
|
<HintChip
|
||||||
|
v-if="config.isDemo"
|
||||||
|
view-key="apply"
|
||||||
|
message="The Spotify cover letter is ready — open it to see how AI drafts from your resume"
|
||||||
|
/>
|
||||||
<header class="apply-list__header">
|
<header class="apply-list__header">
|
||||||
<h1 class="apply-list__title">Apply</h1>
|
<h1 class="apply-list__title">Apply</h1>
|
||||||
<p class="apply-list__subtitle">Approved jobs ready for applications</p>
|
<p class="apply-list__subtitle">Approved jobs ready for applications</p>
|
||||||
|
|
@ -124,6 +129,10 @@ import { ref, onMounted, onUnmounted } from 'vue'
|
||||||
import { RouterLink } from 'vue-router'
|
import { RouterLink } from 'vue-router'
|
||||||
import { useApiFetch } from '../composables/useApi'
|
import { useApiFetch } from '../composables/useApi'
|
||||||
import ApplyWorkspace from '../components/ApplyWorkspace.vue'
|
import ApplyWorkspace from '../components/ApplyWorkspace.vue'
|
||||||
|
import HintChip from '../components/HintChip.vue'
|
||||||
|
import { useAppConfigStore } from '../stores/appConfig'
|
||||||
|
|
||||||
|
const config = useAppConfigStore()
|
||||||
|
|
||||||
// ── Responsive ───────────────────────────────────────────────────────────────
|
// ── Responsive ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, onMounted } from 'vue'
|
import { ref, computed, onMounted } from 'vue'
|
||||||
import { useApiFetch } from '../composables/useApi'
|
import { useApiFetch } from '../composables/useApi'
|
||||||
|
import HintChip from '../components/HintChip.vue'
|
||||||
|
import { useAppConfigStore } from '../stores/appConfig'
|
||||||
|
|
||||||
|
const config = useAppConfigStore()
|
||||||
|
|
||||||
interface Contact {
|
interface Contact {
|
||||||
id: number
|
id: number
|
||||||
|
|
@ -79,6 +83,11 @@ onMounted(fetchContacts)
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="contacts-view">
|
<div class="contacts-view">
|
||||||
|
<HintChip
|
||||||
|
v-if="config.isDemo"
|
||||||
|
view-key="contacts"
|
||||||
|
message="Peregrine logs every recruiter email automatically — no manual entry needed"
|
||||||
|
/>
|
||||||
<header class="contacts-header">
|
<header class="contacts-header">
|
||||||
<h1 class="contacts-title">Contacts</h1>
|
<h1 class="contacts-title">Contacts</h1>
|
||||||
<span class="contacts-count" v-if="total > 0">{{ total }} total</span>
|
<span class="contacts-count" v-if="total > 0">{{ total }} total</span>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="home">
|
<div class="home">
|
||||||
|
<HintChip
|
||||||
|
v-if="config.isDemo"
|
||||||
|
view-key="home"
|
||||||
|
message="Start in Job Review — 12 jobs are waiting for your verdict"
|
||||||
|
/>
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<header class="home__header">
|
<header class="home__header">
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -371,6 +376,10 @@ import { RouterLink } from 'vue-router'
|
||||||
import { useJobsStore } from '../stores/jobs'
|
import { useJobsStore } from '../stores/jobs'
|
||||||
import { useApiFetch } from '../composables/useApi'
|
import { useApiFetch } from '../composables/useApi'
|
||||||
import WorkflowButton from '../components/WorkflowButton.vue'
|
import WorkflowButton from '../components/WorkflowButton.vue'
|
||||||
|
import HintChip from '../components/HintChip.vue'
|
||||||
|
import { useAppConfigStore } from '../stores/appConfig'
|
||||||
|
|
||||||
|
const config = useAppConfigStore()
|
||||||
|
|
||||||
const store = useJobsStore()
|
const store = useJobsStore()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,10 @@ import { useApiFetch } from '../composables/useApi'
|
||||||
import InterviewCard from '../components/InterviewCard.vue'
|
import InterviewCard from '../components/InterviewCard.vue'
|
||||||
import MoveToSheet from '../components/MoveToSheet.vue'
|
import MoveToSheet from '../components/MoveToSheet.vue'
|
||||||
import CompanyResearchModal from '../components/CompanyResearchModal.vue'
|
import CompanyResearchModal from '../components/CompanyResearchModal.vue'
|
||||||
|
import HintChip from '../components/HintChip.vue'
|
||||||
|
import { useAppConfigStore } from '../stores/appConfig'
|
||||||
|
|
||||||
|
const config = useAppConfigStore()
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const store = useInterviewsStore()
|
const store = useInterviewsStore()
|
||||||
|
|
@ -347,6 +351,11 @@ function formatRejectionDate(job: PipelineJob): string {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="interviews-view">
|
<div class="interviews-view">
|
||||||
|
<HintChip
|
||||||
|
v-if="config.isDemo"
|
||||||
|
view-key="interviews"
|
||||||
|
message="Figma sent an offer — open it to see the hired outcome and post-hire feedback"
|
||||||
|
/>
|
||||||
<canvas ref="confettiCanvas" class="confetti-canvas" aria-hidden="true" />
|
<canvas ref="confettiCanvas" class="confetti-canvas" aria-hidden="true" />
|
||||||
|
|
||||||
<Transition name="toast">
|
<Transition name="toast">
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="review">
|
<div class="review">
|
||||||
|
<HintChip
|
||||||
|
v-if="config.isDemo"
|
||||||
|
view-key="review"
|
||||||
|
message="Swipe right to approve, left to skip. One of these jobs is a ghost post — can you spot it?"
|
||||||
|
/>
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<header class="review__header">
|
<header class="review__header">
|
||||||
<div class="review__title-row">
|
<div class="review__title-row">
|
||||||
|
|
@ -214,6 +219,10 @@ import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import { useReviewStore } from '../stores/review'
|
import { useReviewStore } from '../stores/review'
|
||||||
import JobCardStack from '../components/JobCardStack.vue'
|
import JobCardStack from '../components/JobCardStack.vue'
|
||||||
|
import HintChip from '../components/HintChip.vue'
|
||||||
|
import { useAppConfigStore } from '../stores/appConfig'
|
||||||
|
|
||||||
|
const config = useAppConfigStore()
|
||||||
|
|
||||||
const store = useReviewStore()
|
const store = useReviewStore()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue