/* Query key convention: [domain, scope, ...params], always an array, params always last as a single object so `invalidateQueries({queryKey:['users']})` catches every scope under a domain. */ export const qk = { auth: { me: () => ['auth', 'me'] }, // --- real backend endpoints --- users: { all: () => ['users'], list: (p = {}) => ['users', 'list', p], }, roles: { all: () => ['roles'], list: () => ['roles', 'list'], permissions: () => ['roles', 'permissions'], tags: () => ['roles', 'permission-tags'], }, mailbox: { all: () => ['mailbox'], messages: () => ['mailbox', 'messages'], applications: (p = {}) => ['mailbox', 'applications', p], message: (id) => ['mailbox', 'message', id], assignments: (p = {}) => ['mailbox', 'assignments', p], }, jobPosts: { all: () => ['jobPosts'], list: (p = {}) => ['jobPosts', 'list', p], }, jobs: { all: () => ['jobs'], list: (p = {}) => ['jobs', 'list', p], }, candidates: { all: () => ['candidates'], list: (p = {}) => ['candidates', 'list', p], detail: (id) => ['candidates', 'detail', id], }, // Board rows come from the same endpoint as qk.candidates.list but are cached // MAPPED (kanban cards, not the raw envelope), so they need their own key — // sharing one would poison whichever screen mounted first. pipeline: { all: () => ['pipeline'], board: (p = {}) => ['pipeline', 'board', p], transitions: (inboxId) => ['pipeline', 'transitions', inboxId], // One candidate's current ats_results score. Fetched on demand (a card // click), never as part of a list, so it is keyed per candidate + job. candidateScore: (p = {}) => ['pipeline', 'candidate-score', p], }, analytics: { all: () => ['analytics'], kpis: (p = {}) => ['analytics', 'kpis', p], funnel: (p = {}) => ['analytics', 'funnel', p], trend: (p = {}) => ['analytics', 'trend', p], sources: (p = {}) => ['analytics', 'sources', p], recruiters: (p = {}) => ['analytics', 'recruiters', p], }, offers: { all: () => ['offers'], list: (p = {}) => ['offers', 'list', p] }, interviews: { all: () => ['interviews'], range: (p = {}) => ['interviews', 'range', p] }, activity: { all: () => ['activity'], feed: (p = {}) => ['activity', 'feed', p] }, tasks: { all: () => ['tasks'], list: (p = {}) => ['tasks', 'list', p], assignees: () => ['tasks', 'assignees'], }, // --- seed-backed buckets --- // These are not "server state" — the cache IS the store for them, so every // mutation is a setQueryData. See data/seedQueries.js. seed: { all: () => ['seed'], jobs: () => ['seed', 'jobs'], candidates: () => ['seed', 'candidates'], interviews: () => ['seed', 'interviews'], assessments: () => ['seed', 'assessments'], offers: () => ['seed', 'offers'], tasks: () => ['seed', 'tasks'], notifications: () => ['seed', 'notifications'], messages: () => ['seed', 'messages'], activity: () => ['seed', 'activity'], inbox: () => ['seed', 'inbox'], emails: () => ['seed', 'emails'], publishings: () => ['seed', 'publishings'], rbacRoles: () => ['seed', 'rbacRoles'], recruiters: () => ['seed', 'recruiters'], managers: () => ['seed', 'managers'], users: () => ['seed', 'users'], favorites: () => ['seed', 'favorites'], recentlyViewed: () => ['seed', 'recentlyViewed'], }, }