metar grid changes
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { airports } from "@/js/state";
|
||||
import { getAirport } from "@/js/state";
|
||||
import Link from "next/link";
|
||||
|
||||
|
||||
export default function Page({ params }: { params: { icao: string } }) {
|
||||
const airport = airports.get(params.icao);
|
||||
const airport = getAirport(params.icao);
|
||||
return <>
|
||||
<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>
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import React from 'react';
|
||||
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';
|
||||
|
||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
import React from 'react';
|
||||
import { airports } from "@/js/state";
|
||||
import { setAirport } from "@/js/state";
|
||||
import { Airport } from "@/js/airport";
|
||||
import MetarCard from '@/components/MetarCard';
|
||||
import MetarGrid from '@/components/MetarGrid';
|
||||
|
||||
airports.set('KJYO', new Airport('Leesburg Executive Airport', 'KJYO'))
|
||||
airports.set('KHEF', new Airport('Manassas Regional Airpoirt', 'KHEF'))
|
||||
airports.set('KIAD', new Airport('Dulles International Airport', 'KIAD'))
|
||||
airports.set('KFDK', new Airport('Frederick Municipal Airport', 'KFDK'))
|
||||
airports.set('KMRB', new Airport('Eastern West Virginia Regional Airport', 'KMRB'))
|
||||
airports.set('KOKV', new Airport('Winchester Regional Airport', 'KOKV'))
|
||||
airports.set('KFRR', new Airport('Front Royal-Warren County Airport', 'KFRR'))
|
||||
airports.set('KLUA', new Airport('Luray Caverns Airport', 'KLUA'))
|
||||
airports.set('KSHD', new Airport('Shenandoah Valley Airport', 'KSHD'))
|
||||
airports.set('KCHO', new Airport('Charlottesville-Albemarle Airport', 'KCHO'))
|
||||
airports.set('KCJR', new Airport('Culpeper Regional Airport', 'KCJR'))
|
||||
airports.set('KHWY', new Airport('Warrenton-Fauquier Airport', 'KHWY'))
|
||||
airports.set('KRMN', new Airport('Stafford Regional Airport', 'KRMN'))
|
||||
airports.set('KEZF', new Airport('Shannon Airport', 'KEZF'))
|
||||
setAirport('KJYO', new Airport('Leesburg Executive Airport', 'KJYO'))
|
||||
setAirport('KHEF', new Airport('Manassas Regional Airpoirt', 'KHEF'))
|
||||
setAirport('KIAD', new Airport('Dulles International Airport', 'KIAD'))
|
||||
setAirport('KFDK', new Airport('Frederick Municipal Airport', 'KFDK'))
|
||||
setAirport('KMRB', new Airport('Eastern West Virginia Regional Airport', 'KMRB'))
|
||||
setAirport('KOKV', new Airport('Winchester Regional Airport', 'KOKV'))
|
||||
setAirport('KFRR', new Airport('Front Royal-Warren County Airport', 'KFRR'))
|
||||
setAirport('KLUA', new Airport('Luray Caverns Airport', 'KLUA'))
|
||||
setAirport('KSHD', new Airport('Shenandoah Valley Airport', 'KSHD'))
|
||||
setAirport('KCHO', new Airport('Charlottesville-Albemarle Airport', 'KCHO'))
|
||||
setAirport('KCJR', new Airport('Culpeper Regional Airport', 'KCJR'))
|
||||
setAirport('KHWY', new Airport('Warrenton-Fauquier Airport', 'KHWY'))
|
||||
setAirport('KRMN', new Airport('Stafford Regional Airport', 'KRMN'))
|
||||
setAirport('KEZF', new Airport('Shannon Airport', 'KEZF'))
|
||||
|
||||
export default function Page() {
|
||||
return <>
|
||||
<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 className='p-4'>
|
||||
<MetarCard airports={[...airports.values()]}/>
|
||||
<MetarGrid/>
|
||||
</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";
|
||||
|
||||
// export const airportsState = atom({
|
||||
// key: 'airportsState',
|
||||
// default: [] as Airport[]
|
||||
// });
|
||||
const airports: Map<string, Airport> = new Map();
|
||||
|
||||
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),
|
||||
wind_dir_degrees: Number(data.wind_dir_degrees._text),
|
||||
wind_speed_kt: Number(data.wind_speed_kt._text),
|
||||
visibility_statute_mi: data.visibility_statute_mi._text,
|
||||
altim_in_hg: Number(data.altim_in_hg._text),
|
||||
visibility_statute_mi: data.visibility_statute_mi?._text,
|
||||
altim_in_hg: Number(data.altim_in_hg?._text),
|
||||
sea_level_pressure_mb: data.sea_level_pressure_mb?._text,
|
||||
quality_control_flags: {
|
||||
auto: data.quality_control_flags?.auto?._text == 'TRUE',
|
||||
|
||||
Reference in New Issue
Block a user