diff --git a/web/src/App.tsx b/web/src/App.tsx index 9e06b58..7c40c95 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -6,6 +6,7 @@ import { Cities } from './cities/Cities'; import { Database } from './database/Database'; import { Station } from './station/Station'; import { apiHost } from './consts'; +import { WeatherIconStub } from './components/weatherIcons/WeatherIconStub'; console.log("env:", import.meta.env.MODE); console.log("api host:", apiHost); @@ -30,16 +31,21 @@ const App: Component = () => { return (
- +
+
+
+
    + { pages.map(([pageTitle]) => +
  • setPageTitle(pageTitle)} + > + {pageTitle} +
  • + )} +
+
+
{ getPageContent() }
); diff --git a/web/src/assets/ltv_meteo.otf b/web/src/assets/ltv_meteo.otf new file mode 100644 index 0000000..4da2337 Binary files /dev/null and b/web/src/assets/ltv_meteo.otf differ diff --git a/web/src/cities/map/MapView.tsx b/web/src/cities/map/MapView.tsx index 8557823..b2cb0ff 100644 --- a/web/src/cities/map/MapView.tsx +++ b/web/src/cities/map/MapView.tsx @@ -5,13 +5,17 @@ import { WindInputs, WindSignals } from "./WindInputs"; import arrowUrl from "../../assets/arrow.webp"; import { cityCoords } from "../../components/cityCoords"; -import { MapResolution, resolutionProps, ResolutionPropsValue, windProps, WindProps } from "./mapConsts"; -import { drawOnMap } from "./canvasDraw"; +import { MapResolution, resolutionProps, windProps, WindProps } from "./mapConsts"; +import { CityData, drawOnMap } from "./canvasDraw"; +import { IconInputs } from "../../components/weatherIcons/IconInputs"; export const MapView: Component<{ type: MapResolution, data: () => ResultKeyVal[] }> = ({ type, data }) => { const [getCanvas, setCanvas] = createSignal(); const [getImg, setImg] = createSignal(new Image()); - let lastCoords: [string, {x: number, y: number }, number][] = []; + const weatherIconsSingal = createSignal<{[key: string]: string;}>({}); + const [getWeatherIcons] = weatherIconsSingal; + + let lastCoords: CityData = []; const props = resolutionProps[type]; const arrowImg = new Image(); @@ -52,16 +56,18 @@ export const MapView: Component<{ type: MapResolution, data: () => ResultKeyVal[ createEffect(() => { const ctx = getCanvas()!.getContext("2d")!; - const coordsAndData: [string, {x: number, y: number }, number][] = data() + const weatherIcons = getWeatherIcons(); + const coordsAndData: CityData = data() .map(([city, value]) => [ city, cityCoords[city as keyof typeof cityCoords], typeof value === "number" ? value : -99, + weatherIcons[city], ]); lastCoords = coordsAndData; drawOnMap( ctx, - [getImg(),arrowImg], + [getImg(), arrowImg], coordsAndData, getWindData(), props, @@ -76,7 +82,12 @@ export const MapView: Component<{ type: MapResolution, data: () => ResultKeyVal[ return ( <> - { props.showWind && } +
+
+ { props.showWind && } +
+
+
{ + cityData.forEach(([, {x, y}]) => { const localX = props.offsetX + x * props.scale; const localY = props.offsetY + y * props.scale; @@ -28,17 +31,24 @@ export function drawOnMap( ctx.fill(); // weather values - ctx.font = `bold ${props.fontSize}px Rubik`; - ctx.textAlign = "center"; - ctx.textBaseline = "middle"; - coords.forEach(([, {x, y}, value]) => { + cityData.forEach(([, {x, y}, value, icon]) => { const localX = props.offsetX + x * props.scale; const localY = props.offsetY + y * props.scale; + ctx.font = `bold ${props.fontSize}px Rubik`; + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; ctx.fillStyle = "#000000"; const numericValue = roundValues ? Math.round(value) : value; const stringValue = numericValue.toString().replace(".", ","); ctx.fillText(stringValue, localX, localY); + + if (icon) { + ctx.fillStyle = "#FFFFFF"; + ctx.font = `normal ${props.fontSize * 5}px Daira by LTV grafika`; + const iconSize = ctx.measureText(icon); + ctx.fillText(icon, localX + props.boxSize/2 + 10 + iconSize.width/2, localY); + } }); if (!props.showWind) return; diff --git a/web/src/cities/result/ResultView.tsx b/web/src/cities/result/ResultView.tsx index b0373ba..0c90f2a 100644 --- a/web/src/cities/result/ResultView.tsx +++ b/web/src/cities/result/ResultView.tsx @@ -34,7 +34,6 @@ export const ResultView: Component<{ return (
-

Result:

{resultViews.map(viewName => <> diff --git a/web/src/components/weatherIcons/IconInputs.tsx b/web/src/components/weatherIcons/IconInputs.tsx new file mode 100644 index 0000000..bee8cc9 --- /dev/null +++ b/web/src/components/weatherIcons/IconInputs.tsx @@ -0,0 +1,47 @@ +import { Component, Signal } from "solid-js"; +import { weatherIconCities, weatherIcons } from "./iconConsts"; + +import "../../css/weatherIcons.css"; + +export const IconInputs: Component<{ weatherIconsSingal: Signal<{[key: string]: string;}>; }> = ({ + weatherIconsSingal: [getWeatherIcons, setWeatherIcons] +}) => { + + function onIconChange(city: string, icon: string) { + const weatherIcons = { ...getWeatherIcons() }; + weatherIcons[city] = icon; + if (icon === "") delete weatherIcons[city]; + + setWeatherIcons(weatherIcons); + } + + return ( + <> +
+ { weatherIcons.map(icon => + copyToClipboard(icon)}>{ icon }) + } +
+
+ { weatherIconCities.map(city => +
+ {city}: +   + onIconChange(city, e.target.value)} + /> +   +
) + } +
+ + ) +} + +function copyToClipboard(icon: string) { + navigator.clipboard.writeText(icon); +} diff --git a/web/src/components/weatherIcons/WeatherIconStub.tsx b/web/src/components/weatherIcons/WeatherIconStub.tsx new file mode 100644 index 0000000..2c80645 --- /dev/null +++ b/web/src/components/weatherIcons/WeatherIconStub.tsx @@ -0,0 +1,8 @@ +import { Component } from "solid-js"; + +/* Put this in page so browser actually downloads ltv font */ +export const WeatherIconStub: Component<{}> = () => { + return ( +
ABCDEF
+ ) +} diff --git a/web/src/components/weatherIcons/iconConsts.ts b/web/src/components/weatherIcons/iconConsts.ts new file mode 100644 index 0000000..bc1650f --- /dev/null +++ b/web/src/components/weatherIcons/iconConsts.ts @@ -0,0 +1,3 @@ +/* font-family: 'Daira by LTV grafika'; */ +export const weatherIcons = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i"]; +export const weatherIconCities = ['Ainaži', 'Alūksne', 'Bauska', 'Daugavpils', 'Liepāja', 'Madona', 'Priekuļi', 'Rēzekne', 'Rīga', 'Saldus', 'Stende', 'Ventspils', 'Zīlāni']; \ No newline at end of file diff --git a/web/src/css/index.css b/web/src/css/index.css index 16d04fe..a1fc09d 100644 --- a/web/src/css/index.css +++ b/web/src/css/index.css @@ -55,10 +55,30 @@ table tr:hover { background: #c0c0c0; } +@font-face { + font-family: 'Daira by LTV grafika'; + src: url('../assets/ltv_meteo.otf') format('truetype'); + font-weight: normal; + font-style: normal; + font-display: swap; +} + .hidden { display: none; } .visible { display: block; +} + +.grid-1-1 { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 10px; +} + +.grid-1-2 { + display: grid; + grid-template-columns: 1fr 2fr; + gap: 10px; } \ No newline at end of file diff --git a/web/src/css/weatherIcons.css b/web/src/css/weatherIcons.css new file mode 100644 index 0000000..e791efe --- /dev/null +++ b/web/src/css/weatherIcons.css @@ -0,0 +1,25 @@ +.weatherIconButton { + font-family: 'Daira by LTV grafika'; + font-size: 30px; + display: inline-block; + background-color: #ccc; + padding: 3px 4px; + margin: 0 3px; + cursor: pointer; +} + +.weatherIconButton:hover { + background-color: #333; + color: white; +} + +.weatherIconInput { + font-family: 'Daira by LTV grafika'; + font-size: 30px; +} + +.weatherIconStub { + font-family: 'Daira by LTV grafika'; + font-size: 20px; + color: white; +} \ No newline at end of file