From 857ba295402997baa17a0301af45c49a4fcd6d14 Mon Sep 17 00:00:00 2001 From: rasta5man Date: Sun, 28 Apr 2024 16:15:44 +0200 Subject: [PATCH] Add typescript. Idle function to load defalt screen --- package.json | 5 + src/App.css | 4 +- src/App.js | 365 ------------------------------- src/App.tsx | 584 +++++++++++++++++++++++++++++++++++++++++++++++++ src/index.js | 11 - src/index.tsx | 13 ++ src/types.d.ts | 48 ++++ tsconfig.json | 27 +++ 8 files changed, 679 insertions(+), 378 deletions(-) delete mode 100644 src/App.js create mode 100644 src/App.tsx delete mode 100644 src/index.js create mode 100644 src/index.tsx create mode 100644 src/types.d.ts create mode 100644 tsconfig.json diff --git a/package.json b/package.json index d60bd1f..c3cedb1 100644 --- a/package.json +++ b/package.json @@ -9,11 +9,16 @@ "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.3.0", "@testing-library/user-event": "^13.5.0", + "@types/jest": "^29.5.12", + "@types/node": "^20.12.7", + "@types/react": "^18.3.1", + "@types/react-dom": "^18.3.0", "axios": "^0.27.2", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1", "simple-xml-to-json": "^1.2.2", + "typescript": "^5.4.5", "web-vitals": "^2.1.4" }, "scripts": { diff --git a/src/App.css b/src/App.css index 403d04e..9821234 100644 --- a/src/App.css +++ b/src/App.css @@ -25,7 +25,7 @@ { width: 100%; - height: 150vmax; + height: 200vmax; /* height: 5000px; */ pointer-events: none; border: 0; @@ -39,4 +39,4 @@ .scrollMarginTop { scroll-margin-top: 30px; -} +} \ No newline at end of file diff --git a/src/App.js b/src/App.js deleted file mode 100644 index 327a109..0000000 --- a/src/App.js +++ /dev/null @@ -1,365 +0,0 @@ -import React, {useState, useEffect, useRef} from 'react'; -import axios from 'axios' -import {Box, Typography, Paper, Container, Button} from '@mui/material'; -import './App.css'; - -const {convertXML} = require("simple-xml-to-json"); - -const MAIN_HEADER_FONT_SIZE = 50; -const headerFontSize = 20; -const DATA_FONT_SIZE = 42; -const TEMPERATURE_URL = "http://10.0.0.106:3000/gettemperature"; -const DEPARTURES_URL = 'http://10.0.0.106:3000/getdepartures'; -const SOKOLOV_RSS_URL = 'https://www.sokolov.cz/rss/'; -const DAYS_OF_WEEK = ["Neděle", "Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota"]; -let msToMidnight = null; -let updateDayOfWeek; -const OPTIONS = { hour12: false }; -let sokolovFeed; - -// colors in sokolov website -const LOGO_COLOR = '#82c55b' // green -const FONT_COLOR = '#00367b'; - - -function App() { - - var [date, setDate] = useState(new Date()); - var [temperature, setTemperature] = useState("?"); - var [departures, setDepartures] = useState([]); - var [dayOfWeek, setDayOfWeek] = useState(''); - var [feedData, setFeedData] = useState([{title: "Chyba stažení dat, kontaktujte prosím administrátora", description:"", link:"", pubDate: new Date()}]); - var [chosenArticle, setChosenArticle] = useState({clicked: false, url: ""}); - - // to assure, that website in iframe loads at the top - const iframeRef = useRef(null); - //to assure, that feed loads at the top - const containerRef = useRef(null); - - const executeScroll = () => { - iframeRef.current.scrollIntoView(true); - } - - useEffect(()=> { - !chosenArticle.clicked && containerRef.current.scrollIntoView({ behavior: 'smooth' }); - }, [chosenArticle]) - - function updateDate() { - setDate(new Date()); - } - - // go back to rss feed page - const resetWeb = () => { - setChosenArticle({clicked: false, url: ""}); - } - - function getTemperature() { - axios(TEMPERATURE_URL, { - headers: { - 'Access-Control-Allow-Origin': '*', - }}) - .then(response => { - let t = parseFloat(response.data); - //console.log(t); - if(isNaN(t)) return; - - setTemperature(t); - }) - .catch(error => { - console.log(error); - }); - } - - function getDepartures() { - axios(DEPARTURES_URL, { - headers: { - 'Access-Control-Allow-Origin': '*', - }}) - .then(response => { - const departures = response.data; - setDepartures(departures); - }) - .catch(error => { - console.log(error); - }); - } - - function milisecondsToMidnight() { - var midnight = new Date(); - midnight.setHours(24,0,0,0); - - var now = new Date(); - var msToMidnight = midnight - now; //miliseconds to midnight - return msToMidnight + 2000; // just to make sure day change after midnight, I am adding 2 seconds - } - - // we find out how long time is to midnight. after midnight is reached, getDay function is called and name of day is changed (streda --> ctvrtek). - function getDay() { - clearInterval(updateDayOfWeek); - const date = new Date(); - setDayOfWeek(DAYS_OF_WEEK[date.getDay()]); - - msToMidnight = milisecondsToMidnight(); - console.log('setDay called, ms to midnight', msToMidnight); - updateDayOfWeek = setInterval(getDay, msToMidnight); - } - - useEffect(() => { - - updateDate(); - getTemperature(); - getDepartures(); - getDay(); - - var timer = setInterval(updateDate, 1000); - var timerTemperature = setInterval(getTemperature, 60*1000); - var timerDepartures = setInterval(getDepartures, 60*1000); - - return function cleanup() { - clearInterval(timer); - clearInterval(timerTemperature); - clearInterval(timerDepartures); - } - - }, []); - - // rss feed to get articles from sokolov website - const getRssFeed = () => { - axios(SOKOLOV_RSS_URL).then(response => { - const myJson = convertXML(response?.data); - let data = myJson?.rss?.children[0]?.channel?.children; - - if(!Array.isArray(data)) return; - - // first 5 items are informational, so we skip them - const result = data.slice(5).map(item => { - const d = item?.item?.children; - const url = d[1]?.link?.content.replace('amp;',''); - let pubDate = d[3]?.pubDate?.content; - pubDate ? pubDate = new Date(pubDate) : pubDate = new Date(); - - return {title: d[0]?.title?.content, description: d[2]?.description?.content, link: url, pubDate: pubDate} - }) - - console.log(result) - setFeedData(result) - }).catch(e => console.log(e)) - } - - useEffect(() => { - getRssFeed(); - var feed = setInterval(getRssFeed, 6*60*60*1000); //raz za 6 hodin - return function cleanup() { - clearInterval(feed); - } - },[]) - - const buildFeedView = () => { - return feedData.map((item,index) => { - return ( - - {item.title} - setChosenArticle({clicked: true, url: item.link})}>Přečti celý článek ... - {item.description} - {item.pubDate.toLocaleDateString('cs-Cz')} - ) - }) - - } - sokolovFeed = buildFeedView(); - - - return ( - <> -
- - - - - - - - - - - - - - - - { - departures.map(function(item, i){ - return ; - }) - } - -
{date.toLocaleTimeString('sk-SK', OPTIONS)}{dayOfWeek}   {date.toLocaleDateString('sk-SK')}{temperature} ℃
-
-
LINKASMĚRPŘÍJEZD
{item[0]}{item[2]}{item[1]}
-
- -
- -
- -
- {chosenArticle.clicked ? : - - - {sokolovFeed} - - - } -
- - ) - -} - -export default App; - - - -const departures = [ - [ '6', '07:23', 'Sídl.Michal škola', [ 'X', '42' ] ], - [ '3', '07:27', 'Sídliště Michal', [ 'X', '32' ] ], - [ '2', '07:31', 'Sídliště Michal', [ 'X', '42' ] ], - [ '3', '07:34', 'Závodu míru', [ 'X', '42' ] ], - [ '4', '07:34', 'Závodu míru', [ 'X' ] ], - [ '1', '07:35', 'Březová, aut. st.', [ 'X' ] ], - [ '3', '07:45', 'Sídliště Michal', [ 'X' ] ], - [ '33', '07:54', 'sídl.Michal škola', [ 'X', '42' ] ], - [ '1', '07:55', 'Březová, aut. st.', [ 'X' ] ], - [ '3', '07:58', 'Závodu míru', [ 'X', '42' ] ], - [ '3', '08:10', 'Závodu míru', [ 'X', '32' ] ] -] - -// pubDate is date object -const dummyData = [ - { - title: "Silniceeee v Hruškové se dočká opravy", - description:"Silnice v Hruškové se brzy dočká částečné rekonstrukce. To ocení nejen obyvatelé této městské části ale také cyklisté, kteří tudy na jaře a v létě často projíždí.", - link: "https://www.sokolov.cz/vismo/dokumenty2.asp?id_org=15222&id=10822", - pubDate: 'Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)' - }, - { - title: "Nemocnice Sokolov získala akreditaci SAK", - description:"Sokolov 10. dubna 2024 - Zdravotnický holding Penta Hospitals úspěšně pokračuje ve zvyšování kvality a bezpečnosti svých zdravotnických služeb. Po nemocnicích v Roudnici nad Labem, Vrchlabí, Ostrově nebo Písku nyní úspěšně prošla auditem Spojené akreditační komise (SAK) také Nemocnice Sokolov. Udělením akreditace SAK potvrdila, že v Sokolově je pacientům poskytována profesionální a bezpečná péče.", - link: "https://www.sokolov.cz/vismo/dokumenty2.asp?id_org=15222&id=10821", - pubDate: 'Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)' - }, - { - title: "Silnice v Hruškové se dočká opravy", - description:"Silnice v Hruškové se brzy dočká částečné rekonstrukce. To ocení nejen obyvatelé této městské části ale také cyklisté, kteří tudy na jaře a v létě často projíždí.Sokolov 10. dubna 2024 - Zdravotnický holding Penta Hospitals úspěšně pokračuje ve zvyšování kvality a bezpečnosti svých zdravotnických služeb. Po nemocnicích v Roudnici nad Labem, Vrchlabí, Ostrově nebo Písku nyní úspěšně prošla auditem Spojené akreditační komise (SAK) také Nemocnice Sokolov. Udělením akreditace SAK potvrdila, že v Sokolově je pacientům poskytována profesionální a bezpečná péče.", - link: "https://www.pravda.sk/", - pubDate: 'Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)' - }, - { - title: "Silnice v Hruškové se dočká opravy", - description:"Silnice v Hruškové se brzy dočká částečné rekonstrukce. To ocení nejen obyvatelé této městské části ale také cyklisté, kteří tudy na jaře a v létě často projíždí.Sokolov 10. dubna 2024 - Zdravotnický holding Penta Hospitals úspěšně pokračuje ve zvyšování kvality a bezpečnosti svých zdravotnických služeb. Po nemocnicích v Roudnici nad Labem, Vrchlabí, Ostrově nebo Písku nyní úspěšně prošla auditem Spojené akreditační komise (SAK) také Nemocnice Sokolov. Udělením akreditace SAK potvrdila, že v Sokolově je pacientům poskytována profesionální a bezpečná péče.", - link: "https://www.sokolov.cz/vismo/dokumenty2.asp?id_org=15222&id=10820", - pubDate: 'Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)' - }, - { - title: "Silnice v Hruškové se dočká opravy", - description:"Silnice v Hruškové se brzy dočká částečné rekonstrukce. To ocení nejen obyvatelé této městské části ale také cyklisté, kteří tudy na jaře a v létě často projíždí.Sokolov 10. dubna 2024 - Zdravotnický holding Penta Hospitals úspěšně pokračuje ve zvyšování kvality a bezpečnosti svých zdravotnických služeb. Po nemocnicích v Roudnici nad Labem, Vrchlabí, Ostrově nebo Písku nyní úspěšně prošla auditem Spojené akreditační komise (SAK) také Nemocnice Sokolov. Udělením akreditace SAK potvrdila, že v Sokolově je pacientům poskytována profesionální a bezpečná péče.", - link: "https://www.sokolov.cz/vismo/dokumenty2.asp?id_org=15222&id=10822", - pubDate: 'Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)' - }, - { - title: "Silnice v Hruškové se dočká opravy", - description:"Silnice v Hruškové se brzy dočká částečné rekonstrukce. To ocení nejen obyvatelé této městské části ale také cyklisté, kteří tudy na jaře a v létě často projíždí.Sokolov 10. dubna 2024 - Zdravotnický holding Penta Hospitals úspěšně pokračuje ve zvyšování kvality a bezpečnosti svých zdravotnických služeb. Po nemocnicích v Roudnici nad Labem, Vrchlabí, Ostrově nebo Písku nyní úspěšně prošla auditem Spojené akreditační komise (SAK) také Nemocnice Sokolov. Udělením akreditace SAK potvrdila, že v Sokolově je pacientům poskytována profesionální a bezpečná péče.", - link: "https://www.sokolov.cz/vismo/dokumenty2.asp?id_org=15222&id=10822", - pubDate: 'Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)' - }, - { - title: "Silnice v Hruškové se dočká opravy", - description:"Silnice v Hruškové se brzy dočká částečné rekonstrukce. To ocení nejen obyvatelé této městské části ale také cyklisté, kteří tudy na jaře a v létě často projíždí.Sokolov 10. dubna 2024 - Zdravotnický holding Penta Hospitals úspěšně pokračuje ve zvyšování kvality a bezpečnosti svých zdravotnických služeb. Po nemocnicích v Roudnici nad Labem, Vrchlabí, Ostrově nebo Písku nyní úspěšně prošla auditem Spojené akreditační komise (SAK) také Nemocnice Sokolov. Udělením akreditace SAK potvrdila, že v Sokolově je pacientům poskytována profesionální a bezpečná péče.", - link: "https://www.sokolov.cz/vismo/dokumenty2.asp?id_org=15222&id=10822", - pubDate: 'Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)' - }, - { - title: "Silnice v Hruškové se dočká opravy", - description:"Silnice v Hruškové se brzy dočká částečné rekonstrukce. To ocení nejen obyvatelé této městské části ale také cyklisté, kteří tudy na jaře a v létě často projíždí.", - link: "https://www.sokolov.cz/vismo/dokumenty2.asp?id_org=15222&id=10822", - pubDate: 'Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)' - }, - { - title: "Silnice v Hruškové se dočká opravy", - description:"Silnice v Hruškové se brzy dočká částečné rekonstrukce. To ocení nejen obyvatelé této městské části ale také cyklisté, kteří tudy na jaře a v létě často projíždí.Sokolov 10. dubna 2024 - Zdravotnický holding Penta Hospitals úspěšně pokračuje ve zvyšování kvality a bezpečnosti svých zdravotnických služeb. Po nemocnicích v Roudnici nad Labem, Vrchlabí, Ostrově nebo Písku nyní úspěšně prošla auditem Spojené akreditační komise (SAK) také Nemocnice Sokolov. Udělením akreditace SAK potvrdila, že v Sokolově je pacientům poskytována profesionální a bezpečná péče.", - link: "https://www.sokolov.cz/vismo/dokumenty2.asp?id_org=15222&id=10822", - pubDate: 'Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)' - }, - { - title: "Silnice v Hruškové se dočká opravy", - description:"Silnice v Hruškové se brzy dočká částečné rekonstrukce. To ocení nejen obyvatelé této městské části ale také cyklisté, kteří tudy na jaře a v létě často projíždí.", - link: "https://www.sokolov.cz/vismo/dokumenty2.asp?id_org=15222&id=10822", - pubDate: 'Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)' - } -]; - -// const departures = [ -// [ '2', '3', '24.11.22 04:05', 'Závodu míru' ], -// [ '290', '3', '24.11.22 04:25', 'Závodu míru' ], -// [ '292', '3', '24.11.22 04:48', 'Závodu míru' ], -// [ '296', '3', '24.11.22 04:58', 'Závodu míru' ], -// [ '6', '3', '24.11.22 05:05', 'Závodu míru' ], -// [ '300', '3', '24.11.22 05:18', 'Závodu míru' ], -// [ '8', '3', '24.11.22 05:55', 'Závodu míru' ], -// [ '16', '3', '24.11.22 06:30', 'Závodu míru' ], -// [ '1', '33', '24.11.22 06:45', 'sídl. Michal škola' ], -// [ '18', '3', '24.11.22 06:52', 'Hrušková' ], -// [ '310', '3', '24.11.22 07:00', 'Závodu míru' ], -// [ '22', '3', '24.11.22 07:10', 'Závodu míru' ], -// [ '5', '33', '24.11.22 07:50', 'sídl. Michal škola' ], -// [ '32', '3', '24.11.22 08:10', 'Závodu míru' ], -// [ '7', '33', '24.11.22 08:25', 'sídl. Michal škola' ], -// [ '100', '3', '24.11.22 08:30', 'Závodu míru' ], -// [ '9', '33', '24.11.22 08:50', 'sídl. Michal škola' ], -// [ '34', '3', '24.11.22 09:00', 'Závodu míru' ], -// [ '38', '3', '24.11.22 09:20', 'Závodu míru' ], -// [ '11', '33', '24.11.22 09:30', 'sídl. Michal škola' ], -// [ '298', '3', '24.11.22 09:55', 'Závodu míru' ], -// [ '2', '7', '24.11.22 10:10', 'Březová, aut. st.' ], -// [ '13', '33', '24.11.22 10:20', 'sídl. Michal škola' ], -// [ '48', '3', '24.11.22 10:50', 'Závodu míru' ], -// [ '50', '3', '24.11.22 11:13', 'Závodu míru' ], -// [ '15', '33', '24.11.22 11:25', 'sídl. Michal škola' ], -// [ '52', '3', '24.11.22 11:40', 'Závodu míru' ], -// [ '17', '33', '24.11.22 11:52', 'sídl. Michal škola' ], -// [ '56', '3', '24.11.22 12:20', 'Závodu míru' ], -// [ '62', '3', '24.11.22 12:40', 'Závodu míru' ], -// [ '64', '3', '24.11.22 12:55', 'Závodu míru' ], -// [ '19', '33', '24.11.22 13:00', 'sídl. Michal škola' ], -// [ '66', '3', '24.11.22 13:20', 'Stará ovčárna' ], -// [ '21', '33', '24.11.22 13:35', 'sídl. Michal škola' ], -// [ '23', '33', '24.11.22 14:00', 'sídl. Michal škola' ], -// [ '72', '3', '24.11.22 14:05', 'Závodu míru' ], -// [ '25', '33', '24.11.22 14:42', 'sídl. Michal škola' ], -// [ '94', '3', '24.11.22 14:48', 'Závodu míru' ], -// [ '27', '33', '24.11.22 15:05', 'sídl. Michal škola' ], -// [ '106', '3', '24.11.22 15:09', 'Závodu míru' ], -// [ '84', '3', '24.11.22 15:35', 'Závodu míru' ], -// [ '29', '33', '24.11.22 15:35', 'sídl. Michal škola' ], -// [ '6', '7', '24.11.22 15:50', 'Březová, aut. st.' ], -// [ '96', '3', '24.11.22 16:10', 'Závodu míru' ], -// [ '31', '33', '24.11.22 16:10', 'sídl. Michal škola' ], -// [ '4', '7', '24.11.22 16:25', 'Březová, aut. st.' ], -// [ '102', '3', '24.11.22 16:30', 'Závodu míru' ], -// [ '302', '3', '24.11.22 16:44', 'Závodu míru' ], -// [ '8', '7', '24.11.22 16:55', 'Březová, aut. st.' ], -// [ '108', '3', '24.11.22 17:05', 'Stará ovčárna' ], -// [ '112', '3', '24.11.22 17:30', 'Závodu míru' ], -// [ '114', '3', '24.11.22 17:53', 'Závodu míru' ], -// [ '118', '3', '24.11.22 18:10', 'Závodu míru' ], -// [ '120', '3', '24.11.22 18:30', 'Závodu míru' ], -// [ '122', '3', '24.11.22 18:50', 'Závodu míru' ], -// [ '124', '3', '24.11.22 19:15', 'Závodu míru' ], -// [ '126', '3', '24.11.22 19:30', 'Závodu míru' ], -// [ '130', '3', '24.11.22 19:50', 'Závodu míru' ], -// [ '132', '3', '24.11.22 20:15', 'Závodu míru' ], -// [ '134', '3', '24.11.22 20:45', 'Závodu míru' ], -// [ '136', '3', '24.11.22 21:05', 'Závodu míru' ], -// [ '256', '3', '24.11.22 21:20', 'Stará ovčárna' ], -// [ '140', '3', '24.11.22 22:08', 'Stará ovčárna' ] -// ]; diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..a4b508a --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,584 @@ +import React, { useState, useEffect, useRef } from "react"; +import axios from "axios"; +import { Box, Typography, Paper, Container, Button } from "@mui/material"; +import "./App.css"; +import { TChildren, TRssItem, TRssRawItem, TDepartures } from "./types"; +import { convertXML } from "simple-xml-to-json"; + +const MAIN_HEADER_FONT_SIZE = 50; +const DATA_FONT_SIZE = 42; +const TEMPERATURE_URL = "http://10.0.0.106:3000/gettemperature"; +const DEPARTURES_URL = "http://10.0.0.106:3000/getdepartures"; +const SOKOLOV_RSS_URL = "https://www.sokolov.cz/rss/"; +const DAYS_OF_WEEK = [ + "Neděle", + "Pondělí", + "Úterý", + "Středa", + "Čtvrtek", + "Pátek", + "Sobota", +]; +const INACTIVITY_LIMIT = 300000; +const OPTIONS = { hour12: false }; +// colors in sokolov website +const LOGO_COLOR = "#82c55b"; // green +const FONT_COLOR = "#00367b"; // blue + +let msToMidnight: number; +let updateDayOfWeek: ReturnType; +let sokolovFeed: React.JSX.Element[]; + +//function that runs, when user is not active, while article is loaded on screen +function onInactive(ms: number, cb: () => void) { + var wait = setTimeout(cb, ms); + + window.onmousemove = + window.onmousedown = + window.onmousemove = + window.ontouchstart = + window.ontouchmove = + window.ontouchend = + window.onmouseup = + window.onkeydown = + window.onkeyup = + window.onfocus = + function () { + clearTimeout(wait); + wait = setTimeout(cb, ms); + }; +} + +function App() { + var [date, setDate] = useState(new Date()); + var [temperature, setTemperature] = useState("?"); + var [departures, setDepartures] = useState([]); + var [dayOfWeek, setDayOfWeek] = useState(""); + var [chosenArticle, setChosenArticle] = useState({ clicked: false, url: "" }); + var [feedData, setFeedData] = useState([ + { + title: "Chyba stažení dat, kontaktujte prosím administrátora", + description: "", + link: "", + pubDate: new Date(), + guid: "", + }, + ]); + + // check, how long is user inactive, if reading an article. If more than 5 minutes, we load default screen + function idle() { + onInactive(INACTIVITY_LIMIT, function () { + window.onmousemove = + window.onmousedown = + window.onmousemove = + window.ontouchstart = + window.ontouchmove = + window.ontouchend = + window.onmouseup = + window.onkeydown = + window.onkeyup = + window.onfocus = + null; + setChosenArticle({ clicked: false, url: "" }); + }); + } + + // to assure, that website in iframe loads at the top + const iframeRef = useRef(null); + //to assure, that feed loads at the top + const containerRef = useRef(null); + + const executeScroll = () => { + if (iframeRef.current) iframeRef.current.scrollIntoView(true); + }; + + useEffect(() => { + if (containerRef.current) { + !chosenArticle.clicked && + containerRef.current.scrollIntoView({ behavior: "smooth" }); + } + }, [chosenArticle]); + + function updateDate() { + setDate(new Date()); + } + + // go back to rss feed page + const resetWeb = () => { + setChosenArticle({ clicked: false, url: "" }); + }; + + function getTemperature() { + axios(TEMPERATURE_URL, { + headers: { + "Access-Control-Allow-Origin": "*", + }, + }) + .then((response) => { + let t = parseFloat(response.data); + //console.log(t); + if (isNaN(t)) return; + + setTemperature(t); + }) + .catch((error) => { + console.log(error); + }); + } + + function getDepartures() { + axios(DEPARTURES_URL, { + headers: { + "Access-Control-Allow-Origin": "*", + }, + }) + .then((response) => { + const departures: TDepartures = response.data; + setDepartures(departures); + }) + .catch((error) => { + console.log(error); + }); + } + + function milisecondsToMidnight(): number { + var d = new Date(); + var midnight = d.setHours(24, 0, 0, 0); + var now = Date.now(); + var msToMidnight = midnight - now; //miliseconds to midnight + return msToMidnight + 2000; // just to make sure day change after midnight, I am adding 2 seconds + } + + // we find out how long time is to midnight. after midnight is reached, getDay function is called and name of day is changed (streda --> ctvrtek). + function getDay() { + clearInterval(updateDayOfWeek); + const date = new Date(); + setDayOfWeek(DAYS_OF_WEEK[date.getDay()]); + + msToMidnight = milisecondsToMidnight(); + console.log("setDay called, ms to midnight", msToMidnight); + updateDayOfWeek = setInterval(getDay, msToMidnight); + } + + useEffect(() => { + updateDate(); + getTemperature(); + getDepartures(); + getDay(); + + var timer = setInterval(updateDate, 1000); + var timerTemperature = setInterval(getTemperature, 60 * 1000); + var timerDepartures = setInterval(getDepartures, 60 * 1000); + + return function cleanup() { + clearInterval(timer); + clearInterval(timerTemperature); + clearInterval(timerDepartures); + }; + }, []); + + // rss feed to get articles from sokolov website + const getRssFeed = () => { + axios(SOKOLOV_RSS_URL) + .then((response) => { + const myJson = convertXML(response?.data); + + console.log("--------", JSON.stringify(myJson)); + let data: TChildren = myJson?.rss?.children[0]?.channel?.children; + + if (!Array.isArray(data)) return; + + // first 5 items are informational, so we skip them + const result: TRssItem[] = data.slice(5).map((item: TRssRawItem) => { + const d = item?.item?.children; + const url = d[1]?.link?.content.replace("amp;", ""); + let pubDate = d[3]?.pubDate?.content; + pubDate ? (pubDate = new Date(pubDate)) : (pubDate = new Date()); + + return { + title: d[0]?.title?.content, + description: d[2]?.description?.content, + link: url, + pubDate: pubDate, + guid: "", + }; + }); + + console.log(result); + setFeedData(result); + }) + .catch((e) => console.log(e)); + }; + + useEffect(() => { + getRssFeed(); + var feed = setInterval(getRssFeed, 6 * 60 * 60 * 1000); //raz za 6 hodin + return function cleanup() { + clearInterval(feed); + }; + }, []); + + const buildFeedView = (): React.JSX.Element[] => { + if ( + feedData[0].title === + "Chyba stažení dat, kontaktujte prosím administrátora" + ) { + return [ + + + {feedData[0].title} + + + {feedData[0].pubDate.toLocaleDateString("cs-Cz")} + + , + ]; + } + + return feedData.map((item, index) => { + return ( + + + {item.title} + + { + idle(); + setChosenArticle({ clicked: true, url: item.link }); + }} + > + Přečti celý článek ... + + {item.description} + + {item.pubDate.toLocaleDateString("cs-Cz")} + + + ); + }); + }; + sokolovFeed = buildFeedView(); + + return ( + <> +
+ + + + + + + + + + + + + + + + {departures.map(function (item, i) { + return ( + + + + + + ); + })} + +
+ {date.toLocaleTimeString("sk-SK", OPTIONS)} + + {dayOfWeek}   {date.toLocaleDateString("sk-SK")} + {temperature} ℃
+
+
LINKASMĚRPŘÍJEZD
{item[0]}{item[2]}{item[1]}
+
+ +
+ +
+ +
+ {chosenArticle.clicked ? ( + + ) : ( + + + {sokolovFeed} + + + )} +
+ + ); +} + +export default App; + +const departures = [ + ["6", "07:23", "Sídl.Michal škola", ["X", "42"]], + ["3", "07:27", "Sídliště Michal", ["X", "32"]], + ["2", "07:31", "Sídliště Michal", ["X", "42"]], + ["3", "07:34", "Závodu míru", ["X", "42"]], + ["4", "07:34", "Závodu míru", ["X"]], + ["1", "07:35", "Březová, aut. st.", ["X"]], + ["3", "07:45", "Sídliště Michal", ["X"]], + ["33", "07:54", "sídl.Michal škola", ["X", "42"]], + ["1", "07:55", "Březová, aut. st.", ["X"]], + ["3", "07:58", "Závodu míru", ["X", "42"]], + ["3", "08:10", "Závodu míru", ["X", "32"]], +]; + +// pubDate is date object +const dummyData = [ + { + title: "Silniceeee v Hruškové se dočká opravy", + description: + "Silnice v Hruškové se brzy dočká částečné rekonstrukce. To ocení nejen obyvatelé této městské části ale také cyklisté, kteří tudy na jaře a v létě často projíždí.", + link: "https://www.sokolov.cz/vismo/dokumenty2.asp?id_org=15222&id=10822", + pubDate: + "Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)", + }, + { + title: "Nemocnice Sokolov získala akreditaci SAK", + description: + "Sokolov 10. dubna 2024 - Zdravotnický holding Penta Hospitals úspěšně pokračuje ve zvyšování kvality a bezpečnosti svých zdravotnických služeb. Po nemocnicích v Roudnici nad Labem, Vrchlabí, Ostrově nebo Písku nyní úspěšně prošla auditem Spojené akreditační komise (SAK) také Nemocnice Sokolov. Udělením akreditace SAK potvrdila, že v Sokolově je pacientům poskytována profesionální a bezpečná péče.", + link: "https://www.sokolov.cz/vismo/dokumenty2.asp?id_org=15222&id=10821", + pubDate: + "Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)", + }, + { + title: "Silnice v Hruškové se dočká opravy", + description: + "Silnice v Hruškové se brzy dočká částečné rekonstrukce. To ocení nejen obyvatelé této městské části ale také cyklisté, kteří tudy na jaře a v létě často projíždí.Sokolov 10. dubna 2024 - Zdravotnický holding Penta Hospitals úspěšně pokračuje ve zvyšování kvality a bezpečnosti svých zdravotnických služeb. Po nemocnicích v Roudnici nad Labem, Vrchlabí, Ostrově nebo Písku nyní úspěšně prošla auditem Spojené akreditační komise (SAK) také Nemocnice Sokolov. Udělením akreditace SAK potvrdila, že v Sokolově je pacientům poskytována profesionální a bezpečná péče.", + link: "https://www.pravda.sk/", + pubDate: + "Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)", + }, + { + title: "Silnice v Hruškové se dočká opravy", + description: + "Silnice v Hruškové se brzy dočká částečné rekonstrukce. To ocení nejen obyvatelé této městské části ale také cyklisté, kteří tudy na jaře a v létě často projíždí.Sokolov 10. dubna 2024 - Zdravotnický holding Penta Hospitals úspěšně pokračuje ve zvyšování kvality a bezpečnosti svých zdravotnických služeb. Po nemocnicích v Roudnici nad Labem, Vrchlabí, Ostrově nebo Písku nyní úspěšně prošla auditem Spojené akreditační komise (SAK) také Nemocnice Sokolov. Udělením akreditace SAK potvrdila, že v Sokolově je pacientům poskytována profesionální a bezpečná péče.", + link: "https://www.sokolov.cz/vismo/dokumenty2.asp?id_org=15222&id=10820", + pubDate: + "Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)", + }, + { + title: "Silnice v Hruškové se dočká opravy", + description: + "Silnice v Hruškové se brzy dočká částečné rekonstrukce. To ocení nejen obyvatelé této městské části ale také cyklisté, kteří tudy na jaře a v létě často projíždí.Sokolov 10. dubna 2024 - Zdravotnický holding Penta Hospitals úspěšně pokračuje ve zvyšování kvality a bezpečnosti svých zdravotnických služeb. Po nemocnicích v Roudnici nad Labem, Vrchlabí, Ostrově nebo Písku nyní úspěšně prošla auditem Spojené akreditační komise (SAK) také Nemocnice Sokolov. Udělením akreditace SAK potvrdila, že v Sokolově je pacientům poskytována profesionální a bezpečná péče.", + link: "https://www.sokolov.cz/vismo/dokumenty2.asp?id_org=15222&id=10822", + pubDate: + "Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)", + }, + { + title: "Silnice v Hruškové se dočká opravy", + description: + "Silnice v Hruškové se brzy dočká částečné rekonstrukce. To ocení nejen obyvatelé této městské části ale také cyklisté, kteří tudy na jaře a v létě často projíždí.Sokolov 10. dubna 2024 - Zdravotnický holding Penta Hospitals úspěšně pokračuje ve zvyšování kvality a bezpečnosti svých zdravotnických služeb. Po nemocnicích v Roudnici nad Labem, Vrchlabí, Ostrově nebo Písku nyní úspěšně prošla auditem Spojené akreditační komise (SAK) také Nemocnice Sokolov. Udělením akreditace SAK potvrdila, že v Sokolově je pacientům poskytována profesionální a bezpečná péče.", + link: "https://www.sokolov.cz/vismo/dokumenty2.asp?id_org=15222&id=10822", + pubDate: + "Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)", + }, + { + title: "Silnice v Hruškové se dočká opravy", + description: + "Silnice v Hruškové se brzy dočká částečné rekonstrukce. To ocení nejen obyvatelé této městské části ale také cyklisté, kteří tudy na jaře a v létě často projíždí.Sokolov 10. dubna 2024 - Zdravotnický holding Penta Hospitals úspěšně pokračuje ve zvyšování kvality a bezpečnosti svých zdravotnických služeb. Po nemocnicích v Roudnici nad Labem, Vrchlabí, Ostrově nebo Písku nyní úspěšně prošla auditem Spojené akreditační komise (SAK) také Nemocnice Sokolov. Udělením akreditace SAK potvrdila, že v Sokolově je pacientům poskytována profesionální a bezpečná péče.", + link: "https://www.sokolov.cz/vismo/dokumenty2.asp?id_org=15222&id=10822", + pubDate: + "Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)", + }, + { + title: "Silnice v Hruškové se dočká opravy", + description: + "Silnice v Hruškové se brzy dočká částečné rekonstrukce. To ocení nejen obyvatelé této městské části ale také cyklisté, kteří tudy na jaře a v létě často projíždí.", + link: "https://www.sokolov.cz/vismo/dokumenty2.asp?id_org=15222&id=10822", + pubDate: + "Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)", + }, + { + title: "Silnice v Hruškové se dočká opravy", + description: + "Silnice v Hruškové se brzy dočká částečné rekonstrukce. To ocení nejen obyvatelé této městské části ale také cyklisté, kteří tudy na jaře a v létě často projíždí.Sokolov 10. dubna 2024 - Zdravotnický holding Penta Hospitals úspěšně pokračuje ve zvyšování kvality a bezpečnosti svých zdravotnických služeb. Po nemocnicích v Roudnici nad Labem, Vrchlabí, Ostrově nebo Písku nyní úspěšně prošla auditem Spojené akreditační komise (SAK) také Nemocnice Sokolov. Udělením akreditace SAK potvrdila, že v Sokolově je pacientům poskytována profesionální a bezpečná péče.", + link: "https://www.sokolov.cz/vismo/dokumenty2.asp?id_org=15222&id=10822", + pubDate: + "Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)", + }, + { + title: "Silnice v Hruškové se dočká opravy", + description: + "Silnice v Hruškové se brzy dočká částečné rekonstrukce. To ocení nejen obyvatelé této městské části ale také cyklisté, kteří tudy na jaře a v létě často projíždí.", + link: "https://www.sokolov.cz/vismo/dokumenty2.asp?id_org=15222&id=10822", + pubDate: + "Date Fri Apr 12 2024 10:03:45 GMT+0200 (Central European Summer Time)", + }, +]; + +// const departures = [ +// [ '2', '3', '24.11.22 04:05', 'Závodu míru' ], +// [ '290', '3', '24.11.22 04:25', 'Závodu míru' ], +// [ '292', '3', '24.11.22 04:48', 'Závodu míru' ], +// [ '296', '3', '24.11.22 04:58', 'Závodu míru' ], +// [ '6', '3', '24.11.22 05:05', 'Závodu míru' ], +// [ '300', '3', '24.11.22 05:18', 'Závodu míru' ], +// [ '8', '3', '24.11.22 05:55', 'Závodu míru' ], +// [ '16', '3', '24.11.22 06:30', 'Závodu míru' ], +// [ '1', '33', '24.11.22 06:45', 'sídl. Michal škola' ], +// [ '18', '3', '24.11.22 06:52', 'Hrušková' ], +// [ '310', '3', '24.11.22 07:00', 'Závodu míru' ], +// [ '22', '3', '24.11.22 07:10', 'Závodu míru' ], +// [ '5', '33', '24.11.22 07:50', 'sídl. Michal škola' ], +// [ '32', '3', '24.11.22 08:10', 'Závodu míru' ], +// [ '7', '33', '24.11.22 08:25', 'sídl. Michal škola' ], +// [ '100', '3', '24.11.22 08:30', 'Závodu míru' ], +// [ '9', '33', '24.11.22 08:50', 'sídl. Michal škola' ], +// [ '34', '3', '24.11.22 09:00', 'Závodu míru' ], +// [ '38', '3', '24.11.22 09:20', 'Závodu míru' ], +// [ '11', '33', '24.11.22 09:30', 'sídl. Michal škola' ], +// [ '298', '3', '24.11.22 09:55', 'Závodu míru' ], +// [ '2', '7', '24.11.22 10:10', 'Březová, aut. st.' ], +// [ '13', '33', '24.11.22 10:20', 'sídl. Michal škola' ], +// [ '48', '3', '24.11.22 10:50', 'Závodu míru' ], +// [ '50', '3', '24.11.22 11:13', 'Závodu míru' ], +// [ '15', '33', '24.11.22 11:25', 'sídl. Michal škola' ], +// [ '52', '3', '24.11.22 11:40', 'Závodu míru' ], +// [ '17', '33', '24.11.22 11:52', 'sídl. Michal škola' ], +// [ '56', '3', '24.11.22 12:20', 'Závodu míru' ], +// [ '62', '3', '24.11.22 12:40', 'Závodu míru' ], +// [ '64', '3', '24.11.22 12:55', 'Závodu míru' ], +// [ '19', '33', '24.11.22 13:00', 'sídl. Michal škola' ], +// [ '66', '3', '24.11.22 13:20', 'Stará ovčárna' ], +// [ '21', '33', '24.11.22 13:35', 'sídl. Michal škola' ], +// [ '23', '33', '24.11.22 14:00', 'sídl. Michal škola' ], +// [ '72', '3', '24.11.22 14:05', 'Závodu míru' ], +// [ '25', '33', '24.11.22 14:42', 'sídl. Michal škola' ], +// [ '94', '3', '24.11.22 14:48', 'Závodu míru' ], +// [ '27', '33', '24.11.22 15:05', 'sídl. Michal škola' ], +// [ '106', '3', '24.11.22 15:09', 'Závodu míru' ], +// [ '84', '3', '24.11.22 15:35', 'Závodu míru' ], +// [ '29', '33', '24.11.22 15:35', 'sídl. Michal škola' ], +// [ '6', '7', '24.11.22 15:50', 'Březová, aut. st.' ], +// [ '96', '3', '24.11.22 16:10', 'Závodu míru' ], +// [ '31', '33', '24.11.22 16:10', 'sídl. Michal škola' ], +// [ '4', '7', '24.11.22 16:25', 'Březová, aut. st.' ], +// [ '102', '3', '24.11.22 16:30', 'Závodu míru' ], +// [ '302', '3', '24.11.22 16:44', 'Závodu míru' ], +// [ '8', '7', '24.11.22 16:55', 'Březová, aut. st.' ], +// [ '108', '3', '24.11.22 17:05', 'Stará ovčárna' ], +// [ '112', '3', '24.11.22 17:30', 'Závodu míru' ], +// [ '114', '3', '24.11.22 17:53', 'Závodu míru' ], +// [ '118', '3', '24.11.22 18:10', 'Závodu míru' ], +// [ '120', '3', '24.11.22 18:30', 'Závodu míru' ], +// [ '122', '3', '24.11.22 18:50', 'Závodu míru' ], +// [ '124', '3', '24.11.22 19:15', 'Závodu míru' ], +// [ '126', '3', '24.11.22 19:30', 'Závodu míru' ], +// [ '130', '3', '24.11.22 19:50', 'Závodu míru' ], +// [ '132', '3', '24.11.22 20:15', 'Závodu míru' ], +// [ '134', '3', '24.11.22 20:45', 'Závodu míru' ], +// [ '136', '3', '24.11.22 21:05', 'Závodu míru' ], +// [ '256', '3', '24.11.22 21:20', 'Stará ovčárna' ], +// [ '140', '3', '24.11.22 22:08', 'Stará ovčárna' ] +// ]; + +// example of rss return data +/* +const a = { + rss: { + version: "2.0", + children: [ + { + channel: { + children: [ + { + title: { + content: "Sokolov - aktuality", + }, + }, + { + link: { + content: "https://www.sokolov.cz/", + }, + }, + { + description: { + content: "Sokolov - aktuality", + }, + }, + { + ttl: { + content: "60", + }, + }, + { + lastBuildDate: { + content: "Sat, 27 Apr 2024 18:40:22 GMT", + }, + }, + { + item: { + children: [ + { + title: { + content: + "Biskup Tomáš Holub jednal na sokolovské radnici o rekonstrukci kostela na Starém náměstí", + }, + }, + { + link: { + content: + "https://www.sokolov.cz/vismo/dokumenty2.asp?id_org=15222&id=10868", + }, + }, + { + description: { + content: + "V rámci snahy sokolovské radnice o revitalizaci historického centra, jednal starosta Sokolova Petr Kubis s plzeňským biskupem Tomášem Holubem. Tématem schůzky byla rekonstrukce kostela svatého Jakuba Většího, který tvoří jednu z dominant Starého náměstí. Radnice už začala pracovat na obnově kapucínského kláštera. Jednat chce i se zástupci pravoslavné církve o renovaci nedaleké modlitebny. Oprava římskokatolického kostela by měla doplnit celkovou revitalizaci lokality. „Chtěli bychom, aby se Staré náměstí stalo odpočinkovým místem pro obyvatele Sokolova, ale i výchozím bodem pro návštěvníky. Vedle výsadby nových stromů zde připravujeme i instalaci laviček nebo interaktivních prvků, které by popisovaly historii města. Také chceme, aby zde začínaly naučné stezky, které plánujeme vytvořit,“ doplnil starosta Kubis.", + }, + }, + { + pubDate: { + content: "Fri, 26 Apr 2024 16:31:48 GMT", + }, + }, + { + guid: { + content: "dokumenty10868", + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, +}; +*/ diff --git a/src/index.js b/src/index.js deleted file mode 100644 index 3086b9f..0000000 --- a/src/index.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import './index.css' -import App from './App'; - -const root = ReactDOM.createRoot(document.getElementById('root')); -root.render( - - - -); \ No newline at end of file diff --git a/src/index.tsx b/src/index.tsx new file mode 100644 index 0000000..cfd7784 --- /dev/null +++ b/src/index.tsx @@ -0,0 +1,13 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import "./index.css"; +import App from "./App"; + +const root = ReactDOM.createRoot( + document.getElementById("root") as HTMLElement +); +root.render( + + + +); diff --git a/src/types.d.ts b/src/types.d.ts new file mode 100644 index 0000000..fe5324a --- /dev/null +++ b/src/types.d.ts @@ -0,0 +1,48 @@ +// types, composed for axios Rss feed + +export type TRssItem = { + title: string; + description: string; + link: string; + pubDate: Date; + guid: string; + }; + + export type TContent = { content: string }; + + export type TRssRawItem = { + item: { + children: [ + { title: TContent }, + { link: TContent }, + { description: TContent }, + { pubDate: { content: Date } }, + { guid: TContent } + ]; + }; + }; + +export type TChildren = { + children: [ + |{ + title: TContent; + } + | { + link: TContent; + } + | { + description: TContent; + } + | { + ttl: TContent; + } + | { + lastBuildDate: TContent; + } + | { + item: RssRawItem; + } + ]; +}; + +export type TDepartures = array[]; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..5c09d24 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": [ + "src" + ] + } + \ No newline at end of file