basic ui
This commit is contained in:
parent
574b8f4240
commit
b07af64247
25
package-lock.json
generated
25
package-lock.json
generated
@ -10,10 +10,12 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@solidjs/router": "^0.14.9",
|
"@solidjs/router": "^0.14.9",
|
||||||
"bulma": "^1.0.2",
|
"bulma": "^1.0.2",
|
||||||
|
"leaflet": "^1.9.4",
|
||||||
"solid-icons": "^1.1.0",
|
"solid-icons": "^1.1.0",
|
||||||
"solid-js": "^1.9.1"
|
"solid-js": "^1.9.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/leaflet": "^1.9.12",
|
||||||
"sass": "^1.80.1",
|
"sass": "^1.80.1",
|
||||||
"typescript": "^5.5.3",
|
"typescript": "^5.5.3",
|
||||||
"vite": "^5.4.8",
|
"vite": "^5.4.8",
|
||||||
@ -1826,6 +1828,23 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/geojson": {
|
||||||
|
"version": "7946.0.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz",
|
||||||
|
"integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@types/leaflet": {
|
||||||
|
"version": "1.9.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.12.tgz",
|
||||||
|
"integrity": "sha512-BK7XS+NyRI291HIo0HCfE18Lp8oA30H1gpi1tf0mF3TgiCEzanQjOqNZ4x126SXzzi2oNSZhZ5axJp1k0iM6jg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/geojson": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/resolve": {
|
"node_modules/@types/resolve": {
|
||||||
"version": "1.20.2",
|
"version": "1.20.2",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@ -3250,6 +3269,12 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/leaflet": {
|
||||||
|
"version": "1.9.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
|
||||||
|
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==",
|
||||||
|
"license": "BSD-2-Clause"
|
||||||
|
},
|
||||||
"node_modules/leven": {
|
"node_modules/leven": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -11,10 +11,12 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@solidjs/router": "^0.14.9",
|
"@solidjs/router": "^0.14.9",
|
||||||
"bulma": "^1.0.2",
|
"bulma": "^1.0.2",
|
||||||
|
"leaflet": "^1.9.4",
|
||||||
"solid-icons": "^1.1.0",
|
"solid-icons": "^1.1.0",
|
||||||
"solid-js": "^1.9.1"
|
"solid-js": "^1.9.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/leaflet": "^1.9.12",
|
||||||
"sass": "^1.80.1",
|
"sass": "^1.80.1",
|
||||||
"typescript": "^5.5.3",
|
"typescript": "^5.5.3",
|
||||||
"vite": "^5.4.8",
|
"vite": "^5.4.8",
|
||||||
|
6
src/constants/Photos.ts
Normal file
6
src/constants/Photos.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
/** Lista de fotos (Licencia CC) */
|
||||||
|
const PHOTOS: string[] = [
|
||||||
|
"https://images.pexels.com/photos/2532003/pexels-photo-2532003.jpeg?cs=srgb&dl=pexels-jamie-patterson-1318696-2532003.jpg&fm=jpg"
|
||||||
|
];
|
||||||
|
|
||||||
|
export default PHOTOS;
|
@ -1,6 +0,0 @@
|
|||||||
/** Lista de videos (CC) */
|
|
||||||
const VIDEOS: string[] = [
|
|
||||||
"https://www.pexels.com/es-es/download/video/13831212/?fps=60.0&h=720&w=1280"
|
|
||||||
];
|
|
||||||
|
|
||||||
export default VIDEOS;
|
|
0
src/helpers/Api.ts
Normal file
0
src/helpers/Api.ts
Normal file
@ -1,15 +1,15 @@
|
|||||||
import VIDEOS from "../constants/Videos";
|
import PHOTOS from "../constants/Photos";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clase helper para gestionar los vídeos de fondo
|
* Clase helper para gestionar los vídeos de fondo
|
||||||
* encontrados en views/Home
|
* encontrados en views/Home
|
||||||
*/
|
*/
|
||||||
export default class Video {
|
export default class Photo {
|
||||||
/**
|
/**
|
||||||
* Elige un vídeo aleatoriamente de la lista
|
* Elige un vídeo aleatoriamente de la lista
|
||||||
* @returns Vídeo aleatorio
|
* @returns Vídeo aleatorio
|
||||||
*/
|
*/
|
||||||
static random(): string {
|
static random(): string {
|
||||||
return VIDEOS[Math.floor(Math.random()*VIDEOS.length)];
|
return PHOTOS[Math.floor(Math.random()*PHOTOS.length)];
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
/* @refresh reload */
|
/* @refresh reload */
|
||||||
import { render } from 'solid-js/web';
|
import { render } from 'solid-js/web';
|
||||||
import { Router } from "@solidjs/router";
|
import { Router } from "@solidjs/router";
|
||||||
|
import 'leaflet/dist/leaflet.css';
|
||||||
import './styles/bulma.scss';
|
import './styles/bulma.scss';
|
||||||
import routes from './routes';
|
import routes from './routes';
|
||||||
|
|
||||||
|
27
src/interfaces/Embalse.ts
Normal file
27
src/interfaces/Embalse.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
export default interface Embalse {
|
||||||
|
// EMBALSES
|
||||||
|
ID: number;
|
||||||
|
AMBITO_NOMBRE: string;
|
||||||
|
EMBALSE_NOMBRE: string;
|
||||||
|
AGUA_TOTAL: number;
|
||||||
|
ELECTRICO_FLAG: boolean;
|
||||||
|
// LISTADO_EMBALSES
|
||||||
|
CODIGO: number;
|
||||||
|
NOMBRE: string;
|
||||||
|
EMBALSE: string;
|
||||||
|
X: string;
|
||||||
|
Y: string;
|
||||||
|
DEMARC: string;
|
||||||
|
CAUCE: string;
|
||||||
|
GOOGLE: string;
|
||||||
|
OPENSTREETMAP: string;
|
||||||
|
WIKIDATA: string;
|
||||||
|
PROVINCIA: string;
|
||||||
|
CCAA: string;
|
||||||
|
TIPO: string;
|
||||||
|
TITULAR: string;
|
||||||
|
USO: string;
|
||||||
|
COTA_CORON: string;
|
||||||
|
ALT_CIMIEN: string;
|
||||||
|
INFORME: string;
|
||||||
|
}
|
@ -1,10 +1,15 @@
|
|||||||
import { RouteDefinition } from "@solidjs/router";
|
import { RouteDefinition } from "@solidjs/router";
|
||||||
import Home from "./views/Home";
|
import Home from "./views/Home";
|
||||||
|
import Finder from "./views/Finder";
|
||||||
|
|
||||||
const routes: RouteDefinition[] = [
|
const routes: RouteDefinition[] = [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
component: Home
|
component: Home
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/finder',
|
||||||
|
component: Finder
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
155
src/views/Finder.tsx
Normal file
155
src/views/Finder.tsx
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
import { createSignal, onCleanup, onMount } from "solid-js";
|
||||||
|
import L from 'leaflet';
|
||||||
|
import { FaSolidLocationPin } from "solid-icons/fa";
|
||||||
|
import Navbar from "../partials/Navbar";
|
||||||
|
|
||||||
|
function Finder() {
|
||||||
|
const [pos, setPos] = createSignal<[number, number]>([0, 0]);
|
||||||
|
const [geo, setGeo] = createSignal(true);
|
||||||
|
|
||||||
|
let markers: L.Marker[] = [];
|
||||||
|
|
||||||
|
let first = true;
|
||||||
|
let watchId: number = -1;
|
||||||
|
let map: L.Map;
|
||||||
|
|
||||||
|
let me = L.marker([0, 0]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Montar Leafmap
|
||||||
|
*/
|
||||||
|
onMount(() => {
|
||||||
|
map = L.map('map');
|
||||||
|
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||||
|
maxZoom: 19,
|
||||||
|
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
if (geo()) {
|
||||||
|
listenGeolocation();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Limpiar watch de geolocalización si
|
||||||
|
* está activo
|
||||||
|
*/
|
||||||
|
onCleanup(() => {
|
||||||
|
if (watchId !== -1) {
|
||||||
|
navigator.geolocation.clearWatch(watchId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activar / Desactivar uso de Geolocalización
|
||||||
|
*/
|
||||||
|
const toggleGeo = () => {
|
||||||
|
if (geo()) {
|
||||||
|
navigator.geolocation.clearWatch(watchId);
|
||||||
|
watchId = -1;
|
||||||
|
} else {
|
||||||
|
listenGeolocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
setGeo(!geo());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activar listener de geolocalización en tiempo real
|
||||||
|
*/
|
||||||
|
const listenGeolocation = () => {
|
||||||
|
watchId = navigator.geolocation.watchPosition(
|
||||||
|
(pos) => {
|
||||||
|
setPos([pos.coords.latitude, pos.coords.longitude]);
|
||||||
|
handleLocation();
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
alert(err.message);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escribe los puntos relevantes
|
||||||
|
* (Mi ubicación y los embalses cercanos)
|
||||||
|
*/
|
||||||
|
const handleLocation = () => {
|
||||||
|
me.setLatLng(pos());
|
||||||
|
if (first) {
|
||||||
|
map.setView(pos(), 9);
|
||||||
|
me.addTo(map);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
if (markers.length > 0) {
|
||||||
|
markers.forEach((m) => {
|
||||||
|
map.removeLayer(m);
|
||||||
|
})
|
||||||
|
|
||||||
|
markers = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Hacer petición y sacar markers
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escribe la latitud de la tupla manualmente
|
||||||
|
* @param val Latitud dada por el input
|
||||||
|
*/
|
||||||
|
const setLatitudeManual = (val: string) => {
|
||||||
|
const lat = parseFloat(val);
|
||||||
|
|
||||||
|
setPos([lat, pos()[1]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escribe la longitud de la tupla manualmente
|
||||||
|
* @param val longitud dada por el input
|
||||||
|
*/
|
||||||
|
const setLongitudeManual = (val: string) => {
|
||||||
|
const lon = parseFloat(val);
|
||||||
|
|
||||||
|
setPos([pos()[0], lon]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Navbar />
|
||||||
|
<section class="section">
|
||||||
|
<div class="container">
|
||||||
|
<div class="columns is-centered is-vcentered is-multiline">
|
||||||
|
<div class="column is-narrow">
|
||||||
|
<div class="field has-addons has-addons-centered">
|
||||||
|
<div class="control">
|
||||||
|
<input class="input" on:change={(e) => setLatitudeManual(e.target.value)} type="text" disabled={geo()} placeholder="Latitud" value={pos()[0]} />
|
||||||
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<input class="input" on:change={(e) => setLongitudeManual(e.target.value)} type="text" disabled={geo()} placeholder="Longitud" value={pos()[1]} />
|
||||||
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<button disabled={geo()} on:click={() => handleLocation()} class="button is-info">
|
||||||
|
Aplicar
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column is-narrow">
|
||||||
|
<button on:click={() => toggleGeo()} class="button" classList={{ 'is-success': geo(), 'is-danger': !geo() }}>
|
||||||
|
<span class="icon">
|
||||||
|
<FaSolidLocationPin />
|
||||||
|
</span>
|
||||||
|
<span>Geolocalización</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="map" style={{
|
||||||
|
height: '70vh'
|
||||||
|
}}></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Finder;
|
@ -1,11 +1,19 @@
|
|||||||
import { FaSolidGlassWaterDroplet } from "solid-icons/fa"
|
import { FaSolidGlassWaterDroplet } from "solid-icons/fa"
|
||||||
import Navbar from "../partials/Navbar"
|
import Navbar from "../partials/Navbar"
|
||||||
|
import { createSignal } from "solid-js"
|
||||||
|
import Photo from "../helpers/Photo"
|
||||||
|
import { A } from "@solidjs/router";
|
||||||
|
|
||||||
function Home() {
|
function Home() {
|
||||||
|
const [photo, setPhoto] = createSignal(Photo.random());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Navbar />
|
<section class="hero is-fullheight" style={{
|
||||||
<section class="hero is-fullheight-with-navbar">
|
"background-image": `url('${photo()}')`,
|
||||||
|
"background-position": 'center center',
|
||||||
|
"background-size": 'cover',
|
||||||
|
}}>
|
||||||
<div class="hero-body">
|
<div class="hero-body">
|
||||||
<div class="container has-text-centered">
|
<div class="container has-text-centered">
|
||||||
<div class="columns is-centered">
|
<div class="columns is-centered">
|
||||||
@ -14,6 +22,7 @@ function Home() {
|
|||||||
<div class="columns is-centered is-vcentered is-mobile">
|
<div class="columns is-centered is-vcentered is-mobile">
|
||||||
<div class="column is-4">
|
<div class="column is-4">
|
||||||
<figure class="image is-128x128">
|
<figure class="image is-128x128">
|
||||||
|
{/* TODO: Agregar icono */}
|
||||||
<img src="https://bulma.io/assets/images/placeholders/128x128.png" />
|
<img src="https://bulma.io/assets/images/placeholders/128x128.png" />
|
||||||
</figure>
|
</figure>
|
||||||
</div>
|
</div>
|
||||||
@ -26,6 +35,7 @@ function Home() {
|
|||||||
<span>Malackathon</span>
|
<span>Malackathon</span>
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
|
<A class="button is-primary" href="/finder">Buscar</A>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -35,7 +45,7 @@ function Home() {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="section">
|
<section class="section">
|
||||||
<video src="https://www.pexels.com/es-es/download/video/13831212/?fps=60.0&h=720&w=1280"></video>
|
<p>TODO: Agregar tarjetitas guapas</p>
|
||||||
</section>
|
</section>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user