You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
5.6 KiB
JavaScript
208 lines
5.6 KiB
JavaScript
// src/store/noticiasStore.js
|
|
import { defineStore } from "pinia"
|
|
import api from "../axios" // <-- cambia a tu axios (admin) si tienes otro
|
|
|
|
export const useNoticiasStore = defineStore("noticias", {
|
|
state: () => ({
|
|
noticias: [],
|
|
noticia: null,
|
|
|
|
loading: false,
|
|
saving: false,
|
|
deleting: false,
|
|
|
|
error: null,
|
|
|
|
// paginación (si tu back manda meta)
|
|
meta: {
|
|
current_page: 1,
|
|
last_page: 1,
|
|
per_page: 9,
|
|
total: 0,
|
|
},
|
|
|
|
// filtros
|
|
filters: {
|
|
publicado: null, // true/false/null
|
|
categoria: "",
|
|
q: "",
|
|
per_page: 9,
|
|
page: 1,
|
|
},
|
|
}),
|
|
|
|
getters: {
|
|
// para el público: solo publicadas (si ya las filtras en backend, esto es opcional)
|
|
publicadas: (state) => state.noticias.filter((n) => n.publicado),
|
|
|
|
// para ordenar en frontend (opcional)
|
|
ordenadas: (state) =>
|
|
[...state.noticias].sort((a, b) => {
|
|
const da = a.fecha_publicacion ? new Date(a.fecha_publicacion).getTime() : 0
|
|
const db = b.fecha_publicacion ? new Date(b.fecha_publicacion).getTime() : 0
|
|
return db - da
|
|
}),
|
|
},
|
|
|
|
actions: {
|
|
// ========= LISTAR =========
|
|
async cargarNoticias(extraParams = {}) {
|
|
this.loading = true
|
|
this.error = null
|
|
|
|
try {
|
|
const params = {
|
|
per_page: this.filters.per_page,
|
|
page: this.filters.page,
|
|
...extraParams,
|
|
}
|
|
|
|
if (this.filters.publicado !== null && this.filters.publicado !== "") {
|
|
params.publicado = this.filters.publicado ? 1 : 0
|
|
}
|
|
if (this.filters.categoria) params.categoria = this.filters.categoria
|
|
if (this.filters.q) params.q = this.filters.q
|
|
|
|
// Ruta agrupada:
|
|
// GET /api/administracion/noticias
|
|
const res = await api.get("/admin/noticias", { params })
|
|
|
|
this.noticias = res.data?.data ?? []
|
|
this.meta = res.data?.meta ?? this.meta
|
|
} catch (err) {
|
|
this.error = err.response?.data?.message || "Error al cargar noticias"
|
|
console.error(err)
|
|
} finally {
|
|
this.loading = false
|
|
}
|
|
},
|
|
|
|
// ========= VER 1 =========
|
|
async cargarNoticia(id) {
|
|
this.loading = true
|
|
this.error = null
|
|
try {
|
|
const res = await api.get(`/admin/noticias/${id}`)
|
|
this.noticia = res.data?.data ?? res.data
|
|
} catch (err) {
|
|
this.error = err.response?.data?.message || "Error al cargar la noticia"
|
|
console.error(err)
|
|
} finally {
|
|
this.loading = false
|
|
}
|
|
},
|
|
|
|
// ========= CREAR =========
|
|
// payload: { titulo, descripcion_corta, contenido, categoria, tag_color, fecha_publicacion, publicado, destacado, orden, link_url, link_texto, imagen(File) }
|
|
async crearNoticia(payload) {
|
|
this.saving = true
|
|
this.error = null
|
|
|
|
try {
|
|
const form = this._toFormData(payload)
|
|
|
|
const res = await api.post("/admin/noticias", form, {
|
|
headers: { "Content-Type": "multipart/form-data" },
|
|
})
|
|
|
|
const noticia = res.data?.data ?? null
|
|
if (noticia) {
|
|
// opcional: agrega arriba
|
|
this.noticias = [noticia, ...this.noticias]
|
|
}
|
|
return noticia
|
|
} catch (err) {
|
|
this.error = err.response?.data?.message || "Error al crear noticia"
|
|
console.error(err)
|
|
throw err
|
|
} finally {
|
|
this.saving = false
|
|
}
|
|
},
|
|
|
|
// ========= ACTUALIZAR =========
|
|
async actualizarNoticia(id, payload) {
|
|
this.saving = true
|
|
this.error = null
|
|
|
|
try {
|
|
// Si hay imagen (File), conviene multipart
|
|
const hasFile = payload?.imagen instanceof File
|
|
let res
|
|
|
|
if (hasFile) {
|
|
const form = this._toFormData(payload)
|
|
|
|
// Si tu ruta es PUT, axios con multipart PUT funciona.
|
|
res = await api.put(`/admin/noticias/${id}`, form, {
|
|
headers: { "Content-Type": "multipart/form-data" },
|
|
})
|
|
} else {
|
|
// JSON normal
|
|
res = await api.put(`/administracion/noticias/${id}`, payload)
|
|
}
|
|
|
|
const updated = res.data?.data ?? null
|
|
|
|
if (updated) {
|
|
this.noticias = this.noticias.map((n) => (n.id === id ? updated : n))
|
|
if (this.noticia?.id === id) this.noticia = updated
|
|
}
|
|
|
|
return updated
|
|
} catch (err) {
|
|
this.error = err.response?.data?.message || "Error al actualizar noticia"
|
|
console.error(err)
|
|
throw err
|
|
} finally {
|
|
this.saving = false
|
|
}
|
|
},
|
|
|
|
// ========= ELIMINAR =========
|
|
async eliminarNoticia(id) {
|
|
this.deleting = true
|
|
this.error = null
|
|
try {
|
|
await api.delete(`/admin/noticias/${id}`)
|
|
this.noticias = this.noticias.filter((n) => n.id !== id)
|
|
if (this.noticia?.id === id) this.noticia = null
|
|
return true
|
|
} catch (err) {
|
|
this.error = err.response?.data?.message || "Error al eliminar noticia"
|
|
console.error(err)
|
|
throw err
|
|
} finally {
|
|
this.deleting = false
|
|
}
|
|
},
|
|
|
|
// ========= Helpers =========
|
|
setFiltro(key, value) {
|
|
this.filters[key] = value
|
|
},
|
|
|
|
resetFiltros() {
|
|
this.filters = { publicado: null, categoria: "", q: "", per_page: 9, page: 1 }
|
|
},
|
|
|
|
_toFormData(payload = {}) {
|
|
const form = new FormData()
|
|
|
|
Object.entries(payload).forEach(([k, v]) => {
|
|
if (v === undefined || v === null) return
|
|
|
|
// booleans como 1/0 (Laravel feliz)
|
|
if (typeof v === "boolean") {
|
|
form.append(k, v ? "1" : "0")
|
|
return
|
|
}
|
|
|
|
form.append(k, v)
|
|
})
|
|
|
|
return form
|
|
},
|
|
},
|
|
})
|