feat(frontend): add frontend

This commit is contained in:
thek4n 2026-06-05 02:20:20 +03:00
parent aa57e6371d
commit 94fa6eb9be
4 changed files with 68 additions and 15 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
build/ build/
sdkconfig sdkconfig
main/frontend.h

View File

@ -5,6 +5,22 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"> <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<title>IoT Pump controller</title> <title>IoT Pump controller</title>
<style> <style>
:root {
/* Min slider colors */
--min-slider-start: #e94f32;
--min-slider-end: #cb9085;
/* Max slider colors */
--max-slider-start: #fbbf24;
--max-slider-end: #c0bbad;
/* Common slider styles */
--slider-height: 6px;
--slider-radius: 12px;
--thumb-size: 24px;
--shadow-inset: inset 0 1px 2px #00000040;
}
* { * {
box-sizing: border-box; box-sizing: border-box;
user-select: none; user-select: none;
@ -93,7 +109,7 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
font-weight: 600; font-weight: 600;
color: #e2eafc; color: #e0eafc;
font-size: 1.2rem; font-size: 1.2rem;
margin-bottom: 12px; margin-bottom: 12px;
letter-spacing: 0.3px; letter-spacing: 0.3px;
@ -110,28 +126,62 @@
box-shadow: inset 0 1px 2px rgba(0,0,0,0.3), 0 1px 0 rgba(255,255,255,0.1); box-shadow: inset 0 1px 2px rgba(0,0,0,0.3), 0 1px 0 rgba(255,255,255,0.1);
} }
input[type="range"] { .slider-base {
width: 100%; width: 100%;
height: 6px; height: 6px;
-webkit-appearance: none; -webkit-appearance: none;
background: linear-gradient(90deg, #1e6f9f, #4aa3cf); appearance: none;
border-radius: 12px; border-radius: 12px;
cursor: pointer; cursor: pointer;
box-shadow: inset 0 1px 2px #00000040; box-shadow: inset 0 1px 2px #00000040;
} }
input[type="range"]::-webkit-slider-thumb { .min-slider {
width: 100%;
height: var(--slider-height);
-webkit-appearance: none; -webkit-appearance: none;
width: 36px; background: linear-gradient(90deg, var(--min-slider-start), var(--min-slider-end));
height: 36px; border-radius: var(--slider-radius);
background: radial-gradient(circle, #6db3e0, #2c6c9e); cursor: pointer;
box-shadow: var(--shadow-inset);
}
.max-slider {
width: 100%;
height: var(--slider-height);
-webkit-appearance: none;
background: linear-gradient(90deg, var(--max-slider-start), var(--max-slider-end));
border-radius: var(--slider-radius);
cursor: pointer;
box-shadow: var(--shadow-inset);
}
.min-slider::-webkit-slider-thumb {
-webkit-appearance: none;
width: var(--thumb-size);
height: var(--thumb-size);
background: radial-gradient(circle, var(--min-slider-start), var(--min-slider-end));
border-radius: 50%; border-radius: 50%;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(210, 230, 250, 0.7);
border: 1px solid #b8d0ff;
cursor: pointer; cursor: pointer;
transition: transform 0.08s; transition: transform 0.08s;
} }
.max-slider::-webkit-slider-thumb {
-webkit-appearance: none;
width: var(--thumb-size);
height: var(--thumb-size);
background: radial-gradient(circle, var(--max-slider-start), var(--max-slider-end));
border-radius: 50%;
cursor: pointer;
transition: transform 0.08s;
}
/* Optional: Add hover effect for thumbs */
.min-slider::-webkit-slider-thumb:hover,
.max-slider::-webkit-slider-thumb:hover {
transform: scale(1.2);
}
input[type="range"]::-webkit-slider-thumb:active { input[type="range"]::-webkit-slider-thumb:active {
transform: scale(1.15); transform: scale(1.15);
} }
@ -232,7 +282,7 @@
Нижний порог (включение) Нижний порог (включение)
<span id="minThresholdVal">1.40</span> атм <span id="minThresholdVal">1.40</span> атм
</label> </label>
<input type="range" id="minSlider" min="0" max="8" step="0.05" value="1.4"> <input type="range" class="min-slider" id="minSlider" min="0" max="8" step="0.05" value="1.4">
</div> </div>
<div class="slider-group"> <div class="slider-group">
@ -240,7 +290,7 @@
Верхний порог (выключение) Верхний порог (выключение)
<span id="maxThresholdVal">6.20</span> атм <span id="maxThresholdVal">6.20</span> атм
</label> </label>
<input type="range" id="maxSlider" min="0" max="8" step="0.05" value="6.2"> <input type="range" class="max-slider" id="maxSlider" min="0" max="8" step="0.05" value="6.2">
</div> </div>
<button class="save-btn" id="saveButton">💾 СОХРАНИТЬ УСТАНОВКИ</button> <button class="save-btn" id="saveButton">💾 СОХРАНИТЬ УСТАНОВКИ</button>
@ -612,10 +662,10 @@
if (corrected) { if (corrected) {
// дополнительное уведомление о корректировке через тост, но уже показываем общий // дополнительное уведомление о корректировке через тост, но уже показываем общий
toast.innerText = "✓ Корректные пороги сохранены"; toast.innerText = "✓ Корректные пороги сохранены";
setTimeout(() => { toast.innerText = "✓ Пороги успешно сохранены"; }, 1500); // setTimeout(() => { toast.innerText = "✓ Пороги успешно сохранены"; }, 1500);
} else { } else {
toast.innerText = "✓ Пороги сохранены"; toast.innerText = "✓ Пороги сохранены";
setTimeout(() => { toast.innerText = "✓ Пороги успешно сохранены"; }, 1400); // setTimeout(() => { toast.innerText = "✓ Пороги успешно сохранены"; }, 1400);
} }
}); });
} }

View File

@ -12,7 +12,8 @@ init:
build: build:
#!/bin/sh #!/bin/sh
. "{{ESPRESSIF}}/export.sh" . "{{ESPRESSIF}}/export.sh"
idf.py xxd -i assets/index.html > main/frontend.h
idf.py build
upload: upload:

View File

@ -20,6 +20,7 @@
#include "esp_adc/adc_oneshot.h" #include "esp_adc/adc_oneshot.h"
#include "esp_adc/adc_cali.h" #include "esp_adc/adc_cali.h"
#include "esp_adc/adc_cali_scheme.h" #include "esp_adc/adc_cali_scheme.h"
#include "frontend.h"
// ==================== НАСТРОЙКИ ТОЧКИ ДОСТУПА ==================== // ==================== НАСТРОЙКИ ТОЧКИ ДОСТУПА ====================
#define AP_SSID "ESP32_Hotspot" // Имя Wi-Fi сети #define AP_SSID "ESP32_Hotspot" // Имя Wi-Fi сети
@ -256,7 +257,7 @@ static esp_err_t root_get_handler(httpd_req_t *req)
"</html>"; "</html>";
httpd_resp_set_type(req, "text/html; charset=utf-8"); httpd_resp_set_type(req, "text/html; charset=utf-8");
httpd_resp_send(req, response, HTTPD_RESP_USE_STRLEN); httpd_resp_send(req, (const char*)assets_index_html, HTTPD_RESP_USE_STRLEN);
return ESP_OK; return ESP_OK;
} }