From 07cc74014dcc946d9c2e7c35efdd9cc51757bdf1 Mon Sep 17 00:00:00 2001 From: Joachim Date: Fri, 27 Feb 2026 11:08:29 +0100 Subject: [PATCH] fixed-issue-#51-imroved-pipline --- app/pages/dashboard/applications/index.vue | 22 +++++++- app/pages/dashboard/index.vue | 66 +++++++++++++++------- app/pages/dashboard/jobs/index.vue | 24 +++++++- 3 files changed, 90 insertions(+), 22 deletions(-) diff --git a/app/pages/dashboard/applications/index.vue b/app/pages/dashboard/applications/index.vue index d970fb5f..6bb8ae1d 100644 --- a/app/pages/dashboard/applications/index.vue +++ b/app/pages/dashboard/applications/index.vue @@ -11,6 +11,7 @@ useSeoMeta({ description: 'Manage applications across all jobs', }) +const route = useRoute() const router = useRouter() // ── Search ──────────────────────────────────────────────────────────────────── @@ -31,7 +32,26 @@ watch(searchInput, (val) => { const STATUS_OPTIONS = ['new', 'screening', 'interview', 'offer', 'hired', 'rejected'] as const type Status = typeof STATUS_OPTIONS[number] -const activeStatus = useState('app-filter-status', () => undefined) +const initialAppStatus = STATUS_OPTIONS.includes(route.query.status as any) + ? (route.query.status as Status) + : undefined +const activeStatus = useState('app-filter-status', () => initialAppStatus) +// Ensure the state matches the URL on navigation (useState caches across client-side navigations) +if (initialAppStatus !== undefined) { + activeStatus.value = initialAppStatus +} + +// Sync the URL when the status filter changes +watch(activeStatus, (newStatus) => { + const query = { ...route.query } + if (newStatus) { + query.status = newStatus + } + else { + delete query.status + } + router.replace({ query }) +}) const statusFilter = computed(() => activeStatus.value) diff --git a/app/pages/dashboard/index.vue b/app/pages/dashboard/index.vue index 98740ff9..638742e2 100644 --- a/app/pages/dashboard/index.vue +++ b/app/pages/dashboard/index.vue @@ -264,7 +264,15 @@ const isEmpty = computed(() =>
-

Pipeline Overview

+
+

Pipeline Overview

+ + {{ pipelineTotal }} total + +
- +
-
+ +
- -
+ +
- - - {{ config.label }} - - - {{ (pipeline as Record)[status] ?? 0 }} - + +
+ +
+ + + + + {{ config.label }} + +
+ +
+ + {{ (pipeline as Record)[status] ?? 0 }} + + + {{ Math.round(((pipeline as Record)[status] ?? 0) / pipelineTotal * 100) }}% + +
-
- -

No applications in the pipeline yet.

+
+
+ +
+

No applications yet

+

Applications will appear here as candidates apply.

diff --git a/app/pages/dashboard/jobs/index.vue b/app/pages/dashboard/jobs/index.vue index 778d4aef..cf1bc058 100644 --- a/app/pages/dashboard/jobs/index.vue +++ b/app/pages/dashboard/jobs/index.vue @@ -11,8 +11,28 @@ useSeoMeta({ description: 'Manage your job postings', }) -const statusFilter = ref(undefined) -const viewMode = ref<'list' | 'gallery'>('list') +const route = useRoute() +const router = useRouter() + +// Sync statusFilter with ?status= query param +const validStatuses = ['draft', 'open', 'closed', 'archived'] as const +const initialStatus = validStatuses.includes(route.query.status as any) + ? (route.query.status as string) + : undefined +const statusFilter = ref(initialStatus) + +// Sync viewMode with ?view= query param +const initialView = route.query.view === 'gallery' ? 'gallery' : 'list' +const viewMode = ref<'list' | 'gallery'>(initialView) + +// Keep URL in sync when statusFilter or viewMode change +watch([statusFilter, viewMode], ([newStatus, newView]) => { + const query: Record = {} + if (newStatus) query.status = newStatus + if (newView !== 'list') query.view = newView + router.replace({ query }) +}) + const { jobs, total, fetchStatus, error, refresh } = useJobs({ status: statusFilter }) const statusTabs = [