feat: implement Sleepy sleep diary

This commit is contained in:
2026-10-11 12:45:09 +07:00
commit a0fa0e0e56
27 changed files with 8356 additions and 0 deletions

1
public/favicon.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><rect width="512" height="512" rx="112" fill="#f5f4ed"/><circle cx="256" cy="256" r="168" fill="#141413"/><text x="256" y="322" text-anchor="middle" font-family="Georgia, serif" font-size="200" fill="#f5f4ed">☾</text><circle cx="356" cy="176" r="18" fill="#c96442"/></svg>

After

Width:  |  Height:  |  Size: 337 B

View File

@@ -0,0 +1,10 @@
{
"name": "Sleepy - дневник сна",
"short_name": "Sleepy",
"description": "Личный дневник сна.",
"start_url": "/",
"display": "standalone",
"background_color": "#f5f4ed",
"theme_color": "#f5f4ed",
"icons": [{ "src": "/favicon.svg", "sizes": "any", "type": "image/svg+xml", "purpose": "any maskable" }]
}

17
public/sw.js Normal file
View File

@@ -0,0 +1,17 @@
const CACHE = 'sleepy-v1';
const ASSETS = ['/', '/manifest.webmanifest', '/favicon.svg'];
self.addEventListener('install', (event) => {
event.waitUntil(caches.open(CACHE).then((cache) => cache.addAll(ASSETS)));
self.skipWaiting();
});
self.addEventListener('activate', (event) => {
event.waitUntil(caches.keys().then((keys) => Promise.all(keys.filter((key) => key !== CACHE).map((key) => caches.delete(key)))));
self.clients.claim();
});
self.addEventListener('fetch', (event) => {
if (event.request.method !== 'GET') return;
event.respondWith(fetch(event.request).catch(() => caches.match(event.request).then((cached) => cached ?? caches.match('/'))));
});