modified: .gitignore
modified: README.md modified: index.html new file: input.css new file: output.css modified: package-lock.json modified: package.json new file: postcss.config.js modified: script.js new file: tailwind.config.js
This commit is contained in:
parent
096dac61aa
commit
2d947941b5
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
|
apikey.txt
|
||||||
124
README.md
124
README.md
@ -1,56 +1,126 @@
|
|||||||
# Weather App
|
# Weather App v1.0.0
|
||||||
|
|
||||||
Приложение для просмотра погоды.
|
Приложение для просмотра погоды с интерактивным интерфейсом и поддержкой тем.
|
||||||
|
|
||||||
## Описание
|
## Описание
|
||||||
|
|
||||||
Это веб-приложение, которое отображает текущую погоду и почасовой прогноз с использованием API WeatherAPI.com. Интерфейс построен на Tailwind CSS для современного дизайна.
|
Это веб-приложение отображает текущую погоду, почасовой и недельный прогноз с использованием API WeatherAPI.com. Современный адаптивный интерфейс построен на Tailwind CSS с поддержкой светлой и темной тем.
|
||||||
|
|
||||||
## Функциональность
|
## Функциональность
|
||||||
|
|
||||||
- Отображение текущей погоды (температура, влажность, ветер)
|
- **Текущая погода**: температура, влажность, скорость ветра, описание условий
|
||||||
- Таймлапс погоды на день
|
- **Таймлапс**: почасовой прогноз погоды на день с визуализацией
|
||||||
- Адаптивный дизайн
|
- **Недельный прогноз**: погода на 7 дней вперед
|
||||||
- Выбор городов
|
- **Интерактивные графики**: температура и осадки с помощью Chart.js
|
||||||
|
- **Адаптивный дизайн**: корректное отображение на всех устройствах
|
||||||
|
- **Выбор городов**: предустановленный список российских городов
|
||||||
|
- **Система тем**: светлая, темная и автоматическая (по системным настройкам)
|
||||||
|
- **Анимации**: плавные переходы и hover-эффекты
|
||||||
|
|
||||||
## Технологии
|
## Технологии
|
||||||
|
|
||||||
- Node.js
|
### Backend
|
||||||
- Express
|
|
||||||
- Tailwind CSS
|
|
||||||
- HTML5
|
|
||||||
- JavaScript
|
|
||||||
- Swiper.js (для слайдера)
|
|
||||||
- Chart.js (для графиков)
|
|
||||||
- Lucide Icons (для иконок)
|
|
||||||
- Google Fonts (Inter)
|
|
||||||
|
|
||||||
## Установка
|
- **Node.js** v8+ (устаревшая версия, рекомендуется обновить до LTS)
|
||||||
|
- **Express.js** v4.17.1 - веб-сервер
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
|
||||||
|
- **HTML5** - семантическая разметка
|
||||||
|
- **JavaScript** (Vanilla) - клиентская логика
|
||||||
|
- **Tailwind CSS** v3.4.16 - утилитарный CSS фреймворк
|
||||||
|
- **PostCSS** v8.5.6 - обработка CSS
|
||||||
|
- **Autoprefixer** v10.4.21 - вендорные префиксы
|
||||||
|
|
||||||
|
### Библиотеки и CDN
|
||||||
|
|
||||||
|
- **Lucide Icons** - современные SVG иконки
|
||||||
|
- **Swiper.js** v11 - слайдер для таймлапса
|
||||||
|
- **Chart.js** - построение графиков
|
||||||
|
- **Google Fonts** (Inter) - шрифты
|
||||||
|
|
||||||
|
### Стилизация
|
||||||
|
|
||||||
|
- CSS переменные для тематизации
|
||||||
|
- Плавные анимации переходов
|
||||||
|
- Цветовые схемы для разных погодных условий
|
||||||
|
|
||||||
|
## Установка и запуск
|
||||||
|
|
||||||
|
### Системные требования
|
||||||
|
|
||||||
|
- **Node.js** v8+ (⚠️ устаревшая версия, рекомендуется использовать LTS версию Node.js 18+)
|
||||||
|
- **npm** для управления пакетами
|
||||||
|
|
||||||
|
### Установка
|
||||||
|
|
||||||
|
1. **Клонируйте репозиторий:**
|
||||||
|
|
||||||
1. Клонируйте репозиторий:
|
|
||||||
```bash
|
```bash
|
||||||
git clone <url>
|
git clone <repository-url>
|
||||||
cd weather-app
|
cd weather-app
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Установите зависимости:
|
2. **Установите зависимости:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install
|
npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Запустите сервер:
|
3. **Соберите CSS (если необходимо):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build-css
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Запустите сервер:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm start
|
npm start
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Откройте http://localhost:3000 в браузере.
|
5. **Откройте браузер:**
|
||||||
|
Перейдите по адресу http://localhost:3000
|
||||||
|
|
||||||
## Структура проекта
|
### Доступные скрипты
|
||||||
|
|
||||||
- `server.js` - сервер на Express
|
- `npm start` - запуск сервера разработки
|
||||||
- `index.html` - главная страница
|
- `npm run build-css` - сборка Tailwind CSS из `input.css` в `output.css`
|
||||||
- `script.js` - клиентский JavaScript
|
- `npm run watch-css` - автоматическая пересборка CSS при изменениях
|
||||||
- `package.json` - конфигурация
|
|
||||||
|
## API и внешние сервисы
|
||||||
|
|
||||||
|
- **WeatherAPI.com** - источник данных о погоде
|
||||||
|
- **Google Fonts API** - загрузка шрифтов Inter
|
||||||
|
- **CDN сервисы** для библиотек JavaScript (jsDelivr, unpkg)
|
||||||
|
|
||||||
|
## Разработчик
|
||||||
|
|
||||||
|
Разработано: **Fovway**
|
||||||
|
|
||||||
|
Контакты:
|
||||||
|
|
||||||
|
- Email: [admin@fovway.ru](mailto:admin@fovway.ru)
|
||||||
|
|
||||||
|
## Рекомендации
|
||||||
|
|
||||||
|
### Обновление Node.js
|
||||||
|
|
||||||
|
Текущая конфигурация требует Node.js v8, но рекомендуется использовать актуальную LTS версию (18+) для повышения безопасности и производительности.
|
||||||
|
|
||||||
|
### Настройка API ключа
|
||||||
|
|
||||||
|
Для полноценной работы приложения необходимо:
|
||||||
|
|
||||||
|
1. Зарегистрироваться на [WeatherAPI.com](https://weatherapi.com)
|
||||||
|
2. Получить бесплатный API ключ
|
||||||
|
3. Добавить ключ в переменные окружения или конфигурацию сервера(server.js - const API_KEY = "API_KEY_HERE";)
|
||||||
|
|
||||||
|
### Производительность
|
||||||
|
|
||||||
|
- Приложение использует CDN для внешних библиотек, что обеспечивает быструю загрузку
|
||||||
|
- CSS собирается с помощью Tailwind CSS для оптимального размера файлов
|
||||||
|
- Используйте `npm run watch-css` во время разработки для автоматической пересборки стилей
|
||||||
|
|
||||||
## Лицензия
|
## Лицензия
|
||||||
|
|
||||||
|
|||||||
633
index.html
633
index.html
@ -1,201 +1,496 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="ru">
|
<html lang="ru">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Погода</title>
|
<title>Погода</title>
|
||||||
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><defs><style>.a{fill:%233b82f6;}.b{fill:%23ffffff;}</style></defs><circle class='a' cx='16' cy='16' r='12'/><circle class='b' cx='16' cy='16' r='8'/><path class='a' d='M16,4V6M16,26V28M28,16H26M6,16H4M22.5,9.5l-1.5,1.5M8.5,22.5l-1.5,1.5M22.5,22.5l-1.5-1.5M8.5,9.5l-1.5-1.5' stroke='%233b82f6' stroke-width='1.5' fill='none'/><ellipse class='a' cx='20' cy='24' rx='8' ry='4' opacity='0.7'/></svg>">
|
<link
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
rel="icon"
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
type="image/svg+xml"
|
||||||
|
href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><defs><style>.a{fill:%233b82f6;}.b{fill:%23ffffff;}</style></defs><circle class='a' cx='16' cy='16' r='12'/><circle class='b' cx='16' cy='16' r='8'/><path class='a' d='M16,4V6M16,26V28M28,16H26M6,16H4M22.5,9.5l-1.5,1.5M8.5,22.5l-1.5,1.5M22.5,22.5l-1.5-1.5M8.5,9.5l-1.5-1.5' stroke='%233b82f6' stroke-width='1.5' fill='none'/><ellipse class='a' cx='20' cy='24' rx='8' ry='4' opacity='0.7'/></svg>"
|
||||||
|
/>
|
||||||
|
<link rel="stylesheet" href="output.css" />
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
|
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
|
||||||
<!-- Swiper CSS -->
|
<!-- Swiper CSS -->
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css">
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css"
|
||||||
|
/>
|
||||||
<!-- Chart.js -->
|
<!-- Chart.js -->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
<style>
|
<style>
|
||||||
body { font-family: 'Inter', sans-serif; }
|
:root {
|
||||||
.swiper-slide { height: auto; }
|
--theme-bg: linear-gradient(to bottom right, #dbeafe, #ffffff, #e0e7ff);
|
||||||
.timelapse-container { padding-top: 12px; padding-bottom: 12px; }
|
--theme-text: #1e293b;
|
||||||
.timelapse-item { transition: all 0.3s ease; }
|
--theme-text-secondary: #64748b;
|
||||||
.timelapse-item:hover { transform: translateY(-4px); box-shadow: 0 10px 25px rgba(0,0,0,0.1); }
|
--theme-card-bg: #ffffff;
|
||||||
|
--theme-border: #e2e8f0;
|
||||||
|
--theme-shadow: rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Стили для графиков */
|
[data-theme="dark"] {
|
||||||
|
--theme-bg: linear-gradient(to bottom right, #1e293b, #0f172a, #1e3a8a);
|
||||||
|
--theme-text: #f8fafc;
|
||||||
|
--theme-text-secondary: #cbd5e1;
|
||||||
|
--theme-card-bg: #1e293b;
|
||||||
|
--theme-border: #334155;
|
||||||
|
--theme-shadow: rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: "Inter", sans-serif;
|
||||||
|
background: var(--theme-bg);
|
||||||
|
color: var(--theme-text);
|
||||||
|
min-height: 100vh;
|
||||||
|
transition: background 0.3s ease, color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Динамические элементы с поддержкой темы */
|
||||||
|
.dynamic-card {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dynamic-card.dark-theme {
|
||||||
|
background: #1e293b;
|
||||||
|
border-color: #334155;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dynamic-card.light-theme {
|
||||||
|
background: #ffffff;
|
||||||
|
border-color: #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-slide {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
.timelapse-container {
|
||||||
|
padding-top: 12px;
|
||||||
|
padding-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Стили для графиков */
|
||||||
|
.chart-container {
|
||||||
|
position: relative;
|
||||||
|
height: 300px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-container canvas {
|
||||||
|
max-height: 300px;
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
.chart-container {
|
.chart-container {
|
||||||
position: relative;
|
height: 250px;
|
||||||
height: 300px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.chart-container canvas {
|
@media (max-width: 768px) {
|
||||||
max-height: 300px;
|
.chart-container {
|
||||||
width: 100% !important;
|
height: 200px;
|
||||||
height: 100% !important;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 1024px) {
|
/* Анимации для переключения темы */
|
||||||
.chart-container {
|
* {
|
||||||
height: 250px;
|
transition: background-color 0.3s ease, color 0.3s ease,
|
||||||
}
|
border-color 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
/* Стили для переключателя темы */
|
||||||
.chart-container {
|
.theme-button {
|
||||||
height: 200px;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
.theme-button.active {
|
||||||
|
background-color: #3b82f6;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-button.active i {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Стили для кнопок темы */
|
||||||
|
#theme-light,
|
||||||
|
#theme-auto,
|
||||||
|
#theme-dark {
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
#theme-light:hover,
|
||||||
|
#theme-auto:hover,
|
||||||
|
#theme-dark:hover {
|
||||||
|
background-color: #f1f5f9;
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark #theme-light:hover,
|
||||||
|
.dark #theme-auto:hover,
|
||||||
|
.dark #theme-dark:hover {
|
||||||
|
background-color: #334155;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Поддержка тем через data-theme атрибут */
|
||||||
|
[data-theme="dark"] {
|
||||||
|
@apply dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Глобальные стили для темной темы */
|
||||||
|
[data-theme="dark"] * {
|
||||||
|
transition: background-color 0.3s ease, color 0.3s ease,
|
||||||
|
border-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Плавные переходы для карточек */
|
||||||
|
.weather-card {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather-card:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Цветные стили для погодных иконок */
|
||||||
|
.weather-icon.sun {
|
||||||
|
color: #f59e0b;
|
||||||
|
}
|
||||||
|
.weather-icon.sun-dark {
|
||||||
|
color: #fbbf24;
|
||||||
|
}
|
||||||
|
.weather-icon.cloud {
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
.weather-icon.cloud-dark {
|
||||||
|
color: #9ca3af;
|
||||||
|
}
|
||||||
|
.weather-icon.rain {
|
||||||
|
color: #3b82f6;
|
||||||
|
}
|
||||||
|
.weather-icon.rain-dark {
|
||||||
|
color: #60a5fa;
|
||||||
|
}
|
||||||
|
.weather-icon.snow {
|
||||||
|
color: #06b6d4;
|
||||||
|
}
|
||||||
|
.weather-icon.snow-dark {
|
||||||
|
color: #67e8f9;
|
||||||
|
}
|
||||||
|
.weather-icon.thunder {
|
||||||
|
color: #8b5cf6;
|
||||||
|
}
|
||||||
|
.weather-icon.thunder-dark {
|
||||||
|
color: #a78bfa;
|
||||||
|
}
|
||||||
|
.weather-icon.fog {
|
||||||
|
color: #9ca3af;
|
||||||
|
}
|
||||||
|
.weather-icon.fog-dark {
|
||||||
|
color: #d1d5db;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
.weather-icon.wind {
|
||||||
|
color: #10b981;
|
||||||
|
}
|
||||||
|
.weather-icon.wind-dark {
|
||||||
|
color: #34d399;
|
||||||
|
}
|
||||||
|
.weather-icon.drizzle {
|
||||||
|
color: #06b6d4;
|
||||||
|
}
|
||||||
|
.weather-icon.drizzle-dark {
|
||||||
|
color: #22d3ee;
|
||||||
|
}
|
||||||
|
.weather-icon.hail {
|
||||||
|
color: #6366f1;
|
||||||
|
}
|
||||||
|
.weather-icon.hail-dark {
|
||||||
|
color: #818cf8;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-gradient-to-br from-blue-50 via-white to-indigo-50 min-h-screen">
|
<body class="min-h-screen">
|
||||||
<div class="container mx-auto max-w-7xl px-4 py-8">
|
<div class="container mx-auto max-w-7xl px-4 py-8">
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<header class="text-center mb-12">
|
<header class="text-center mb-12">
|
||||||
<div class="flex items-center justify-center gap-3 mb-4">
|
<div class="flex items-center justify-center gap-3 mb-4">
|
||||||
<div class="p-3 bg-blue-500 rounded-full">
|
<div class="p-3 bg-blue-500 rounded-full">
|
||||||
<i data-lucide="cloud-sun" class="w-8 h-8 text-white"></i>
|
<i data-lucide="cloud-sun" class="w-8 h-8 text-white"></i>
|
||||||
</div>
|
</div>
|
||||||
<h1 class="text-4xl md:text-5xl font-bold text-gray-800">Погода</h1>
|
<h1
|
||||||
</div>
|
class="text-4xl md:text-5xl font-bold"
|
||||||
<p class="text-gray-600 text-lg">Узнайте погоду в вашем городе</p>
|
style="color: var(--theme-text)"
|
||||||
<div class="mt-4 flex items-center justify-center gap-2 text-gray-700">
|
>
|
||||||
<i data-lucide="calendar" class="w-5 h-5"></i>
|
Погода
|
||||||
<span class="font-medium" id="current-date">Загрузка...</span>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
<p class="text-lg" style="color: var(--theme-text-secondary)">
|
||||||
|
Узнайте погоду в вашем городе
|
||||||
<!-- City Selector -->
|
</p>
|
||||||
<div class="bg-white rounded-2xl shadow-xl p-8 mb-12 border border-gray-100">
|
<div
|
||||||
<div class="flex flex-col md:flex-row items-center gap-6">
|
class="mt-4 flex items-center justify-center gap-2"
|
||||||
<div class="flex items-center gap-3 text-gray-700">
|
style="color: var(--theme-text)"
|
||||||
<i data-lucide="map-pin" class="w-5 h-5"></i>
|
>
|
||||||
<label for="city" class="font-medium text-lg">Выберите город:</label>
|
<i data-lucide="calendar" class="w-5 h-5"></i>
|
||||||
</div>
|
<span class="font-medium" id="current-date">Загрузка...</span>
|
||||||
<select id="city" class="flex-1 px-6 py-3 border-2 border-gray-200 rounded-xl focus:border-blue-500 focus:ring-2 focus:ring-blue-200 transition-all duration-200 bg-white text-gray-700 font-medium min-w-[200px]">
|
|
||||||
<option value="Moscow">Москва</option>
|
|
||||||
<option value="Saint Petersburg">Санкт-Петербург</option>
|
|
||||||
<option value="Novosibirsk">Новосибирск</option>
|
|
||||||
<option value="Yekaterinburg">Екатеринбург</option>
|
|
||||||
<option value="Nizhny Novgorod">Нижний Новгород</option>
|
|
||||||
<option value="Kazan">Казань</option>
|
|
||||||
<option value="Chelyabinsk">Челябинск</option>
|
|
||||||
<option value="Omsk">Омск</option>
|
|
||||||
<option value="Samara">Самара</option>
|
|
||||||
<option value="Rostov-on-Don">Ростов-на-Дону</option>
|
|
||||||
</select>
|
|
||||||
<button id="get-weather" class="px-8 py-3 bg-blue-500 hover:bg-blue-600 text-white font-semibold rounded-xl transition-all duration-200 transform hover:scale-105 shadow-lg hover:shadow-xl flex items-center gap-2">
|
|
||||||
<i data-lucide="search" class="w-5 h-5"></i>
|
|
||||||
Выбрать
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Weather Info -->
|
<!-- Theme Toggle -->
|
||||||
<div class="weather-info">
|
<div class="mt-6 flex items-center justify-center gap-4">
|
||||||
<!-- Current Weather Section -->
|
<div
|
||||||
<div id="current-weather" class="hidden bg-white rounded-2xl shadow-xl p-8 mb-8 border border-gray-100">
|
class="flex items-center gap-2 bg-gray-100 dark:bg-gray-700 rounded-lg p-1"
|
||||||
<div class="text-center">
|
>
|
||||||
<h2 class="text-2xl font-bold text-gray-800 mb-6 flex items-center justify-center gap-2">
|
<button
|
||||||
<i data-lucide="thermometer" class="w-6 h-6"></i>
|
id="theme-light"
|
||||||
Текущая погода
|
class="p-2 rounded-md transition-all duration-200 dark:text-gray-300"
|
||||||
</h2>
|
title="Светлая тема"
|
||||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
>
|
||||||
<div class="text-center">
|
<i
|
||||||
<div class="flex items-center justify-center gap-2 mb-2">
|
data-lucide="sun"
|
||||||
<i data-lucide="thermometer" class="w-5 h-5 text-blue-500"></i>
|
class="w-5 h-5 text-gray-600 dark:text-gray-300"
|
||||||
<p class="text-4xl font-bold text-blue-500" id="current-temp">--°C</p>
|
></i>
|
||||||
</div>
|
</button>
|
||||||
<p class="text-gray-600" id="current-desc">Загрузка...</p>
|
<button
|
||||||
</div>
|
id="theme-auto"
|
||||||
<div class="text-center">
|
class="p-2 rounded-md transition-all duration-200 dark:text-gray-300"
|
||||||
<div class="flex items-center justify-center gap-2 mb-2">
|
title="Системная тема"
|
||||||
<i data-lucide="droplets" class="w-5 h-5 text-blue-500"></i>
|
>
|
||||||
<div>
|
<i
|
||||||
<p class="text-lg text-gray-600">Влажность</p>
|
data-lucide="monitor"
|
||||||
<p class="text-2xl font-semibold text-gray-800" id="current-humidity">--%</p>
|
class="w-5 h-5 text-gray-600 dark:text-gray-300"
|
||||||
</div>
|
></i>
|
||||||
</div>
|
</button>
|
||||||
</div>
|
<button
|
||||||
<div class="text-center">
|
id="theme-dark"
|
||||||
<div class="flex items-center justify-center gap-2 mb-2">
|
class="p-2 rounded-md transition-all duration-200 dark:text-gray-300"
|
||||||
<i data-lucide="wind" class="w-5 h-5 text-blue-500"></i>
|
title="Темная тема"
|
||||||
<div>
|
>
|
||||||
<p class="text-lg text-gray-600">Ветер</p>
|
<i
|
||||||
<p class="text-2xl font-semibold text-gray-800" id="current-wind">-- км/ч</p>
|
data-lucide="moon"
|
||||||
</div>
|
class="w-5 h-5 text-gray-600 dark:text-gray-300"
|
||||||
</div>
|
></i>
|
||||||
</div>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Timelapse Section -->
|
|
||||||
<div class="timelapse-weather bg-white rounded-2xl shadow-xl p-8 border border-gray-100">
|
|
||||||
<h2 class="text-2xl font-bold text-gray-800 mb-6 flex items-center gap-2">
|
|
||||||
<i data-lucide="clock" class="w-6 h-6"></i>
|
|
||||||
Погода на весь день
|
|
||||||
</h2>
|
|
||||||
<div class="swiper timelapse-container">
|
|
||||||
<div id="timelapse-container" class="swiper-wrapper"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Weekly Weather Section -->
|
|
||||||
<div class="weekly-weather bg-white rounded-2xl shadow-xl p-8 border border-gray-100 mt-8">
|
|
||||||
<h2 class="text-2xl font-bold text-gray-800 mb-6 flex items-center gap-2">
|
|
||||||
<i data-lucide="calendar-days" class="w-6 h-6"></i>
|
|
||||||
Погода на неделю
|
|
||||||
</h2>
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-7 gap-4" id="weekly-container">
|
|
||||||
<!-- Карточки недельного прогноза будут добавлены сюда -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Charts Section -->
|
|
||||||
<div class="charts-section bg-white rounded-2xl shadow-xl p-8 border border-gray-100 mt-8">
|
|
||||||
<h2 class="text-2xl font-bold text-gray-800 mb-6 flex items-center gap-2">
|
|
||||||
<i data-lucide="bar-chart-3" class="w-6 h-6"></i>
|
|
||||||
Графики погоды
|
|
||||||
</h2>
|
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
|
||||||
<!-- Temperature Chart -->
|
|
||||||
<div class="chart-container">
|
|
||||||
<h3 class="text-lg font-semibold text-gray-700 mb-4 flex items-center gap-2">
|
|
||||||
<i data-lucide="thermometer" class="w-5 h-5 text-blue-500"></i>
|
|
||||||
Температура (°C)
|
|
||||||
</h3>
|
|
||||||
<canvas id="temperatureChart"></canvas>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Precipitation Chart -->
|
|
||||||
<div class="chart-container">
|
|
||||||
<h3 class="text-lg font-semibold text-gray-700 mb-4 flex items-center gap-2">
|
|
||||||
<i data-lucide="cloud-rain" class="w-5 h-5 text-blue-500"></i>
|
|
||||||
Осадки (мм)
|
|
||||||
</h3>
|
|
||||||
<canvas id="precipitationChart"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- City Selector -->
|
||||||
|
<div class="weather-card rounded-2xl shadow-xl p-8 mb-12">
|
||||||
|
<div class="flex flex-col md:flex-row items-center gap-6">
|
||||||
|
<div
|
||||||
|
class="flex items-center gap-3"
|
||||||
|
style="color: var(--theme-text-secondary)"
|
||||||
|
>
|
||||||
|
<i data-lucide="map-pin" class="w-5 h-5 text-blue-500"></i>
|
||||||
|
<label
|
||||||
|
for="city"
|
||||||
|
class="font-medium text-lg"
|
||||||
|
style="color: var(--theme-text-secondary)"
|
||||||
|
>Выберите город:</label
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<select
|
||||||
|
id="city"
|
||||||
|
class="flex-1 px-6 py-3 border-2 border-gray-200 rounded-xl focus:border-blue-500 focus:ring-2 focus:ring-blue-200 transition-all duration-200 bg-white text-gray-700 font-medium min-w-[200px]"
|
||||||
|
>
|
||||||
|
<option value="Moscow">Москва</option>
|
||||||
|
<option value="Saint Petersburg">Санкт-Петербург</option>
|
||||||
|
<option value="Novosibirsk">Новосибирск</option>
|
||||||
|
<option value="Yekaterinburg">Екатеринбург</option>
|
||||||
|
<option value="Nizhny Novgorod">Нижний Новгород</option>
|
||||||
|
<option value="Kazan">Казань</option>
|
||||||
|
<option value="Chelyabinsk">Челябинск</option>
|
||||||
|
<option value="Omsk">Омск</option>
|
||||||
|
<option value="Samara">Самара</option>
|
||||||
|
<option value="Rostov-on-Don">Ростов-на-Дону</option>
|
||||||
|
</select>
|
||||||
|
<button
|
||||||
|
id="get-weather"
|
||||||
|
class="px-8 py-3 bg-blue-500 hover:bg-blue-600 text-white font-semibold rounded-xl transition-all duration-200 transform hover:scale-105 shadow-lg hover:shadow-xl flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<i data-lucide="search" class="w-5 h-5"></i>
|
||||||
|
Выбрать
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Weather Info -->
|
||||||
|
<div class="weather-info">
|
||||||
|
<!-- Current Weather Section -->
|
||||||
|
<div
|
||||||
|
id="current-weather"
|
||||||
|
class="hidden weather-card rounded-2xl shadow-xl p-8 mb-8"
|
||||||
|
>
|
||||||
|
<div class="text-center">
|
||||||
|
<h2
|
||||||
|
class="text-2xl font-bold mb-6 flex items-center justify-center gap-2"
|
||||||
|
style="color: var(--theme-text)"
|
||||||
|
>
|
||||||
|
<i data-lucide="thermometer" class="w-6 h-6 text-blue-500"></i>
|
||||||
|
Текущая погода
|
||||||
|
</h2>
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||||
|
<div class="text-center">
|
||||||
|
<div class="flex items-center justify-center gap-2 mb-2">
|
||||||
|
<i
|
||||||
|
data-lucide="thermometer"
|
||||||
|
class="w-5 h-5 text-blue-500"
|
||||||
|
></i>
|
||||||
|
<p class="text-4xl font-bold text-blue-500" id="current-temp">
|
||||||
|
--°C
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<p
|
||||||
|
class="text-lg"
|
||||||
|
id="current-desc"
|
||||||
|
style="color: var(--theme-text-secondary)"
|
||||||
|
>
|
||||||
|
Загрузка...
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="text-center">
|
||||||
|
<div class="flex items-center justify-center gap-2 mb-2">
|
||||||
|
<i data-lucide="droplets" class="w-5 h-5 text-blue-500"></i>
|
||||||
|
<div>
|
||||||
|
<p
|
||||||
|
class="text-lg"
|
||||||
|
style="color: var(--theme-text-secondary)"
|
||||||
|
>
|
||||||
|
Влажность
|
||||||
|
</p>
|
||||||
|
<p
|
||||||
|
class="text-2xl font-semibold"
|
||||||
|
id="current-humidity"
|
||||||
|
style="color: var(--theme-text)"
|
||||||
|
>
|
||||||
|
--%
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-center">
|
||||||
|
<div class="flex items-center justify-center gap-2 mb-2">
|
||||||
|
<i data-lucide="wind" class="w-5 h-5 text-blue-500"></i>
|
||||||
|
<div>
|
||||||
|
<p
|
||||||
|
class="text-lg"
|
||||||
|
style="color: var(--theme-text-secondary)"
|
||||||
|
>
|
||||||
|
Ветер
|
||||||
|
</p>
|
||||||
|
<p
|
||||||
|
class="text-2xl font-semibold"
|
||||||
|
id="current-wind"
|
||||||
|
style="color: var(--theme-text)"
|
||||||
|
>
|
||||||
|
-- км/ч
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Timelapse Section -->
|
||||||
|
<div class="timelapse-weather weather-card rounded-2xl shadow-xl p-8">
|
||||||
|
<h2
|
||||||
|
class="text-2xl font-bold mb-6 flex items-center gap-2"
|
||||||
|
style="color: var(--theme-text)"
|
||||||
|
>
|
||||||
|
<i data-lucide="clock" class="w-6 h-6 text-blue-500"></i>
|
||||||
|
Погода на весь день
|
||||||
|
</h2>
|
||||||
|
<div class="swiper timelapse-container">
|
||||||
|
<div id="timelapse-container" class="swiper-wrapper"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Weekly Weather Section -->
|
||||||
|
<div class="weekly-weather weather-card rounded-2xl shadow-xl p-8 mt-8">
|
||||||
|
<h2
|
||||||
|
class="text-2xl font-bold mb-6 flex items-center gap-2"
|
||||||
|
style="color: var(--theme-text)"
|
||||||
|
>
|
||||||
|
<i data-lucide="calendar-days" class="w-6 h-6 text-blue-500"></i>
|
||||||
|
Погода на неделю
|
||||||
|
</h2>
|
||||||
|
<div
|
||||||
|
class="grid grid-cols-1 md:grid-cols-7 gap-4"
|
||||||
|
id="weekly-container"
|
||||||
|
>
|
||||||
|
<!-- Карточки недельного прогноза будут добавлены сюда -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Charts Section -->
|
||||||
|
<div class="charts-section weather-card rounded-2xl shadow-xl p-8 mt-8">
|
||||||
|
<h2
|
||||||
|
class="text-2xl font-bold mb-6 flex items-center gap-2"
|
||||||
|
style="color: var(--theme-text)"
|
||||||
|
>
|
||||||
|
<i data-lucide="bar-chart-3" class="w-6 h-6 text-blue-500"></i>
|
||||||
|
Графики погоды
|
||||||
|
</h2>
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||||
|
<!-- Temperature Chart -->
|
||||||
|
<div class="chart-container">
|
||||||
|
<h3
|
||||||
|
class="text-lg font-semibold text-gray-700 mb-4 flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<i data-lucide="thermometer" class="w-5 h-5 text-blue-500"></i>
|
||||||
|
Температура (°C)
|
||||||
|
</h3>
|
||||||
|
<canvas id="temperatureChart"></canvas>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Precipitation Chart -->
|
||||||
|
<div class="chart-container">
|
||||||
|
<h3
|
||||||
|
class="text-lg font-semibold text-gray-700 mb-4 flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<i data-lucide="cloud-rain" class="w-5 h-5 text-blue-500"></i>
|
||||||
|
Осадки (мм)
|
||||||
|
</h3>
|
||||||
|
<canvas id="precipitationChart"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<footer class="mt-8 mb-8 text-center">
|
<footer class="mt-8 mb-8 text-center">
|
||||||
<div class="text-gray-500 text-sm">
|
<div class="text-sm" style="color: var(--theme-text-secondary)">
|
||||||
<p class="mb-1">Разработано: <span class="font-medium">Fovway</span></p>
|
<p class="mb-1">
|
||||||
<p>
|
Разработано:
|
||||||
<i data-lucide="mail" class="w-3 h-3 inline mr-1"></i>
|
<span class="font-medium" style="color: var(--theme-text)"
|
||||||
<a href="mailto:admin@fovway.ru" class="hover:text-blue-500 transition-colors duration-200">
|
>Fovway</span
|
||||||
admin@fovway.ru
|
>
|
||||||
</a>
|
</p>
|
||||||
</p>
|
<p>
|
||||||
</div>
|
<i data-lucide="mail" class="w-3 h-3 inline mr-1"></i>
|
||||||
|
<a
|
||||||
|
href="mailto:admin@fovway.ru"
|
||||||
|
class="transition-colors duration-200 text-blue-500 hover:text-blue-600"
|
||||||
|
>
|
||||||
|
admin@fovway.ru
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script src="script.js"></script>
|
<script src="script.js"></script>
|
||||||
<!-- Swiper JS -->
|
<!-- Swiper JS -->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
lucide.createIcons();
|
lucide.createIcons();
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
16
input.css
Normal file
16
input.css
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
/* Custom styles */
|
||||||
|
.weather-card {
|
||||||
|
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
|
||||||
|
border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));
|
||||||
|
box-shadow: 0 20px 25px -5px rgba(0,0,0,0.1), 0 10px 10px -5px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .weather-card {
|
||||||
|
background-color: rgb(30 41 55 / var(--tw-bg-opacity, 1));
|
||||||
|
border-color: rgb(71 85 105 / var(--tw-border-opacity, 1));
|
||||||
|
box-shadow: 0 20px 25px -5px rgba(0,0,0,0.3), 0 10px 10px -5px rgba(0,0,0,0.3);
|
||||||
|
}
|
||||||
1187
output.css
Normal file
1187
output.css
Normal file
File diff suppressed because it is too large
Load Diff
1513
package-lock.json
generated
1513
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,9 @@
|
|||||||
"description": "Weather app with timelapse",
|
"description": "Weather app with timelapse",
|
||||||
"main": "server.js",
|
"main": "server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node server.js"
|
"start": "node server.js",
|
||||||
|
"build-css": "tailwindcss -i input.css -o output.css",
|
||||||
|
"watch-css": "tailwindcss -i input.css -o output.css --watch"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "8"
|
"node": "8"
|
||||||
@ -13,6 +15,8 @@
|
|||||||
"express": "^4.17.1"
|
"express": "^4.17.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"tailwindcss": "^4.1.14"
|
"autoprefixer": "^10.4.21",
|
||||||
|
"postcss": "^8.5.6",
|
||||||
|
"tailwindcss": "^3.4.16"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
9
tailwind.config.js
Normal file
9
tailwind.config.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: ["./index.html", "./script.js"],
|
||||||
|
darkMode: 'class',
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user