metar grid changes
This commit is contained in:
110
package-lock.json
generated
110
package-lock.json
generated
@@ -8,6 +8,10 @@
|
|||||||
"name": "pcs-ui",
|
"name": "pcs-ui",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-svg-core": "^6.4.2",
|
||||||
|
"@fortawesome/free-regular-svg-icons": "^6.4.2",
|
||||||
|
"@fortawesome/free-solid-svg-icons": "^6.4.2",
|
||||||
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
"next": "13.4.12",
|
"next": "13.4.12",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
@@ -121,6 +125,63 @@
|
|||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@fortawesome/fontawesome-common-types": {
|
||||||
|
"version": "6.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.2.tgz",
|
||||||
|
"integrity": "sha512-1DgP7f+XQIJbLFCTX1V2QnxVmpLdKdzzo2k8EmvDOePfchaIGQ9eCHj2up3/jNEbZuBqel5OxiaOJf37TWauRA==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@fortawesome/fontawesome-svg-core": {
|
||||||
|
"version": "6.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.2.tgz",
|
||||||
|
"integrity": "sha512-gjYDSKv3TrM2sLTOKBc5rH9ckje8Wrwgx1CxAPbN5N3Fm4prfi7NsJVWd1jklp7i5uSCVwhZS5qlhMXqLrpAIg==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "6.4.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@fortawesome/free-regular-svg-icons": {
|
||||||
|
"version": "6.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.4.2.tgz",
|
||||||
|
"integrity": "sha512-0+sIUWnkgTVVXVAPQmW4vxb9ZTHv0WstOa3rBx9iPxrrrDH6bNLsDYuwXF9b6fGm+iR7DKQvQshUH/FJm3ed9Q==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "6.4.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@fortawesome/free-solid-svg-icons": {
|
||||||
|
"version": "6.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.2.tgz",
|
||||||
|
"integrity": "sha512-sYwXurXUEQS32fZz9hVCUUv/xu49PEJEyUOsA51l6PU/qVgfbTb2glsTEaJngVVT8VqBATRIdh7XVgV1JF1LkA==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "6.4.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@fortawesome/react-fontawesome": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==",
|
||||||
|
"dependencies": {
|
||||||
|
"prop-types": "^15.8.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@fortawesome/fontawesome-svg-core": "~1 || ~6",
|
||||||
|
"react": ">=16.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@humanwhocodes/config-array": {
|
"node_modules/@humanwhocodes/config-array": {
|
||||||
"version": "0.11.10",
|
"version": "0.11.10",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
|
||||||
@@ -3447,7 +3508,6 @@
|
|||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@@ -3907,7 +3967,6 @@
|
|||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.4.0",
|
"loose-envify": "^1.4.0",
|
||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
@@ -3974,8 +4033,7 @@
|
|||||||
"node_modules/react-is": {
|
"node_modules/react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/read-cache": {
|
"node_modules/read-cache": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@@ -5065,6 +5123,43 @@
|
|||||||
"integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==",
|
"integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@fortawesome/fontawesome-common-types": {
|
||||||
|
"version": "6.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.2.tgz",
|
||||||
|
"integrity": "sha512-1DgP7f+XQIJbLFCTX1V2QnxVmpLdKdzzo2k8EmvDOePfchaIGQ9eCHj2up3/jNEbZuBqel5OxiaOJf37TWauRA=="
|
||||||
|
},
|
||||||
|
"@fortawesome/fontawesome-svg-core": {
|
||||||
|
"version": "6.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.2.tgz",
|
||||||
|
"integrity": "sha512-gjYDSKv3TrM2sLTOKBc5rH9ckje8Wrwgx1CxAPbN5N3Fm4prfi7NsJVWd1jklp7i5uSCVwhZS5qlhMXqLrpAIg==",
|
||||||
|
"requires": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "6.4.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@fortawesome/free-regular-svg-icons": {
|
||||||
|
"version": "6.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.4.2.tgz",
|
||||||
|
"integrity": "sha512-0+sIUWnkgTVVXVAPQmW4vxb9ZTHv0WstOa3rBx9iPxrrrDH6bNLsDYuwXF9b6fGm+iR7DKQvQshUH/FJm3ed9Q==",
|
||||||
|
"requires": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "6.4.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@fortawesome/free-solid-svg-icons": {
|
||||||
|
"version": "6.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.2.tgz",
|
||||||
|
"integrity": "sha512-sYwXurXUEQS32fZz9hVCUUv/xu49PEJEyUOsA51l6PU/qVgfbTb2glsTEaJngVVT8VqBATRIdh7XVgV1JF1LkA==",
|
||||||
|
"requires": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "6.4.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@fortawesome/react-fontawesome": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==",
|
||||||
|
"requires": {
|
||||||
|
"prop-types": "^15.8.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@humanwhocodes/config-array": {
|
"@humanwhocodes/config-array": {
|
||||||
"version": "0.11.10",
|
"version": "0.11.10",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
|
||||||
@@ -7351,8 +7446,7 @@
|
|||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"object-hash": {
|
"object-hash": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
@@ -7642,7 +7736,6 @@
|
|||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"loose-envify": "^1.4.0",
|
"loose-envify": "^1.4.0",
|
||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
@@ -7686,8 +7779,7 @@
|
|||||||
"react-is": {
|
"react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"read-cache": {
|
"read-cache": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-svg-core": "^6.4.2",
|
||||||
|
"@fortawesome/free-regular-svg-icons": "^6.4.2",
|
||||||
|
"@fortawesome/free-solid-svg-icons": "^6.4.2",
|
||||||
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
"next": "13.4.12",
|
"next": "13.4.12",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { airports } from "@/js/state";
|
import { getAirport } from "@/js/state";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
|
||||||
|
|
||||||
export default function Page({ params }: { params: { icao: string } }) {
|
export default function Page({ params }: { params: { icao: string } }) {
|
||||||
const airport = airports.get(params.icao);
|
const airport = getAirport(params.icao);
|
||||||
return <>
|
return <>
|
||||||
<div className="border-b border-gray-200 bg-gray-400 px-4 py-5 sm:px-6 flex justify-between">
|
<div className="border-b border-gray-200 bg-gray-400 px-4 py-5 sm:px-6 flex justify-between">
|
||||||
<h3 className="text-base font-semibold leading-6 text-gray-900">{airport?.name}</h3>
|
<h3 className="text-base font-semibold leading-6 text-gray-900">{airport?.name}</h3>
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import RecoilRootWrapper from '@app/recoil-root-wrapper';
|
import RecoilRootWrapper from '@app/recoil-root-wrapper';
|
||||||
|
|
||||||
|
|
||||||
|
import '@fortawesome/fontawesome-svg-core/styles.css';
|
||||||
|
// Prevent fontawesome from adding its CSS since we did it manually above:
|
||||||
|
import { config } from '@fortawesome/fontawesome-svg-core';
|
||||||
|
config.autoAddCss = false; /* eslint-disable import/first */
|
||||||
import 'styles/globals.css';
|
import 'styles/globals.css';
|
||||||
|
|
||||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { airports } from "@/js/state";
|
import { setAirport } from "@/js/state";
|
||||||
import { Airport } from "@/js/airport";
|
import { Airport } from "@/js/airport";
|
||||||
import MetarCard from '@/components/MetarCard';
|
import MetarGrid from '@/components/MetarGrid';
|
||||||
|
|
||||||
airports.set('KJYO', new Airport('Leesburg Executive Airport', 'KJYO'))
|
setAirport('KJYO', new Airport('Leesburg Executive Airport', 'KJYO'))
|
||||||
airports.set('KHEF', new Airport('Manassas Regional Airpoirt', 'KHEF'))
|
setAirport('KHEF', new Airport('Manassas Regional Airpoirt', 'KHEF'))
|
||||||
airports.set('KIAD', new Airport('Dulles International Airport', 'KIAD'))
|
setAirport('KIAD', new Airport('Dulles International Airport', 'KIAD'))
|
||||||
airports.set('KFDK', new Airport('Frederick Municipal Airport', 'KFDK'))
|
setAirport('KFDK', new Airport('Frederick Municipal Airport', 'KFDK'))
|
||||||
airports.set('KMRB', new Airport('Eastern West Virginia Regional Airport', 'KMRB'))
|
setAirport('KMRB', new Airport('Eastern West Virginia Regional Airport', 'KMRB'))
|
||||||
airports.set('KOKV', new Airport('Winchester Regional Airport', 'KOKV'))
|
setAirport('KOKV', new Airport('Winchester Regional Airport', 'KOKV'))
|
||||||
airports.set('KFRR', new Airport('Front Royal-Warren County Airport', 'KFRR'))
|
setAirport('KFRR', new Airport('Front Royal-Warren County Airport', 'KFRR'))
|
||||||
airports.set('KLUA', new Airport('Luray Caverns Airport', 'KLUA'))
|
setAirport('KLUA', new Airport('Luray Caverns Airport', 'KLUA'))
|
||||||
airports.set('KSHD', new Airport('Shenandoah Valley Airport', 'KSHD'))
|
setAirport('KSHD', new Airport('Shenandoah Valley Airport', 'KSHD'))
|
||||||
airports.set('KCHO', new Airport('Charlottesville-Albemarle Airport', 'KCHO'))
|
setAirport('KCHO', new Airport('Charlottesville-Albemarle Airport', 'KCHO'))
|
||||||
airports.set('KCJR', new Airport('Culpeper Regional Airport', 'KCJR'))
|
setAirport('KCJR', new Airport('Culpeper Regional Airport', 'KCJR'))
|
||||||
airports.set('KHWY', new Airport('Warrenton-Fauquier Airport', 'KHWY'))
|
setAirport('KHWY', new Airport('Warrenton-Fauquier Airport', 'KHWY'))
|
||||||
airports.set('KRMN', new Airport('Stafford Regional Airport', 'KRMN'))
|
setAirport('KRMN', new Airport('Stafford Regional Airport', 'KRMN'))
|
||||||
airports.set('KEZF', new Airport('Shannon Airport', 'KEZF'))
|
setAirport('KEZF', new Airport('Shannon Airport', 'KEZF'))
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
return <>
|
return <>
|
||||||
<div className="border-b border-gray-200 bg-gray-400 px-4 py-5 sm:px-6">
|
<div className="border-b border-gray-200 bg-gray-400 px-4 py-5 sm:px-6">
|
||||||
<h3 className="text-base font-semibold leading-6 text-gray-900">Airports</h3>
|
<h3 className="text-lg font-bold leading-6 text-gray-900">Airports</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className='p-4'>
|
<div className='p-4'>
|
||||||
<MetarCard airports={[...airports.values()]}/>
|
<MetarGrid/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|||||||
7
src/atoms/index.ts
Normal file
7
src/atoms/index.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export const airportsState = atom({
|
||||||
|
key: 'airportsState',
|
||||||
|
default: [] as Airport[]
|
||||||
|
});
|
||||||
|
|
||||||
|
import { Airport } from "@/js/airport";
|
||||||
|
import { atom } from "recoil";
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
import { Airport } from "@/js/airport";
|
|
||||||
import { Metar, getMetars } from "@/js/weather"
|
|
||||||
import Link from "next/link"
|
|
||||||
|
|
||||||
export default async function MetarCard({airports}: {airports: Airport[]}) {
|
|
||||||
const metars = await getMetars(airports);
|
|
||||||
for (let i = 0; i < airports.length; i++) {
|
|
||||||
airports[i].metar = metars[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
function metarBGColor(metar: Metar | undefined) {
|
|
||||||
if (metar?.flight_category == 'VFR') {
|
|
||||||
return 'bg-emerald-600'
|
|
||||||
} else if (metar?.flight_category == 'MVFR') {
|
|
||||||
return 'bg-blue-600'
|
|
||||||
} else if (metar?.flight_category == 'IFR') {
|
|
||||||
return 'bg-red-600'
|
|
||||||
} else if (metar?.flight_category == 'LIFR') {
|
|
||||||
return 'bg-purple-600'
|
|
||||||
} else {
|
|
||||||
return 'bg-black'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
|
||||||
{airports.map((airport) => (
|
|
||||||
<div
|
|
||||||
key={airport.metar?.station_id}
|
|
||||||
className={`relative flex items-center space-x-3 rounded-lg border border-gray-300 bg-white px-4 py-2 shadow-sm focus-within:ring-2 focus-within:ring-indigo-500 focus-within:ring-offset-2 hover:border-gray-400`}
|
|
||||||
>
|
|
||||||
<div className="min-w-0 flex-1">
|
|
||||||
<Link href={`/airport/${airport.icao}`}>
|
|
||||||
<span className="absolute inset-0" aria-hidden="true" />
|
|
||||||
<p className="text-gray-900 pb-1">{airport.name} ({airport.metar?.station_id})</p>
|
|
||||||
<p className='text-sm font-medium text-gray-500'>{airport.metar?.raw_text}</p>
|
|
||||||
<div className='mt-2'>
|
|
||||||
<span className={`truncate text-sm text-white ${metarBGColor(airport.metar)} inline-block py-2 px-4 rounded-full`}>{airport.metar?.flight_category}</span>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
73
src/components/MetarGrid.tsx
Normal file
73
src/components/MetarGrid.tsx
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import { Airport } from "@/js/airport";
|
||||||
|
import { getAirports, setAirport } from "@/js/state";
|
||||||
|
import { Metar, getMetars } from "@/js/weather"
|
||||||
|
import Link from "next/link"
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
|
import { faLocationArrow } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
|
export default async function MetarGrid() {
|
||||||
|
const airports: Airport[] = getAirports();
|
||||||
|
|
||||||
|
async function update() {
|
||||||
|
const airports: Airport[] = getAirports();
|
||||||
|
const metars = await getMetars(airports);
|
||||||
|
for (let i = 0; i < airports.length; i++) {
|
||||||
|
airports[i].metar = metars[i];
|
||||||
|
setAirport(airports[i].icao, airports[i]);
|
||||||
|
}
|
||||||
|
// setTimeout(update, 30 * 60 * 1000);
|
||||||
|
// setTimeout(update, 5000);
|
||||||
|
}
|
||||||
|
await update();
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||||
|
{airports.map((airport) => (
|
||||||
|
<MetarCard airport={airport}/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function MetarCard({ airport}: { airport: Airport}) {
|
||||||
|
function metarBGColor(metar: Metar | undefined) {
|
||||||
|
if (metar?.flight_category == 'VFR') {
|
||||||
|
return 'bg-emerald-600'
|
||||||
|
} else if (metar?.flight_category == 'MVFR') {
|
||||||
|
return 'bg-blue-600'
|
||||||
|
} else if (metar?.flight_category == 'IFR') {
|
||||||
|
return 'bg-orange-600'
|
||||||
|
} else if (metar?.flight_category == 'LIFR') {
|
||||||
|
return 'bg-red-600'
|
||||||
|
} else {
|
||||||
|
return 'bg-black'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={airport.metar?.station_id}
|
||||||
|
className={`relative flex items-center space-x-3 rounded-lg border border-gray-300 bg-white px-4 py-2 shadow-sm focus-within:ring-2 focus-within:ring-indigo-500 focus-within:ring-offset-2 hover:border-gray-400`}
|
||||||
|
>
|
||||||
|
<div className="min-w-0 flex-1">
|
||||||
|
<Link href={`/airport/${airport.icao}`}>
|
||||||
|
<span className="absolute inset-0" aria-hidden="true" />
|
||||||
|
<p className="text-gray-900 pb-1"><span className='font-semibold'>{airport.icao}</span> {airport.name}</p>
|
||||||
|
<hr/>
|
||||||
|
<p className='text-sm font-medium text-gray-500'>{airport.metar?.raw_text}</p>
|
||||||
|
<div className='mt-2'>
|
||||||
|
<span className={`truncate text-sm text-white ${metarBGColor(airport.metar)} inline-block py-2 px-4 rounded-full`}>{airport.metar?.flight_category? airport.metar?.flight_category : 'UNKN'}</span>
|
||||||
|
<span className="truncate inline-block py-2 px-2">
|
||||||
|
{airport.metar && airport.metar.wind_dir_degrees && airport.metar.wind_dir_degrees != 0?
|
||||||
|
// <FontAwesomeIcon icon={faLocationArrow} size="2xs" style={{rotate: `${-45 + airport.metar.wind_dir_degrees}deg`}}/> : <></>
|
||||||
|
<FontAwesomeIcon icon={faLocationArrow} style={{rotate: `${-45 + airport.metar.wind_dir_degrees}deg`}} className="pr-1"/>: <></>
|
||||||
|
}
|
||||||
|
{airport.metar?.wind_speed_kt} KT
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,9 +1,15 @@
|
|||||||
// import { atom } from "recoil";
|
|
||||||
import { Airport } from "./airport";
|
import { Airport } from "./airport";
|
||||||
|
|
||||||
// export const airportsState = atom({
|
const airports: Map<string, Airport> = new Map();
|
||||||
// key: 'airportsState',
|
|
||||||
// default: [] as Airport[]
|
|
||||||
// });
|
|
||||||
|
|
||||||
export const airports: Map<string, Airport> = new Map();
|
export function setAirport(icao: string, airport: Airport) {
|
||||||
|
airports.set(icao, airport);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getAirport(icao: string): Airport | undefined {
|
||||||
|
return airports.get(icao);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getAirports(): Airport[] {
|
||||||
|
return [...airports.values()];
|
||||||
|
}
|
||||||
@@ -52,8 +52,8 @@ export async function getMetars(airports: Airport[]): Promise<Metar[]> {
|
|||||||
dewpoint_c: Number(data.dewpoint_c._text),
|
dewpoint_c: Number(data.dewpoint_c._text),
|
||||||
wind_dir_degrees: Number(data.wind_dir_degrees._text),
|
wind_dir_degrees: Number(data.wind_dir_degrees._text),
|
||||||
wind_speed_kt: Number(data.wind_speed_kt._text),
|
wind_speed_kt: Number(data.wind_speed_kt._text),
|
||||||
visibility_statute_mi: data.visibility_statute_mi._text,
|
visibility_statute_mi: data.visibility_statute_mi?._text,
|
||||||
altim_in_hg: Number(data.altim_in_hg._text),
|
altim_in_hg: Number(data.altim_in_hg?._text),
|
||||||
sea_level_pressure_mb: data.sea_level_pressure_mb?._text,
|
sea_level_pressure_mb: data.sea_level_pressure_mb?._text,
|
||||||
quality_control_flags: {
|
quality_control_flags: {
|
||||||
auto: data.quality_control_flags?.auto?._text == 'TRUE',
|
auto: data.quality_control_flags?.auto?._text == 'TRUE',
|
||||||
|
|||||||
Reference in New Issue
Block a user