feat: initialize new tab page with Preact and Vite setup
- Added index.html as the main entry point for the application. - Created package.json with dependencies for Preact, Halfmoon, and TypeScript. - Included favicon.svg for the application icon. - Added robots.txt for search engine directives. - Created app.css for styling the application. - Implemented app.tsx as the main application component with Navbar and Container. - Developed container component to display a greeting and search form. - Added weather description JSON data for dynamic weather updates. - Built navbar component to fetch and display current weather information. - Set up index.css for global styles. - Configured main.tsx to render the application. - Added TypeScript environment definitions. - Established TypeScript configuration files for app and node. - Configured Vite with Preact preset and PostCSS for production optimizations.
This commit is contained in:
parent
3ebaf0a468
commit
2f60206e25
18 changed files with 965 additions and 0 deletions
0
src/components/app.css
Normal file
0
src/components/app.css
Normal file
13
src/components/app.tsx
Normal file
13
src/components/app.tsx
Normal file
|
@ -0,0 +1,13 @@
|
|||
import Navbar from './navbar';
|
||||
import Container from './container';
|
||||
|
||||
import './app.css';
|
||||
|
||||
export default () => {
|
||||
return (
|
||||
<>
|
||||
<Navbar />
|
||||
<Container />
|
||||
</>
|
||||
)
|
||||
}
|
14
src/components/container/index.tsx
Normal file
14
src/components/container/index.tsx
Normal file
|
@ -0,0 +1,14 @@
|
|||
export default () => {
|
||||
return (
|
||||
<>
|
||||
<div class="container bg-body-tertiary shadow text-center position-absolute top-50 start-50 translate-middle mx-auto py-4">
|
||||
<h6 class="display-4">Hello, Seth.</h6>
|
||||
<br />
|
||||
<br />
|
||||
<form role="search" action={"https://www.google.com/search"} method="get">
|
||||
<input class="form-control me-2" autoFocus type="search" placeholder="Search with Google" aria-label="Search with Google" name="q" />
|
||||
</form>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
282
src/components/navbar/desc.json
Normal file
282
src/components/navbar/desc.json
Normal file
|
@ -0,0 +1,282 @@
|
|||
{
|
||||
"0":{
|
||||
"day":{
|
||||
"description":"Sunny",
|
||||
"image":"http://openweathermap.org/img/wn/01d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Clear",
|
||||
"image":"http://openweathermap.org/img/wn/01n@2x.png"
|
||||
}
|
||||
},
|
||||
"1":{
|
||||
"day":{
|
||||
"description":"Mainly Sunny",
|
||||
"image":"http://openweathermap.org/img/wn/01d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Mainly Clear",
|
||||
"image":"http://openweathermap.org/img/wn/01n@2x.png"
|
||||
}
|
||||
},
|
||||
"2":{
|
||||
"day":{
|
||||
"description":"Partly Cloudy",
|
||||
"image":"http://openweathermap.org/img/wn/02d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Partly Cloudy",
|
||||
"image":"http://openweathermap.org/img/wn/02n@2x.png"
|
||||
}
|
||||
},
|
||||
"3":{
|
||||
"day":{
|
||||
"description":"Cloudy",
|
||||
"image":"http://openweathermap.org/img/wn/03d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Cloudy",
|
||||
"image":"http://openweathermap.org/img/wn/03n@2x.png"
|
||||
}
|
||||
},
|
||||
"45":{
|
||||
"day":{
|
||||
"description":"Foggy",
|
||||
"image":"http://openweathermap.org/img/wn/50d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Foggy",
|
||||
"image":"http://openweathermap.org/img/wn/50n@2x.png"
|
||||
}
|
||||
},
|
||||
"48":{
|
||||
"day":{
|
||||
"description":"Rime Fog",
|
||||
"image":"http://openweathermap.org/img/wn/50d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Rime Fog",
|
||||
"image":"http://openweathermap.org/img/wn/50n@2x.png"
|
||||
}
|
||||
},
|
||||
"51":{
|
||||
"day":{
|
||||
"description":"Light Drizzle",
|
||||
"image":"http://openweathermap.org/img/wn/09d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Light Drizzle",
|
||||
"image":"http://openweathermap.org/img/wn/09n@2x.png"
|
||||
}
|
||||
},
|
||||
"53":{
|
||||
"day":{
|
||||
"description":"Drizzle",
|
||||
"image":"http://openweathermap.org/img/wn/09d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Drizzle",
|
||||
"image":"http://openweathermap.org/img/wn/09n@2x.png"
|
||||
}
|
||||
},
|
||||
"55":{
|
||||
"day":{
|
||||
"description":"Heavy Drizzle",
|
||||
"image":"http://openweathermap.org/img/wn/09d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Heavy Drizzle",
|
||||
"image":"http://openweathermap.org/img/wn/09n@2x.png"
|
||||
}
|
||||
},
|
||||
"56":{
|
||||
"day":{
|
||||
"description":"Light Freezing Drizzle",
|
||||
"image":"http://openweathermap.org/img/wn/09d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Light Freezing Drizzle",
|
||||
"image":"http://openweathermap.org/img/wn/09n@2x.png"
|
||||
}
|
||||
},
|
||||
"57":{
|
||||
"day":{
|
||||
"description":"Freezing Drizzle",
|
||||
"image":"http://openweathermap.org/img/wn/09d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Freezing Drizzle",
|
||||
"image":"http://openweathermap.org/img/wn/09n@2x.png"
|
||||
}
|
||||
},
|
||||
"61":{
|
||||
"day":{
|
||||
"description":"Light Rain",
|
||||
"image":"http://openweathermap.org/img/wn/10d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Light Rain",
|
||||
"image":"http://openweathermap.org/img/wn/10n@2x.png"
|
||||
}
|
||||
},
|
||||
"63":{
|
||||
"day":{
|
||||
"description":"Rain",
|
||||
"image":"http://openweathermap.org/img/wn/10d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Rain",
|
||||
"image":"http://openweathermap.org/img/wn/10n@2x.png"
|
||||
}
|
||||
},
|
||||
"65":{
|
||||
"day":{
|
||||
"description":"Heavy Rain",
|
||||
"image":"http://openweathermap.org/img/wn/10d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Heavy Rain",
|
||||
"image":"http://openweathermap.org/img/wn/10n@2x.png"
|
||||
}
|
||||
},
|
||||
"66":{
|
||||
"day":{
|
||||
"description":"Light Freezing Rain",
|
||||
"image":"http://openweathermap.org/img/wn/10d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Light Freezing Rain",
|
||||
"image":"http://openweathermap.org/img/wn/10n@2x.png"
|
||||
}
|
||||
},
|
||||
"67":{
|
||||
"day":{
|
||||
"description":"Freezing Rain",
|
||||
"image":"http://openweathermap.org/img/wn/10d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Freezing Rain",
|
||||
"image":"http://openweathermap.org/img/wn/10n@2x.png"
|
||||
}
|
||||
},
|
||||
"71":{
|
||||
"day":{
|
||||
"description":"Light Snow",
|
||||
"image":"http://openweathermap.org/img/wn/13d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Light Snow",
|
||||
"image":"http://openweathermap.org/img/wn/13n@2x.png"
|
||||
}
|
||||
},
|
||||
"73":{
|
||||
"day":{
|
||||
"description":"Snow",
|
||||
"image":"http://openweathermap.org/img/wn/13d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Snow",
|
||||
"image":"http://openweathermap.org/img/wn/13n@2x.png"
|
||||
}
|
||||
},
|
||||
"75":{
|
||||
"day":{
|
||||
"description":"Heavy Snow",
|
||||
"image":"http://openweathermap.org/img/wn/13d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Heavy Snow",
|
||||
"image":"http://openweathermap.org/img/wn/13n@2x.png"
|
||||
}
|
||||
},
|
||||
"77":{
|
||||
"day":{
|
||||
"description":"Snow Grains",
|
||||
"image":"http://openweathermap.org/img/wn/13d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Snow Grains",
|
||||
"image":"http://openweathermap.org/img/wn/13n@2x.png"
|
||||
}
|
||||
},
|
||||
"80":{
|
||||
"day":{
|
||||
"description":"Light Showers",
|
||||
"image":"http://openweathermap.org/img/wn/09d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Light Showers",
|
||||
"image":"http://openweathermap.org/img/wn/09n@2x.png"
|
||||
}
|
||||
},
|
||||
"81":{
|
||||
"day":{
|
||||
"description":"Showers",
|
||||
"image":"http://openweathermap.org/img/wn/09d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Showers",
|
||||
"image":"http://openweathermap.org/img/wn/09n@2x.png"
|
||||
}
|
||||
},
|
||||
"82":{
|
||||
"day":{
|
||||
"description":"Heavy Showers",
|
||||
"image":"http://openweathermap.org/img/wn/09d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Heavy Showers",
|
||||
"image":"http://openweathermap.org/img/wn/09n@2x.png"
|
||||
}
|
||||
},
|
||||
"85":{
|
||||
"day":{
|
||||
"description":"Light Snow Showers",
|
||||
"image":"http://openweathermap.org/img/wn/13d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Light Snow Showers",
|
||||
"image":"http://openweathermap.org/img/wn/13n@2x.png"
|
||||
}
|
||||
},
|
||||
"86":{
|
||||
"day":{
|
||||
"description":"Snow Showers",
|
||||
"image":"http://openweathermap.org/img/wn/13d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Snow Showers",
|
||||
"image":"http://openweathermap.org/img/wn/13n@2x.png"
|
||||
}
|
||||
},
|
||||
"95":{
|
||||
"day":{
|
||||
"description":"Thunderstorm",
|
||||
"image":"http://openweathermap.org/img/wn/11d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Thunderstorm",
|
||||
"image":"http://openweathermap.org/img/wn/11n@2x.png"
|
||||
}
|
||||
},
|
||||
"96":{
|
||||
"day":{
|
||||
"description":"Light Thunderstorms With Hail",
|
||||
"image":"http://openweathermap.org/img/wn/11d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Light Thunderstorms With Hail",
|
||||
"image":"http://openweathermap.org/img/wn/11n@2x.png"
|
||||
}
|
||||
},
|
||||
"99":{
|
||||
"day":{
|
||||
"description":"Thunderstorm With Hail",
|
||||
"image":"http://openweathermap.org/img/wn/11d@2x.png"
|
||||
},
|
||||
"night":{
|
||||
"description":"Thunderstorm With Hail",
|
||||
"image":"http://openweathermap.org/img/wn/11n@2x.png"
|
||||
}
|
||||
}
|
||||
}
|
62
src/components/navbar/index.tsx
Normal file
62
src/components/navbar/index.tsx
Normal file
|
@ -0,0 +1,62 @@
|
|||
import { useState } from 'preact/hooks';
|
||||
import { ChevronLeft, ChevronRight } from 'lucide-preact';
|
||||
|
||||
import desc from "./desc.json";
|
||||
|
||||
const fetchWeather = async (lat: number, long: number) => {
|
||||
const req = await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${long}¤t=temperature_2m,is_day,weather_code&timezone=${Intl.DateTimeFormat().resolvedOptions().timeZone}`)
|
||||
const res = await req.json();
|
||||
|
||||
return res as {
|
||||
current: {
|
||||
temperature_2m: number,
|
||||
is_day: number;
|
||||
weather_code: number;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default () => {
|
||||
const [weather, setWeather] = useState<string>("Loading...");
|
||||
const [imgSrc, setSrc] = useState<string>("favicon.svg");
|
||||
const [wttrDesc, setWttrDesc] = useState<string>("Loading...");
|
||||
|
||||
const getWeather = async (coords: GeolocationCoordinates) => {
|
||||
const weather = await fetchWeather(coords.latitude, coords.longitude);
|
||||
|
||||
const weatherCode = weather.current.weather_code;
|
||||
const isDay = weather.current.is_day === 1;
|
||||
const dayOrNight = isDay ? "Day" : "Night";
|
||||
const weatherDesc = desc[weatherCode.toString() as keyof typeof desc][dayOrNight.toLowerCase() as "day" | "night"];
|
||||
|
||||
setWeather(`${weather.current.temperature_2m}°C`);
|
||||
setSrc(weatherDesc.image);
|
||||
setWttrDesc(`${weatherDesc.description} & ${dayOrNight}`);
|
||||
}
|
||||
|
||||
(async () => {
|
||||
const req = await fetch("https://cf.ipv4-army.workers.dev/")
|
||||
const res = await req.json();
|
||||
return await getWeather(res);
|
||||
})()
|
||||
|
||||
return (
|
||||
<>
|
||||
<nav class="navbar shadow fixed-top" style="background-color: var(--bs-content-bg); border-bottom: var(--bs-border-width) solid var(--bs-content-border-color);">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-brand">
|
||||
<img src={imgSrc} alt="Logo" width="24" height="24" class="d-inline-block align-text-top" />
|
||||
{wttrDesc}
|
||||
</div>
|
||||
<span class="navbar-text">
|
||||
{weather}
|
||||
</span>
|
||||
<div class="d-flex hstack gap-2" role="search">
|
||||
<button type="button" class="btn btn-outline-light btn-sm" onClick={history.back}><ChevronLeft size={20} /></button>
|
||||
<button type="button" class="btn btn-outline-light btn-sm" onClick={history.forward}><ChevronRight size={20} /></button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</>
|
||||
)
|
||||
}
|
0
src/index.css
Normal file
0
src/index.css
Normal file
6
src/main.tsx
Normal file
6
src/main.tsx
Normal file
|
@ -0,0 +1,6 @@
|
|||
import { render } from 'preact'
|
||||
import './index.css'
|
||||
import 'halfmoon/css/halfmoon.min.css';
|
||||
import App from './components/app.tsx'
|
||||
|
||||
render(<App />, document.getElementById('app')!)
|
1
src/vite-env.d.ts
vendored
Normal file
1
src/vite-env.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/// <reference types="vite/client" />
|
Loading…
Add table
Add a link
Reference in a new issue