se termina crud de aplicaciones

master/frontend-google-map
Francisco Sandoval 2023-06-26 16:50:59 -04:00
parent 495de145ee
commit 9229cf80e3
7 changed files with 237 additions and 17 deletions

View File

@ -0,0 +1,44 @@
<script>
import { createEventDispatcher } from "svelte";
const dispatch = createEventDispatcher();
export let title = "modal title";
export let className = "";
export let classTitle = "";
export let classHeader = "";
export let size = "";
</script>
<!-- Modal -->
<div
class={"modal show " + className}
tabindex="-1"
aria-hidden="true"
style="display: block; background-color: rgb(0 0 0 / 30%)"
>
<div class={"modal-dialog " + (size ? " modal-" + size : "")}>
<div class="modal-content">
<div class={"modal-header " + classHeader}>
<h5 class={"modal-title " + classTitle}>{title}</h5>
<button
type="button"
class="btn-close"
aria-label="Close"
on:click|preventDefault={() => dispatch("close")}
/>
</div>
<div class="modal-body">
<slot />
</div>
<div class="modal-footer py-2">
<slot name="buttons" />
<div class="me-auto" />
<button
type="button"
class="btn btn-secondary border border-light"
on:click|preventDefault={() => dispatch("close")}>Cerrar</button
>
</div>
</div>
</div>
</div>

View File

@ -6,7 +6,7 @@
let persona = {}
$: persona = $storeSession
$: avatar = $storeSession?.avatar_img || '/avatars/avatar1.jpg';
$: avatar = $storeSession?.avatar_img || '/avatars/avatar2.png';
function onLogout() {
sessionStorage.clear();

View File

@ -1,40 +1,81 @@
<script>
import Paginate from "$/components/Paginate.svelte";
import { getAplicaciones } from "$/services/aplicaciones";
import ModalAplicacion from "./ModalAplicacion.svelte";
const limit = 15;
let page = 1;
let offset = 0;
let count = 0;
let ordering = 'id_aplicacion'
let aplicaciones = []
let aplicacion = null
$: onPage(page)
async function onPage(p) {
try {
offset = (p - 1) * limit;
const data = await getAplicaciones({ offset, limit, ordering })
aplicaciones = data.results;
count = data.count;
} catch (error) {
alert(error)
}
}
onPage(1)
function onEdita(item) {
aplicacion = item;
}
function onNuevo() {
aplicacion = {}
}
function onOrderBy(field) {
ordering = ordering === field ? '-' + field : field;
onPage(page)
}
</script>
<h1 class="h3 mb-3">Aplicaciones</h1>
<div class="card">
<div class="card-header">
<button class="btn btn-outline-secondary" on:click|preventDefault={onNuevo}><i class="bi bi-plus-lg"></i> Nuevo</button>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-sm">
<table class="table table-sm table-bordered">
<thead>
<tr>
<th>ID</th>
<th>Nombre</th>
<th></th>
<tr class="table-secondary">
<th style="width:5%">Nro</th>
<th>
<a href={"#"} on:click|preventDefault={() => onOrderBy('id_aplicacion')}>ID</a>
{#if ordering === 'id_aplicacion'}<i class="bi bi-caret-up-fill"></i>{/if}
{#if ordering === '-id_aplicacion'}<i class="bi bi-caret-down-fill"></i>{/if}
</th>
<th>
<a href={"#"} on:click|preventDefault={() => onOrderBy('app')}>Nombre</a>
{#if ordering === 'app'}<i class="bi bi-caret-up-fill"></i>{/if}
{#if ordering === '-app'}<i class="bi bi-caret-down-fill"></i>{/if}
</th>
<th>
<a href={"#"} on:click|preventDefault={() => onOrderBy('vigente')}>Vigente</a>
{#if ordering === 'vigente'}<i class="bi bi-caret-up-fill"></i>{/if}
{#if ordering === '-vigente'}<i class="bi bi-caret-down-fill"></i>{/if}
</th>
</tr>
</thead>
<tbody>
{#each aplicaciones as app, index}
<tr>
<td></td>
<td></td>
<td></td>
<td class="table-secondary">{offset + index + 1}</td>
<td>{app.id_aplicacion}</td>
<td><a href={"#"} on:click|preventDefault={() => onEdita(app)}>{app.app}</a></td>
<td>{app.vigente}</td>
</tr>
{/each}
</tbody>
</table>
</div>
@ -44,7 +85,15 @@
{offset}
{limit}
{count}
on:page={ev => onPage(ev.detail)}
on:page={ev => page = ev.detail}
/>
</div>
</div>
{#if aplicacion}
<ModalAplicacion
{aplicacion}
on:close={() => aplicacion = null}
on:refresh={() => onPage(page)}
/>
{/if}

View File

@ -0,0 +1,85 @@
<script>
import Modal from "../../components/Modal.svelte";
import { getAplicacion, createAplicacion, updateAplicacion, deleteAplicacion } from "$/services/aplicaciones";
import { createEventDispatcher } from "svelte";
const dispatch = createEventDispatcher();
export let aplicacion = {}
let form = {}
$: begin(aplicacion.id_aplicacion)
async function begin(id) {
try {
if (!id) return;
form = await getAplicacion(id) || {}
} catch (error) {
alert(error.detail || error)
}
}
async function onSave() {
try {
if (aplicacion.id_aplicacion) {
form = await updateAplicacion(form)
} else {
form = await createAplicacion(form)
}
alert('Se ha guardado la aplicación')
dispatch('refresh')
dispatch('close')
} catch (error) {
if (error.detail) {
alert(error.detail)
} else {
alert(JSON.stringify(error))
}
}
}
async function onDelete() {
try {
if (!confirm('Eliminará el registro?')) return;
await deleteAplicacion(form.id_aplicacion)
alert('Se ha eliminado la aplicación')
dispatch('refresh')
dispatch('close')
} catch (error) {
alert(error.detail || error)
}
}
</script>
<Modal title={'Aplicacion #' + (aplicacion.id_aplicacion || 'Nuevo')}
size="lg"
on:close={() => dispatch('close')}
>
<div class="form">
<div class="row mb-3">
<div class="col-md-3">ID</div>
<div class="col-md">
{#if aplicacion.id_aplicacion}
<input type="number" value={form.id_aplicacion} disabled class="form-control">
{:else}
<input type="number" bind:value={form.id_aplicacion} required class="form-control">
{/if}
</div>
</div>
<div class="row mb-3">
<div class="col-md-3">Nombre</div>
<div class="col-md">
<input type="text" bind:value={form.app} required class="form-control">
</div>
</div>
<div class="mb-3">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" bind:checked={form.vigente} role="switch" id="vigente">
<label class="form-check-label" for="vigente">Vigente</label>
</div>
</div>
</div>
<svelte:fragment slot="buttons">
<button class="btn btn-primary" on:click|preventDefault={onSave}>Guardar</button>
<button class="btn btn-danger" on:click|preventDefault={onDelete}>Eliminar</button>
</svelte:fragment>
</Modal>

View File

@ -23,7 +23,7 @@
<div class="card-body">
<div class="m-sm-4">
<div class="text-center mb-4">
<img src="/avatars/avatar1.jpg" alt="Avatar"
<img src="/avatars/avatar2.png" alt="Avatar"
class="img-fluid rounded-circle" width="132" height="132"
/>
</div>

View File

@ -13,8 +13,8 @@
</div>
<div class="card-body text-center">
<img
src="/avatars/avatar1.jpg"
alt="Christina Mason"
src="/avatars/avatar2.png"
alt={`${persona.nombres} ${persona.apellido_a} ${persona.apellido_b}`}
class="img-fluid rounded-circle mb-2"
width="128"
height="128"

View File

@ -1,6 +1,48 @@
import { getToken } from './_config'
import { base, getToken } from './_config'
export async function getAplicaciones(params) {
//
const query = !params ? '' : '?' + (new URLSearchParams(params).toString());
const res = await fetch(`${base}/aplicaciones/${query}`, {
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
})
if (!res.ok) throw await res.json()
return res.json()
}
export async function getAplicacion(id) {
const res = await fetch(`${base}/aplicaciones/${id}/`, {
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
})
if (!res.ok) throw await res.json()
return res.json()
}
export async function createAplicacion(data) {
const res = await fetch(`${base}/aplicaciones/`, {
method: 'POST',
body: JSON.stringify(data),
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
})
if (!res.ok) throw await res.json()
return res.json()
}
export async function updateAplicacion({ id_aplicacion: id, ...data }) {
const res = await fetch(`${base}/aplicaciones/${id}/`, {
method: 'PATCH',
body: JSON.stringify(data),
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
})
if (!res.ok) throw await res.json()
return res.json()
}
export async function deleteAplicacion(id) {
const res = await fetch(`${base}/aplicaciones/${id}/`, {
method: 'DELETE',
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
})
if (!res.ok) throw await res.json()
return res.text()
}