// src/api/CategoriesApi.js export default class CategoriesApi { constructor(token) { // IMPORTANTE: singular "Tag", no "Tags" this.baseUrl = 'https://inventory-bff.dream-views.com/api/v1/Tag'; this.token = token; } headers(json = true) { return { accept: 'application/json', ...(json ? { 'Content-Type': 'application/json' } : {}), ...(this.token ? { Authorization: `Bearer ${this.token}` } : {}), }; } // Utilidad: validar ObjectId (24-hex) — el DAL lo exige para ChangeStatus static isHex24(v) { return typeof v === 'string' && /^[0-9a-fA-F]{24}$/.test(v); } // (Opcional) Utilidad: validar campos mínimos en create/update para evitar 400 static ensureFields(obj, fields) { const missing = fields.filter((k) => obj[k] === undefined || obj[k] === null || obj[k] === ''); if (missing.length) { throw new Error(`Missing required field(s): ${missing.join(', ')}`); } } // GET /Tag/GetAll async getAll() { const res = await fetch(`${this.baseUrl}/GetAll`, { method: 'GET', headers: this.headers(false), }); if (!res.ok) { throw new Error(`GetAll error ${res.status}: ${await res.text()}`); } return res.json(); } // POST /Tag/Create // payload esperado (min): tenantId, tagName, typeId(_id TagType), slug, displayOrder, icon, parentTagId([]) async create(payload) { // Validaciones básicas para evitar 400 comunes CategoriesApi.ensureFields(payload, ['tenantId', 'tagName', 'typeId', 'icon']); if (!Array.isArray(payload.parentTagId)) { payload.parentTagId = []; } const res = await fetch(`${this.baseUrl}/Create`, { method: 'POST', headers: this.headers(), body: JSON.stringify(payload), }); if (!res.ok) { throw new Error(`Create error ${res.status}: ${await res.text()}`); } return res.json(); } // PUT /Tag/Update // payload esperado (min): id(GUID) ó _id(24-hex) según backend, + tenantId, tagName, typeId, icon, etc. async update(payload) { CategoriesApi.ensureFields(payload, ['tenantId', 'tagName', 'typeId', 'icon']); const res = await fetch(`${this.baseUrl}/Update`, { method: 'PUT', headers: this.headers(), body: JSON.stringify(payload), }); if (!res.ok) { throw new Error(`Update error ${res.status}: ${await res.text()}`); } return res.json(); } // PATCH /Tag/ChangeStatus // Debe mandarse { id: <_id 24-hex>, status: 'Active'|'Inactive' } async changeStatus({ id, status }) { if (!CategoriesApi.isHex24(id)) { // Evitar el 500 "String should contain only hexadecimal digits." throw new Error('ChangeStatus requires a Mongo _id (24-hex) for "id".'); } if (!status) { throw new Error('ChangeStatus requires "status" field.'); } const res = await fetch(`${this.baseUrl}/ChangeStatus`, { method: 'PATCH', headers: this.headers(), body: JSON.stringify({ id, status }), }); if (!res.ok) { throw new Error(`ChangeStatus error ${res.status}: ${await res.text()}`); } // Algunos endpoints devuelven vacío; devolvemos parsed o true try { return await res.json(); } catch { return true; } } // DELETE /Tag/Delete (si lo usan; muchos usan soft-delete con ChangeStatus/Update) async delete(payload) { const res = await fetch(`${this.baseUrl}/Delete`, { method: 'DELETE', headers: this.headers(), body: JSON.stringify(payload), }); if (!res.ok) { throw new Error(`Delete error ${res.status}: ${await res.text()}`); } return res.json(); } }