├── .nvmrc ├── .nowignore ├── public ├── logo.png ├── social.png ├── favicon.ico ├── apple-icon.png ├── logo-small.png ├── robots.txt ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon-96x96.png ├── ms-icon-70x70.png ├── apple-icon-57x57.png ├── apple-icon-60x60.png ├── apple-icon-72x72.png ├── apple-icon-76x76.png ├── ms-icon-144x144.png ├── ms-icon-150x150.png ├── ms-icon-310x310.png ├── android-icon-36x36.png ├── android-icon-48x48.png ├── android-icon-72x72.png ├── android-icon-96x96.png ├── apple-icon-114x114.png ├── apple-icon-120x120.png ├── apple-icon-144x144.png ├── apple-icon-152x152.png ├── apple-icon-180x180.png ├── android-icon-144x144.png ├── android-icon-192x192.png ├── apple-icon-precomposed.png ├── browserconfig.xml ├── sitemap.xml └── manifest.json ├── .npmrc ├── .vscode └── settings.json ├── tailwind.config.cjs ├── src ├── consts.js ├── pages │ ├── AirportPage │ │ ├── windDirectionAnimation.css │ │ ├── WindDirectionSvg.svg │ │ ├── Compass.js │ │ ├── AirportRunwaysMap.js │ │ ├── WindDirectionBackground.js │ │ ├── AirportHeader.js │ │ ├── AirportPage.js │ │ ├── AirportRunways.js │ │ └── AirportRunwayCard.js │ ├── TermsPage.js │ ├── SelectAirportPage │ │ └── SelectAirportPage.js │ ├── ContactsPage.js │ └── CookiesPolicyPage.js ├── index.js ├── setupTests.js ├── components │ ├── ScrollToTop.js │ ├── DebugDot.js │ ├── PageLayout.js │ ├── ScrollManagement.js │ ├── Loading │ │ ├── Loading.css │ │ └── Loading.js │ ├── CookiesConsent │ │ ├── useCookiesConsent.js │ │ └── CookiesConsent.js │ ├── Footer.js │ ├── RunwaysBackground.js │ ├── RunwaysMap │ │ ├── RunwayIdent.js │ │ ├── Runway.js │ │ ├── RunwaysMap.js │ │ └── RunwayBlock.js │ ├── NavBar.js │ └── AirportSelectInput.js ├── hooks │ ├── useStickyState.js │ ├── useAirportFetch.js │ └── useCalculateActiveRunways.js ├── AirportContext.js ├── index.css ├── helpers.js ├── App.js └── serviceWorker.js ├── postcss.config.cjs ├── server ├── Dockerfile ├── helpers │ └── downloadData.cjs ├── main.cjs └── api │ └── runway.cjs ├── nginx.conf ├── .gitignore ├── Dockerfile ├── vite.config.js ├── package.json ├── index.html └── README.md /.nvmrc: -------------------------------------------------------------------------------- 1 | 20.13.1 -------------------------------------------------------------------------------- /.nowignore: -------------------------------------------------------------------------------- 1 | data -------------------------------------------------------------------------------- /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/logo.png -------------------------------------------------------------------------------- /public/social.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/social.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/apple-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/apple-icon.png -------------------------------------------------------------------------------- /public/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/logo-small.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | audit=false 2 | legacy-peer-deps=true 3 | force=true 4 | registry=https://registry.npmjs.org/ -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.ignoreLimitWarning": true, 3 | "prettier.printWidth": 80 4 | } 5 | -------------------------------------------------------------------------------- /public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/favicon-16x16.png -------------------------------------------------------------------------------- /public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/favicon-32x32.png -------------------------------------------------------------------------------- /public/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/favicon-96x96.png -------------------------------------------------------------------------------- /public/ms-icon-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/ms-icon-70x70.png -------------------------------------------------------------------------------- /public/apple-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/apple-icon-57x57.png -------------------------------------------------------------------------------- /public/apple-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/apple-icon-60x60.png -------------------------------------------------------------------------------- /public/apple-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/apple-icon-72x72.png -------------------------------------------------------------------------------- /public/apple-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/apple-icon-76x76.png -------------------------------------------------------------------------------- /public/ms-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/ms-icon-144x144.png -------------------------------------------------------------------------------- /public/ms-icon-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/ms-icon-150x150.png -------------------------------------------------------------------------------- /public/ms-icon-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/ms-icon-310x310.png -------------------------------------------------------------------------------- /public/android-icon-36x36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/android-icon-36x36.png -------------------------------------------------------------------------------- /public/android-icon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/android-icon-48x48.png -------------------------------------------------------------------------------- /public/android-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/android-icon-72x72.png -------------------------------------------------------------------------------- /public/android-icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/android-icon-96x96.png -------------------------------------------------------------------------------- /public/apple-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/apple-icon-114x114.png -------------------------------------------------------------------------------- /public/apple-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/apple-icon-120x120.png -------------------------------------------------------------------------------- /public/apple-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/apple-icon-144x144.png -------------------------------------------------------------------------------- /public/apple-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/apple-icon-152x152.png -------------------------------------------------------------------------------- /public/apple-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/apple-icon-180x180.png -------------------------------------------------------------------------------- /public/android-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/android-icon-144x144.png -------------------------------------------------------------------------------- /public/android-icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/android-icon-192x192.png -------------------------------------------------------------------------------- /public/apple-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epranka/runway-app/HEAD/public/apple-icon-precomposed.png -------------------------------------------------------------------------------- /tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | content: ["./src/**/*.{js,jsx,ts,tsx}", "./public/index.html"], 3 | }; 4 | -------------------------------------------------------------------------------- /src/consts.js: -------------------------------------------------------------------------------- 1 | export const DEFAULT_METAR_PROVIDER = "aviationweather"; 2 | export const METAR_PROVIDER_STORAGE_KEY = "metarProvider"; 3 | -------------------------------------------------------------------------------- /postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | ...(process.env.NODE_ENV === "production" ? { cssnano: {} } : {}), 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /src/pages/AirportPage/windDirectionAnimation.css: -------------------------------------------------------------------------------- 1 | @keyframes animateBackground { 2 | from { 3 | background-position-y: 0; 4 | } 5 | to { 6 | background-position-y: 160px; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import App from "./App"; 4 | import "./index.css"; 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById("root") 11 | ); 12 | -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /public/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | #ffffff -------------------------------------------------------------------------------- /server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:20.13.1-alpine AS node 2 | 3 | WORKDIR /app 4 | 5 | COPY package.json /app 6 | COPY package-lock.json /app 7 | COPY .npmrc /app 8 | RUN npm ci 9 | 10 | COPY server /app/server 11 | 12 | ENV SERVER_PORT=80 13 | ENV NODE_ENV=production 14 | 15 | EXPOSE 80 16 | 17 | CMD ["node", "server/main.cjs"] -------------------------------------------------------------------------------- /src/pages/AirportPage/WindDirectionSvg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/ScrollToTop.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | import { useLocation } from "react-router-dom"; 3 | 4 | const ScrollToTop = () => { 5 | const { pathname } = useLocation(); 6 | 7 | useEffect(() => { 8 | window.scrollTo(0, 0); 9 | }, [pathname]); 10 | 11 | return null; 12 | }; 13 | 14 | export default ScrollToTop; 15 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | 4 | location / { 5 | root /usr/share/nginx/html; 6 | index index.html index.htm; 7 | try_files $uri $uri/ /index.html; 8 | } 9 | 10 | error_page 500 502 503 504 /50x.html; 11 | 12 | location = /50x.html { 13 | root /usr/share/nginx/html; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /server/helpers/downloadData.cjs: -------------------------------------------------------------------------------- 1 | const request = require('request'); 2 | 3 | const downloadFile = (url) => { 4 | return new Promise((resolve, reject) => { 5 | request.get(url, (error, _response, body) => { 6 | if (error) return reject(error); 7 | return resolve(body); 8 | }); 9 | }); 10 | }; 11 | 12 | module.exports = downloadFile; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /dist 13 | 14 | # misc 15 | .DS_Store 16 | .env 17 | .env.local 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | 26 | .now -------------------------------------------------------------------------------- /src/components/DebugDot.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function DebugDot(props) { 4 | const { x, y, ident } = props; 5 | 6 | return ( 7 | 8 | {ident} 9 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /public/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | https://runway.airportdb.io/ 4 | 5 | 6 | https://runway.airportdb.io/contacts 7 | 8 | 9 | https://runway.airportdb.io/policy/cookies 10 | 11 | 12 | https://runway.airportdb.io/policy/terms-of-usage 13 | 14 | -------------------------------------------------------------------------------- /src/components/PageLayout.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import CookiesConsent from "./CookiesConsent/CookiesConsent"; 3 | import Footer from "./Footer"; 4 | import NavBar from "./NavBar"; 5 | import ScrollToTop from "./ScrollToTop"; 6 | 7 | export default function PageLayout(props) { 8 | return ( 9 | <> 10 | 11 | 12 | {props.children} 13 |