avance editar paraderos desde mapa
parent
169c0766de
commit
d440df819f
|
@ -1,14 +1,16 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from 'svelte'
|
import { onMount, createEventDispatcher } from 'svelte'
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
export let google_api_key = null;
|
export let google_api_key = null;
|
||||||
export let center = null;
|
export let center = null;
|
||||||
export let zoom = 4;
|
export let zoom = 4;
|
||||||
export let marks = [];
|
export let marks = [];
|
||||||
|
|
||||||
let mapEl = null;
|
let mapEl = null;
|
||||||
|
let infoWindow;
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
console.log('onMount')
|
|
||||||
if (!globalThis.google) {
|
if (!globalThis.google) {
|
||||||
const el = document.createElement('script')
|
const el = document.createElement('script')
|
||||||
el.src = "https://maps.googleapis.com/maps/api/js?key=" + google_api_key + "&callback=initMap&v=weekly"
|
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;
|
if (!google || !mapEl) return;
|
||||||
|
|
||||||
const map = new google.maps.Map(mapEl, { zoom, center });
|
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) {
|
for (const mark of marks) {
|
||||||
const { position, title, location } = mark;
|
const { position, title, location, url_image, id_paradero } = mark;
|
||||||
const marker = new google.maps.Marker({
|
const marker = new google.maps.Marker({ position, map, title });
|
||||||
position,
|
|
||||||
map,
|
|
||||||
title,
|
|
||||||
});
|
|
||||||
|
|
||||||
marker.addListener("click", () => {
|
marker.addListener("click", () => {
|
||||||
infoWindow.close();
|
infoWindow.close();
|
||||||
|
const imagen = url_image ? `<img alt="Imagen" src="${url_image}" width="200">` : ''
|
||||||
const html = `
|
const html = `
|
||||||
<h1>${title}</h1>
|
<h1>${title}</h1>
|
||||||
<p>${location}</p>
|
<p>${location}</p>
|
||||||
|
<button class="btn btn-primary" onclick="onEdita(${id_paradero})">Editar</button>
|
||||||
|
<hr>
|
||||||
|
${imagen}
|
||||||
`
|
`
|
||||||
infoWindow.setContent(html);
|
infoWindow.setContent(html);
|
||||||
infoWindow.open(marker.getMap(), marker);
|
infoWindow.open(marker.getMap(), marker);
|
||||||
|
@ -49,6 +51,11 @@
|
||||||
console.log({ zoom: map.zoom });
|
console.log({ zoom: map.zoom });
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
globalThis.onEdita = function(id_paradero) {
|
||||||
|
infoWindow.close();
|
||||||
|
dispatch('edita', id_paradero)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div bind:this={mapEl} style="height: 800px; max-height: 90vh;">Cargando...</div>
|
<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 { storeParaderos } from "$/stores/global";
|
||||||
import GoogleMap from '$/components/GoogleMap.svelte'
|
import GoogleMap from '$/components/GoogleMap.svelte'
|
||||||
import IconLoading from "$/components/IconLoading.svelte";
|
import IconLoading from "$/components/IconLoading.svelte";
|
||||||
|
import ModalParadero from "./ModalParadero.svelte";
|
||||||
|
|
||||||
let my_map = null;
|
|
||||||
let data_map = null
|
let data_map = null
|
||||||
|
let paradero = null
|
||||||
|
|
||||||
$: init_google_map($storeParaderos)
|
$: init_google_map($storeParaderos)
|
||||||
$: console.log({ data_map })
|
|
||||||
|
|
||||||
async function init_google_map(data_inicial) {
|
async function init_google_map(data_inicial) {
|
||||||
const paraderos = data_inicial || await getMarcasParaderos()
|
const paraderos = data_inicial || await getMarcasParaderos()
|
||||||
|
@ -17,7 +17,9 @@
|
||||||
data_map = paraderos;
|
data_map = paraderos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onEdita(id_paradero) {
|
||||||
|
paradero = { id_paradero }
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<PageTitle>Paraderos</PageTitle>
|
<PageTitle>Paraderos</PageTitle>
|
||||||
|
@ -33,9 +35,15 @@
|
||||||
center={data_map.center}
|
center={data_map.center}
|
||||||
zoom={data_map.zoom}
|
zoom={data_map.zoom}
|
||||||
marks={data_map.marks}
|
marks={data_map.marks}
|
||||||
|
on:edita={ev => onEdita(ev.detail)}
|
||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<IconLoading />
|
<IconLoading />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</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