se agrega mantenedor de personas

master/frontend-google-map
Francisco Sandoval 2023-07-17 15:43:39 -04:00
parent 52946ed518
commit 7f08de69a1
14 changed files with 166 additions and 53 deletions

View File

@ -27,6 +27,7 @@ footer>.container>.row { display: block; }
.navbar-bg { .navbar-bg {
position: relative; position: relative;
background: #cce0ef;
} }
.navbar-bg::after { .navbar-bg::after {
position: absolute; position: absolute;
@ -56,4 +57,18 @@ footer::after {
} }
footer.footer { background: #0A132D; } footer.footer { background: #0A132D; }
.text-muted { color: #fff !important; } .text-muted { color: #fff !important; }
input:required:invalid,
select:required:invalid,
textarea:required:invalid
{
border-color: var(--bs-danger);
}
input:required:valid,
select:required:valid,
textarea:required:valid
{
border-color: var(--bs-success);
}

View File

@ -1,3 +1,7 @@
<svelte:head>
<title>Transporte: Acceso</title>
</svelte:head>
<script> <script>
import { routes } from '$/routes/guest.routes' import { routes } from '$/routes/guest.routes'
import { Router, Route, createHistory } from 'svelte-navigator' import { Router, Route, createHistory } from 'svelte-navigator'

View File

@ -1,3 +1,7 @@
<svelte:head>
<title>Transporte: Usuario</title>
</svelte:head>
<script> <script>
import 'bootstrap/dist/css/bootstrap.min.css' import 'bootstrap/dist/css/bootstrap.min.css'
import '@adminkit/core/dist/css/app.css' import '@adminkit/core/dist/css/app.css'

View File

@ -42,6 +42,11 @@
<span class="align-middle">Usuarios</span> <span class="align-middle">Usuarios</span>
</SideLink> </SideLink>
<SideLink to="/personas">
<i class="align-middle bi bi-people fs-4" />
<span class="align-middle">Personas</span>
</SideLink>
</ul> </ul>
</div> </div>

View File

@ -1,10 +0,0 @@
<script>
let count = 0
const increment = () => {
count += 1
}
</script>
<button on:click={increment}>
count is {count}
</button>

View File

@ -28,7 +28,7 @@
<div class="input-group mb-3"> <div class="input-group mb-3">
<div class="input-group-text">Región</div> <div class="input-group-text">Región</div>
<select bind:value={form.id_region} class="form-control" required> <select bind:value={form.id_region} class="form-select" required>
<option value=""></option> <option value=""></option>
{#each regiones as region} {#each regiones as region}
<option value={region.id_region}>{region.nombre_region}</option> <option value={region.id_region}>{region.nombre_region}</option>

View File

@ -0,0 +1,61 @@
<script>
import { Link } from 'svelte-navigator'
import Paginate from '$/components/Paginate.svelte'
import { getPersonas } from '$/services/personas';
let page = 1;
let limit = 15;
let personas = { results: [], count: 0 };
$: onPage(page)
async function onPage(page) {
try {
const offset = (page - 1) * limit;
personas = await getPersonas({ offset, limit })
} catch (error) {
alert(error.detail || error)
}
}
</script>
<h2 class="h3 mb-3">Personas</h2>
<div class="card">
<div class="card-header">
<Link to='/personas/nuevo' class="btn btn-primary">
<i class="bi bi-plus-lg"></i> Nuevo
</Link>
</div>
<div class="card-body">
<table class="table table-sm">
<thead>
<tr>
<th>RUT</th>
<th>Nombres</th>
<th>Apellido 1</th>
<th>Apellido 2</th>
<th>Teléfono</th>
</tr>
</thead>
<tbody>
{#each personas.results as p}
<tr>
<td><Link to={'/personas/' + p.rut}>{p.rut}-{p.dv}</Link></td>
<td>{p.nombres}</td>
<td>{p.apellido_a}</td>
<td>{p.apellido_b}</td>
<td>{p.fono}</td>
</tr>
{/each}
</tbody>
</table>
</div>
<div class="card-footer">
<Paginate
offset={(page - 1) / limit}
{limit}
count={personas.count}
on:page={ev => page = ev.detail}
/>
</div>
</div>

View File

@ -27,11 +27,11 @@
<div class="row"> <div class="row">
<div class="col-md mb-3"> <div class="col-md mb-3">
RUT RUT
<input type="text" value={rut} class="form-control" disabled={!es_nuevo} required on:input={onChangeRut}> <input type="text" value={rut} class="form-control" required disabled={!es_nuevo} on:input={onChangeRut}>
</div> </div>
<div class="col-md mb-3"> <div class="col-md mb-3">
Tipo Tratamiento Tipo Tratamiento
<select bind:value={form.id_tipo_tratamiento} class="form-control"> <select bind:value={form.id_tipo_tratamiento} class="form-select">
<option value=""></option> <option value=""></option>
{#each tipos_tratamiento as tipo} {#each tipos_tratamiento as tipo}
<option value={tipo.id_tipo_tratamiento}>{tipo.tratamiento}</option> <option value={tipo.id_tipo_tratamiento}>{tipo.tratamiento}</option>
@ -73,7 +73,7 @@
<div class="row"> <div class="row">
<div class="col-md mb-3"> <div class="col-md mb-3">
Comuna Comuna
<select bind:value={form.id_comuna} class="form-control"> <select bind:value={form.id_comuna} class="form-select">
<option value=""></option> <option value=""></option>
</select> </select>
</div> </div>

View File

@ -1,34 +0,0 @@
<script>
import Paginate from '$/components/Paginate.svelte'
let page = 1;
let limit = 15;
let count = 0;
let personas = [];
</script>
<h2 class="h3 mb-3">Personas</h2>
<div class="card">
<div class="card-header"><button class="btn btn-outline-primary">Nuevo</button></div>
<div class="card-body">
<table class="table table-sm">
<thead>
<tr>
<th>RUT</th>
<th>Nombres</th>
<th>Apellido 1</th>
<th>Apellido 2</th>
<th>Teléfono</th>
</tr>
</thead>
</table>
</div>
<div class="card-footer">
<Paginate
offset={(page - 1) / limit}
{limit}
{count}
on:page={ev => page = ev.detail}
/>
</div>
</div>

View File

@ -0,0 +1,62 @@
<script>
import { onMount } from 'svelte'
import { storeLayout } from '$/stores/global'
import FormPersona from './Form.svelte'
import { Link, useParams, useNavigate } from 'svelte-navigator';
import { getPersona, createPersona, updatePersona } from '$/services/personas';
onMount(() => {
$storeLayout.showSidebar = false;
return () => {
$storeLayout.showSidebar = true;
}
})
const params = useParams()
const navigate = useNavigate()
let es_nuevo = true;
let form = {}
$: es_nuevo = !$params.rut
$: begin($params)
async function begin({ rut = null }) {
try {
if (!rut) return; // si es nuevo, no busco informacion
form = await getPersona(rut)
} catch (error) {
alert(error.detail || error)
}
}
async function onSave() {
try {
if (es_nuevo) {
// para crear un usuario, es requerido enviar los datos de la persona ademas.
await createPersona(form)
} else {
await updatePersona(form)
}
alert('Datos guardados con exito!')
navigate('/personas')
} catch (error) {
alert(error.detail || error)
}
}
</script>
<h3 class="h3 mb-3">{es_nuevo ? 'Nuevo Persona': 'Editar Persona'}</h3>
<form action="" on:submit|preventDefault={onSave}>
<div class="card">
<div class="card-header d-flex">
<button type="submit" class="btn btn-primary"><i class="bi bi-save"></i> Guardar</button>
<div class="m-auto"></div>
<Link to="/personas" class="btn btn-outline-secondary">Volver</Link>
</div>
<div class="card-body">
<h4 class="h4 mb-3">Datos de la persona</h4>
<FormPersona bind:form={form} {es_nuevo} />
</div>
</div>
</form>

View File

@ -6,6 +6,9 @@ import PageUsuarios from '$/pages/usuarios/Admin.svelte'
import PageUsuarioCreate from '$/pages/usuarios/Usuario.svelte' import PageUsuarioCreate from '$/pages/usuarios/Usuario.svelte'
import PageUsuarioModifica from '$/pages/usuarios/Usuario.svelte' import PageUsuarioModifica from '$/pages/usuarios/Usuario.svelte'
import PageComunas from '$/pages/comunas/Admin.svelte' import PageComunas from '$/pages/comunas/Admin.svelte'
import PagePersonas from '$/pages/personas/Admin.svelte'
import PagePersonaCreate from '$/pages/personas/Persona.svelte'
import PagePersonaModifica from '$/pages/personas/Persona.svelte'
export const routes = [ export const routes = [
{ path: '/', component: PageHome }, { path: '/', component: PageHome },
@ -15,5 +18,8 @@ export const routes = [
{ path: '/usuarios/nuevo', component: PageUsuarioCreate }, { path: '/usuarios/nuevo', component: PageUsuarioCreate },
{ path: '/usuarios/:login', component: PageUsuarioModifica }, { path: '/usuarios/:login', component: PageUsuarioModifica },
{ path: '/comunas', component: PageComunas }, { path: '/comunas', component: PageComunas },
{ path: '/personas', component: PagePersonas },
{ path: '/personas/nuevo', component: PagePersonaCreate },
{ path: '/personas/:rut', component: PagePersonaModifica },
{ path: '*', component: PageError }, { path: '*', component: PageError },
] ]

View File

@ -6,7 +6,7 @@ export async function getPersonas(params) {
const res = await fetch(`${base}/personas/${query}`, { const res = await fetch(`${base}/personas/${query}`, {
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" } headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
}) })
if (!res.ok) throw await res.json() if (!res.ok) throw await res.text()
return res.json() return res.json()
} }
@ -14,7 +14,7 @@ export async function getPersona(rut) {
const res = await fetch(`${base}/personas/${rut}/`, { const res = await fetch(`${base}/personas/${rut}/`, {
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" } headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
}) })
if (!res.ok) throw await res.json() if (!res.ok) throw await res.text()
return res.json() return res.json()
} }
@ -24,7 +24,7 @@ export async function createPersona(data) {
body: JSON.stringify(data), body: JSON.stringify(data),
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" } headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
}) })
if (!res.ok) throw await res.json() if (!res.ok) throw await res.text()
return res.json() return res.json()
} }
@ -34,6 +34,6 @@ export async function updatePersona({ rut: id = null, ...data }) {
body: JSON.stringify(data), body: JSON.stringify(data),
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" } headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
}) })
if (!res.ok) throw await res.json() if (!res.ok) throw await res.text()
return res.json() return res.json()
} }