/** * Single source of truth for every backend URL the SPA talks to. * * Convention: a path that needs an id is a function `(id) => '/...//'`; * a path without an id stays a plain string. Callers should never build URLs * by hand — if a URL isn't here, it's missing. * * spec 0004: task images moved to the `/api/tasks/{id}/images/` sub-resource * (with `/content/` for the binary blob). Mirror that here. * * Every entity exposes a DETAIL endpoint so single-resource fetches don't * have to reuse UPDATE/DELETE keys just because they produce the same URL. */ export const apiEndpoints = { AUTH: { LOGIN: '/api/token/', REFRESH: '/api/token/refresh/', }, STUDENTS: { LIST: '/api/students/', CREATE: '/api/students/', DETAIL: (studentId) => `/api/students/${studentId}/`, UPDATE: (studentId) => `/api/students/${studentId}/`, DELETE: (studentId) => `/api/students/${studentId}/`, }, SUBJECTS: { LIST: '/api/subjects/', CREATE: '/api/subjects/', DETAIL: (subjectId) => `/api/subjects/${subjectId}/`, UPDATE: (subjectId) => `/api/subjects/${subjectId}/`, DELETE: (subjectId) => `/api/subjects/${subjectId}/`, }, TERMS: { LIST: '/api/terms/', CREATE: '/api/terms/', DETAIL: (termId) => `/api/terms/${termId}/`, UPDATE: (termId) => `/api/terms/${termId}/`, DELETE: (termId) => `/api/terms/${termId}/`, }, STORIES: { LIST: '/api/stories/', CREATE: '/api/stories/', DETAIL: (storyId) => `/api/stories/${storyId}/`, UPDATE: (storyId) => `/api/stories/${storyId}/`, DELETE: (storyId) => `/api/stories/${storyId}/`, }, TASKS: { LIST: '/api/tasks/', CREATE: '/api/tasks/', DETAIL: (taskId) => `/api/tasks/${taskId}/`, UPDATE: (taskId) => `/api/tasks/${taskId}/`, DELETE: (taskId) => `/api/tasks/${taskId}/`, IMAGES: { LIST: (taskId) => `/api/tasks/${taskId}/images/`, CREATE: (taskId) => `/api/tasks/${taskId}/images/`, DELETE: (taskId, imageId) => `/api/tasks/${taskId}/images/${imageId}/`, CONTENT: (taskId, imageId) => `/api/tasks/${taskId}/images/${imageId}/content/`, }, }, } export default apiEndpoints