gigafibre-fsm/apps/ops/src/api/presets.js
louispaulb 9b9d307bdf feat: dispatch planning mode, offer pool, shared presets, recurrence selector
- Planning mode toggle: shift availability as background blocks on timeline
  (week view shows green=available, yellow=on-call; month view per-tech)
- On-call/guard shift editor with RRULE recurrence on tech schedules
- Uber-style job offer pool: broadcast/targeted/pool modes with pricing,
  SMS notifications, accept/decline flow, overload detection alerts
- Shared resource group presets via ERPNext Dispatch Preset doctype
  (replaces localStorage, shared between supervisors)
- Google Calendar-style RecurrenceSelector component with contextual
  quick options + custom RRULE editor, integrated in booking overlay
  and extra shift editor
- Remove default "Repos" ghost chips — only visible in planning mode
- Clean up debug console.logs across API, store, and page layers
- Add extra_shifts Custom Field on Dispatch Technician doctype

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 22:44:18 -04:00

47 lines
1.5 KiB
JavaScript

// ── Dispatch Preset CRUD — shared resource group presets ─────────────────────
import { BASE_URL } from 'src/config/erpnext'
import { authFetch } from './auth'
async function apiGet (path) {
const res = await authFetch(BASE_URL + path)
const data = await res.json()
if (data.exc) throw new Error(data.exc)
return data
}
export async function fetchPresets () {
const data = await apiGet('/api/resource/Dispatch%20Preset?fields=["*"]&limit_page_length=100&order_by=creation+asc')
return data.data || []
}
export async function createPreset (payload) {
const res = await authFetch(
`${BASE_URL}/api/resource/Dispatch%20Preset`,
{ method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) },
)
const data = await res.json()
if (data.exc) throw new Error(data.exc)
return data.data
}
export async function updatePreset (name, payload) {
const res = await authFetch(
`${BASE_URL}/api/resource/Dispatch%20Preset/${encodeURIComponent(name)}`,
{ method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) },
)
const data = await res.json()
if (data.exc) throw new Error(data.exc)
return data.data
}
export async function deletePreset (name) {
const res = await authFetch(
`${BASE_URL}/api/resource/Dispatch%20Preset/${encodeURIComponent(name)}`,
{ method: 'DELETE' },
)
if (!res.ok) {
const data = await res.json().catch(() => ({}))
throw new Error(data.exception || 'Delete failed')
}
}