se agrega mantenedor de comunas

master/frontend-google-map
Francisco Sandoval 2023-07-12 21:55:07 -04:00
parent ee3d94144e
commit 926fbf0ec8
7 changed files with 265 additions and 1 deletions

View File

@ -9,4 +9,5 @@
<div class="sidebar-header text-red mt-3">Mantenedores</div>
<SideLink to="/aplicaciones">Aplicaciones</SideLink>
<SideLink to="/usuarios">Usuarios</SideLink>
<SideLink to="/comunas">Comunas</SideLink>
</nav>

View File

@ -0,0 +1,128 @@
<script>
import { Link } from 'svelte-navigator'
import Paginate from '$/components/Paginate.svelte'
import PageTitle from '$/components/PageTitle.svelte'
import { getComunas, getComuna, createComuna, updateComuna, deleteComuna } from '$/services/comunas'
import Modal from '$/components/Modal.svelte';
import FormComuna from './Form.svelte';
let comuna = null
let es_nuevo = true
let comunas = { count: 0, results: [] }
let page = 1
const limit = 15
$: onPage(page)
async function onPage(page) {
try {
const offset = (page - 1) * limit;
comunas = await getComunas({ offset, limit, ordering: 'id_region' })
} catch(error) {
alert(error.detail || error)
}
}
function onNuevo() {
comuna = {}
es_nuevo = true
}
async function onEditar({ id_comuna }) {
try {
comuna = await getComuna(id_comuna)
es_nuevo = false
} catch (error) {
alert(error.detail || error)
}
}
async function onSave() {
try {
if (es_nuevo) {
await createComuna(comuna)
} else {
await updateComuna(comuna)
}
alert('Comuna guardada con exito')
comuna = null; // se cierra el modal
onPage(page) // refresco la tabla de registros
} catch (error) {
alert(error.detail || error)
}
}
async function onDelete() {
try {
if (!confirm(`Desea eliminar la comuna [${comuna.nombre_comuna}]?`)) return;
await deleteComuna(comuna.id_comuna)
alert('Comuna eliminada con exito')
comuna = null; // se cierra el modal
onPage(page) // refresco la tabla de registros
} catch (error) {
alert(error.detail || error)
}
}
</script>
<PageTitle>Comunas</PageTitle>
<div class="mb-3 d-flex">
<button class="btn btn-pill-primary" on:click|preventDefault={onNuevo}>Nuevo</button>
<div class="m-auto"></div>
<Link to='/' class="btn btn-pill-secondary">Volver</Link>
</div>
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr class="table-accent">
<th>ID</th>
<th>Nombre</th>
<th>Región</th>
</tr>
</thead>
<tbody>
{#each comunas.results as row}
<tr>
<td><a class="d-block" href={"#"} on:click|preventDefault={() => onEditar(row)}>{row.id_comuna}</a></td>
<td>{row.nombre_comuna}</td>
<td>{row.id_region}</td>
</tr>
{/each}
</tbody>
</table>
</div>
<div class="d-flex">
<a href={"#"} class="btn btn-sm btn-outline-dark mr-3" on:click|preventDefault={() => onPage(page)}>Refrescar</a>
<Paginate
offset={(page - 1) * limit}
{limit}
count={comunas.count}
on:page={ev => page = ev.detail}
/>
</div>
{#if !!comuna}
<form action="" on:submit|preventDefault={onSave}>
<Modal title="Comuna"
on:close={() => comuna = null}
>
<FormComuna bind:form={comuna} {es_nuevo} />
<svelte:fragment slot="buttons">
<button type="submit" class="btn btn-primary">Guardar</button>
{#if !es_nuevo}
<button class="btn btn-danger" on:click|preventDefault={onDelete}>Eliminar</button>
{/if}
</svelte:fragment>
</Modal>
</form>
{/if}
<style>
.table-responsive {
max-height: calc(100vh - 300px);
}
</style>

View File

@ -0,0 +1,37 @@
<script>
import { getRegiones } from '$/services/regiones'
export let form = {}
export let es_nuevo = true
let regiones = []
$: begin()
async function begin() {
try {
regiones = await getRegiones()
} catch (error) {
alert(error.detail || error)
}
}
</script>
<div class="input-group mb-3">
<div class="input-group-text">ID</div>
<input type="number" bind:value={form.id_comuna} class="form-control" disabled>
</div>
<div class="input-group mb-3">
<div class="input-group-text">Comuna</div>
<input type="text" bind:value={form.nombre_comuna} class="form-control" required>
</div>
<div class="input-group mb-3">
<div class="input-group-text">Región</div>
<select bind:value={form.id_region} class="form-control" required>
<option value=""></option>
{#each regiones as region}
<option value={region.id_region}>{region.nombre_region}</option>
{/each}
</select>
</div>

View File

@ -11,7 +11,7 @@
</div>
<div class="col-md mb-3 pt-3">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="persona-es_vigente" checked={form.vigente}>
<input type="checkbox" class="custom-control-input" id="persona-es_vigente" bind:checked={form.vigente}>
<label class="custom-control-label" for="persona-es_vigente">Vigente</label>
</div>
</div>

View File

@ -5,6 +5,7 @@ import PageAplicaciones from '$/pages/aplicaciones/Admin.svelte'
import PageUsuarios from '$/pages/usuarios/Admin.svelte'
import PageUsuarioCreate from '$/pages/usuarios/Create.svelte'
import PageUsuarioModifica from '$/pages/usuarios/Create.svelte'
import PageComunas from '$/pages/comunas/Admin.svelte'
export const routes = [
{ path: '/', component: PageHome },
@ -13,5 +14,6 @@ export const routes = [
{ path: '/usuarios', component: PageUsuarios },
{ path: '/usuarios/nuevo', component: PageUsuarioCreate },
{ path: '/usuarios/:login', component: PageUsuarioModifica },
{ path: '/comunas', component: PageComunas },
{ path: '*', component: PageError },
]

View File

@ -0,0 +1,48 @@
import { base, getToken } from './_config'
export async function getComunas(params) {
const query = !params ? '' : '?' + (new URLSearchParams(params).toString());
const res = await fetch(`${base}/comunas/${query}`, {
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
})
if (!res.ok) throw await res.text()
return res.json()
}
export async function getComuna(id) {
const res = await fetch(`${base}/comunas/${id}/`, {
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
})
if (!res.ok) throw await res.text()
return res.json()
}
export async function createComuna(data) {
const res = await fetch(`${base}/comunas/`, {
method: 'POST',
body: JSON.stringify(data),
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
})
if (!res.ok) throw await res.text()
return res.json()
}
export async function updateComuna({ id_comuna: id, ...data }) {
const res = await fetch(`${base}/comunas/${id}/`, {
method: 'PATCH',
body: JSON.stringify(data),
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
})
if (!res.ok) throw await res.text()
return res.json()
}
export async function deleteComuna(id) {
const res = await fetch(`${base}/comunas/${id}/`, {
method: 'DELETE',
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
})
if (!res.ok) throw await res.text()
return res.text()
}

View File

@ -0,0 +1,48 @@
import { base, getToken } from './_config'
export async function getRegiones(params) {
const query = !params ? '' : '?' + (new URLSearchParams(params).toString());
const res = await fetch(`${base}/regiones/${query}`, {
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
})
if (!res.ok) throw await res.text()
return res.json()
}
export async function getRegion(id) {
const res = await fetch(`${base}/regiones/${id}/`, {
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
})
if (!res.ok) throw await res.text()
return res.json()
}
export async function createRegion(data) {
const res = await fetch(`${base}/regiones/`, {
method: 'POST',
body: JSON.stringify(data),
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
})
if (!res.ok) throw await res.text()
return res.json()
}
export async function updateRegion({ id, ...data }) {
const res = await fetch(`${base}/regiones/${id}/`, {
method: 'PATCH',
body: JSON.stringify(data),
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
})
if (!res.ok) throw await res.text()
return res.json()
}
export async function deleteRegion(id) {
const res = await fetch(`${base}/regiones/${id}/`, {
method: 'DELETE',
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
})
if (!res.ok) throw await res.text()
return res.json()
}