From a3c48b55a13616e8221ca644e128d0b2b33f38c3 Mon Sep 17 00:00:00 2001 From: Macbook Date: Sun, 14 Dec 2025 00:01:54 +0300 Subject: [PATCH] =?UTF-8?q?=D1=81=D0=BF=D0=B8=D0=BD=D0=BD=D0=B5=D1=80=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B8=20=D1=81=20?= =?UTF-8?q?=D1=81=D0=B5=D1=80=D0=B2=D0=B5=D1=80=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/static/css/layout.css | 28 ++++++++++++++++++++++++++++ api/static/js/api.js | 39 +++++++++++++++++++++++++++++++-------- api/templates/layout.html | 8 ++++++++ 3 files changed, 67 insertions(+), 8 deletions(-) diff --git a/api/static/css/layout.css b/api/static/css/layout.css index b7d1727..f090e7c 100644 --- a/api/static/css/layout.css +++ b/api/static/css/layout.css @@ -3,3 +3,31 @@ body { background-repeat: repeat; background-size: 512px auto; } + +.loader-bg { + width: 50px; + height: 50px; + border-radius: 50%; + + /* светлый фон */ + background: rgba(255, 255, 255, 0.85); + + /* мягкая тень = эффект размытия краёв */ + box-shadow: + 0 0 0 8px rgba(255, 255, 255, 0.35), + 0 0 20px rgba(0, 0, 0, 0.08); + + /* чуть сглаживаем */ + backdrop-filter: blur(2px); +} + +/* плавное появление */ +#globalLoader { + transition: opacity .15s ease-in-out; +} +#globalLoader.d-none { + opacity: 0; +} +#globalLoader:not(.d-none) { + opacity: 1; +} \ No newline at end of file diff --git a/api/static/js/api.js b/api/static/js/api.js index b827918..c2783f7 100644 --- a/api/static/js/api.js +++ b/api/static/js/api.js @@ -1,4 +1,23 @@ // api.js +let loaderTimeout = null; + +function showLoader() { + const loader = document.getElementById('globalLoader'); + if (!loader) return; + + clearTimeout(loaderTimeout); + loader.classList.remove('d-none'); +} + +function hideLoader() { + const loader = document.getElementById('globalLoader'); + if (!loader) return; + + loaderTimeout = setTimeout(() => { + loader.classList.add('d-none'); + }, 200); // задержка 0.2 сек +} + export async function apiRequest(url, payload = {}, method = 'POST') { method = method.toUpperCase(); @@ -12,21 +31,25 @@ export async function apiRequest(url, payload = {}, method = 'POST') { credentials: 'same-origin' }; - // --- Если GET → добавляем payload в URL --- if (method === 'GET') { const params = new URLSearchParams(payload); finalUrl = `${url}?${params.toString()}`; } else { - // --- Для остальных методов → отправляем body --- options.body = JSON.stringify(payload); } - const res = await fetch(finalUrl, options); + showLoader(); - if (!res.ok) { - const text = await res.text(); - throw new Error(`HTTP ${res.status}: ${text}`); + try { + const res = await fetch(finalUrl, options); + + if (!res.ok) { + const text = await res.text(); + throw new Error(`HTTP ${res.status}: ${text}`); + } + + return await res.json(); + } finally { + hideLoader(); } - - return res.json(); } \ No newline at end of file diff --git a/api/templates/layout.html b/api/templates/layout.html index 6fdbdf5..5f71a98 100644 --- a/api/templates/layout.html +++ b/api/templates/layout.html @@ -25,6 +25,14 @@ {% block body %}{% endblock %} +
+
+
+ Loading... +
+
+
+