├── .gitignore ├── .vscode ├── extensions.json └── launch.json ├── LICENSE ├── README.md ├── astro.config.mjs ├── package-lock.json ├── package.json ├── pnpm-lock.yaml ├── public ├── Mockup_Preview.png ├── _redirects.txt ├── favicon.ico ├── favicon.svg ├── google3b8fb4e0392121a9.html ├── icons │ ├── 1024.png │ ├── 144.png │ ├── 180.png │ ├── 192.png │ ├── 384.png │ ├── 512.png │ └── 64.png ├── manifest.json ├── robots.txt ├── serviceWorker.js └── sitemap.xml ├── src ├── assets │ ├── desktop │ │ ├── 113d.webp │ │ ├── 113n.webp │ │ ├── 116d.webp │ │ ├── 116n.webp │ │ ├── 119d.webp │ │ ├── 119n.webp │ │ ├── 122d.webp │ │ ├── 122n.webp │ │ ├── 143d.webp │ │ ├── 143n.webp │ │ ├── 176d.webp │ │ ├── 176n.webp │ │ ├── 179d.webp │ │ ├── 179n.webp │ │ ├── 182d.webp │ │ ├── 182n.webp │ │ ├── 185d.webp │ │ ├── 185n.webp │ │ ├── 200d.webp │ │ ├── 200n.webp │ │ ├── 227d.webp │ │ ├── 227n.webp │ │ ├── 230d.webp │ │ ├── 230n.webp │ │ ├── 296d.webp │ │ ├── 296n.webp │ │ ├── 305d.webp │ │ ├── 305n.webp │ │ ├── 350d.webp │ │ ├── 350n.webp │ │ ├── 389d.webp │ │ ├── 389n.webp │ │ ├── 392d.webp │ │ ├── 392n.webp │ │ ├── index.ts │ │ └── unknown.webp │ ├── icons │ │ ├── 113d.svg │ │ ├── 113n.svg │ │ ├── 116d.svg │ │ ├── 116n.svg │ │ ├── 119d.svg │ │ ├── 119n.svg │ │ ├── 122dn.svg │ │ ├── 143d.svg │ │ ├── 143n.svg │ │ ├── 176d.svg │ │ ├── 176n.svg │ │ ├── 179d.svg │ │ ├── 179n.svg │ │ ├── 182d.svg │ │ ├── 182n.svg │ │ ├── 185d.svg │ │ ├── 185n.svg │ │ ├── 200d.svg │ │ ├── 200n.svg │ │ ├── 227d.svg │ │ ├── 227n.svg │ │ ├── 230d.svg │ │ ├── 230n.svg │ │ ├── 284d.svg │ │ ├── 284n.svg │ │ ├── 296d.svg │ │ ├── 296n.svg │ │ ├── 305d.svg │ │ ├── 305n.svg │ │ ├── 317d.svg │ │ ├── 317n.svg │ │ ├── 335d.svg │ │ ├── 335n.svg │ │ ├── 350d.svg │ │ ├── 350n.svg │ │ ├── 359d.svg │ │ ├── 359n.svg │ │ ├── 365d.svg │ │ ├── 365n.svg │ │ ├── 377d.svg │ │ ├── 377n.svg │ │ ├── 389d.svg │ │ ├── 389n.svg │ │ ├── 392d.svg │ │ ├── 392n.svg │ │ ├── index.ts │ │ └── unknown.svg │ ├── index.ts │ ├── misc │ │ ├── CLogo.webp │ │ ├── arrow.svg │ │ ├── compass.svg │ │ ├── first-quarter.svg │ │ ├── fullmoon.svg │ │ ├── last-quarter.svg │ │ ├── newmoon.svg │ │ ├── sunrise.svg │ │ ├── sunset.svg │ │ ├── vortex.svg │ │ ├── waning-crescent.svg │ │ ├── waning-gibbous.svg │ │ ├── waxing-crescent.svg │ │ ├── waxing-gibbous.svg │ │ └── wind.svg │ └── mobile │ │ ├── 113d.webp │ │ ├── 113n.webp │ │ ├── 116d.webp │ │ ├── 116n.webp │ │ ├── 119d.webp │ │ ├── 119n.webp │ │ ├── 122d.webp │ │ ├── 122n.webp │ │ ├── 143d.webp │ │ ├── 143n.webp │ │ ├── 176d.webp │ │ ├── 176n.webp │ │ ├── 179d.webp │ │ ├── 179n.webp │ │ ├── 182d.webp │ │ ├── 182n.webp │ │ ├── 185d.webp │ │ ├── 185n.webp │ │ ├── 200d.webp │ │ ├── 200n.webp │ │ ├── 227d.webp │ │ ├── 227n.webp │ │ ├── 230d.webp │ │ ├── 230n.webp │ │ ├── 296d.webp │ │ ├── 296n.webp │ │ ├── 305d.webp │ │ ├── 305n.webp │ │ ├── 350d.webp │ │ ├── 350n.webp │ │ ├── 389d.webp │ │ ├── 389n.webp │ │ ├── 392d.webp │ │ ├── 392n.webp │ │ ├── index.ts │ │ └── unknown.webp ├── components │ ├── BlurCard.astro │ ├── ForecastCard.astro │ ├── Header.astro │ ├── MiscDetails.astro │ ├── Preact │ │ ├── AirQuality.tsx │ │ ├── CoverImage.tsx │ │ ├── ForecastWeather.tsx │ │ ├── Loader.tsx │ │ ├── SearchBar.tsx │ │ ├── TimeInfo.tsx │ │ ├── WeatherChart.tsx │ │ ├── WeatherIcon.tsx │ │ ├── WeatherInfo.tsx │ │ └── WindCard.tsx │ ├── SVG │ │ ├── CloudSVG.tsx │ │ ├── LogoSVG.tsx │ │ └── MapPin.tsx │ ├── TempChart.astro │ └── WeatherCard.astro ├── env.d.ts ├── hooks │ ├── useFetchWeather.ts │ └── useIconCode.ts ├── layouts │ └── Layout.astro ├── pages │ └── index.astro ├── store │ └── weatherStore.ts ├── types │ └── types.d.ts └── utils │ ├── Toaster.tsx │ └── useHorizontalScroll.tsx ├── tailwind.config.cjs └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | 4 | # generated types 5 | .astro/ 6 | 7 | # dependencies 8 | node_modules/ 9 | 10 | # logs 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # environment variables 17 | .env 18 | .env.production 19 | 20 | # macOS-specific files 21 | .DS_Store 22 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["astro-build.astro-vscode"], 3 | "unwantedRecommendations": [] 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "command": "./node_modules/.bin/astro dev", 6 | "name": "Development server", 7 | "request": "launch", 8 | "type": "node-terminal" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 ChiragChrg 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Netlify Status](https://api.netlify.com/api/v1/badges/549e2ddd-1d58-4f2a-89b3-b5e066bb9f0d/deploy-status)](https://app.netlify.com/sites/vortexa/deploys) 2 | ##### Created : 26/08/2023 3 | 4 | # Vortexa - Weather App 5 | Explore comprehensive weather insights and forecasts with Vortexa. Stay informed about current conditions, forecasts, and meteorological data, and gain valuable insights into weather patterns and trends. 6 | 7 | 8 | ### Preview 9 | ![Portfolio Preview](public/Mockup_Preview.png) 10 | 11 | ## Tools and TechStacks used : 12 | 13 |
14 | Astro JS 20 | Preact JS 26 | Typescript 32 | Tailwind CSS 38 | Nanostores 44 | D3 JS 50 | API 56 |
57 | 58 | 59 | ## This is the upgraded version of CliMate weather app 60 | -------------------------------------------------------------------------------- /astro.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'astro/config'; 2 | import preact from "@astrojs/preact"; 3 | import tailwind from "@astrojs/tailwind"; 4 | 5 | // https://astro.build/config 6 | export default defineConfig({ 7 | integrations: [preact(), tailwind()] 8 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vortexa", 3 | "type": "module", 4 | "version": "0.0.1", 5 | "scripts": { 6 | "dev": "astro dev --host", 7 | "start": "astro dev", 8 | "build": "astro build", 9 | "preview": "astro preview", 10 | "astro": "astro" 11 | }, 12 | "dependencies": { 13 | "@astrojs/check": "^0.5.10", 14 | "@astrojs/preact": "^3.1.1", 15 | "@astrojs/tailwind": "^5.1.0", 16 | "@nanostores/preact": "^0.5.1", 17 | "astro": "^4.5.12", 18 | "d3": "^7.9.0", 19 | "luxon": "^3.4.4", 20 | "nanostores": "^0.10.0", 21 | "preact": "^10.20.1", 22 | "sharp": "^0.33.3", 23 | "tailwindcss": "^3.4.3", 24 | "typescript": "^5.4.3" 25 | }, 26 | "devDependencies": { 27 | "@types/d3": "^7.4.3", 28 | "@types/luxon": "^3.4.2" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /public/Mockup_Preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/public/Mockup_Preview.png -------------------------------------------------------------------------------- /public/_redirects.txt: -------------------------------------------------------------------------------- 1 | /* /index.html 200 -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/public/favicon.ico -------------------------------------------------------------------------------- /public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 11 | 14 | 17 | 20 | 23 | 24 | 26 | 27 | 28 | 29 | 31 | 32 | 33 | 34 | 36 | 37 | 38 | 39 | 41 | 42 | 43 | 44 | 46 | 47 | 48 | 49 | 51 | 52 | 53 | 54 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /public/google3b8fb4e0392121a9.html: -------------------------------------------------------------------------------- 1 | google-site-verification: google3b8fb4e0392121a9.html -------------------------------------------------------------------------------- /public/icons/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/public/icons/1024.png -------------------------------------------------------------------------------- /public/icons/144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/public/icons/144.png -------------------------------------------------------------------------------- /public/icons/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/public/icons/180.png -------------------------------------------------------------------------------- /public/icons/192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/public/icons/192.png -------------------------------------------------------------------------------- /public/icons/384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/public/icons/384.png -------------------------------------------------------------------------------- /public/icons/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/public/icons/512.png -------------------------------------------------------------------------------- /public/icons/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/public/icons/64.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Vortexa | Weather Insights", 3 | "short_name": "Vortexa", 4 | "description": "Explore comprehensive weather insights and forecasts with Vortexa. Stay informed about current conditions, forecasts, and meteorological data, and gain valuable insights into weather patterns and trends.", 5 | "theme_color": "#ffffff", 6 | "background_color": "#ffffff", 7 | "start_url": ".", 8 | "id": "/", 9 | "display": "standalone", 10 | "orientation": "portrait", 11 | "dir": "ltr", 12 | "lang": "en", 13 | "display_override": [ 14 | "standalone", 15 | "fullscreen", 16 | "window-controls-overlay" 17 | ], 18 | "categories": [ 19 | "weather", 20 | "information" 21 | ], 22 | "icons": [ 23 | { 24 | "src": "./icons/144.png", 25 | "sizes": "144x144", 26 | "type": "image/png", 27 | "purpose": "any" 28 | }, 29 | { 30 | "src": "./icons/192.png", 31 | "sizes": "192x192", 32 | "type": "image/png", 33 | "purpose": "maskable" 34 | }, 35 | { 36 | "src": "./icons/384.png", 37 | "sizes": "384x384", 38 | "type": "image/png" 39 | }, 40 | { 41 | "src": "./icons/512.png", 42 | "sizes": "512x512", 43 | "type": "image/png" 44 | } 45 | ] 46 | } -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | Sitemap: https://chiragchrg.netlify.app/sitemap.xml -------------------------------------------------------------------------------- /public/serviceWorker.js: -------------------------------------------------------------------------------- 1 | const CacheName = "vortexa-V-1.0"; 2 | const CacheList = [ 3 | "icons/144.png", 4 | ]; 5 | //Installing Service Worker 6 | self.addEventListener("install", event => { 7 | event.waitUntil( 8 | caches.open(CacheName).then((cache) => { 9 | // console.log("Checking Cache"); 10 | return cache.addAll(CacheList); 11 | }) 12 | ); 13 | }); 14 | 15 | //Fetching Service Worker 16 | self.addEventListener("fetch", event => { 17 | event.respondWith( 18 | caches.match(event.request).then((response) => { 19 | if (response) { 20 | return response; 21 | } 22 | return fetch(event.request); 23 | }) 24 | ); 25 | }); 26 | 27 | //Activating Service Worker 28 | self.addEventListener("activate", event => { 29 | event.waitUntil( 30 | caches.keys().then((cacheNames) => { 31 | return Promise.all( 32 | cacheNames.map((cache) => { 33 | if (cache !== CacheName) { 34 | return caches.delete(cache); 35 | } 36 | }) 37 | ); 38 | }) 39 | ); 40 | }); -------------------------------------------------------------------------------- /public/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | https://vortexa.netlify.app/ 5 | 2023-09-13T07:52:19+00:00 6 | 1.00 7 | 8 | -------------------------------------------------------------------------------- /src/assets/desktop/113d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/113d.webp -------------------------------------------------------------------------------- /src/assets/desktop/113n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/113n.webp -------------------------------------------------------------------------------- /src/assets/desktop/116d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/116d.webp -------------------------------------------------------------------------------- /src/assets/desktop/116n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/116n.webp -------------------------------------------------------------------------------- /src/assets/desktop/119d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/119d.webp -------------------------------------------------------------------------------- /src/assets/desktop/119n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/119n.webp -------------------------------------------------------------------------------- /src/assets/desktop/122d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/122d.webp -------------------------------------------------------------------------------- /src/assets/desktop/122n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/122n.webp -------------------------------------------------------------------------------- /src/assets/desktop/143d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/143d.webp -------------------------------------------------------------------------------- /src/assets/desktop/143n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/143n.webp -------------------------------------------------------------------------------- /src/assets/desktop/176d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/176d.webp -------------------------------------------------------------------------------- /src/assets/desktop/176n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/176n.webp -------------------------------------------------------------------------------- /src/assets/desktop/179d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/179d.webp -------------------------------------------------------------------------------- /src/assets/desktop/179n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/179n.webp -------------------------------------------------------------------------------- /src/assets/desktop/182d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/182d.webp -------------------------------------------------------------------------------- /src/assets/desktop/182n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/182n.webp -------------------------------------------------------------------------------- /src/assets/desktop/185d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/185d.webp -------------------------------------------------------------------------------- /src/assets/desktop/185n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/185n.webp -------------------------------------------------------------------------------- /src/assets/desktop/200d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/200d.webp -------------------------------------------------------------------------------- /src/assets/desktop/200n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/200n.webp -------------------------------------------------------------------------------- /src/assets/desktop/227d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/227d.webp -------------------------------------------------------------------------------- /src/assets/desktop/227n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/227n.webp -------------------------------------------------------------------------------- /src/assets/desktop/230d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/230d.webp -------------------------------------------------------------------------------- /src/assets/desktop/230n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/230n.webp -------------------------------------------------------------------------------- /src/assets/desktop/296d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/296d.webp -------------------------------------------------------------------------------- /src/assets/desktop/296n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/296n.webp -------------------------------------------------------------------------------- /src/assets/desktop/305d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/305d.webp -------------------------------------------------------------------------------- /src/assets/desktop/305n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/305n.webp -------------------------------------------------------------------------------- /src/assets/desktop/350d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/350d.webp -------------------------------------------------------------------------------- /src/assets/desktop/350n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/350n.webp -------------------------------------------------------------------------------- /src/assets/desktop/389d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/389d.webp -------------------------------------------------------------------------------- /src/assets/desktop/389n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/389n.webp -------------------------------------------------------------------------------- /src/assets/desktop/392d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/392d.webp -------------------------------------------------------------------------------- /src/assets/desktop/392n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/392n.webp -------------------------------------------------------------------------------- /src/assets/desktop/index.ts: -------------------------------------------------------------------------------- 1 | import type { ImageMetadata } from "astro"; 2 | type WeatherImages = { 3 | [key: string]: ImageMetadata; 4 | }; 5 | 6 | // Desktop Weather Images 7 | import D_113d from "./113d.webp" 8 | import D_113n from "./113n.webp" 9 | 10 | import D_116d from "./116d.webp" 11 | import D_116n from "./116n.webp" 12 | 13 | import D_119d from "./119d.webp" 14 | import D_119n from "./119n.webp" 15 | 16 | import D_122d from "./122d.webp" 17 | import D_122n from "./122n.webp" 18 | 19 | import D_143d from "./143d.webp" 20 | import D_143n from "./143n.webp" 21 | 22 | import D_176d from "./176d.webp" 23 | import D_176n from "./176n.webp" 24 | 25 | import D_179d from "./179d.webp" 26 | import D_179n from "./179n.webp" 27 | 28 | import D_182d from "./182d.webp" 29 | import D_182n from "./182n.webp" 30 | 31 | import D_185d from "./185d.webp" 32 | import D_185n from "./185n.webp" 33 | 34 | import D_200d from "./200d.webp" 35 | import D_200n from "./200n.webp" 36 | 37 | import D_230d from "./230d.webp" 38 | import D_230n from "./230n.webp" 39 | 40 | import D_227d from "./227d.webp" 41 | import D_227n from "./227n.webp" 42 | 43 | import D_296d from "./296d.webp" 44 | import D_296n from "./296n.webp" 45 | 46 | import D_305d from "./305d.webp" 47 | import D_305n from "./305n.webp" 48 | 49 | import D_350d from "./350d.webp" 50 | import D_350n from "./350n.webp" 51 | 52 | import D_389d from "./389d.webp" 53 | import D_389n from "./389n.webp" 54 | 55 | import D_392d from "./392d.webp" 56 | import D_392n from "./392n.webp" 57 | import D_Unknown from "./unknown.webp" 58 | 59 | export const DesktopImg: WeatherImages = { 60 | "113d": D_113d, 61 | "113n": D_113n, 62 | "116d": D_116d, 63 | "116n": D_116n, 64 | "119d": D_119d, 65 | "119n": D_119n, 66 | "122d": D_122d, 67 | "122n": D_122n, 68 | "143d": D_143d, 69 | "143n": D_143n, 70 | "176d": D_176d, 71 | "176n": D_176n, 72 | "179d": D_179d, 73 | "179n": D_179n, 74 | "182d": D_182d, 75 | "182n": D_182n, 76 | "185d": D_185d, 77 | "185n": D_185n, 78 | "200d": D_200d, 79 | "200n": D_200n, 80 | "230d": D_230d, 81 | "230n": D_230n, 82 | "227d": D_227d, 83 | "227n": D_227n, 84 | "284d": D_176d, 85 | "284n": D_176n, 86 | "296d": D_296d, 87 | "296n": D_296n, 88 | "305d": D_305d, 89 | "305n": D_305n, 90 | "317d": D_182d, 91 | "317n": D_182n, 92 | "335d": D_230d, 93 | "335n": D_230n, 94 | "350d": D_350d, 95 | "350n": D_350n, 96 | "359d": D_305d, 97 | "359n": D_305n, 98 | "365d": D_185d, 99 | "365n": D_185n, 100 | "377d": D_350d, 101 | "377n": D_350n, 102 | "389d": D_389d, 103 | "389n": D_389n, 104 | "392d": D_392d, 105 | "392n": D_392n, 106 | "default": D_Unknown, 107 | } -------------------------------------------------------------------------------- /src/assets/desktop/unknown.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/desktop/unknown.webp -------------------------------------------------------------------------------- /src/assets/icons/113d.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/assets/icons/113n.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/assets/icons/116d.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/assets/icons/116n.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/assets/icons/119d.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/assets/icons/119n.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/assets/icons/122dn.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/assets/icons/200d.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/assets/icons/200n.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/assets/icons/305d.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/assets/icons/305n.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/assets/icons/350d.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/assets/icons/350n.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/assets/icons/359d.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/assets/icons/359n.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/assets/icons/377d.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/assets/icons/377n.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/assets/icons/389d.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/assets/icons/389n.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/assets/icons/index.ts: -------------------------------------------------------------------------------- 1 | import type { ImageMetadata } from "astro"; 2 | 3 | type WeatherImages = { 4 | [key: string]: ImageMetadata; 5 | }; 6 | 7 | // Weather Icons 8 | import d113 from "./113d.svg"; 9 | import n113 from "./113n.svg"; 10 | 11 | import d116 from "./116d.svg"; 12 | import n116 from "./116n.svg"; 13 | 14 | import d119 from "./119d.svg"; 15 | import n119 from "./119n.svg"; 16 | 17 | import dn122 from "./122dn.svg"; 18 | 19 | import d143 from "./143d.svg"; 20 | import n143 from "./143n.svg"; 21 | 22 | import d176 from "./176d.svg"; 23 | import n176 from "./176n.svg"; 24 | 25 | import d179 from "./179d.svg"; 26 | import n179 from "./179n.svg"; 27 | 28 | import d182 from "./182d.svg"; 29 | import n182 from "./182n.svg"; 30 | 31 | import d185 from "./185d.svg"; 32 | import n185 from "./185n.svg"; 33 | 34 | import d200 from "./200d.svg"; 35 | import n200 from "./200n.svg"; 36 | 37 | import d227 from "./227d.svg"; 38 | import n227 from "./227n.svg"; 39 | 40 | import d230 from "./230d.svg"; 41 | import n230 from "./230n.svg"; 42 | 43 | import d284 from "./284d.svg"; 44 | import n284 from "./284n.svg"; 45 | 46 | import d296 from "./296d.svg"; 47 | import n296 from "./296n.svg"; 48 | 49 | import d305 from "./305d.svg"; 50 | import n305 from "./305n.svg"; 51 | 52 | import d317 from "./317d.svg"; 53 | import n317 from "./317n.svg"; 54 | 55 | import d335 from "./335d.svg"; 56 | import n335 from "./335n.svg"; 57 | 58 | import d350 from "./350d.svg"; 59 | import n350 from "./350n.svg"; 60 | 61 | import d359 from "./359d.svg"; 62 | import n359 from "./359n.svg"; 63 | 64 | import d365 from "./365d.svg"; 65 | import n365 from "./365n.svg"; 66 | 67 | import d377 from "./377d.svg"; 68 | import n377 from "./377n.svg"; 69 | 70 | import d389 from "./389d.svg"; 71 | import n389 from "./389n.svg"; 72 | 73 | import d392 from "./392d.svg"; 74 | import n392 from "./392n.svg"; 75 | 76 | import Unknown from "./unknown.svg"; 77 | 78 | export const WeatherIcons: WeatherImages = { 79 | "113d": d113, 80 | "113n": n113, 81 | "116d": d116, 82 | "116n": n116, 83 | "119d": d119, 84 | "119n": n119, 85 | "122d": dn122, 86 | "122n": dn122, 87 | "143d": d143, 88 | "143n": n143, 89 | "176d": d176, 90 | "176n": n176, 91 | "179d": d179, 92 | "179n": n179, 93 | "182d": d182, 94 | "182n": n182, 95 | "185d": d185, 96 | "185n": n185, 97 | "200d": d200, 98 | "200n": n200, 99 | "227d": d227, 100 | "227n": n227, 101 | "230d": d230, 102 | "230n": n230, 103 | "284d": d284, 104 | "284n": n284, 105 | "296d": d296, 106 | "296n": n296, 107 | "305d": d305, 108 | "305n": n305, 109 | "317d": d317, 110 | "317n": n317, 111 | "335d": d335, 112 | "335n": n335, 113 | "350d": d350, 114 | "350n": n350, 115 | "359d": d359, 116 | "359n": n359, 117 | "365d": d365, 118 | "365n": n365, 119 | "377d": d377, 120 | "377n": n377, 121 | "389d": d389, 122 | "389n": n389, 123 | "392d": d392, 124 | "392n": n392, 125 | "default": Unknown, 126 | }; 127 | -------------------------------------------------------------------------------- /src/assets/icons/unknown.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /src/assets/index.ts: -------------------------------------------------------------------------------- 1 | import type { ImageMetadata } from "astro"; 2 | type WeatherImages = { 3 | [key: string]: ImageMetadata; 4 | }; 5 | 6 | // Misc Icons 7 | export { default as CLogo } from "./misc/CLogo.webp" 8 | export { default as VortexSVG } from "./misc/vortex.svg" 9 | export { default as SunriseSVG } from "./misc/sunrise.svg" 10 | export { default as SunsetSVG } from "./misc/sunset.svg" 11 | export { default as ArrowSVG } from "./misc/arrow.svg" 12 | export { default as CompassSVG } from "./misc/compass.svg" 13 | export { default as WindSVG } from "./misc/wind.svg" 14 | 15 | // Moon Phase Icons 16 | import FullMoonSVG from "./misc/fullmoon.svg" 17 | import NewMoonSVG from "./misc/newmoon.svg" 18 | import FirstQuarterSVG from "./misc/first-quarter.svg" 19 | import LastQuarterSVG from "./misc/last-quarter.svg" 20 | import WanCrescentSVG from "./misc/waning-crescent.svg" 21 | import WanGibbousSVG from "./misc/waning-gibbous.svg" 22 | import WaxCrescentSVG from "./misc/waxing-crescent.svg" 23 | import WaxGibbousSVG from "./misc/waxing-gibbous.svg" 24 | 25 | export const MoonIcons: WeatherImages = { 26 | "Full_Moon": FullMoonSVG, 27 | "New_Moon": NewMoonSVG, 28 | "First_Quarter": FirstQuarterSVG, 29 | "Last_Quarter": LastQuarterSVG, 30 | "Waning_Crescent": WanCrescentSVG, 31 | "Waning_Gibbous": WanGibbousSVG, 32 | "Waxing_Crescent": WaxCrescentSVG, 33 | "Waxing_Gibbous": WaxGibbousSVG, 34 | } -------------------------------------------------------------------------------- /src/assets/misc/CLogo.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/misc/CLogo.webp -------------------------------------------------------------------------------- /src/assets/misc/arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/assets/misc/compass.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 7 | 10 | 13 | 16 | -------------------------------------------------------------------------------- /src/assets/misc/first-quarter.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /src/assets/misc/fullmoon.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /src/assets/misc/last-quarter.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /src/assets/misc/newmoon.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /src/assets/misc/sunrise.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | -------------------------------------------------------------------------------- /src/assets/misc/sunset.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /src/assets/misc/vortex.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 11 | 14 | 17 | 20 | 23 | 24 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/assets/misc/waning-crescent.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /src/assets/misc/waning-gibbous.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /src/assets/misc/waxing-crescent.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /src/assets/misc/waxing-gibbous.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /src/assets/misc/wind.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /src/assets/mobile/113d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/113d.webp -------------------------------------------------------------------------------- /src/assets/mobile/113n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/113n.webp -------------------------------------------------------------------------------- /src/assets/mobile/116d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/116d.webp -------------------------------------------------------------------------------- /src/assets/mobile/116n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/116n.webp -------------------------------------------------------------------------------- /src/assets/mobile/119d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/119d.webp -------------------------------------------------------------------------------- /src/assets/mobile/119n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/119n.webp -------------------------------------------------------------------------------- /src/assets/mobile/122d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/122d.webp -------------------------------------------------------------------------------- /src/assets/mobile/122n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/122n.webp -------------------------------------------------------------------------------- /src/assets/mobile/143d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/143d.webp -------------------------------------------------------------------------------- /src/assets/mobile/143n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/143n.webp -------------------------------------------------------------------------------- /src/assets/mobile/176d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/176d.webp -------------------------------------------------------------------------------- /src/assets/mobile/176n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/176n.webp -------------------------------------------------------------------------------- /src/assets/mobile/179d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/179d.webp -------------------------------------------------------------------------------- /src/assets/mobile/179n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/179n.webp -------------------------------------------------------------------------------- /src/assets/mobile/182d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/182d.webp -------------------------------------------------------------------------------- /src/assets/mobile/182n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/182n.webp -------------------------------------------------------------------------------- /src/assets/mobile/185d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/185d.webp -------------------------------------------------------------------------------- /src/assets/mobile/185n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/185n.webp -------------------------------------------------------------------------------- /src/assets/mobile/200d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/200d.webp -------------------------------------------------------------------------------- /src/assets/mobile/200n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/200n.webp -------------------------------------------------------------------------------- /src/assets/mobile/227d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/227d.webp -------------------------------------------------------------------------------- /src/assets/mobile/227n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/227n.webp -------------------------------------------------------------------------------- /src/assets/mobile/230d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/230d.webp -------------------------------------------------------------------------------- /src/assets/mobile/230n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/230n.webp -------------------------------------------------------------------------------- /src/assets/mobile/296d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/296d.webp -------------------------------------------------------------------------------- /src/assets/mobile/296n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/296n.webp -------------------------------------------------------------------------------- /src/assets/mobile/305d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/305d.webp -------------------------------------------------------------------------------- /src/assets/mobile/305n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/305n.webp -------------------------------------------------------------------------------- /src/assets/mobile/350d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/350d.webp -------------------------------------------------------------------------------- /src/assets/mobile/350n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/350n.webp -------------------------------------------------------------------------------- /src/assets/mobile/389d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/389d.webp -------------------------------------------------------------------------------- /src/assets/mobile/389n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/389n.webp -------------------------------------------------------------------------------- /src/assets/mobile/392d.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/392d.webp -------------------------------------------------------------------------------- /src/assets/mobile/392n.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/392n.webp -------------------------------------------------------------------------------- /src/assets/mobile/index.ts: -------------------------------------------------------------------------------- 1 | import type { ImageMetadata } from "astro"; 2 | type WeatherImages = { 3 | [key: string]: ImageMetadata; 4 | }; 5 | 6 | // Mobile Weather Images 7 | import M_113d from "./113d.webp" 8 | import M_113n from "./113n.webp" 9 | 10 | import M_116d from "./116d.webp" 11 | import M_116n from "./116n.webp" 12 | 13 | import M_119d from "./119d.webp" 14 | import M_119n from "./119n.webp" 15 | 16 | import M_122d from "./122d.webp" 17 | import M_122n from "./122n.webp" 18 | 19 | import M_143d from "./143d.webp" 20 | import M_143n from "./143n.webp" 21 | 22 | import M_176d from "./176d.webp" 23 | import M_176n from "./176n.webp" 24 | 25 | import M_179d from "./179d.webp" 26 | import M_179n from "./179n.webp" 27 | 28 | import M_182d from "./182d.webp" 29 | import M_182n from "./182n.webp" 30 | 31 | import M_185d from "./185d.webp" 32 | import M_185n from "./185n.webp" 33 | 34 | import M_200d from "./200d.webp" 35 | import M_200n from "./200n.webp" 36 | 37 | import M_230d from "./230d.webp" 38 | import M_230n from "./230n.webp" 39 | 40 | import M_227d from "./227d.webp" 41 | import M_227n from "./227n.webp" 42 | 43 | import M_296d from "./296d.webp" 44 | import M_296n from "./296n.webp" 45 | 46 | import M_305d from "./305d.webp" 47 | import M_305n from "./305n.webp" 48 | 49 | import M_350d from "./350d.webp" 50 | import M_350n from "./350n.webp" 51 | 52 | import M_389d from "./389d.webp" 53 | import M_389n from "./389n.webp" 54 | 55 | import M_392d from "./392d.webp" 56 | import M_392n from "./392n.webp" 57 | import M_Unknown from "./unknown.webp" 58 | 59 | export const MobileImg: WeatherImages = { 60 | "113d": M_113d, 61 | "113n": M_113n, 62 | "116d": M_116d, 63 | "116n": M_116n, 64 | "119d": M_119d, 65 | "119n": M_119n, 66 | "122d": M_122d, 67 | "122n": M_122n, 68 | "143d": M_143d, 69 | "143n": M_143n, 70 | "176d": M_176d, 71 | "176n": M_176n, 72 | "179d": M_179d, 73 | "179n": M_179n, 74 | "182d": M_182d, 75 | "182n": M_182n, 76 | "185d": M_185d, 77 | "185n": M_185n, 78 | "200d": M_200d, 79 | "200n": M_200n, 80 | "230d": M_230d, 81 | "230n": M_230n, 82 | "227d": M_227d, 83 | "227n": M_227n, 84 | "284d": M_176d, 85 | "284n": M_176n, 86 | "296d": M_296d, 87 | "296n": M_296n, 88 | "305d": M_305d, 89 | "305n": M_305n, 90 | "317d": M_182d, 91 | "317n": M_182n, 92 | "335d": M_230d, 93 | "335n": M_230n, 94 | "350d": M_350d, 95 | "350n": M_350n, 96 | "359d": M_305d, 97 | "359n": M_305n, 98 | "365d": M_185d, 99 | "365n": M_185n, 100 | "377d": M_350d, 101 | "377n": M_350n, 102 | "389d": M_389d, 103 | "389n": M_389n, 104 | "392d": M_392d, 105 | "392n": M_392n, 106 | "default": M_Unknown, 107 | } -------------------------------------------------------------------------------- /src/assets/mobile/unknown.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tigercoder0218/Weather-Observation-App/17ee8a3d8c76111d2ac7f9a863d5e8acdf32cf0c/src/assets/mobile/unknown.webp -------------------------------------------------------------------------------- /src/components/BlurCard.astro: -------------------------------------------------------------------------------- 1 | --- 2 | const { className = "" } = Astro.props; 3 | --- 4 | 5 |
6 | 7 |
8 | -------------------------------------------------------------------------------- /src/components/ForecastCard.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import BlurCard from "./BlurCard.astro"; 3 | import ForecastWeather from "./Preact/ForecastWeather"; 4 | --- 5 | 6 |
7 | 8 | 9 | 10 |
11 | -------------------------------------------------------------------------------- /src/components/Header.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Image } from "astro:assets"; 3 | import { VortexSVG } from "../assets"; 4 | import SearchBar from "./Preact/SearchBar"; 5 | --- 6 | 7 |
10 |
11 | Vortexa_Logo 18 | 19 |

20 | VORTEXA 21 |

22 |
23 | 24 | 25 | 26 | 51 |
52 | 53 | 58 | -------------------------------------------------------------------------------- /src/components/MiscDetails.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import BlurCard from "./BlurCard.astro"; 3 | import { SunChart, TimeCard } from "./Preact/TimeInfo"; 4 | import { MiscInfo } from "./Preact/WeatherInfo"; 5 | import WindCard from "./Preact/WindCard"; 6 | import AirQuality from "./Preact/AirQuality"; 7 | --- 8 | 9 |
10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
31 | -------------------------------------------------------------------------------- /src/components/Preact/AirQuality.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "preact/hooks" 2 | import { useStore } from '@nanostores/preact' 3 | import { weather } from '../../store/weatherStore' 4 | 5 | const AirQuality = () => { 6 | const $weather = useStore(weather) 7 | const [aqi, setAqi] = useState(0) 8 | 9 | const getColorCode = (value: number) => { 10 | if (value <= 50) { 11 | return "#00E400" //green 12 | } else if (value <= 100) { 13 | return "#FFFF00" //yellow 14 | } else if (value <= 150) { 15 | return "#FF7E00" //orange 16 | } else if (value <= 200) { 17 | return "#FF0000" //red 18 | } else if (value <= 300) { 19 | return "#8B008B" //purple 20 | } else { 21 | return "#800000" //maroon 22 | } 23 | } 24 | 25 | const getAirQuality = (value: number) => { 26 | if (value <= 50) { 27 | return "Good" 28 | } else if (value <= 100) { 29 | return "Moderate" 30 | } else if (value <= 150) { 31 | return "Caution" 32 | } else if (value <= 200) { 33 | return "Unhealthy" 34 | } else if (value <= 300) { 35 | return "Very unhealthy" 36 | } else { 37 | return "Hazardous" 38 | } 39 | } 40 | 41 | const getAirQualityMessage = (value: number) => { 42 | if (value <= 50) { 43 | return "Perfect day for a Walk."; 44 | } else if (value <= 100) { 45 | return "Enjoy the outdoors!"; 46 | } else if (value <= 150) { 47 | return "Consider limiting outdoor time."; 48 | } else if (value <= 200) { 49 | return "Avoid strenuous work."; 50 | } else if (value <= 300) { 51 | return "Stay indoors, close windows"; 52 | } else { 53 | return "Stay indoors, use purifiers."; 54 | } 55 | } 56 | 57 | useEffect(() => { 58 | if (!$weather) return 59 | 60 | const pollutants = Object.entries($weather?.current?.air_quality).map(obj => { 61 | if (obj[0] == "co") { 62 | // this API gives co values in 3 digit number so reducing to 2 digit 63 | return obj[1] / 10 64 | } else { 65 | return obj[1] 66 | } 67 | }) 68 | const HighestPollutant = pollutants.reduce((acc, curr) => { 69 | return Math.max(acc, curr) 70 | }, 0) 71 | 72 | setAqi(HighestPollutant) 73 | }, [$weather]) 74 | 75 | return ( 76 |
77 |
78 | 87 | 88 | 89 | Air Quality Index 90 |
91 | 92 |
93 |
94 | {aqi.toFixed()} 95 | 96 |
97 | {getAirQuality(aqi)} 98 |

{getAirQualityMessage(aqi)}

99 |
100 |
101 | 102 |
103 |
104 | 105 | {$weather?.current?.air_quality?.pm2_5} 106 | 107 | PM2.5 108 |
109 | 110 |
111 | 112 | {$weather?.current?.air_quality?.pm10} 113 | 114 | PM10 115 |
116 |
117 | 118 | {$weather?.current?.air_quality?.so2} 119 | 120 | SO2 121 |
122 |
123 | 124 | {$weather?.current?.air_quality?.no2} 125 | 126 | NO2 127 |
128 |
129 | 130 | {$weather?.current?.air_quality?.o3} 131 | 132 | O3 133 |
134 |
135 | 136 | {($weather?.current?.air_quality?.co ? ($weather?.current?.air_quality?.co / 10).toFixed() : '0')} 137 | 138 | CO 139 |
140 |
141 |
142 |
143 | ) 144 | } 145 | 146 | export default AirQuality -------------------------------------------------------------------------------- /src/components/Preact/CoverImage.tsx: -------------------------------------------------------------------------------- 1 | import { imageCode } from "../../store/weatherStore"; 2 | import { DesktopImg } from "../../assets/desktop"; 3 | import { MobileImg } from "../../assets/mobile"; 4 | import { useStore } from "@nanostores/preact" 5 | import { useEffect, useState } from "preact/hooks"; 6 | 7 | type Props = { 8 | background?: boolean 9 | } 10 | 11 | const CoverImage = ({ background = false }: Props) => { 12 | const $imageCode = useStore(imageCode) 13 | const isClient = typeof window !== 'undefined'; 14 | const [isMobile, setIsMobile] = useState(false) 15 | 16 | useEffect(() => { 17 | if (typeof document !== 'undefined') 18 | setIsMobile(document?.documentElement?.clientWidth <= 850) 19 | }, []) 20 | 21 | 22 | if (isClient && $imageCode !== null) 23 | return ( 24 |
28 | { 29 | isMobile ? BG_Img 35 | : 36 | BG_Img 42 | } 43 |
44 | ) 45 | } 46 | 47 | export default CoverImage -------------------------------------------------------------------------------- /src/components/Preact/ForecastWeather.tsx: -------------------------------------------------------------------------------- 1 | import { useStore } from '@nanostores/preact' 2 | import { imperialUnit, weather } from '../../store/weatherStore' 3 | import { WeatherIcons } from '../../assets/icons' 4 | import { getIconCode } from '../../hooks/useIconCode' 5 | import { DateTime } from 'luxon'; 6 | 7 | const ForecastWeather = () => { 8 | const $forecast = useStore(weather) || null 9 | const isClient = typeof window !== 'undefined'; 10 | const $imperialUnit = useStore(imperialUnit) 11 | 12 | if (isClient && $forecast !== null) 13 | return ( 14 |
15 |
16 | 17 | 18 | 19 | 2 Days Forecast 20 |
21 | 22 |
23 | {$forecast?.forecast?.forecastday?.map((obj, index) => { 24 | const code = obj?.day?.condition?.code 25 | const iconCode = getIconCode(code) 26 | 27 | if (index !== 0) 28 | return
29 |
30 | {index == 1 ? "Tomorrow" : "Overmorrow"} 31 | {DateTime.fromFormat(`${obj.date}`, 'yyyy-MM-dd')?.toFormat('dd LLL yyyy')} 32 |
33 | 34 |
35 |
36 | Weather_Icon 41 | 42 |
43 | Avg Temp 44 |
45 | 46 | {$imperialUnit ? obj?.day?.avgtemp_f.toFixed() : obj?.day?.avgtemp_c.toFixed()} 47 | 48 | °{$imperialUnit ? "F" : "C"} 49 |
50 |
51 |
52 | 53 |
54 |
55 | Humidity 56 | {obj?.day?.avghumidity}% 57 |
58 |
59 | Chance of Rain 60 | {obj?.day?.daily_chance_of_rain}% 61 |
62 |
63 | Sunrise 64 | {obj?.astro?.sunrise} 65 |
66 |
67 | Sunset 68 | {obj?.astro?.sunset} 69 |
70 |
71 |
72 |
73 | } 74 | )} 75 |
76 |
77 | ) 78 | } 79 | 80 | export default ForecastWeather -------------------------------------------------------------------------------- /src/components/Preact/Loader.tsx: -------------------------------------------------------------------------------- 1 | import { useStore } from '@nanostores/preact' 2 | import { useEffect, useState } from 'preact/hooks' 3 | import { imageCode } from '../../store/weatherStore' 4 | import CloudSVG from '../SVG/CloudSVG' 5 | import LogoSVG from '../SVG/LogoSVG' 6 | import { DesktopImg } from "../../assets/desktop"; 7 | import { MobileImg } from "../../assets/mobile"; 8 | 9 | type ColorType = { 10 | [key: string]: string 11 | } 12 | 13 | const Loader = () => { 14 | const [isLoading, setIsLoading] = useState(true) 15 | const $imageCode = useStore(imageCode) 16 | 17 | const D_Colors: ColorType = { 18 | "113d": "#0875f6", 19 | "113n": "#072b63", 20 | "116d": "#027cf5", 21 | "116n": "#061643", 22 | "119d": "#0953e9", 23 | "119n": "#08194c", 24 | "122d": "#0442ae", 25 | "122n": "#041448", 26 | "143d": "#24a7f1", 27 | "143n": "#113749", 28 | "176d": "#2a3e52", 29 | "176n": "#091423", 30 | "179d": "#7ea1c7", 31 | "179n": "#1a2236", 32 | "182d": "#28609d", 33 | "182n": "#081830", 34 | "185d": "#253e5d", 35 | "185n": "#081e32", 36 | "200d": "#0c1b41", 37 | "200n": "#172450", 38 | "230d": "#5e7a95", 39 | "230n": "#0a1b33", 40 | "277d": "#0d317b", 41 | "277n": "#012771", 42 | "284d": "#5e7a95", 43 | "284n": "#0a1b33", 44 | "296d": "#c9dcdc", 45 | "296n": "#0d223b", 46 | "305d": "#c5edd6", 47 | "305n": "#0e2745", 48 | "317d": "#28609d", 49 | "317n": "#081830", 50 | "335d": "#5e7a95", 51 | "335n": "#0a1b33", 52 | "350d": "#4975a8", 53 | "350n": "#051643", 54 | "359d": "#c5edd6", 55 | "359n": "#0e2745", 56 | "365d": "#253e5d", 57 | "365n": "#081e32", 58 | "377d": "#4975a8", 59 | "377n": "#051643", 60 | "389d": "#172939", 61 | "389n": "#101c28", 62 | "392d": "#2e4974", 63 | "392n": "#09326b", 64 | "default": "#5488EE", 65 | } 66 | 67 | const M_Colors: ColorType = { 68 | "113d": "#0253f0", 69 | "113n": "#031649", 70 | "116d": "#0146e9", 71 | "116n": "#041538", 72 | "119d": "#0650b0", 73 | "119n": "#0c0e3d", 74 | "122d": "#103785", 75 | "122n": "#020b44", 76 | "143d": "#3492e0", 77 | "143n": "#0d2e41", 78 | "176d": "#2a3e5e", 79 | "176n": "#021933", 80 | "179d": "#87a6c8", 81 | "179n": "#11335c", 82 | "182d": "#174fa5", 83 | "182n": "#081736", 84 | "185d": "#293c55", 85 | "185n": "#0c182f", 86 | "200d": "#1c2b5f", 87 | "200n": "#112552", 88 | "230d": "#888ea0", 89 | "230n": "#05192b", 90 | "277d": "#14378d", 91 | "277n": "#040b22", 92 | "296d": "#aaaeb4", 93 | "296n": "#051728", 94 | "284d": "#2a3e5e", 95 | "284n": "#021933", 96 | "305d": "#cbdbdc", 97 | "305n": "#031d32", 98 | "317d": "#174fa5", 99 | "317n": "#081736", 100 | "335d": "#888ea0", 101 | "335n": "#05192b", 102 | "350d": "#7c9bc8", 103 | "350n": "#000e29", 104 | "359d": "#cbdbdc", 105 | "359n": "#031d32", 106 | "365d": "#293c55", 107 | "365n": "#0c182f", 108 | "377d": "#7c9bc8", 109 | "377n": "#000e29", 110 | "389d": "#030f1b", 111 | "389n": "#0f2035", 112 | "392d": "#112351", 113 | "392n": "#040d2a", 114 | "default": "#5488EE", 115 | } 116 | 117 | useEffect(() => { 118 | if (isLoading && $imageCode !== null) { 119 | setTimeout(() => { 120 | setIsLoading(false) 121 | document.body.style.overflowY = "visible" 122 | }, 1000) 123 | } 124 | 125 | if (!isLoading && document?.documentElement?.clientWidth <= 640) { 126 | // Mobile Image Colors Avg 127 | setTimeout(() => { 128 | document.documentElement.style.setProperty("--baseClr", M_Colors[$imageCode || "default"]) 129 | document.querySelector("meta[name='theme-color']")?.setAttribute("content", M_Colors[$imageCode || "default"]); 130 | }, 1000) 131 | } else { 132 | // Desktop Image Colors Avg 133 | setTimeout(() => { 134 | document.documentElement.style.setProperty("--baseClr", D_Colors[$imageCode || "default"]) 135 | document.querySelector("meta[name='theme-color']")?.setAttribute("content", D_Colors[$imageCode || "default"]); 136 | }, 1000) 137 | } 138 | }, [$imageCode, isLoading]) 139 | 140 | return ( 141 |
144 |
145 | Loader_BG_Img 150 | Loader_BG_Img 155 |
156 | 157 |
158 | 159 | 160 | 161 |
162 | 163 |
164 |

VORTEXA

165 | Loading... 166 |
167 |
168 | ) 169 | } 170 | 171 | export default Loader 172 | 173 | -------------------------------------------------------------------------------- /src/components/Preact/SearchBar.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, useRef } from 'preact/hooks' 2 | import { FetchWeatherQuery, FetchWeatherPosition } from '../../hooks/useFetchWeather'; 3 | import MapPin from '../SVG/MapPin'; 4 | import { toastData, weather } from '../../store/weatherStore'; 5 | import { useIconCode } from '../../hooks/useIconCode'; 6 | 7 | 8 | const SearchBar = () => { 9 | const [query, setQuery] = useState("mangalore") 10 | const SearchRef = useRef(null) 11 | 12 | const HandleSearch = async (e?: Event) => { 13 | e?.preventDefault() 14 | if (!query) return 15 | 16 | const data = await FetchWeatherQuery(query); 17 | // console.log("DOTAAA", data); 18 | if (data) { 19 | weather.set(data) 20 | useIconCode() 21 | SearchRef.current?.blur() 22 | } 23 | }; 24 | 25 | const setPosition = async (position: any) => { 26 | const pos = { 27 | latitude: position.coords.latitude.toString(), 28 | longitude: position.coords.longitude.toString() 29 | } 30 | 31 | try { 32 | const data = await FetchWeatherPosition(pos); 33 | weather.set(data) 34 | useIconCode() 35 | } catch (error) { 36 | console.log(error) 37 | } 38 | } 39 | 40 | const handleError = (error: any) => { 41 | console.log("Error:", error); 42 | switch (error.code) { 43 | case error.PERMISSION_DENIED: 44 | toastData.set({ 45 | status: "error", 46 | message: error.message 47 | }) 48 | break; 49 | case error.POSITION_UNAVAILABLE: 50 | toastData.set({ 51 | status: "error", 52 | message: error.message 53 | }) 54 | break; 55 | case error.TIMEOUT: 56 | toastData.set({ 57 | status: "error", 58 | message: error.message 59 | }) 60 | break; 61 | default: 62 | toastData.set({ 63 | status: "error", 64 | message: error.message 65 | }) 66 | } 67 | 68 | // If geolocation access is denied, fetch results for "mangalore" by default 69 | if (query == "") setQuery("Mangalore") 70 | HandleSearch() 71 | } 72 | 73 | const HandleGeoLocation = async () => { 74 | if (SearchRef.current?.value) { 75 | //Reset Searchbar value on geolocation btn click 76 | SearchRef.current.value = "" 77 | } 78 | 79 | if ("geolocation" in navigator) { 80 | navigator.geolocation.getCurrentPosition( 81 | setPosition, handleError, 82 | { enableHighAccuracy: true, maximumAge: 10000 }) 83 | } else { 84 | console.log("No GeoLocation Support") 85 | toastData.set({ 86 | status: "error", 87 | message: "No GeoLocation Support" 88 | }) 89 | } 90 | }; 91 | 92 | useEffect(() => { 93 | //Get User Location automatically onLoad 94 | // HandleGeoLocation() 95 | 96 | // Initial Fetch 97 | if (query == "") setQuery("Mangalore") 98 | HandleSearch() 99 | }, []) 100 | 101 | return ( 102 |
103 |
104 | setQuery(e.currentTarget.value)} 108 | className="w-full h-[35px] px-4 rounded border-none outline-none text-black" 109 | placeholder="Search City" 110 | ref={SearchRef} 111 | /> 112 |
113 | 114 | 117 |
118 | ) 119 | } 120 | 121 | export default SearchBar -------------------------------------------------------------------------------- /src/components/Preact/WeatherIcon.tsx: -------------------------------------------------------------------------------- 1 | import { useStore } from "@nanostores/preact"; 2 | import { WeatherIcons } from "../../assets/icons"; 3 | import { imageCode, imperialUnit, weather } from "../../store/weatherStore"; 4 | 5 | const WeatherIcon = () => { 6 | const $imageCode = useStore(imageCode) || null 7 | const $weather = useStore(weather) 8 | const $imperialUnit = useStore(imperialUnit) 9 | const isClient = typeof window !== 'undefined'; 10 | 11 | if (isClient && $weather) 12 | return ( 13 |
14 |
15 | Weather_Icon 20 | 21 | {$weather?.current?.condition?.text?.replaceAll("possible", "")} 22 |
23 | 24 | 31 |
32 | ) 33 | } 34 | 35 | export default WeatherIcon -------------------------------------------------------------------------------- /src/components/Preact/WindCard.tsx: -------------------------------------------------------------------------------- 1 | import { Fragment } from 'preact' 2 | import { useMemo } from 'preact/hooks' 3 | import { useStore } from '@nanostores/preact' 4 | import { imperialUnit, weather } from '../../store/weatherStore' 5 | import { ArrowSVG, CompassSVG, WindSVG } from '../../assets' 6 | 7 | const WindCard = () => { 8 | const $weather = useStore(weather) || null 9 | const $imperialUnit = useStore(imperialUnit) 10 | const isClient = typeof window !== 'undefined'; 11 | 12 | const windSpeed = useMemo(() => { 13 | if (!isClient) return; 14 | 15 | const minWind = $imperialUnit ? $weather?.current?.wind_mph : $weather?.current?.wind_kph 16 | // const maxWind = $imperialUnit ? $weather?.current?.gust_mph : $weather?.current?.gust_kph 17 | 18 | // return `${minWind}/${maxWind}` 19 | return minWind 20 | }, [$imperialUnit, $weather]) 21 | 22 | const windDir: { [key: string]: string } = { 23 | N: "North", 24 | S: "South", 25 | E: "East", 26 | W: "West", 27 | NE: "North-East", 28 | NW: "North-West", 29 | SE: "South-East", 30 | SW: "South-West", 31 | NNE: "North #(North-East)", 32 | NNW: "North #(North-West)", 33 | SSE: "South #(South-East)", 34 | SSW: "South #(South-West)", 35 | ENE: "East #(North-East)", 36 | ESE: "East #(South-East)", 37 | WNW: "West #(North-West)", 38 | WSW: "West #(South-West)", 39 | } // "#" is just used as a split() identifier 40 | 41 | if (isClient && $weather) 42 | return ( 43 |
44 |
45 | Compass_Icon 46 | Arrow_Icon 53 |
54 | 55 |
56 |
57 | WindSVG 58 |
59 | {windSpeed?.toFixed()} 60 | {$imperialUnit ? " mph" : " km/h"} 61 |
62 |
63 |
64 | Wind direction : 65 | 66 | {windDir[$weather?.current?.wind_dir || "N"].split("#")?.map((dir, index) => ( 67 | // If Wind direction has 2 words, break it into next line for mobile view 68 | 69 | {index > 0 &&
} 70 | {dir} 71 |
72 | ))} 73 |
74 | {/* 75 | {windDir[$weather?.current?.wind_dir || "N"].replace("#", "")} 76 | */} 77 |
78 |
79 |
80 | ) 81 | } 82 | 83 | export default WindCard -------------------------------------------------------------------------------- /src/components/SVG/CloudSVG.tsx: -------------------------------------------------------------------------------- 1 | type Props = { 2 | width?: string, 3 | height?: string, 4 | className?: string, 5 | } 6 | 7 | const CloudSVG = ({ width = "169", height = "120", className = "" }: Props) => { 8 | return ( 9 | 16 | 22 | 23 | 31 | 32 | 33 | 34 | 42 | 43 | 44 | 45 | 46 | 47 | ) 48 | } 49 | 50 | export default CloudSVG -------------------------------------------------------------------------------- /src/components/SVG/LogoSVG.tsx: -------------------------------------------------------------------------------- 1 | type Props = { 2 | size?: string, 3 | className?: string, 4 | } 5 | 6 | const LogoSVG = ({ size = "50px", className = "" }: Props) => { 7 | return ( 8 | 15 | 19 | 23 | 27 | 31 | 35 | 39 | 43 | 44 | 52 | 53 | 54 | 55 | 56 | 57 | ) 58 | } 59 | 60 | export default LogoSVG -------------------------------------------------------------------------------- /src/components/SVG/MapPin.tsx: -------------------------------------------------------------------------------- 1 | type Props = { 2 | width?: string, 3 | height?: string, 4 | className?: string, 5 | } 6 | 7 | const MapPin = ({ width = "50px", height = "50px", className = "" }: Props) => { 8 | return ( 9 | 13 | 14 | 15 | 16 | 17 | ) 18 | } 19 | 20 | export default MapPin -------------------------------------------------------------------------------- /src/components/TempChart.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import BlurCard from "./BlurCard.astro"; 3 | import WeatherChart from "./Preact/WeatherChart"; 4 | --- 5 | 6 |
7 | 8 | 9 | 10 |
11 | -------------------------------------------------------------------------------- /src/components/WeatherCard.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { WeatherMainInfo, TempDetails } from "./Preact/WeatherInfo"; 3 | import WeatherIcon from "./Preact/WeatherIcon"; 4 | import CoverImage from "./Preact/CoverImage"; 5 | --- 6 | 7 |
10 |
11 | 12 | 13 |
14 | 15 | 16 |
17 |
18 | 19 | 20 |
21 | -------------------------------------------------------------------------------- /src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/hooks/useFetchWeather.ts: -------------------------------------------------------------------------------- 1 | import { toastData } from "../store/weatherStore" 2 | 3 | interface LocationType { 4 | latitude: string, 5 | longitude: string, 6 | } 7 | 8 | const API_KEY = import.meta.env.PUBLIC_API_KEY as string 9 | const BASE_URL = `https://api.weatherapi.com/v1/forecast.json` 10 | 11 | export const FetchWeatherQuery = async (query: string) => { 12 | const URL_Params = new URLSearchParams({ 13 | key: API_KEY, 14 | q: query, 15 | days: "3", 16 | aqi: "yes", 17 | alerts: "no" 18 | }) 19 | 20 | try { 21 | const res = await fetch(`${BASE_URL}?${URL_Params.toString()}`) 22 | const data = await res.json() 23 | // console.log("Fetch:", data) 24 | 25 | if (!data.error) { 26 | return data 27 | } else { 28 | toastData.set({ 29 | status: "error", 30 | message: "Invalid City name!" 31 | }) 32 | throw new Error("Invalid City name!"); 33 | } 34 | } catch (err) { 35 | console.log("ERROR:", err) 36 | } 37 | } 38 | 39 | export const FetchWeatherPosition = async (pos: LocationType) => { 40 | const URL_Params = new URLSearchParams({ 41 | key: API_KEY, 42 | q: `${pos.latitude},${pos.longitude}`, 43 | days: "3", 44 | aqi: "yes", 45 | alerts: "no" 46 | }) 47 | 48 | try { 49 | const res = await fetch(`${BASE_URL}?${URL_Params.toString()}`) 50 | const data = await res.json() 51 | // console.log("GEO:", data) 52 | 53 | if (!data.error) { 54 | return data 55 | } else { 56 | toastData.set({ 57 | status: "error", 58 | message: "Invalid Position coordinates!" 59 | }) 60 | throw new Error("Invalid Position coordinates!"); 61 | } 62 | } catch (err) { 63 | console.log("ERROR:", err) 64 | } 65 | } -------------------------------------------------------------------------------- /src/hooks/useIconCode.ts: -------------------------------------------------------------------------------- 1 | import { imageCode } from "../store/weatherStore"; 2 | import { weather } from "../store/weatherStore"; 3 | 4 | interface IconMappingType { 5 | [key: string]: string 6 | } 7 | 1240 8 | const IconMapping: IconMappingType = { 9 | "1000": "113", 10 | "1003": "116", 11 | "1006": "119", 12 | "1009": "122", 13 | "1030": "143", 14 | "1135": "143", 15 | "1147": "143", 16 | "1063": "176", 17 | "1180": "176", 18 | "1186": "176", 19 | "1150": "176", 20 | "1153": "176", 21 | "1240": "176", 22 | "1066": "179", 23 | "1210": "179", 24 | "1216": "179", 25 | "1255": "179", 26 | "1213": "179", 27 | "1219": "179", 28 | "1069": "182", 29 | "1249": "182", 30 | "1072": "185", 31 | "1168": "185", 32 | "1087": "200", 33 | "1273": "200", 34 | "1114": "227", 35 | "1117": "230", 36 | "1171": "284", 37 | "1198": "284", 38 | "1201": "284", 39 | "1183": "296", 40 | "1189": "296", 41 | "1192": "305", 42 | "1195": "305", 43 | "1243": "305", 44 | "1204": "317", 45 | "1207": "317", 46 | "1222": "335", 47 | "1258": "335", 48 | "1225": "335", 49 | "1237": "350", 50 | "1261": "350", 51 | "1246": "359", 52 | "1252": "365", 53 | "1264": "377", 54 | "1276": "389", 55 | "1279": "392", 56 | "1282": "392", 57 | }; 58 | 59 | export const useIconCode = async () => { 60 | const $weather = weather.get() 61 | 62 | if ($weather) { 63 | // const IconCode = IconMapping[1282] 64 | const IconCode = IconMapping[$weather?.current?.condition?.code] 65 | const isDay = $weather?.current?.is_day ? "d" : "n" 66 | // console.log(IconCode + isDay) 67 | // imageCode.set(IconCode + "n") 68 | imageCode.set(IconCode + isDay) 69 | } else { 70 | imageCode.set(null) 71 | } 72 | } 73 | 74 | export const getIconCode = (code: number) => { 75 | if (!code) return 76 | 77 | const IconCode = IconMapping[code] 78 | return IconCode + "d" 79 | } -------------------------------------------------------------------------------- /src/layouts/Layout.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Header from "../components/Header.astro"; 3 | import Loader from "../components/Preact/Loader"; 4 | import { Toaster } from "../utils/Toaster"; 5 | 6 | interface Props { 7 | title: string; 8 | } 9 | 10 | const { title } = Astro.props; 11 | --- 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | {title} 21 | 25 | 29 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 | 52 | 53 | 54 |
55 | 56 | 57 | 58 | 59 | 66 | 67 | 68 | 69 | 154 | 155 | 166 | -------------------------------------------------------------------------------- /src/pages/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import MiscDetails from "../components/MiscDetails.astro"; 3 | import WeatherCard from "../components/WeatherCard.astro"; 4 | import Layout from "../layouts/Layout.astro"; 5 | import TempChart from "../components/TempChart.astro"; 6 | import CoverImage from "../components/Preact/CoverImage"; 7 | import ForecastCard from "../components/ForecastCard.astro"; 8 | import { Image } from "astro:assets"; 9 | import { CLogo } from "../assets"; 10 | --- 11 | 12 | 13 |
16 | 17 | 18 | 19 | 20 |
21 | 22 | 67 | 68 | 69 |
70 | -------------------------------------------------------------------------------- /src/store/weatherStore.ts: -------------------------------------------------------------------------------- 1 | import type { weatherType } from "../types/types"; 2 | import { atom } from "nanostores"; 3 | 4 | export const weather = atom(null) 5 | 6 | export const imageCode = atom(null) 7 | 8 | export const imperialUnit = atom(false) 9 | 10 | type ToastType = { 11 | status: "success" | "error" | "warn", 12 | message: string, 13 | autoClose?: number, 14 | position?: "top-center", 15 | toastID?: number, 16 | } 17 | 18 | export const toastData = atom(null) -------------------------------------------------------------------------------- /src/types/types.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'luxon'; 2 | 3 | type AirQualityType = { 4 | co: number, 5 | no2: number, 6 | o3: number, 7 | so2: number, 8 | pm2_5: number, 9 | pm10: number, 10 | "us-epa-index": number, 11 | "gb-defra-index": number 12 | } 13 | 14 | type ConditionType = { 15 | text: string, 16 | icon: string, 17 | code: number 18 | } 19 | 20 | export type HourType = { 21 | time_epoch: number, 22 | time: string, 23 | temp_c: number, 24 | temp_f: number, 25 | is_day: number, 26 | condition: ConditionType, 27 | wind_mph: number, 28 | wind_kph: number, 29 | wind_degree: number, 30 | wind_dir: string, 31 | pressure_mb: number, 32 | pressure_in: number, 33 | precip_mm: number, 34 | precip_in: number, 35 | humidity: number, 36 | cloud: number, 37 | feelslike_c: number, 38 | feelslike_f: number, 39 | windchill_c: number, 40 | windchill_f: number, 41 | heatindex_c: number, 42 | heatindex_f: number, 43 | dewpoint_c: number, 44 | dewpoint_f: number, 45 | will_it_rain: number, 46 | chance_of_rain: number, 47 | will_it_snow: number, 48 | chance_of_snow: number, 49 | vis_km: number, 50 | vis_miles: number, 51 | gust_mph: number, 52 | gust_kph: number, 53 | uv: number, 54 | air_quality: AirQualityType 55 | } 56 | 57 | export interface weatherType { 58 | location: { 59 | name: string, 60 | region: string, 61 | country: string, 62 | lat: number, 63 | lon: number, 64 | tz_id: string, 65 | localtime_epoch: number, 66 | localtime: string 67 | }, 68 | current: { 69 | last_updated_epoch: number, 70 | last_updated: string, 71 | temp_c: number, 72 | temp_f: number, 73 | is_day: number, 74 | condition: ConditionType, 75 | wind_mph: number, 76 | wind_kph: number, 77 | wind_degree: number, 78 | wind_dir: string, 79 | pressure_mb: number, 80 | pressure_in: number, 81 | precip_mm: number, 82 | precip_in: number, 83 | humidity: number, 84 | cloud: number, 85 | feelslike_c: number, 86 | feelslike_f: number, 87 | vis_km: number, 88 | vis_miles: number, 89 | uv: number, 90 | gust_mph: number, 91 | gust_kph: number, 92 | air_quality: AirQualityType 93 | }, 94 | forecast: { 95 | forecastday: { 96 | astro: { 97 | sunrise: string, 98 | sunset: string, 99 | moonrise: string, 100 | moonset: string, 101 | moon_phase: string, 102 | moon_illumination: string, 103 | is_moon_up: number, 104 | is_sun_up: number 105 | }, 106 | date: string, 107 | date_epoch: number, 108 | day: { 109 | maxtemp_c: number, 110 | maxtemp_f: number, 111 | mintemp_c: number, 112 | mintemp_f: number, 113 | avgtemp_c: number, 114 | avgtemp_f: number, 115 | maxwind_mph: number, 116 | maxwind_kph: number, 117 | totalprecip_mm: number, 118 | totalprecip_in: number, 119 | totalsnow_cm: number, 120 | avgvis_km: number, 121 | avgvis_miles: number, 122 | avghumidity: number, 123 | daily_will_it_rain: number, 124 | daily_chance_of_rain: number, 125 | daily_will_it_snow: number, 126 | daily_chance_of_snow: number, 127 | condition: ConditionType, 128 | uv: number, 129 | air_quality: AirQualityType 130 | }, 131 | hour: HourType[], 132 | }[] 133 | } 134 | } -------------------------------------------------------------------------------- /src/utils/Toaster.tsx: -------------------------------------------------------------------------------- 1 | import { useStore } from "@nanostores/preact" 2 | import { toastData } from "../store/weatherStore" 3 | import { useEffect } from "preact/hooks" 4 | 5 | export const Toaster = () => { 6 | const $toastData = useStore(toastData) 7 | 8 | useEffect(() => { 9 | setTimeout(async () => { 10 | toastData.set(null) 11 | }, 4000) 12 | }, [$toastData]) 13 | 14 | const styles = { 15 | display: $toastData ? "flex" : "hidden", 16 | top: $toastData ? "4rem" : "0", 17 | opacity: $toastData ? "1" : "0", 18 | scale: $toastData ? "1" : "0.75", 19 | } 20 | 21 | return ( 22 |
23 |
24 | {$toastData?.status == "success" && } 25 | {$toastData?.status == "error" && } 26 | {$toastData?.status == "warn" && ⚠️} 27 | 28 | {$toastData?.message} 29 |
30 |
31 | ) 32 | } 33 | -------------------------------------------------------------------------------- /src/utils/useHorizontalScroll.tsx: -------------------------------------------------------------------------------- 1 | import { type RefObject } from 'preact'; 2 | import { useEffect, useState } from 'preact/hooks'; 3 | 4 | function useHorizontalScroll(ref: RefObject): RefObject { 5 | const [isDragging, setIsDragging] = useState(false); 6 | const [startX, setStartX] = useState(0); 7 | const [scrollLeft, setScrollLeft] = useState(0); 8 | 9 | useEffect(() => { 10 | const chartContainer = ref.current; 11 | 12 | const handleMouseDown = (e: MouseEvent) => { 13 | setIsDragging(true); 14 | setStartX(e.pageX - chartContainer!.offsetLeft); 15 | setScrollLeft(chartContainer!.scrollLeft); 16 | chartContainer!.style.cursor = 'grabbing'; 17 | }; 18 | 19 | const handleMouseUp = () => { 20 | setIsDragging(false); 21 | chartContainer!.style.cursor = 'grab'; 22 | }; 23 | 24 | const handleMouseMove = (e: MouseEvent) => { 25 | if (!isDragging) return; 26 | e.preventDefault(); 27 | const x = e.pageX - chartContainer!.offsetLeft; 28 | const walk = (x - startX) * 2; 29 | chartContainer!.scrollLeft = scrollLeft - walk; 30 | }; 31 | 32 | if (chartContainer) { 33 | chartContainer.addEventListener('mousedown', handleMouseDown); 34 | chartContainer.addEventListener('mouseup', handleMouseUp); 35 | chartContainer.addEventListener('mousemove', handleMouseMove); 36 | } 37 | 38 | return () => { 39 | if (chartContainer) { 40 | chartContainer.removeEventListener('mousedown', handleMouseDown); 41 | chartContainer.removeEventListener('mouseup', handleMouseUp); 42 | chartContainer.removeEventListener('mousemove', handleMouseMove); 43 | } 44 | }; 45 | }, [ref, isDragging, startX, scrollLeft]); 46 | 47 | return ref; 48 | } 49 | 50 | export default useHorizontalScroll; 51 | -------------------------------------------------------------------------------- /tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], 4 | theme: { 5 | extend: { 6 | fontFamily: { 7 | lexend: ["var(--lexend)"] 8 | }, 9 | screens: { 10 | '1xl': '1440px', 11 | } 12 | }, 13 | }, 14 | plugins: [], 15 | } 16 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/strict", 3 | "compilerOptions": { 4 | "jsx": "react-jsx", 5 | "jsxImportSource": "preact" 6 | } 7 | } --------------------------------------------------------------------------------