Skip to content

Where this file lives

  • This path (docs/jobs/jobs-admin-dashboard-design.md) is inside the rakletv3 repo so it shows up in the workspace and can be linked from Trello.
  • Trello title: Create dashboard for Jobs module

Design: Jobs admin dashboard / module home

Generated by /office-hours on 2026-04-10
Branch: feat/jobs-dashboard
Repo: rakletadmin/rakletv3
Status: PR #13581
Mode: Builder

Problem Statement

The admin Jobs module currently behaves like a set of disconnected status lists. The user can open published, pending, draft, archived, and settings, but there is no single screen that answers the first operational questions:

  • Is the job board enabled?
  • Do we have jobs waiting for approval?
  • Do we have enough live jobs?
  • Are those jobs getting seen?
  • Do we have members looking for work?

This is especially awkward because the route the user pointed at, admin.raklet.org/ng#/manager/jobs/, is only the module shell today. In Raklet.Backend/Content/scripts/core/manager/jobs/job.module.js, manager.job is abstract and there is no overview state under the root.

The product is also more than postings. Raklet already tracks both sides of the marketplace:

  • job postings in JobPosting
  • job seekers in OrganisationMembership.IsLookingForAJob

But the current admin Jobs UI only exposes posting tables and settings. The operator cannot see the supply side and demand side together.

What Makes This Cool

It turns Jobs from a maintenance tab into an operating console.

One glance should tell an admin whether the board is alive, blocked, or quietly dead.

Also, the root route finally means something. That matters more than another list tab.

Constraints

  • Stack: AngularJS manager app under Raklet.Backend/Content/scripts/core/manager/jobs/, V2 API under Raklet.Api/Controllers/V2/, EF-backed services in Services/.
  • Existing UI shape: Jobs already has tabbed sub-pages in manager/jobs/templates/job.html. Any new dashboard has to fit that manager shell, not invent a new app pattern.
  • Existing data already available: pending job count via SessionService.OrganisationPendingJobsCount, job counts and job seeker counts via Services/Extensions/NavigationExtensions.cs, per-job ViewCount on JobPosting, board settings via V2SocialController.GetJobBoardSettings.
  • Ghost metric risk: There is a JobApplication entity in Models/Models/JobApplication.cs, but it is not wired into the current admin Jobs flow. Public job detail still uses ApplyToEmail / mailto: in Application/Views/Job/Details.cshtml. So an "applications funnel" dashboard would be fake in v1.
  • Performance: The dashboard cannot make one HTTP call per card. Summary data needs a single response shape, ideally cacheable.
  • Navigation: The existing tabs for Published, Pending, Draft, Archived, and Settings still matter. The dashboard should sit above them, not replace them.
  • i18n: New labels should follow the same translate-key pattern used across the manager app.

Premises

  1. This is a module home problem first, analytics problem second. The dashboard should become the default landing experience for Jobs.
  2. v1 should optimize for action, not charts. Counts, backlog, exposure, settings health, and quick links beat a pretty graph with no next step.
  3. Job seekers belong in the dashboard. Raklet already treats them as part of the Jobs surface in NavigationExtensions.GetBadgeCounts.
  4. No application metrics in v1. There is no trustworthy in-product application funnel today.
  5. "Exposure" should be labeled honestly. ViewCount is lifetime per job. Unless Raklet adds dated view events, v1 should say "total views" or "most viewed jobs", not "views in the last 30 days".
  6. Settings health is part of dashboard health. A disabled board, or a board locked down to plans only, is just as important as a pending backlog.
  7. One summary payload. Cards, alerts, and quick lists should come from one endpoint or one cached service call.

Approaches Considered

Approach A: KPI strip above the existing published list

Summary: Keep manager.job.publishedlist as the de facto home and add a dashboard strip above the current job-list table.

Effort: M
Risk: Low-Med

Pros: - Smallest diff. - Reuses job-published-list.html and the existing list mental model. - Gets metrics in front of admins quickly.

Cons: - The root route problem remains awkward. - Job seekers and settings health will feel bolted onto a published-jobs page. - "Dashboard" becomes a header fragment, not a real module home.

Reuses: job-list.html, JobService.getJobs, OrganizationService.Organization.OrganisationPendingJobsCount, existing manager card patterns.

Approach B: Dedicated module overview state and root landing

Summary: Add manager.job.overview, make Jobs navigation land there, and treat it as the home screen for the module. The overview shows KPI cards, health alerts, quick actions, recent pending items, and top viewed published jobs.

Effort: M-L
Risk: Med

Pros: - Solves the actual IA problem. - Fits the Trello ask more honestly: a dashboard for the module, not a decorated list. - Creates room for future analytics without crowding the moderation tables.

Cons: - Requires route and navigation work. - Needs a dedicated summary DTO instead of piggybacking on list responses. - Slightly larger implementation surface than Approach A.

Reuses: existing manager dashboard patterns, existing jobs tabs, JobPostingService, NavigationExtensions.GetBadgeCounts, V2SocialController job board settings.

Approach C: Inbox-first operations dashboard

Summary: Make the Jobs home mostly an attention queue: pending approvals, disabled-board warning, no-live-jobs warning, restricted-visibility warning, and top-viewed jobs as a side panel.

Effort: M
Risk: Low

Pros: - Most directly actionable. - Keeps the dashboard from turning into vanity reporting. - Very strong for teams doing moderation and community ops.

Cons: - Underserves admins who want a quick health snapshot. - Can feel sparse for orgs without current issues. - Still needs a design decision about where job seeker visibility belongs.

Reuses: pending job count cache, settings service, existing job tables.

Choose Approach B, but shape the content with the operating-system instinct from Approach C.

That means:

  • Jobs should land on a real overview screen
  • the first screen should answer operational questions
  • the overview should route the user into Published, Pending, Draft, Archived, and Settings with one click

This is the best tradeoff because the user did not ask for "job analytics." They asked for a dashboard for the Jobs module, and the real module problem is that there is no useful home screen today.

CEO review scope decision, 2026-04-11

Keep this as a module-home dashboard, not an activation cockpit.

The stronger activation-cockpit version would put blocking tasks first, e.g. "your board is disabled", "you have 4 jobs waiting", "your visibility settings hide this from most members." That is tempting, but it is not v1 scope. v1 should stay a clean Jobs home screen with useful summary cards, quick actions, and health signals.

Concrete decisions:

  • Add a real Overview tab before Published.
  • Make /ng#/manager/jobs/ redirect to manager.job.overview.
  • Update sidebar/mobile Jobs navigation to point to /ng#/manager/jobs/overview, or rely on the root redirect if keeping link churn lower.
  • Treat restricted visibility settings as neutral info badges by default, not warnings. They may be intentional.
  • Treat these as warnings only: job board disabled, zero published jobs, pending approval backlog.
  • Keep activation cockpit, recommendations engine, and "next best action" workflow out of v1.

v1 Dashboard Content

Top KPI row

  • Published jobs
  • Pending approval
  • Draft jobs
  • Job seekers
  • Total views on published jobs with explicit lifetime labeling

Health / attention block

Show alerts when:

  • job board is disabled
  • there are zero published jobs
  • there are pending jobs waiting approval

Show neutral info badges, not alerts, when:

  • job list visibility is restricted
  • job detail visibility is restricted

Quick actions

  • Create job posting
  • Review pending jobs
  • Open settings
  • Open published jobs

Supporting panels

  • Most viewed published jobs
    Fields: position, company, view count, published date
  • Recently submitted pending jobs
    Fields: position, posted by, created date

Explicitly not in v1

  • application funnel
  • activation cockpit / recommendations engine
  • conversion rates
  • time-series charts
  • notification or email performance
  • applicant management

Rough Wireframe

[ Jobs ]

+----------------+----------------+----------------+----------------+------------------+
| Published      | Pending        | Draft          | Job Seekers    | Total Views      |
| 18             | 4              | 7              | 23             | 1,482            |
+----------------+----------------+----------------+----------------+------------------+

[ Warning ] 4 jobs are waiting for approval.
[ Warning ] Job detail visibility is limited to Members Only.

[ Create Job ] [ Review Pending ] [ Open Settings ] [ Published Jobs ]

+-----------------------------------+  +----------------------------------+
| Most Viewed Jobs                  |  | Recently Submitted               |
| Senior Designer      312 views    |  | Product Manager    2 hours ago   |
| Community Lead       221 views    |  | Backend Engineer   yesterday     |
| Events Coordinator   155 views    |  | ...                              |
+-----------------------------------+  +----------------------------------+

API Sketch

Route: GET v2/organisations/{organisationId}/jobs/overview

Response shape:

{
  "counts": {
    "published": 18,
    "pending": 4,
    "draft": 7,
    "archived": 3,
    "jobSeekers": 23,
    "totalPublishedViews": 1482
  },
  "settings": {
    "isJobBoardEnabled": true,
    "jobPostPermissionType": "MembersOnly",
    "jobListPermissionType": "Public",
    "jobDetailPermissionType": "MembersOnly"
  },
  "topViewedJobs": [
    {
      "id": "guid",
      "position": "Senior Designer",
      "company": "Raklet",
      "viewCount": 312,
      "publishedOn": "2026-04-01T12:00:00Z"
    }
  ],
  "recentPendingJobs": [
    {
      "id": "guid",
      "position": "Product Manager",
      "fullName": "Jane Doe",
      "createdOn": "2026-04-10T08:10:00Z"
    }
  ],
  "alerts": [
    {
      "type": "warning",
      "key": "pending_jobs_waiting_approval"
    }
  ]
}

Data Notes

  • Published / Pending / Draft / Archived counts: query JobPosting by JobPostingStatus
  • Job seekers: use the same rule already encoded in NavigationExtensions, active/frozen members/sub-members with IsLookingForAJob
  • Total views: sum ViewCount across published jobs only
  • Top viewed jobs: published jobs ordered by ViewCount DESC
  • Recent pending jobs: pending jobs ordered by CreatedOn DESC
  • Settings: reuse the existing job board settings document rather than duplicating the logic

Cache Notes

This is a good fit for a cached summary.

  • Key: {organisationId}-JobsDashboard-v1
  • TTL: 10-15 minutes is enough for v1
  • Purge on: create, update, delete, publish/approve, archive, unarchive, and job board settings save

The job write paths already purge several job-related keys in JobPostingService. The dashboard key should join that same invalidation graph.

Open Questions

  1. Should Archived appear as a KPI in the first row, or stay secondary?
  2. Is there any admin-facing need to drill from Job seekers into a management page, or is the count + link-out enough for v1?

Success Criteria

  • An admin can answer "Is Jobs healthy?" in under 10 seconds from the module landing screen.
  • The Jobs sidebar click no longer leads to a shell-only route with no overview.
  • A pending backlog is obvious without switching tabs.
  • A disabled or overly restricted board is visible without opening Settings.
  • The overview loads with one summary request, not one request per card.

Distribution Plan

Ships through the existing Raklet Admin deployment pipeline.

No new product surface outside the existing admin module. This is an IA and summary-data improvement inside admin.raklet.org/ng#/manager/jobs/....

Next Steps

  1. Add a real overview state under manager.job and make Jobs land there.
  2. Implement a single overview summary endpoint in V2 API.
  3. Build overview cards, alerts, and quick-link panels in the AngularJS manager UI.
  4. Add empty / warning / restricted-settings states.
  5. QA with these cases:
  6. board disabled
  7. zero published jobs
  8. pending jobs exist
  9. high-view jobs exist
  10. no job seekers
  11. restricted list/detail permissions

CEO Review Notes

Generated by /plan-ceo-review on 2026-04-11. Mode: SELECTIVE_EXPANSION, with expansion declined. Final scope: module-home dashboard.

Premise Challenge

OK: The plan is solving the right UI gap. manager.job is currently an abstract shell under jobs/, while the user-facing route request points exactly at the missing module home.

WARNING: Do not turn ViewCount into the hero success metric. It is lifetime exposure, not dated demand. Use it as a secondary signal only.

WARNING: Application funnel metrics stay out because the current public flow uses ApplyToEmail / mailto: and the JobApplication entity is not wired into the admin Jobs module.

Scope Decision

Rejected expansion: activation cockpit.

Reason: it is a better 12-month direction, but it changes v1 from a module home into an operations/recommendations system. That creates extra copy, prioritization, and settings semantics work before the basic dashboard exists.

Architecture Review

Admin route
  /ng#/manager/jobs/overview
        |
        v
JobOverviewController
        |
        v
JobService.getOverview()
        |
        v
GET v2/organisations/{organisationId}/jobs/overview
        |
        +--> JobPostingService / RakletDb
        |       counts, total published views, top viewed jobs, recent pending jobs
        |
        +--> OrganisationMembership query
        |       job seekers count, matching NavigationExtensions rule
        |
        +--> Job board settings source
                enabled + permission summary

Key constraint: Keep this to one summary endpoint. Do not call getJobs() repeatedly for Published, Pending, Draft, Archived, then aggregate client-side.

Error And Edge Cases

Case Expected behavior
Summary endpoint fails Show inline overview error, keep tabs usable.
No published jobs Show zero state and CTA to create a job.
Pending jobs exist Show warning and link to Pending tab.
Board disabled Show warning and link to Settings.
Restricted visibility Show neutral info badge, not warning.
Very long job title/company Truncate in top-viewed/recent panels.
User lands on /jobs/ Redirect to overview.
User refreshes deep list route Existing list routes continue to work.

Test Map

Unit / service tests
  counts by status
  total published view sum
  job seeker count rule
  top viewed ordering
  recent pending ordering

API tests
  org-scoped overview response
  zero data response
  forbidden cross-org access

Angular / UI tests
  /jobs/ redirects to overview
  overview renders loading, error, zero, and success states
  quick links navigate to existing tabs
  restricted visibility renders info badge

Performance Notes

  • Use one summary call.
  • Keep top viewed and recent pending lists capped, e.g. 5 items each.
  • Cache the summary with a short TTL and purge on job mutations plus settings save.
  • Do not add dated trend metrics unless dated job view/application events exist.

UX Notes

Open Jobs
   |
   v
Overview
   |
   +--> Warning if disabled / zero live jobs / pending backlog
   |
   +--> KPI row
   |
   +--> Quick actions
   |
   +--> Most viewed + recent pending
   |
   +--> Existing tabs remain available

Information hierarchy:

  1. Board health warnings
  2. KPI row
  3. Quick actions
  4. Supporting panels
  5. Existing tabs

CEO Verdict

Clear with tightened scope. Build the module-home dashboard first. Defer activation cockpit and application funnel until there is product evidence and data plumbing to support them.

The Assignment

Ask one support or customer-success teammate: when a customer says "our Jobs area is not working," what is the first thing they check today?

That answer should decide the first card and the first warning block on the overview screen.

What I noticed about how you think

  • You said "Admin panelde job dashboard'a ihtiyacımız var", not "let's add analytics." That pushes the work toward a useful module home instead of vanity charts.
  • You pointed at the exact route, /ng#/manager/jobs/. Good instinct. It exposed that the root surface is the real UX gap.
  • You framed the work as "Create dashboard for Jobs module", not "redesign published jobs." That kept the thinking at the module level, where the better answer lives.