HR-ATS-Portal/frontend/src/lib/queryKeys.js

179 lines
6.4 KiB
JavaScript

/* 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],
pendingApprovals: () => ['users', 'pending-approvals'],
},
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],
counts: () => ['mailbox', 'counts'],
// Under `mailbox` on purpose: every existing invalidateQueries on
// qk.mailbox.all() already refreshes the intake gate's ledger, so an
// override or a sync needs no extra invalidation.
triage: (p = {}) => ['mailbox', 'triage', p],
sync: (id) => ['mailbox', 'sync', id],
// Sheet form applicants live under the same mailbox prefix so the Inbox
// channel toggle can invalidate both email and form caches together.
formSheets: () => ['mailbox', 'form-sheets'],
formData: (p = {}) => ['mailbox', 'form-data', p],
formRow: (id) => ['mailbox', 'form-row', id],
formCounts: (p = {}) => ['mailbox', 'form-counts', p],
applicationTotal: () => ['mailbox', 'application-total'],
formTotal: (p = {}) => ['mailbox', 'form-total', p],
},
assessments: {
all: () => ['assessments'],
list: (p = {}) => ['assessments', 'list', p],
counts: () => ['assessments', 'counts'],
},
cvBank: {
all: () => ['cvBank'],
list: () => ['cvBank', 'list'],
},
notifications: {
all: () => ['notifications'],
list: (p = {}) => ['notifications', 'list', p],
},
managers: {
all: () => ['managers'],
list: (p = {}) => ['managers', 'list', p],
directory: () => ['managers', 'directory'],
},
orgSettings: {
all: () => ['orgSettings'],
list: (p = {}) => ['orgSettings', 'list', p],
},
savedSearches: {
all: () => ['savedSearches'],
list: (p = {}) => ['savedSearches', 'list', p],
},
search: {
query: (p = {}) => ['search', p],
},
feedbackTemplates: {
all: () => ['feedbackTemplates'],
list: () => ['feedbackTemplates', 'list'],
},
jobPosts: {
all: () => ['jobPosts'],
list: (p = {}) => ['jobPosts', 'list', p],
departments: (p = {}) => ['jobPosts', 'departments', p],
},
jobs: {
all: () => ['jobs'],
list: (p = {}) => ['jobs', 'list', p],
requisitionStatuses: () => ['jobs', 'requisition-statuses'],
statusHistory: (id) => ['jobs', 'status-history', id],
},
talent: {
all: () => ['talent'],
account: () => ['talent', 'account'],
runs: (jobId) => ['talent', 'runs', jobId],
run: (runId) => ['talent', 'run', runId],
profiles: (p = {}) => ['talent', 'profiles', p],
profile: (id) => ['talent', 'profile', id],
},
candidates: {
all: () => ['candidates'],
list: (p = {}) => ['candidates', 'list', p],
count: (p = {}) => ['candidates', 'count', p],
detail: (id) => ['candidates', 'detail', id],
history: (id, p = {}) => ['candidates', 'history', id, p],
matching: (p = {}) => ['candidates', 'matching', p],
matchingDetail: (id) => ['candidates', 'matching', '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] },
forms: {
all: () => ['forms'],
list: (p = {}) => ['forms', 'list', p],
definitions: () => ['forms', 'definitions'],
},
interviews: {
all: () => ['interviews'],
range: (p = {}) => ['interviews', 'range', p],
byInbox: (inboxId) => ['interviews', 'inbox', inboxId],
},
costs: {
all: () => ['costs'],
list: (p = {}) => ['costs', 'list', p],
sources: () => ['costs', 'sources'],
},
reports: {
all: () => ['reports'],
list: () => ['reports', 'list'],
runs: (id) => ['reports', 'runs', id],
},
assignments: {
all: () => ['assignments'],
job: (jobPostId) => ['assignments', 'job', jobPostId],
application: (inboxId) => ['assignments', 'application', inboxId],
},
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'],
},
}