avance editar paraderos desde mapa
parent
169c0766de
commit
d440df819f
|
@ -1,14 +1,16 @@
|
|||
<script>
|
||||
import { onMount } from 'svelte'
|
||||
import { onMount, createEventDispatcher } from 'svelte'
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
export let google_api_key = null;
|
||||
export let center = null;
|
||||
export let zoom = 4;
|
||||
export let marks = [];
|
||||
|
||||
let mapEl = null;
|
||||
let infoWindow;
|
||||
|
||||
onMount(() => {
|
||||
console.log('onMount')
|
||||
if (!globalThis.google) {
|
||||
const el = document.createElement('script')
|
||||
el.src = "https://maps.googleapis.com/maps/api/js?key=" + google_api_key + "&callback=initMap&v=weekly"
|
||||
|
@ -25,21 +27,21 @@
|
|||
if (!google || !mapEl) return;
|
||||
|
||||
const map = new google.maps.Map(mapEl, { zoom, center });
|
||||
const infoWindow = new google.maps.InfoWindow();
|
||||
infoWindow = new google.maps.InfoWindow();
|
||||
|
||||
for (const mark of marks) {
|
||||
const { position, title, location } = mark;
|
||||
const marker = new google.maps.Marker({
|
||||
position,
|
||||
map,
|
||||
title,
|
||||
});
|
||||
const { position, title, location, url_image, id_paradero } = mark;
|
||||
const marker = new google.maps.Marker({ position, map, title });
|
||||
|
||||
marker.addListener("click", () => {
|
||||
infoWindow.close();
|
||||
const imagen = url_image ? `<img alt="Imagen" src="${url_image}" width="200">` : ''
|
||||
const html = `
|
||||
<h1>${title}</h1>
|
||||
<p>${location}</p>
|
||||
<button class="btn btn-primary" onclick="onEdita(${id_paradero})">Editar</button>
|
||||
<hr>
|
||||
${imagen}
|
||||
`
|
||||
infoWindow.setContent(html);
|
||||
infoWindow.open(marker.getMap(), marker);
|
||||
|
@ -49,6 +51,11 @@
|
|||
console.log({ zoom: map.zoom });
|
||||
});
|
||||
};
|
||||
|
||||
globalThis.onEdita = function(id_paradero) {
|
||||
infoWindow.close();
|
||||
dispatch('edita', id_paradero)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div bind:this={mapEl} style="height: 800px; max-height: 90vh;">Cargando...</div>
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
<script>
|
||||
import Modal from "$/components/Modal.svelte";
|
||||
import { getParadero, getUrlImagen, createParadero, updateParadero, deleteParadero, saveImageParadero } from "$/services/paraderos";
|
||||
|
||||
import { createEventDispatcher } from "svelte";
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
export let paradero = { id_paradero: null };
|
||||
let form = {};
|
||||
let inputfile = null;
|
||||
let imagenEl = null;
|
||||
|
||||
$: infoParadero(paradero)
|
||||
|
||||
async function infoParadero({ id_paradero }) {
|
||||
try {
|
||||
if (!id_paradero) return;
|
||||
form = await getParadero(id_paradero)
|
||||
} catch (error) {
|
||||
alert(error)
|
||||
}
|
||||
}
|
||||
|
||||
async function onSaveParadero() {
|
||||
try {
|
||||
form = form.id_paradero ? await updateParadero(form) : await createParadero(form)
|
||||
alert('Información guardada')
|
||||
} catch (error) {
|
||||
alert(error)
|
||||
}
|
||||
}
|
||||
|
||||
async function onDeleteParadero() {
|
||||
try {
|
||||
await deleteParadero(form.id_paradero)
|
||||
alert('Paradero eliminado')
|
||||
dispatch('delete', form)
|
||||
dispatch('close')
|
||||
} catch (error) {
|
||||
alert(error)
|
||||
}
|
||||
}
|
||||
|
||||
async function onChangeImage() {
|
||||
try {
|
||||
const { url_image } = await saveImageParadero(paradero.id_paradero, inputfile.files[0])
|
||||
imagenEl.src = url_image + '?nocache=' + (new Date()).valueOf()
|
||||
alert('Imagen cambiada')
|
||||
} catch (error) {
|
||||
alert(error)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<form on:submit|preventDefault={onSaveParadero}>
|
||||
<Modal size="lg"
|
||||
title={'Paradero #' + paradero.id_paradero}
|
||||
on:close={() => dispatch('close')}>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-text">Dirección</div>
|
||||
<input type="text" bind:value={form.stop_name} class="form-control">
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-text">Latitud</div>
|
||||
<input type="number" step="any" bind:value={form.stop_lat} class="form-control">
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-text">Longitud</div>
|
||||
<input type="number" step="any" bind:value={form.stop_lon} class="form-control">
|
||||
</div>
|
||||
|
||||
{#if form.id_paradero}
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-text"><i class="bi bi-image"></i></div>
|
||||
<div class="form-control"><input type="file" bind:this={inputfile}></div>
|
||||
<button class="btn btn-primary" on:click|preventDefault={onChangeImage}>Cambiar Imagen</button>
|
||||
</div>
|
||||
|
||||
<img alt="Imagen Paradero" class="img-fluid" bind:this={imagenEl} src={getUrlImagen(form.id_paradero)}>
|
||||
{/if}
|
||||
|
||||
<svelte:fragment slot="buttons">
|
||||
<button type="submit" class="btn btn-primary me-2">
|
||||
<i class="bi bi-save"></i> Guardar
|
||||
</button>
|
||||
<button class="btn btn-danger me-2" on:click|preventDefault={onDeleteParadero}>
|
||||
<i class="bi bi-trash"></i> Eliminar
|
||||
</button>
|
||||
</svelte:fragment>
|
||||
</Modal>
|
||||
</form>
|
|
@ -4,12 +4,12 @@
|
|||
import { storeParaderos } from "$/stores/global";
|
||||
import GoogleMap from '$/components/GoogleMap.svelte'
|
||||
import IconLoading from "$/components/IconLoading.svelte";
|
||||
import ModalParadero from "./ModalParadero.svelte";
|
||||
|
||||
let my_map = null;
|
||||
let data_map = null
|
||||
let paradero = null
|
||||
|
||||
$: init_google_map($storeParaderos)
|
||||
$: console.log({ data_map })
|
||||
|
||||
async function init_google_map(data_inicial) {
|
||||
const paraderos = data_inicial || await getMarcasParaderos()
|
||||
|
@ -17,7 +17,9 @@
|
|||
data_map = paraderos;
|
||||
}
|
||||
|
||||
|
||||
function onEdita(id_paradero) {
|
||||
paradero = { id_paradero }
|
||||
}
|
||||
</script>
|
||||
|
||||
<PageTitle>Paraderos</PageTitle>
|
||||
|
@ -33,9 +35,15 @@
|
|||
center={data_map.center}
|
||||
zoom={data_map.zoom}
|
||||
marks={data_map.marks}
|
||||
on:edita={ev => onEdita(ev.detail)}
|
||||
/>
|
||||
{:else}
|
||||
<IconLoading />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{#if paradero}
|
||||
<ModalParadero {paradero} on:close={() => paradero = null} />
|
||||
{/if}
|
|
@ -0,0 +1,65 @@
|
|||
|
||||
import { base, getToken } from './_config'
|
||||
|
||||
export function getUrlImagen(id_paradero) {
|
||||
return `${base}/paraderos/image/${id_paradero}`
|
||||
}
|
||||
|
||||
export async function getParaderos(params) {
|
||||
const query = !params ? '' : '?' + (new URLSearchParams(params).toString());
|
||||
const res = await fetch(`${base}/paraderos/${query}`, {
|
||||
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
|
||||
})
|
||||
if (!res.ok) throw await res.text()
|
||||
return res.json()
|
||||
}
|
||||
|
||||
export async function getParadero(rut) {
|
||||
const res = await fetch(`${base}/paraderos/${rut}/`, {
|
||||
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
|
||||
})
|
||||
if (!res.ok) throw await res.text()
|
||||
return res.json()
|
||||
}
|
||||
|
||||
export async function createParadero(data) {
|
||||
const res = await fetch(`${base}/paraderos/`, {
|
||||
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 updateParadero({ id_paradero: id = null, ...data }) {
|
||||
const res = await fetch(`${base}/paraderos/${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 deleteParadero(id) {
|
||||
const res = await fetch(`${base}/paraderos/${id}/`, {
|
||||
method: 'DELETE',
|
||||
headers: { "Authorization": `Bearer ${getToken()}`, "Content-Type": "application/json" }
|
||||
})
|
||||
if (!res.ok) throw await res.text()
|
||||
return res.json()
|
||||
}
|
||||
|
||||
export async function saveImageParadero(id = null, file) {
|
||||
const form = new FormData()
|
||||
form.append('imagen', file)
|
||||
|
||||
const res = await fetch(`${base}/paraderos/image/${id}/`, {
|
||||
method: 'POST',
|
||||
body: form,
|
||||
headers: { "Authorization": `Bearer ${getToken()}` }
|
||||
})
|
||||
if (!res.ok) throw await res.text()
|
||||
return res.json()
|
||||
}
|
Loading…
Reference in New Issue