Move mobile UI to its own page, and redirect to it
This commit is contained in:
parent
b836e5e8eb
commit
1672d4de94
@ -3,12 +3,14 @@ import { Route, HashRouter } from "@solidjs/router";
|
|||||||
import { Editor } from "./pages/Editor";
|
import { Editor } from "./pages/Editor";
|
||||||
import { Index } from "./pages/Index";
|
import { Index } from "./pages/Index";
|
||||||
import { Arrow } from "./pages/Arrow";
|
import { Arrow } from "./pages/Arrow";
|
||||||
|
import { IndexMobile } from "./pages/IndexMobile";
|
||||||
|
|
||||||
export default function() {
|
export default function() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<HashRouter>
|
<HashRouter>
|
||||||
<Route path="/" component={Index} />
|
<Route path="/" component={Index} />
|
||||||
|
<Route path="/mobile" component={IndexMobile} />
|
||||||
<Route path="/editor" component={Editor} />
|
<Route path="/editor" component={Editor} />
|
||||||
<Route path="/arrow" component={Arrow} />
|
<Route path="/arrow" component={Arrow} />
|
||||||
</HashRouter>
|
</HashRouter>
|
||||||
|
@ -10,6 +10,13 @@ export function Index() {
|
|||||||
const container = <div class="md:h-[98vh] h-[65vh] md:rounded-lg dark:opacity-60" />;
|
const container = <div class="md:h-[98vh] h-[65vh] md:rounded-lg dark:opacity-60" />;
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
|
// Detect screen size and ratio,
|
||||||
|
// and redirect to mobile page if neccesary
|
||||||
|
if (window.matchMedia("only screen and (max-width: 760px)").matches) {
|
||||||
|
window.location.replace("/#/mobile");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
global_map = L.map(container as HTMLElement)
|
global_map = L.map(container as HTMLElement)
|
||||||
.setView([-16.40171, -71.53040], 13);
|
.setView([-16.40171, -71.53040], 13);
|
||||||
|
|
||||||
|
@ -1,8 +1,154 @@
|
|||||||
|
import { createEffect, createResource, createSignal, For, onMount } from "solid-js";
|
||||||
|
import L from "leaflet";
|
||||||
|
import { Line, Lines, Route, Routes } from "../new_types";
|
||||||
|
|
||||||
|
let global_map: L.Map | null = null;
|
||||||
|
const [global_count, set_global_count] = createSignal(0);
|
||||||
|
|
||||||
export function IndexMobile() {
|
export function IndexMobile() {
|
||||||
|
const container = <div class="h-screen w-screen md:rounded-lg dark:opacity-80" />;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
// Detect screen size and ratio,
|
||||||
|
// and redirect to pc page if neccesary
|
||||||
|
if (!window.matchMedia("only screen and (max-width: 760px)").matches) {
|
||||||
|
window.location.replace("/#/");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
global_map = L.map(container as HTMLElement)
|
||||||
|
.setView([-16.40171, -71.53040], 13);
|
||||||
|
|
||||||
|
L.tileLayer("/tiles/{z}/{x}/{y}.jpg", {
|
||||||
|
maxZoom: 17,
|
||||||
|
minZoom: 12,
|
||||||
|
attribution: "Map data © <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a>",
|
||||||
|
}).addTo(global_map);
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
Mobile index :D
|
{container}
|
||||||
|
<LinesContainer />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function LinesContainer() {
|
||||||
|
const [selected_line, set_selected_line] = createSignal(-1);
|
||||||
|
const [linesData] = createResource<Lines>(async() => {
|
||||||
|
const res = await fetch("/n/lines.json");
|
||||||
|
if (!res.ok) throw new Error("Error fetching data");
|
||||||
|
return res.json();
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="fixed bottom-0 left-0 w-screen text-c-on-bg z-[500]">
|
||||||
|
<div class="py-1">
|
||||||
|
<For each={linesData() ?? []}>
|
||||||
|
{(line) => <RouteChipContainer line={line} active_line={selected_line()} />}
|
||||||
|
</For>
|
||||||
|
</div>
|
||||||
|
<div class="py-2 bg-c-bg">
|
||||||
|
<For each={linesData() ?? []}>
|
||||||
|
{(line) => (
|
||||||
|
<LineChip
|
||||||
|
line={line}
|
||||||
|
activate={() => set_selected_line(line.id)}
|
||||||
|
deactivate={() => set_selected_line(-1)}
|
||||||
|
selected={selected_line() === line.id}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function LineChip(props: {
|
||||||
|
line: Line,
|
||||||
|
selected: boolean,
|
||||||
|
activate: () => void,
|
||||||
|
deactivate: () => void,
|
||||||
|
}) {
|
||||||
|
const active_classes = () => (props.selected ? "bg-r-hover-bg text-r-hover-on-bg" : "text-r-hover-bg");
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
class={`inline-block border-2 border-r-hover-bg py-1 px-4 rounded-lg ml-2 font-bold ${active_classes()}`}
|
||||||
|
style={`--hover-bg: ${props.line.hover_bg};--hover-on-bg: ${props.line.hover_on_bg}`}
|
||||||
|
onClick={() => {
|
||||||
|
if (props.selected) {
|
||||||
|
props.deactivate();
|
||||||
|
} else {
|
||||||
|
props.activate();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Linea {props.line.name}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function RouteChipContainer(props: {line: Line, active_line: number}) {
|
||||||
|
const [routesData] = createResource<Routes>(async() => {
|
||||||
|
const res = await fetch(`/n/routes_${props.line.id}.json`);
|
||||||
|
if (!res.ok) throw new Error("Error fetching data");
|
||||||
|
return res.json();
|
||||||
|
});
|
||||||
|
|
||||||
|
const container_classes = () => (props.active_line === props.line.id ? "inline-block" : "hidden");
|
||||||
|
return (
|
||||||
|
<div class={container_classes()}
|
||||||
|
style={`--hover-bg: ${props.line.hover_bg};--hover-on-bg: ${props.line.hover_on_bg}`}
|
||||||
|
>
|
||||||
|
<For each={routesData() ?? []}>
|
||||||
|
{(route) => <RouteChip route={route} color={props.line.color} />}
|
||||||
|
</For>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function RouteChip(props: {route: Route, color: string}) {
|
||||||
|
const route = props.route;
|
||||||
|
const [active, set_active] = createSignal(false);
|
||||||
|
|
||||||
|
// Create departure and return polylines
|
||||||
|
const departure_polyline = L.polyline(route.departure, { color: props.color });
|
||||||
|
const return_polyline = L.polyline(route.return, { color: props.color });
|
||||||
|
|
||||||
|
// Render the lines into the map
|
||||||
|
// TODO: Change the UI to allow selecting departure and return separately
|
||||||
|
// and then update this
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
if (global_count() === 0 || active() === true) {
|
||||||
|
departure_polyline.addTo(global_map!);
|
||||||
|
return_polyline.addTo(global_map!);
|
||||||
|
} else {
|
||||||
|
departure_polyline.removeFrom(global_map!);
|
||||||
|
return_polyline.removeFrom(global_map!);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const toggle_active = () => {
|
||||||
|
if (active()) {
|
||||||
|
set_active(false);
|
||||||
|
set_global_count((c) => c - 1);
|
||||||
|
} else {
|
||||||
|
set_active(true);
|
||||||
|
set_global_count((c) => c + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const active_classes = () => (active() === true ? "bg-r-hover-bg text-r-hover-on-bg" : "bg-white text-r-hover-bg");
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
class={`inline-block rounded-full ml-2 border border-r-hover-bg py-1 px-2
|
||||||
|
${active_classes()}`}
|
||||||
|
onClick={toggle_active}
|
||||||
|
>
|
||||||
|
Ruta {route.name}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user