From 1917bf89742faf2daf0ee29fa66fc26cc8702782 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 21 Jun 2026 18:30:32 +0000 Subject: [PATCH 001/117] Use native share sheet on iOS for event link MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Przycisk udostępniania korzysta z navigator.share (systemowy Share Sheet: iMessage/WhatsApp…) na telefonie, z fallbackiem do schowka na desktopie. Wykrywanie wsparcia po stronie klienta, by uniknąć rozjazdu z SSR. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_017ErbidN4HCXywidwUdDcbf --- src/app/event/[id]/page.tsx | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/app/event/[id]/page.tsx b/src/app/event/[id]/page.tsx index 690b394..301dcb0 100644 --- a/src/app/event/[id]/page.tsx +++ b/src/app/event/[id]/page.tsx @@ -37,6 +37,11 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> const [newSlot, setNewSlot] = useState(''); const [copied, setCopied] = useState(false); + const [canShare, setCanShare] = useState(false); + + useEffect(() => { + setCanShare(typeof navigator !== 'undefined' && typeof navigator.share === 'function'); + }, []); const load = useCallback(async () => { const [{ data: ev, error: evErr }, { data: sl }, { data: vo }, { data: pr }] = await Promise.all([ @@ -158,9 +163,24 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> router.push('/'); } - async function copyLink() { + async function shareLink() { + const url = window.location.href; + // Na iOS/mobile użyj natywnego Share Sheet (iMessage/WhatsApp…); to gest użytkownika. + if (typeof navigator !== 'undefined' && typeof navigator.share === 'function') { + try { + await navigator.share({ + title: event?.title ? `Wypad: ${event.title}` : 'Wypad', + text: event?.title ? `Ustalmy termin: ${event.title}` : 'Ustalmy termin wypadu', + url, + }); + } catch { + /* użytkownik anulował udostępnianie — nic nie robimy */ + } + return; + } + // Fallback (desktop): skopiuj link do schowka. try { - await navigator.clipboard.writeText(window.location.href); + await navigator.clipboard.writeText(url); setCopied(true); setTimeout(() => setCopied(false), 1500); } catch { @@ -221,8 +241,8 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> )}
- From 0ca3f2a67190cebf4d41eb7946a0d13f4673f515 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 21 Jun 2026 18:32:23 +0000 Subject: [PATCH 002/117] Add quick time-slot presets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Chipy „Dziś/Jutro/Piątek/Sobota 19:00" wstawiają termin jednym tapem — mniej dłubania w pickerze daty na telefonie. Wspólny helper slotPresets.ts użyty w formularzu tworzenia (wypełnia wiersze) i przy dodawaniu terminu na stronie wypadu (wstawia od razu). Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_017ErbidN4HCXywidwUdDcbf --- src/app/event/[id]/page.tsx | 27 +++++++++++++++++++++---- src/app/globals.css | 3 +++ src/app/page.tsx | 21 +++++++++++++++++++ src/lib/slotPresets.ts | 40 +++++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 src/lib/slotPresets.ts diff --git a/src/app/event/[id]/page.tsx b/src/app/event/[id]/page.tsx index 301dcb0..991f025 100644 --- a/src/app/event/[id]/page.tsx +++ b/src/app/event/[id]/page.tsx @@ -6,6 +6,7 @@ import { useRouter } from 'next/navigation'; import { supabase } from '@/lib/supabaseClient'; import { useAuth } from '@/lib/auth'; import type { Availability, EventRow, Profile, Slot, Vote } from '@/lib/types'; +import { SLOT_PRESETS } from '@/lib/slotPresets'; const CHOICES: { value: Availability; label: string; cls: string }[] = [ { value: 'yes', label: 'Mogę', cls: 'active-yes' }, @@ -89,15 +90,20 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> }; }, [eventId, load]); - async function addSlot(e: React.FormEvent) { - e.preventDefault(); - if (!newSlot) return; + async function insertSlot(localValue: string) { + if (!localValue) return; await supabase.from('slots').insert({ event_id: eventId, - starts_at: new Date(newSlot).toISOString(), + starts_at: new Date(localValue).toISOString(), created_by: displayName, created_by_user_id: userId, }); + } + + async function addSlot(e: React.FormEvent) { + e.preventDefault(); + if (!newSlot) return; + await insertSlot(newSlot); setNewSlot(''); } @@ -356,6 +362,19 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> ); })} +
+ {SLOT_PRESETS.map((p) => ( + + ))} +
+
+
+ {SLOT_PRESETS.map((p) => ( + + ))} +
{proposedSlots.map((slot, i) => (
(czas lokalny). + +function pad(n: number): string { + return String(n).padStart(2, '0'); +} + +// Date → "YYYY-MM-DDTHH:mm" w czasie lokalnym (format datetime-local). +function toLocalInput(d: Date): string { + return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`; +} + +function atHour(d: Date, hour: number): Date { + const r = new Date(d); + r.setHours(hour, 0, 0, 0); + return r; +} + +// Najbliższy dzień tygodnia (0 = niedziela … 6 = sobota); jeśli dziś jest ten dzień, zwraca dziś. +function nextWeekday(from: Date, weekday: number): Date { + const r = new Date(from); + r.setDate(r.getDate() + ((weekday - r.getDay() + 7) % 7)); + return r; +} + +export type SlotPreset = { label: string; build: (now?: Date) => string }; + +export const SLOT_PRESETS: SlotPreset[] = [ + { label: 'Dziś 19:00', build: (now = new Date()) => toLocalInput(atHour(now, 19)) }, + { + label: 'Jutro 19:00', + build: (now = new Date()) => { + const d = new Date(now); + d.setDate(d.getDate() + 1); + return toLocalInput(atHour(d, 19)); + }, + }, + { label: 'Piątek 19:00', build: (now = new Date()) => toLocalInput(atHour(nextWeekday(now, 5), 19)) }, + { label: 'Sobota 19:00', build: (now = new Date()) => toLocalInput(atHour(nextWeekday(now, 6), 19)) }, +]; From b4cdea488eac70b7811cf3796793a9350bc32e00 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 21 Jun 2026 19:13:52 +0000 Subject: [PATCH 003/117] Fix vote flicker on rapid clicks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Szybkie naprzemienne klikanie powodowało „mruganie" własnego wyboru: każde zdarzenie realtime przeładowywało całość z bazy, a odpowiedzi wracały w złej kolejności względem niezatwierdzonych zapisów. Trzymamy ostatni zamierzony głos w refie i nakładamy go na każde przeładowanie, aż baza go potwierdzi. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_017ErbidN4HCXywidwUdDcbf --- src/app/event/[id]/page.tsx | 48 +++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/src/app/event/[id]/page.tsx b/src/app/event/[id]/page.tsx index 991f025..9f551f7 100644 --- a/src/app/event/[id]/page.tsx +++ b/src/app/event/[id]/page.tsx @@ -1,6 +1,6 @@ 'use client'; -import { use, useCallback, useEffect, useMemo, useState } from 'react'; +import { use, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; import { supabase } from '@/lib/supabaseClient'; @@ -40,6 +40,10 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> const [copied, setCopied] = useState(false); const [canShare, setCanShare] = useState(false); + // Ostatni zamierzony głos użytkownika per slot — utrzymywany aż baza go potwierdzi. + // Chroni przed „mruganiem" przy szybkim, naprzemiennym klikaniu (wyścig realtime). + const pendingVotesRef = useRef>(new Map()); + useEffect(() => { setCanShare(typeof navigator !== 'undefined' && typeof navigator.share === 'function'); }, []); @@ -57,11 +61,40 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> } else { setEvent(ev as EventRow); setSlots((sl ?? []) as Slot[]); - setVotes((vo ?? []) as Vote[]); setMembers((pr ?? []) as Profile[]); + + // Nałóż oczekujące głosy bieżącego użytkownika na świeży stan z bazy: + // jego ostatni wybór wygrywa, dopóki baza go nie potwierdzi (wtedy czyścimy pending). + const dbVotes = (vo ?? []) as Vote[]; + const pending = pendingVotesRef.current; + const merged = dbVotes.map((v) => { + if (v.user_id === userId && pending.has(v.slot_id)) { + const want = pending.get(v.slot_id)!; + if (v.availability === want) { + pending.delete(v.slot_id); + return v; + } + return { ...v, availability: want }; + } + return v; + }); + for (const [slotId, want] of pending) { + if (!merged.some((v) => v.user_id === userId && v.slot_id === slotId)) { + merged.push({ + id: `optimistic-${slotId}-${userId}`, + event_id: eventId, + slot_id: slotId, + user_id: userId, + participant_name: displayName, + availability: want, + created_at: new Date().toISOString(), + }); + } + } + setVotes(merged); } setLoading(false); - }, [eventId]); + }, [eventId, userId, displayName]); useEffect(() => { load(); @@ -116,6 +149,8 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> } async function vote(slotId: string, availability: Availability) { + // Zapamiętaj zamiar — przeładowania z bazy będą go respektować aż do potwierdzenia. + pendingVotesRef.current.set(slotId, availability); // Optymistyczna aktualizacja: pokaż wybór od razu, zanim baza odpowie — // bez tego na komórce tap wygląda jakby nie zadziałał (feedback dopiero po realtime). setVotes((prev) => { @@ -139,8 +174,11 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> { event_id: eventId, slot_id: slotId, user_id: userId, participant_name: displayName, availability }, { onConflict: 'slot_id,user_id' }, ); - // Przy błędzie cofnij optymistyczną zmianę, pobierając prawdziwy stan z bazy. - if (error) load(); + // Przy błędzie porzuć zamiar i wróć do prawdziwego stanu z bazy. + if (error) { + pendingVotesRef.current.delete(slotId); + load(); + } } async function confirmSlot(slotId: string, startsAt: string) { From cb119aa5995bada9279d26163bc8a4c50fb2b7f6 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 21 Jun 2026 19:21:01 +0000 Subject: [PATCH 004/117] Polish iOS: PNG icons, dark controls, status bar, touch targets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Ikony PNG (180/192/512) z SVG przez sharp; apple-touch-icon na PNG, bo iOS słabo renderuje SVG na ekranie głównym. Dodane do manifestu. - color-scheme: dark — natywny picker daty i kontrolki w ciemnym motywie. - statusBarStyle: black-translucent — pasek statusu pasuje do ciemnej apki. - Większe cele dotykowe: ✕ usuwania i chipy presetów (~40px). - Brak szarego tap-highlight, stabilny -webkit-text-size-adjust. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_017ErbidN4HCXywidwUdDcbf --- public/icon-180.png | Bin 0 -> 3381 bytes public/icon-192.png | Bin 0 -> 3345 bytes public/icon-512.png | Bin 0 -> 11646 bytes public/manifest.webmanifest | 12 ++++++++++++ src/app/globals.css | 14 +++++++++++--- src/app/layout.tsx | 4 ++-- 6 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 public/icon-180.png create mode 100644 public/icon-192.png create mode 100644 public/icon-512.png diff --git a/public/icon-180.png b/public/icon-180.png new file mode 100644 index 0000000000000000000000000000000000000000..871c537428a161001258a2b958860a5f3b05aae0 GIT binary patch literal 3381 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 LNkvXXu0mjfu&`Gd literal 0 HcmV?d00001 diff --git a/public/icon-192.png b/public/icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..f939341b8b1051745d9de48926a3ba525902711f GIT binary patch literal 3345 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 literal 0 HcmV?d00001 diff --git a/public/icon-512.png b/public/icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..17e6eccd100fbb0260a1f13e442a9aea1ff702f5 GIT binary patch literal 11646 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 D9KuJ- literal 0 HcmV?d00001 diff --git a/public/manifest.webmanifest b/public/manifest.webmanifest index 082c1bc..cb6d1c5 100644 --- a/public/manifest.webmanifest +++ b/public/manifest.webmanifest @@ -13,6 +13,18 @@ "sizes": "any", "type": "image/svg+xml", "purpose": "any maskable" + }, + { + "src": "/icon-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "/icon-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "any maskable" } ] } diff --git a/src/app/globals.css b/src/app/globals.css index 0db1868..72bc442 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -11,9 +11,13 @@ --maybe: #eab308; --no: #ef4444; --radius: 14px; + /* Ciemny motyw również dla kontrolek natywnych (picker daty, scrollbary) na iOS. */ + color-scheme: dark; } -* { box-sizing: border-box; } +* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; } + +html { -webkit-text-size-adjust: 100%; } html, body { margin: 0; @@ -89,7 +93,7 @@ button.ghost.danger { color: var(--no); border-color: rgba(239, 68, 68, 0.4); } button.ghost.danger:hover { background: rgba(239, 68, 68, 0.1); border-color: var(--no); } .chips { gap: 8px; } -button.chip { padding: 6px 12px; font-size: 0.85rem; font-weight: 500; } +button.chip { min-height: 40px; padding: 8px 14px; font-size: 0.85rem; font-weight: 500; } .row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; } .spacer { flex: 1; } @@ -118,7 +122,11 @@ button.chip { padding: 6px 12px; font-size: 0.85rem; font-weight: 500; } .slot-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; } .slot-date { font-weight: 600; font-size: 1.05rem; } -.slot-del { padding: 4px 10px; font-size: 0.85rem; line-height: 1; color: var(--muted); } +.slot-del { + min-width: 40px; min-height: 40px; + display: inline-flex; align-items: center; justify-content: center; + padding: 4px 10px; font-size: 1rem; line-height: 1; color: var(--muted); +} .slot-del:hover { color: var(--no); border-color: var(--no); } .badge { font-size: 0.75rem; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index d9f75d6..1282d93 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -8,8 +8,8 @@ export const metadata: Metadata = { title: 'Planner — ustalajcie terminy bez chaosu', description: 'Zaproponuj terminy wypadu, zbierz głosy znajomych i zobacz wynik na żywo.', manifest: '/manifest.webmanifest', - appleWebApp: { capable: true, statusBarStyle: 'default', title: 'Planner' }, - icons: { icon: '/icon.svg', apple: '/icon.svg' }, + appleWebApp: { capable: true, statusBarStyle: 'black-translucent', title: 'Planner' }, + icons: { icon: '/icon.svg', apple: '/icon-180.png' }, }; export const viewport: Viewport = { From 0880d4834911ffa4fc39fd7cad5356160c801f21 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 21 Jun 2026 19:31:04 +0000 Subject: [PATCH 005/117] Redesign: clean minimal dark theme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Przeprojektowanie warstwy wizualnej w stronę czystego, minimalnego dark mode (Apple-like): spokojniejsza, neutralniejsza paleta, hairline'owe obramowania, więcej powietrza, subtelne cienie i pille, segmentowana kontrolka głosowania (Mogę/Może/Nie), kolory systemowe iOS dla yes/maybe/no, focus-ring na inputach. Wszystkie klasy i zmienne CSS zachowane — markup bez zmian. Theme/splash kolory zsynchronizowane z nową paletą. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_017ErbidN4HCXywidwUdDcbf --- public/manifest.webmanifest | 4 +- src/app/globals.css | 191 ++++++++++++++++++++++-------------- src/app/layout.tsx | 2 +- 3 files changed, 118 insertions(+), 79 deletions(-) diff --git a/public/manifest.webmanifest b/public/manifest.webmanifest index cb6d1c5..bd14a00 100644 --- a/public/manifest.webmanifest +++ b/public/manifest.webmanifest @@ -5,8 +5,8 @@ "start_url": "/", "scope": "/", "display": "standalone", - "background_color": "#0b1020", - "theme_color": "#4f46e5", + "background_color": "#0a0b12", + "theme_color": "#5b57f2", "icons": [ { "src": "/icon.svg", diff --git a/src/app/globals.css b/src/app/globals.css index 72bc442..98f9d55 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,16 +1,19 @@ :root { - --bg: #0b1020; - --card: #151a2e; - --card-2: #1b2238; - --text: #e6e9f5; - --muted: #9aa3c0; - --border: #2a3252; - --primary: #4f46e5; - --primary-hover: #6366f1; - --yes: #22c55e; - --maybe: #eab308; - --no: #ef4444; - --radius: 14px; + --bg: #0a0b12; + --card: #15161e; + --card-2: #1c1e28; + --text: #f2f3f7; + --muted: #9499a8; + --border: rgba(255, 255, 255, 0.09); + --border-strong: rgba(255, 255, 255, 0.16); + --primary: #5b57f2; + --primary-hover: #6f6cf6; + --yes: #30d158; + --maybe: #ffd60a; + --no: #ff453a; + --radius: 18px; + --radius-sm: 12px; + --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 10px 30px rgba(0, 0, 0, 0.18); /* Ciemny motyw również dla kontrolek natywnych (picker daty, scrollbary) na iOS. */ color-scheme: dark; } @@ -24,76 +27,91 @@ html, body { padding: 0; background: var(--bg); color: var(--text); - font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif; + font-family: -apple-system, system-ui, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 1.5; -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; } .container { - max-width: 720px; + max-width: 680px; margin: 0 auto; /* Marginesy + bezpieczne obszary iOS (notch, pasek home) w trybie standalone. */ padding: - calc(24px + env(safe-area-inset-top)) calc(16px + env(safe-area-inset-right)) - calc(64px + env(safe-area-inset-bottom)) calc(16px + env(safe-area-inset-left)); + calc(28px + env(safe-area-inset-top)) calc(20px + env(safe-area-inset-right)) + calc(72px + env(safe-area-inset-bottom)) calc(20px + env(safe-area-inset-left)); } -h1 { font-size: 1.9rem; margin: 0 0 4px; } -h2 { font-size: 1.15rem; margin: 0 0 12px; } +h1 { font-size: 1.7rem; font-weight: 700; letter-spacing: -0.021em; margin: 0 0 4px; } +h2 { font-size: 1.05rem; font-weight: 600; letter-spacing: -0.012em; margin: 0 0 14px; } +p { margin: 0 0 12px; } p.lead { color: var(--muted); margin-top: 0; } -a { color: var(--primary-hover); } +a { color: var(--primary-hover); text-decoration: none; } +a:hover { text-decoration: underline; } .card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); - padding: 18px; + padding: 20px; margin-bottom: 16px; + box-shadow: var(--shadow); } label { display: block; font-size: 0.85rem; color: var(--muted); margin-bottom: 6px; } input[type="text"], +input[type="email"], input[type="datetime-local"] { width: 100%; - padding: 12px 14px; + padding: 13px 15px; background: var(--card-2); color: var(--text); border: 1px solid var(--border); - border-radius: 10px; + border-radius: var(--radius-sm); font-size: 1rem; + transition: border-color 0.15s ease, box-shadow 0.15s ease; } -input::placeholder { color: #6b7392; } +input:focus { + outline: none; + border-color: var(--primary); + box-shadow: 0 0 0 3px rgba(91, 87, 242, 0.25); +} +input::placeholder { color: #6a6f80; } -.field { margin-bottom: 14px; } +.field { margin-bottom: 16px; } button { cursor: pointer; border: none; - border-radius: 10px; - padding: 12px 16px; + border-radius: var(--radius-sm); + padding: 13px 18px; font-size: 1rem; font-weight: 600; + letter-spacing: -0.01em; background: var(--primary); color: white; - transition: background 0.15s ease, transform 0.05s ease; + transition: background 0.15s ease, transform 0.06s ease, opacity 0.15s ease; } button:hover { background: var(--primary-hover); } -button:active { transform: translateY(1px); } -button:disabled { opacity: 0.5; cursor: not-allowed; } +button:active { transform: scale(0.975); } +button:disabled { opacity: 0.45; cursor: not-allowed; } +button:focus-visible { outline: 2px solid var(--primary-hover); outline-offset: 2px; } button.ghost { - background: transparent; + background: var(--card-2); border: 1px solid var(--border); color: var(--text); font-weight: 500; } -button.ghost:hover { background: var(--card-2); } +button.ghost:hover { background: #262833; border-color: var(--border-strong); } -button.ghost.danger { color: var(--no); border-color: rgba(239, 68, 68, 0.4); } -button.ghost.danger:hover { background: rgba(239, 68, 68, 0.1); border-color: var(--no); } +button.ghost.danger { color: var(--no); border-color: rgba(255, 69, 58, 0.35); background: rgba(255, 69, 58, 0.08); } +button.ghost.danger:hover { background: rgba(255, 69, 58, 0.14); border-color: var(--no); } .chips { gap: 8px; } -button.chip { min-height: 40px; padding: 8px 14px; font-size: 0.85rem; font-weight: 500; } +button.chip { min-height: 40px; padding: 9px 14px; font-size: 0.85rem; font-weight: 500; border-radius: 999px; } .row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; } .spacer { flex: 1; } @@ -101,60 +119,80 @@ button.chip { min-height: 40px; padding: 8px 14px; font-size: 0.85rem; font-weig .small { font-size: 0.85rem; } .banner { - background: #3b2a12; - border: 1px solid #6b4d1f; - color: #fce6b5; + background: rgba(255, 214, 10, 0.08); + border: 1px solid rgba(255, 214, 10, 0.28); + color: #f6e7b0; border-radius: var(--radius); padding: 16px; margin-bottom: 16px; font-size: 0.92rem; } -.banner code { background: rgba(0,0,0,0.3); padding: 1px 6px; border-radius: 6px; } +.banner code { background: rgba(0, 0, 0, 0.35); padding: 1px 6px; border-radius: 6px; } .slot { border: 1px solid var(--border); - border-radius: 12px; - padding: 14px; + border-radius: var(--radius-sm); + padding: 16px; margin-bottom: 12px; background: var(--card-2); + transition: border-color 0.15s ease, box-shadow 0.15s ease; } -.slot.winner { border-color: var(--yes); box-shadow: 0 0 0 1px var(--yes) inset; } +.slot.winner { border-color: rgba(48, 209, 88, 0.5); box-shadow: 0 0 0 1px rgba(48, 209, 88, 0.5) inset; } -.slot-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; } -.slot-date { font-weight: 600; font-size: 1.05rem; } +.slot-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; } +.slot-date { font-weight: 600; font-size: 1.05rem; letter-spacing: -0.01em; } .slot-del { min-width: 40px; min-height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 4px 10px; font-size: 1rem; line-height: 1; color: var(--muted); } .slot-del:hover { color: var(--no); border-color: var(--no); } + .badge { - font-size: 0.75rem; - font-weight: 700; - padding: 2px 8px; + font-size: 0.72rem; + font-weight: 600; + padding: 3px 10px; border-radius: 999px; - background: var(--yes); - color: #06310f; + background: rgba(48, 209, 88, 0.16); + color: var(--yes); + letter-spacing: 0.01em; + white-space: nowrap; } +.badge-open { background: rgba(255, 214, 10, 0.16); color: var(--maybe); } -.tally { display: flex; gap: 14px; font-size: 0.85rem; margin-bottom: 10px; } -.tally .yes { color: var(--yes); } -.tally .maybe { color: var(--maybe); } -.tally .no { color: var(--no); } +.tally { display: flex; gap: 8px; margin-bottom: 12px; } +.tally span { font-size: 0.8rem; font-weight: 600; padding: 3px 9px; border-radius: 999px; } +.tally .yes { color: var(--yes); background: rgba(48, 209, 88, 0.14); } +.tally .maybe { color: var(--maybe); background: rgba(255, 214, 10, 0.14); } +.tally .no { color: var(--no); background: rgba(255, 69, 58, 0.14); } -.choices { display: flex; gap: 8px; } +/* Głosowanie jako kontrolka segmentowa (iOS-like). */ +.choices { + display: flex; + gap: 4px; + background: rgba(0, 0, 0, 0.25); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + padding: 4px; +} .choices button { flex: 1; - background: var(--card); - border: 1px solid var(--border); + background: transparent; + border: none; color: var(--muted); font-weight: 600; + border-radius: 9px; + padding: 10px 8px; } -.choices button.active-yes { background: var(--yes); color: #06310f; border-color: var(--yes); } -.choices button.active-maybe { background: var(--maybe); color: #3b2f04; border-color: var(--maybe); } -.choices button.active-no { background: var(--no); color: #3b0a0a; border-color: var(--no); } - -.voters { font-size: 0.82rem; color: var(--muted); margin-top: 8px; } +.choices button:hover { background: rgba(255, 255, 255, 0.05); } +.choices button.active-yes { background: var(--yes); color: #04210d; } +.choices button.active-maybe { background: var(--maybe); color: #3b2f04; } +.choices button.active-no { background: var(--no); color: #fff; } +.choices button.active-yes:hover { background: var(--yes); } +.choices button.active-maybe:hover { background: var(--maybe); } +.choices button.active-no:hover { background: var(--no); } + +.voters { font-size: 0.82rem; color: var(--muted); margin-top: 10px; line-height: 1.7; } .voters .name { color: var(--text); } .center { text-align: center; } @@ -165,15 +203,15 @@ button.chip { min-height: 40px; padding: 8px 14px; font-size: 0.85rem; font-weig display: flex; align-items: center; justify-content: space-between; - padding: 14px; + padding: 16px; margin-bottom: 8px; - background: var(--card-2); + background: var(--card); border: 1px solid var(--border); - border-radius: 12px; + border-radius: 14px; text-decoration: none; color: var(--text); } -.list-item:hover { border-color: var(--primary); } +.list-item:hover { border-color: var(--border-strong); } .list-item-title { font-weight: 600; } /* Karty wypadów na osi czasu */ @@ -182,29 +220,30 @@ button.chip { min-height: 40px; padding: 8px 14px; font-size: 0.85rem; font-weig align-items: center; justify-content: space-between; gap: 12px; - padding: 14px; + padding: 16px; margin-bottom: 10px; - background: var(--card-2); + background: var(--card); border: 1px solid var(--border); - border-radius: 12px; + border-radius: 14px; text-decoration: none; color: var(--text); + box-shadow: var(--shadow); + transition: background 0.15s ease, border-color 0.15s ease, transform 0.06s ease; } -.event-card:hover { border-color: var(--primary); } -.event-card-title { font-weight: 600; } +.event-card:hover { background: var(--card-2); border-color: var(--border-strong); } +.event-card:active { transform: scale(0.99); } +.event-card-title { font-weight: 600; letter-spacing: -0.01em; } .event-card-status { flex-shrink: 0; text-align: right; } -.badge-open { background: var(--maybe); color: #3b2f04; } - /* Baner ustalonego terminu na stronie wypadu */ .confirmed-banner { margin-top: 12px; - padding: 12px 14px; - border-radius: 12px; - background: rgba(34, 197, 94, 0.12); - border: 1px solid var(--yes); + padding: 14px 16px; + border-radius: var(--radius-sm); + background: rgba(48, 209, 88, 0.12); + border: 1px solid rgba(48, 209, 88, 0.4); color: var(--yes); font-weight: 600; } -.slot.confirmed { border-color: var(--yes); box-shadow: 0 0 0 1px var(--yes) inset; } +.slot.confirmed { border-color: rgba(48, 209, 88, 0.5); box-shadow: 0 0 0 1px rgba(48, 209, 88, 0.5) inset; } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 1282d93..2c10930 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -13,7 +13,7 @@ export const metadata: Metadata = { }; export const viewport: Viewport = { - themeColor: '#4f46e5', + themeColor: '#5b57f2', width: 'device-width', initialScale: 1, viewportFit: 'cover', From ee6db72392234e6200b195acf0eca816127eccd3 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 22 Jun 2026 14:16:35 +0000 Subject: [PATCH 006/117] Redesign layout: iOS-style grouped lists and hierarchy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pełna przebudowa układu (nie tylko kolory): - Dashboard: large title + powitanie, sekcje jako szare nagłówki, wypady jako zgrupowana lista (jedna wyspa z separatorami) z chevronami, prominentny „+ Nowy wypad", zdegradowany „Wyloguj", przyjazny stan pusty. - Strona wypadu: back-link, przeprojektowany nagłówek (tytuł/miejsce/organizator), „Czekamy na…" jako pille, subtelniejsze „Usuń wypad". - globals.css: nowe prymitywy iOS (list-group/list-row, section-label, large-title, empty-state, pill-wait/done, back-link); usunięte event-card/list-item. Czysto prezentacyjne — logika i baza bez zmian. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_017ErbidN4HCXywidwUdDcbf --- src/app/event/[id]/page.tsx | 33 +++++++------- src/app/globals.css | 91 ++++++++++++++++++++++++++----------- src/app/page.tsx | 60 ++++++++++++------------ 3 files changed, 114 insertions(+), 70 deletions(-) diff --git a/src/app/event/[id]/page.tsx b/src/app/event/[id]/page.tsx index 9f551f7..152bf43 100644 --- a/src/app/event/[id]/page.tsx +++ b/src/app/event/[id]/page.tsx @@ -275,10 +275,13 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> return (
-

← Wszystkie wypady

-

{event?.title}

- {event?.location &&

📍 {event.location}

} - {event?.created_by &&

Organizuje: {event.created_by}

} + ‹ Wszystkie wypady + +
+

{event?.title}

+ {event?.location &&

📍 {event.location}

} + {event?.created_by &&

Organizuje: {event.created_by}

} +
{event?.confirmed_at && (
✅ Ustalono: {formatSlot(event.confirmed_at)}
@@ -296,20 +299,18 @@ export default function EventPage({ params }: { params: Promise<{ id: string }>
-

Głosujesz jako {displayName}.

- {slots.length > 0 && members.length > 0 && ( - missingVoters.length > 0 ? ( -

- ⏳ Czekamy jeszcze na: {missingVoters.join(', ')} -

- ) : ( -

- ✅ Cała paczka już zagłosowała. -

- ) +
+ {missingVoters.length > 0 ? ( + ⏳ Czekamy na: {missingVoters.join(', ')} + ) : ( + ✅ Cała paczka zagłosowała + )} +
)} +

Głosujesz jako {displayName}.

+

Proponowane terminy

@@ -425,7 +426,7 @@ export default function EventPage({ params }: { params: Promise<{ id: string }>

{isOrganizer && ( - )} diff --git a/src/app/globals.css b/src/app/globals.css index 98f9d55..2252b3a 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -198,42 +198,81 @@ button.chip { min-height: 40px; padding: 9px 14px; font-size: 0.85rem; font-weig .center { text-align: center; } .mt { margin-top: 16px; } -/* Lista ekip na stronie głównej */ -.list-item { - display: flex; - align-items: center; - justify-content: space-between; - padding: 16px; - margin-bottom: 8px; +/* Nagłówek strony (iOS large title) */ +.app-header { margin-bottom: 18px; } +.large-title { font-size: 2rem; font-weight: 700; letter-spacing: -0.022em; margin: 0 0 2px; } + +/* Nagłówki sekcji (jak grupy w Ustawieniach iOS) */ +.section-label { + font-size: 0.78rem; + font-weight: 600; + letter-spacing: 0.04em; + text-transform: uppercase; + color: var(--muted); + margin: 26px 4px 8px; +} +.section-label.faded { color: #6a6f80; } + +/* Zgrupowana lista — jedna „wyspa" z cienkimi separatorami */ +.list-group { background: var(--card); border: 1px solid var(--border); - border-radius: 14px; - text-decoration: none; - color: var(--text); + border-radius: 16px; + overflow: hidden; + box-shadow: var(--shadow); } -.list-item:hover { border-color: var(--border-strong); } -.list-item-title { font-weight: 600; } - -/* Karty wypadów na osi czasu */ -.event-card { +.list-row { display: flex; align-items: center; - justify-content: space-between; gap: 12px; - padding: 16px; - margin-bottom: 10px; - background: var(--card); - border: 1px solid var(--border); - border-radius: 14px; + padding: 15px 16px; text-decoration: none; color: var(--text); + transition: background 0.15s ease, transform 0.06s ease; +} +.list-row + .list-row { border-top: 1px solid var(--border); } +.list-row:hover { background: var(--card-2); } +.list-row:active { transform: scale(0.992); } +.list-row-main { min-width: 0; flex: 1; } +.list-row-title { font-weight: 600; letter-spacing: -0.01em; } +.row-chevron { flex-shrink: 0; color: var(--muted); font-size: 1.3rem; line-height: 1; } + +/* Drobna linia meta (miejsce, organizator) */ +.meta { font-size: 0.85rem; color: var(--muted); margin: 3px 0 0; } +.meta:first-child { margin-top: 0; } + +/* Stan pusty */ +.empty-state { + text-align: center; + padding: 44px 24px; + background: var(--card); + border: 1px solid var(--border); + border-radius: var(--radius); box-shadow: var(--shadow); - transition: background 0.15s ease, border-color 0.15s ease, transform 0.06s ease; } -.event-card:hover { background: var(--card-2); border-color: var(--border-strong); } -.event-card:active { transform: scale(0.99); } -.event-card-title { font-weight: 600; letter-spacing: -0.01em; } -.event-card-status { flex-shrink: 0; text-align: right; } +.empty-state .emoji { font-size: 2.4rem; line-height: 1; } +.empty-state h2 { margin: 14px 0 4px; } +.empty-state p { color: var(--muted); margin: 0 auto 18px; max-width: 30ch; } + +/* Pille statusu głosowania */ +.pill-wait, .pill-done { + display: inline-block; + font-size: 0.85rem; + font-weight: 500; + padding: 8px 14px; + border-radius: 999px; +} +.pill-wait { color: var(--maybe); background: rgba(255, 214, 10, 0.12); border: 1px solid rgba(255, 214, 10, 0.25); } +.pill-done { color: var(--yes); background: rgba(48, 209, 88, 0.12); border: 1px solid rgba(48, 209, 88, 0.3); } + +/* Back link (iOS) */ +.back-link { + display: inline-flex; + align-items: center; + font-size: 0.95rem; + color: var(--primary-hover); + margin-bottom: 14px; +} /* Baner ustalonego terminu na stronie wypadu */ .confirmed-banner { diff --git a/src/app/page.tsx b/src/app/page.tsx index 44ec199..5adf40b 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -113,20 +113,18 @@ export default function Home() { return (
-
-

Planner

- - Cześć, {displayName} -
-

Wasze wypady w jednym miejscu — proponujcie terminy i ustalajcie kiedy.

- -
- - - -
+
+
+

Planner

+ + +
+

Cześć, {displayName} — wasze wypady w jednym miejscu.

+
+ + {showForm && ( @@ -215,8 +213,13 @@ export default function Home() { {loading &&

Wczytuję…

} - {!loading && events.length === 0 && ( -

Brak wypadów. Kliknij „+ Nowy wypad", żeby zaproponować pierwszy.

+ {!loading && events.length === 0 && !showForm && ( +
+
🗓️
+

Brak wypadów

+

Zaproponuj pierwszy termin i wyślij znajomym.

+ +
)} @@ -229,23 +232,24 @@ export default function Home() { function Timeline({ title, events, muted }: { title: string; events: EventRow[]; muted?: boolean }) { if (events.length === 0) return null; return ( -
-

{title}

- {events.map((ev) => ( - -
-
{ev.title}
- {ev.location &&
📍 {ev.location}
} -
-
+
+
{title}
+
+ {events.map((ev) => ( + +
+
{ev.title}
+ {ev.location &&
📍 {ev.location}
} +
{ev.confirmed_at ? ( {formatDate(ev.confirmed_at)} ) : ( Zbieramy terminy )} -
- - ))} + + + ))} +
); } From 2c535f7286ce1e5a94f28b0972f83fc9e4afee7b Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 22 Jun 2026 14:35:50 +0000 Subject: [PATCH 007/117] Hybrid redesign: iOS base with rich accents + avatar picker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wybór awatara przy pierwszym logowaniu (emoji), zapisany w user_metadata i profiles (nowa kolumna avatar). Dashboard wzbogacony zgodnie z kierunkiem hybrydowym: nagłówek z ikoną appki i awatarem usera, gradientowy CTA, karty wypadów z awatarami głosujących, ikonami daty/godziny/miejsca i paskiem „% zagłosowało"; baner z poradą. Strona wypadu: awatary uczestników i ikonki. Bez okładek/statystyk/dwóch kolumn — lekkie, jednokolumnowe, mobile-first. Nowe: src/lib/avatars.ts, src/components/icons.tsx, src/components/Avatar.tsx. Zmiana schematu: profiles.avatar (uruchom schema.sql ponownie). Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_017ErbidN4HCXywidwUdDcbf --- CLAUDE.md | 18 +-- src/app/event/[id]/page.tsx | 58 +++++++--- src/app/globals.css | 82 +++++++++++++- src/app/page.tsx | 214 +++++++++++++++++++++++++++--------- src/components/Avatar.tsx | 36 ++++++ src/components/icons.tsx | 45 ++++++++ src/lib/auth.tsx | 59 +++++++--- src/lib/avatars.ts | 22 ++++ src/lib/types.ts | 1 + supabase/schema.sql | 4 + 10 files changed, 451 insertions(+), 88 deletions(-) create mode 100644 src/components/Avatar.tsx create mode 100644 src/components/icons.tsx create mode 100644 src/lib/avatars.ts diff --git a/CLAUDE.md b/CLAUDE.md index c8cd7ab..ddcc0af 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -50,11 +50,15 @@ Guidance for AI assistants (and humans) working in this repository. │ ├── event/[id]/page.tsx # Strona wypadu: terminy, głosowanie, wynik na żywo, ustalanie terminu │ └── api/keepalive/route.ts # Endpoint pingowany cronem — utrzymuje bazę aktywną ├── components/ - │ └── SetupBanner.tsx # Baner gdy brak konfiguracji Supabase + │ ├── SetupBanner.tsx # Baner gdy brak konfiguracji Supabase + │ ├── Avatar.tsx # Avatar (emoji/inicjały) + AvatarStack + │ └── icons.tsx # Lekkie ikony inline SVG (kalendarz, zegar, pin…) └── lib/ ├── supabaseClient.ts # Klient Supabase + flaga isSupabaseConfigured - ├── auth.tsx # AuthProvider (logowanie e-mail/OTP, nazwa) + hook useAuth - └── types.ts # Typy: EventRow, Slot, Vote, Availability + ├── auth.tsx # AuthProvider (logowanie e-mail/OTP, nazwa+awatar) + hook useAuth + ├── slotPresets.ts # Szybkie presety terminów (chipy) + ├── avatars.ts # Lista emoji-awatarów + deterministyczne kolory/inicjały + └── types.ts # Typy: EventRow, Slot, Vote, Profile, Availability ``` **Punkty wejścia:** `src/app/page.tsx` (`/`, dashboard wszystkich wypadów) oraz @@ -64,7 +68,7 @@ serwerowej poza renderowaniem stron i endpointem keepalive. **Model produktu:** jeden wspólny planer dla jednej (stałej) paczki znajomych — bez „ekip". Wejście wymaga **logowania** (e-mail + kod OTP, Supabase Auth); po pierwszym -logowaniu użytkownik ustawia nazwę (w `user_metadata`). Sesja jest trwała. +logowaniu użytkownik ustawia nazwę i wybiera awatar (w `user_metadata`). Sesja jest trwała. ## Model danych @@ -76,9 +80,9 @@ Zdefiniowany w `supabase/schema.sql` (skrypt idempotentny — można uruchomić - **slots** — proponowany termin (`starts_at`) powiązany z wypadem. - **votes** — głos uczestnika: `availability` ∈ `yes | maybe | no`; `user_id` (konto) + `participant_name` (migawka nazwy). Unikalność: `(slot_id, user_id)`. -- **profiles** — lista „paczki": `id` (= `auth.users.id`) + `display_name`. Zapisywana - przez apkę po zalogowaniu (upsert w `auth.tsx`). Służy do pokazania „kto jeszcze nie - zagłosował", bo klient z kluczem `anon` nie ma dostępu do `auth.users`. +- **profiles** — lista „paczki": `id` (= `auth.users.id`) + `display_name` + `avatar` (emoji). + Zapisywana przez apkę po zalogowaniu (upsert w `auth.tsx`). Służy do pokazania „kto jeszcze + nie zagłosował" i awatarów uczestników, bo klient z kluczem `anon` nie ma dostępu do `auth.users`. - Nazwy wyświetlane trzymamy w `user_metadata` Supabase Auth oraz w `profiles`; przy głosach/wypadach zapisujemy dodatkowo migawkę nazwy. diff --git a/src/app/event/[id]/page.tsx b/src/app/event/[id]/page.tsx index 152bf43..55cb092 100644 --- a/src/app/event/[id]/page.tsx +++ b/src/app/event/[id]/page.tsx @@ -7,6 +7,8 @@ import { supabase } from '@/lib/supabaseClient'; import { useAuth } from '@/lib/auth'; import type { Availability, EventRow, Profile, Slot, Vote } from '@/lib/types'; import { SLOT_PRESETS } from '@/lib/slotPresets'; +import { Avatar, AvatarStack, type Person } from '@/components/Avatar'; +import { IconPin } from '@/components/icons'; const CHOICES: { value: Availability; label: string; cls: string }[] = [ { value: 'yes', label: 'Mogę', cls: 'active-yes' }, @@ -248,10 +250,19 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> const maxYes = useMemo(() => Math.max(0, ...stats.map((s) => s.yes)), [stats]); - const participants = useMemo( - () => Array.from(new Set(votes.map((v) => v.participant_name))), - [votes], - ); + const profileById = useMemo(() => new Map(members.map((m) => [m.id, m])), [members]); + + // Uczestnicy, którzy oddali jakikolwiek głos — z awatarami (do stosu na górze). + const participantsPeople = useMemo(() => { + const seen = new Map(); + for (const v of votes) { + const key = v.user_id ?? `name:${v.participant_name}`; + if (seen.has(key)) continue; + const prof = v.user_id ? profileById.get(v.user_id) : undefined; + seen.set(key, { name: prof?.display_name ?? v.participant_name, avatar: prof?.avatar ?? null }); + } + return Array.from(seen.values()); + }, [votes, profileById]); // Kto z paczki nie oddał jeszcze żadnego głosu w tym wypadzie. const missingVoters = useMemo(() => { @@ -279,7 +290,11 @@ export default function EventPage({ params }: { params: Promise<{ id: string }>

{event?.title}

- {event?.location &&

📍 {event.location}

} + {event?.location && ( +

+ {event.location} +

+ )} {event?.created_by &&

Organizuje: {event.created_by}

}
@@ -292,11 +307,14 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> {copied ? 'Skopiowano ✓' : canShare ? 'Udostępnij link 📤' : 'Skopiuj link dla znajomych'} - - {participants.length > 0 - ? `${participants.length} ${participants.length === 1 ? 'osoba' : 'osób'} już głosowało` - : 'Nikt jeszcze nie głosował'} - + {participantsPeople.length > 0 ? ( + + + {participantsPeople.length} głosowało + + ) : ( + Nikt jeszcze nie głosował + )}
{slots.length > 0 && members.length > 0 && ( @@ -375,14 +393,18 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> {slotVotes.length > 0 && (
- {slotVotes.map((v) => ( - - {v.participant_name} - {' '} - {v.availability === 'yes' ? '✓' : v.availability === 'maybe' ? '~' : '✗'} - {' '} - - ))} + {slotVotes.map((v) => { + const prof = v.user_id ? profileById.get(v.user_id) : undefined; + const name = prof?.display_name ?? v.participant_name; + return ( + + + {name} + {' '} + {v.availability === 'yes' ? '✓' : v.availability === 'maybe' ? '~' : '✗'} + + ); + })}
)} diff --git a/src/app/globals.css b/src/app/globals.css index 2252b3a..861b642 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -192,8 +192,9 @@ button.chip { min-height: 40px; padding: 9px 14px; font-size: 0.85rem; font-weig .choices button.active-maybe:hover { background: var(--maybe); } .choices button.active-no:hover { background: var(--no); } -.voters { font-size: 0.82rem; color: var(--muted); margin-top: 10px; line-height: 1.7; } +.voters { font-size: 0.82rem; color: var(--muted); margin-top: 10px; display: flex; flex-wrap: wrap; gap: 6px 12px; } .voters .name { color: var(--text); } +.voter-chip { display: inline-flex; align-items: center; gap: 5px; } .center { text-align: center; } .mt { margin-top: 16px; } @@ -286,3 +287,82 @@ button.chip { min-height: 40px; padding: 9px 14px; font-size: 0.85rem; font-weig } .slot.confirmed { border-color: rgba(48, 209, 88, 0.5); box-shadow: 0 0 0 1px rgba(48, 209, 88, 0.5) inset; } + +/* ===== Hybryda: nagłówek, awatary, karty wypadów, postęp ===== */ + +.dash-header { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; } +.app-icon { width: 42px; height: 42px; border-radius: 12px; flex-shrink: 0; box-shadow: var(--shadow); } + +/* Awatary */ +.avatar { + display: inline-flex; align-items: center; justify-content: center; + border-radius: 50%; color: #fff; font-weight: 600; line-height: 1; + border: 2px solid var(--card); flex-shrink: 0; overflow: hidden; user-select: none; +} +.avatar-stack { display: inline-flex; } +.avatar-stack > * + * { margin-left: -9px; } +.avatar-more { background: var(--card-2); color: var(--muted); } + +/* Wybór awatara (setup) */ +.avatar-picker { display: grid; grid-template-columns: repeat(auto-fill, minmax(46px, 1fr)); gap: 8px; } +.avatar-option { + background: var(--card-2); border: 1px solid var(--border); border-radius: 12px; + font-size: 1.4rem; padding: 8px 0; min-height: 48px; color: inherit; font-weight: 400; +} +.avatar-option:hover { background: #262833; } +.avatar-option.selected { + border-color: var(--primary); + box-shadow: 0 0 0 2px rgba(91, 87, 242, 0.4); + background: rgba(91, 87, 242, 0.12); +} + +/* Gradientowy CTA */ +.cta-gradient { + width: 100%; + background: linear-gradient(135deg, #6d6af6, #4f46e5); + box-shadow: 0 8px 24px rgba(91, 87, 242, 0.35); + padding: 15px 18px; + font-size: 1.02rem; +} +.cta-gradient:hover { background: linear-gradient(135deg, #7b78f8, #5a51ea); } + +/* Karta wypadu (bogata) */ +.event-rich { + display: block; + background: var(--card); + border: 1px solid var(--border); + border-radius: 16px; + padding: 16px; + margin-bottom: 12px; + text-decoration: none; + color: var(--text); + box-shadow: var(--shadow); + transition: background 0.15s ease, border-color 0.15s ease, transform 0.06s ease; +} +.event-rich:hover { background: var(--card-2); border-color: var(--border-strong); } +.event-rich:active { transform: scale(0.992); } +.event-rich-head { display: flex; align-items: center; gap: 10px; } +.event-rich-title { font-weight: 600; font-size: 1.05rem; letter-spacing: -0.01em; flex: 1; min-width: 0; } + +.event-meta { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); font-size: 0.88rem; } +.event-meta svg { flex-shrink: 0; opacity: 0.85; } +.event-meta-row { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 8px; } +.event-rich-foot { display: flex; align-items: center; gap: 12px; margin-top: 14px; min-height: 28px; } +.event-rich-foot .spacer { flex: 1; } + +/* Pasek postępu głosowania */ +.progress-wrap { margin-top: 12px; display: flex; align-items: center; gap: 10px; } +.progress { flex: 1; height: 7px; border-radius: 999px; background: rgba(255, 255, 255, 0.08); overflow: hidden; } +.progress-bar { height: 100%; border-radius: 999px; transition: width 0.3s ease; } +.progress-label { font-size: 0.8rem; font-weight: 600; white-space: nowrap; } + +/* Baner z poradą */ +.tip-banner { + display: flex; align-items: center; gap: 12px; + margin-top: 24px; padding: 14px 16px; + background: rgba(91, 87, 242, 0.08); + border: 1px solid rgba(91, 87, 242, 0.22); + border-radius: 14px; + color: var(--muted); font-size: 0.88rem; +} +.tip-banner .tip-icon { color: var(--primary-hover); flex-shrink: 0; } diff --git a/src/app/page.tsx b/src/app/page.tsx index 5adf40b..bf0fcbe 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -5,24 +5,37 @@ import Link from 'next/link'; import { useRouter } from 'next/navigation'; import { supabase } from '@/lib/supabaseClient'; import { useAuth, signOut } from '@/lib/auth'; -import type { EventRow } from '@/lib/types'; +import type { EventRow, Slot, Vote, Profile } from '@/lib/types'; import { SLOT_PRESETS } from '@/lib/slotPresets'; +import { Avatar, AvatarStack, type Person } from '@/components/Avatar'; +import { IconCalendar, IconClock, IconPin, IconChevron, IconBulb } from '@/components/icons'; -function formatDate(iso: string): string { - return new Date(iso).toLocaleString('pl-PL', { +function fmtDate(iso: string): string { + return new Date(iso).toLocaleDateString('pl-PL', { weekday: 'short', day: 'numeric', month: 'long', - hour: '2-digit', - minute: '2-digit', + year: 'numeric', }); } +function fmtTime(iso: string): string { + return new Date(iso).toLocaleTimeString('pl-PL', { hour: '2-digit', minute: '2-digit' }); +} +function progressColor(p: number): string { + return p >= 67 ? 'var(--yes)' : p >= 34 ? 'var(--maybe)' : 'var(--no)'; +} + +type Agg = { voters: Person[]; percent: number; dateIso: string | null }; +const EMPTY_AGG: Agg = { voters: [], percent: 0, dateIso: null }; export default function Home() { const router = useRouter(); - const { userId, displayName } = useAuth(); + const { userId, displayName, avatar } = useAuth(); const [events, setEvents] = useState([]); + const [slots, setSlots] = useState([]); + const [votes, setVotes] = useState([]); + const [profiles, setProfiles] = useState([]); const [loading, setLoading] = useState(true); const [showForm, setShowForm] = useState(false); @@ -33,19 +46,27 @@ export default function Home() { const [error, setError] = useState(''); const load = useCallback(async () => { - const { data } = await supabase - .from('events') - .select('*') - .order('created_at', { ascending: false }); - setEvents((data ?? []) as EventRow[]); + const [{ data: ev }, { data: sl }, { data: vo }, { data: pr }] = await Promise.all([ + supabase.from('events').select('*').order('created_at', { ascending: false }), + supabase.from('slots').select('*'), + supabase.from('votes').select('*'), + supabase.from('profiles').select('*'), + ]); + setEvents((ev ?? []) as EventRow[]); + setSlots((sl ?? []) as Slot[]); + setVotes((vo ?? []) as Vote[]); + setProfiles((pr ?? []) as Profile[]); setLoading(false); }, []); useEffect(() => { load(); const channel = supabase - .channel('events-dashboard') + .channel('dashboard') .on('postgres_changes', { event: '*', schema: 'public', table: 'events' }, () => load()) + .on('postgres_changes', { event: '*', schema: 'public', table: 'slots' }, () => load()) + .on('postgres_changes', { event: '*', schema: 'public', table: 'votes' }, () => load()) + .on('postgres_changes', { event: '*', schema: 'public', table: 'profiles' }, () => load()) .subscribe(); return () => { supabase.removeChannel(channel); @@ -75,7 +96,6 @@ export default function Home() { return; } - // Wstaw zaproponowane terminy (jeśli podano) jednym zapytaniem. const slotRows = proposedSlots .filter((s) => s) .map((s) => ({ @@ -96,33 +116,70 @@ export default function Home() { const open: EventRow[] = []; const upcoming: EventRow[] = []; const past: EventRow[] = []; - for (const ev of events) { - if (!ev.confirmed_at) { - open.push(ev); - } else if (new Date(ev.confirmed_at).getTime() >= now) { - upcoming.push(ev); - } else { - past.push(ev); - } + if (!ev.confirmed_at) open.push(ev); + else if (new Date(ev.confirmed_at).getTime() >= now) upcoming.push(ev); + else past.push(ev); } upcoming.sort((a, b) => new Date(a.confirmed_at!).getTime() - new Date(b.confirmed_at!).getTime()); past.sort((a, b) => new Date(b.confirmed_at!).getTime() - new Date(a.confirmed_at!).getTime()); return { open, upcoming, past }; }, [events]); + // Agregaty per wypad: głosujący (z awatarami), % paczki, reprezentatywna data. + const aggByEvent = useMemo(() => { + const profileById = new Map(profiles.map((p) => [p.id, p])); + const slotsBy = new Map(); + for (const s of slots) { + const arr = slotsBy.get(s.event_id) ?? []; + arr.push(s); + slotsBy.set(s.event_id, arr); + } + const votesBy = new Map(); + for (const v of votes) { + const arr = votesBy.get(v.event_id) ?? []; + arr.push(v); + votesBy.set(v.event_id, arr); + } + const memberCount = profiles.length; + const result = new Map(); + for (const ev of events) { + const seen = new Map(); + for (const v of votesBy.get(ev.id) ?? []) { + const key = v.user_id ?? `name:${v.participant_name}`; + if (seen.has(key)) continue; + const prof = v.user_id ? profileById.get(v.user_id) : undefined; + seen.set(key, { name: prof?.display_name ?? v.participant_name, avatar: prof?.avatar ?? null }); + } + const voters = Array.from(seen.values()); + const percent = memberCount > 0 ? Math.round((voters.length / memberCount) * 100) : 0; + const evSlots = (slotsBy.get(ev.id) ?? []) + .slice() + .sort((a, b) => new Date(a.starts_at).getTime() - new Date(b.starts_at).getTime()); + const dateIso = ev.confirmed_at ?? evSlots[0]?.starts_at ?? null; + result.set(ev.id, { voters, percent, dateIso }); + } + return result; + }, [events, slots, votes, profiles]); + return (
-
-
-

Planner

- - -
-

Cześć, {displayName} — wasze wypady w jednym miejscu.

+
+ {/* eslint-disable-next-line @next/next/no-img-element */} + +

Planner

+ +
+
+ + Cześć, {displayName} — proponujcie terminy i ustalajcie kiedy. + + + +
- @@ -222,34 +279,93 @@ export default function Home() { )} - - - +
+
+
+ + {!loading && events.length > 0 && ( +
+ + Im więcej osób zagłosuje, tym łatwiej ustalić idealny termin. +
+ )}
); } -function Timeline({ title, events, muted }: { title: string; events: EventRow[]; muted?: boolean }) { +function Section({ + title, + events, + agg, + variant, + muted, +}: { + title: string; + events: EventRow[]; + agg: Map; + variant: 'open' | 'upcoming' | 'past'; + muted?: boolean; +}) { if (events.length === 0) return null; return (
{title}
-
- {events.map((ev) => ( - -
-
{ev.title}
- {ev.location &&
📍 {ev.location}
} -
- {ev.confirmed_at ? ( - {formatDate(ev.confirmed_at)} - ) : ( - Zbieramy terminy - )} - - - ))} -
+ {events.map((ev) => ( + + ))}
); } + +function EventCard({ ev, agg, variant }: { ev: EventRow; agg: Agg; variant: 'open' | 'upcoming' | 'past' }) { + return ( + +
+ {ev.title} + +
+ + {ev.location && ( +
+ {ev.location} +
+ )} + +
+ {agg.dateIso ? ( + <> + {fmtDate(agg.dateIso)} + {fmtTime(agg.dateIso)} + + ) : ( + Zbieramy terminy + )} +
+ +
+ {agg.voters.length > 0 ? ( + + ) : ( + Nikt jeszcze nie głosował + )} + + {variant === 'past' && ✓ Zakończony} + {variant === 'upcoming' && Ustalony} +
+ + {variant === 'open' && ( +
+
+
+
+ + {agg.percent}% zagłosowało + +
+ )} + + ); +} diff --git a/src/components/Avatar.tsx b/src/components/Avatar.tsx new file mode 100644 index 0000000..9b19911 --- /dev/null +++ b/src/components/Avatar.tsx @@ -0,0 +1,36 @@ +import { colorFromString, initials } from '@/lib/avatars'; + +export type Person = { name: string; avatar?: string | null }; + +// Awatar = wybrane emoji na neutralnym kółku; fallback = inicjały na kolorze z imienia. +export function Avatar({ name, avatar, size = 32 }: Person & { size?: number }) { + const style: React.CSSProperties = { + width: size, + height: size, + fontSize: avatar ? size * 0.56 : size * 0.4, + background: avatar ? 'var(--card-2)' : colorFromString(name), + }; + return ( + + {avatar || initials(name)} + + ); +} + +export function AvatarStack({ people, max = 5, size = 28 }: { people: Person[]; max?: number; size?: number }) { + if (people.length === 0) return null; + const shown = people.slice(0, max); + const extra = people.length - shown.length; + return ( +
+ {shown.map((p, i) => ( + + ))} + {extra > 0 && ( + + +{extra} + + )} +
+ ); +} diff --git a/src/components/icons.tsx b/src/components/icons.tsx new file mode 100644 index 0000000..cf28aad --- /dev/null +++ b/src/components/icons.tsx @@ -0,0 +1,45 @@ +// Lekkie ikony inline SVG (bez dodatkowej zależności), styl lucide-like. +import type { SVGProps } from 'react'; + +type IconProps = SVGProps & { size?: number }; + +function Svg({ children, size = 16, ...props }: IconProps & { children: React.ReactNode }) { + return ( + + ); +} + +export const IconCalendar = (p: IconProps) => ( + +); +export const IconClock = (p: IconProps) => ( + +); +export const IconPin = (p: IconProps) => ( + +); +export const IconCheck = (p: IconProps) => ( + +); +export const IconPlus = (p: IconProps) => ( + +); +export const IconChevron = (p: IconProps) => ( + +); +export const IconBulb = (p: IconProps) => ( + +); diff --git a/src/lib/auth.tsx b/src/lib/auth.tsx index c838622..aebb27c 100644 --- a/src/lib/auth.tsx +++ b/src/lib/auth.tsx @@ -4,8 +4,9 @@ import { createContext, useContext, useEffect, useState } from 'react'; import type { Session } from '@supabase/supabase-js'; import { supabase, isSupabaseConfigured } from '@/lib/supabaseClient'; import SetupBanner from '@/components/SetupBanner'; +import { AVATARS } from '@/lib/avatars'; -type AuthCtx = { userId: string; displayName: string }; +type AuthCtx = { userId: string; displayName: string; avatar: string }; const Ctx = createContext(null); @@ -38,12 +39,18 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { // kto jeszcze nie zagłosował (klient nie ma dostępu do auth.users). useEffect(() => { if (!session) return; - const name = (session.user.user_metadata?.display_name as string | undefined)?.trim(); + const meta = session.user.user_metadata ?? {}; + const name = (meta.display_name as string | undefined)?.trim(); if (!name) return; supabase .from('profiles') .upsert( - { id: session.user.id, display_name: name, updated_at: new Date().toISOString() }, + { + id: session.user.id, + display_name: name, + avatar: (meta.avatar as string | undefined) ?? null, + updated_at: new Date().toISOString(), + }, { onConflict: 'id' }, ) .then(() => {}); @@ -62,11 +69,16 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { if (!session) return ; - const displayName = - (session.user.user_metadata?.display_name as string | undefined)?.trim() ?? ''; - if (!displayName) return ; + const meta = session.user.user_metadata ?? {}; + const displayName = (meta.display_name as string | undefined)?.trim() ?? ''; + const avatar = (meta.avatar as string | undefined) ?? ''; + if (!displayName || !avatar) { + return ; + } - return {children}; + return ( + {children} + ); } export async function signOut() { @@ -177,17 +189,20 @@ function LoginForm() { ); } -function NameForm() { - const [name, setName] = useState(''); +function SetupForm({ initialName, initialAvatar }: { initialName: string; initialAvatar: string }) { + const [name, setName] = useState(initialName); + const [avatar, setAvatar] = useState(initialAvatar || AVATARS[0]); const [busy, setBusy] = useState(false); const [error, setError] = useState(''); async function save(e: React.FormEvent) { e.preventDefault(); - if (!name.trim() || busy) return; + if (!name.trim() || !avatar || busy) return; setBusy(true); setError(''); - const { error } = await supabase.auth.updateUser({ data: { display_name: name.trim() } }); + const { error } = await supabase.auth.updateUser({ + data: { display_name: name.trim(), avatar }, + }); if (error) { setError(error.message); setBusy(false); @@ -200,10 +215,12 @@ function NameForm() {

Planner

-

Jak masz na imię?

-

Tę nazwę zobaczą inni przy Twoich głosach.

+

Twój profil

+

Tę nazwę i awatar zobaczą inni przy Twoich głosach.

+
+
+ +
+ {AVATARS.map((a) => ( + + ))} +
+
{error &&

{error}

} -
+ + {open && ( + <> +
+
+ {!showEmoji ? ( + <> + + + + + ) : ( +
+ {AVATARS.map((a) => ( + + ))} +
+ )} + {error &&

{error}

} +
+ + )} + + +
+ ); +} diff --git a/src/lib/auth.tsx b/src/lib/auth.tsx index aebb27c..d132065 100644 --- a/src/lib/auth.tsx +++ b/src/lib/auth.tsx @@ -1,10 +1,11 @@ 'use client'; -import { createContext, useContext, useEffect, useState } from 'react'; +import { createContext, useContext, useEffect, useRef, useState } from 'react'; import type { Session } from '@supabase/supabase-js'; import { supabase, isSupabaseConfigured } from '@/lib/supabaseClient'; import SetupBanner from '@/components/SetupBanner'; -import { AVATARS } from '@/lib/avatars'; +import { Avatar } from '@/components/Avatar'; +import { AVATARS, uploadAvatarImage } from '@/lib/avatars'; type AuthCtx = { userId: string; displayName: string; avatar: string }; @@ -73,7 +74,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { const displayName = (meta.display_name as string | undefined)?.trim() ?? ''; const avatar = (meta.avatar as string | undefined) ?? ''; if (!displayName || !avatar) { - return ; + return ; } return ( @@ -189,11 +190,36 @@ function LoginForm() { ); } -function SetupForm({ initialName, initialAvatar }: { initialName: string; initialAvatar: string }) { +function SetupForm({ + userId, + initialName, + initialAvatar, +}: { + userId: string; + initialName: string; + initialAvatar: string; +}) { const [name, setName] = useState(initialName); const [avatar, setAvatar] = useState(initialAvatar || AVATARS[0]); const [busy, setBusy] = useState(false); + const [uploading, setUploading] = useState(false); const [error, setError] = useState(''); + const fileRef = useRef(null); + + async function onFile(e: React.ChangeEvent) { + const file = e.target.files?.[0]; + e.target.value = ''; + if (!file) return; + setUploading(true); + setError(''); + try { + setAvatar(await uploadAvatarImage(userId, file)); + } catch (err) { + setError(err instanceof Error ? err.message : 'Nie udało się wgrać zdjęcia.'); + } finally { + setUploading(false); + } + } async function save(e: React.FormEvent) { e.preventDefault(); @@ -230,6 +256,13 @@ function SetupForm({ initialName, initialAvatar }: { initialName: string; initia
+
+ + + +
{AVATARS.map((a) => ( {open && ( - <> -
-
- {!showEmoji ? ( - <> - - + +
+ + +
+ +
+ {AVATARS.map((a) => ( + -
+ +
+ +
+ { + setName(e.target.value); + setSavedName(false); + }} + style={{ flex: 1 }} + /> + - - ) : ( -
- {AVATARS.map((a) => ( - - ))}
- )} - {error &&

{error}

} +
+ + {error &&

{error}

} + +
- +
)} From 942b482f56c91ebb509f4e8461ae476dbac9af38 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 22 Jun 2026 15:19:39 +0000 Subject: [PATCH 010/117] Liquid Glass styling on dashboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Próbka kierunku Apple „Liquid Glass" na samym dashboardzie: nasycone, statyczne tło (GlassBackground) prześwitujące przez matowe szkło kart, CTA i banera (backdrop-blur + saturate + hairline + wewnętrzny odblask). Style scope'owane pod .glass-page, więc strona wypadu i modale pozostają płaskie. Bez zmian logiki/bazy. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_017ErbidN4HCXywidwUdDcbf --- src/app/globals.css | 48 ++++++++++++++++++++++++++++++ src/app/page.tsx | 4 ++- src/components/GlassBackground.tsx | 9 ++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/components/GlassBackground.tsx diff --git a/src/app/globals.css b/src/app/globals.css index 22e8517..0a98084 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -413,3 +413,51 @@ img.avatar { display: inline-block; } color: var(--muted); font-size: 0.88rem; } .tip-banner .tip-icon { color: var(--primary-hover); flex-shrink: 0; } + +/* ===== Liquid Glass (dashboard) ===== */ +.glass-page { position: relative; z-index: 1; } + +.glass-bg { + position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; + background: #07070d; +} +.glass-blob { + position: absolute; width: 70vw; height: 70vw; max-width: 480px; max-height: 480px; + border-radius: 50%; filter: blur(90px); +} +.glass-blob-1 { top: -8%; left: -12%; opacity: 0.55; background: linear-gradient(135deg, #7c3aed, #4f46e5); } +.glass-blob-2 { bottom: -12%; right: -14%; opacity: 0.5; background: linear-gradient(135deg, #2563eb, #06b6d4); } + +/* Recepta szkła: półprzezroczyste tło + rozmycie/saturacja + krawędź + mokry odblask. */ +.glass-page .event-rich, +.glass-page .card, +.glass-page .empty-state, +.glass-page .tip-banner { + background: rgba(255, 255, 255, 0.05); + border-color: rgba(255, 255, 255, 0.10); + -webkit-backdrop-filter: blur(18px) saturate(180%); + backdrop-filter: blur(18px) saturate(180%); + box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.15), 0 16px 40px rgba(0, 0, 0, 0.35); +} +.glass-page .event-rich:hover, +.glass-page .card:hover { background: rgba(255, 255, 255, 0.08); border-color: rgba(255, 255, 255, 0.14); } + +/* Szklisty CTA zamiast pełnego gradientu */ +.glass-page .cta-gradient { + background: rgba(255, 255, 255, 0.12); + border: 1px solid rgba(255, 255, 255, 0.16); + -webkit-backdrop-filter: blur(18px) saturate(160%); + backdrop-filter: blur(18px) saturate(160%); + box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.22); + color: #fff; +} +.glass-page .cta-gradient:hover { background: rgba(255, 255, 255, 0.18); } + +.glass-page .section-label { color: rgba(255, 255, 255, 0.5); letter-spacing: 0.12em; } + +/* Pasek postępu: ciemny „żelowy" tor, kolorowy wskaźnik (sygnał %) zostaje */ +.glass-page .progress { + background: rgba(0, 0, 0, 0.4); + border: 1px solid rgba(255, 255, 255, 0.04); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5); +} diff --git a/src/app/page.tsx b/src/app/page.tsx index a76d9b8..1b5ca68 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -9,6 +9,7 @@ import type { EventRow, Slot, Vote, Profile } from '@/lib/types'; import { SLOT_PRESETS } from '@/lib/slotPresets'; import { AvatarStack, type Person } from '@/components/Avatar'; import ProfileMenu from '@/components/ProfileMenu'; +import GlassBackground from '@/components/GlassBackground'; import { IconCalendar, IconClock, IconPin, IconChevron, IconBulb } from '@/components/icons'; function fmtDate(iso: string): string { @@ -164,7 +165,8 @@ export default function Home() { }, [events, slots, votes, profiles]); return ( -
+
+
Cześć, {displayName} diff --git a/src/components/GlassBackground.tsx b/src/components/GlassBackground.tsx new file mode 100644 index 0000000..9d9b926 --- /dev/null +++ b/src/components/GlassBackground.tsx @@ -0,0 +1,9 @@ +// Statyczne, nasycone tło „Liquid Glass" — kolorowe bloby prześwitujące przez szkło kart. +export default function GlassBackground() { + return ( +
From 9157ca746092e86b852301fe1a6fb11b2b664d93 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 22 Jun 2026 20:11:24 +0000 Subject: [PATCH 019/117] Show guest login on all *.vercel.app hosts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Poprzedni warunek (-git-) nie łapał URL-i per-deploy Vercela, więc guzik gościa się nie pokazywał. Pokazujemy go na każdym *.vercel.app i localhost; ukryty tylko na własnej domenie produkcyjnej. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_017ErbidN4HCXywidwUdDcbf --- src/lib/auth.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lib/auth.tsx b/src/lib/auth.tsx index 81def95..23acfdd 100644 --- a/src/lib/auth.tsx +++ b/src/lib/auth.tsx @@ -94,10 +94,11 @@ function LoginForm() { const [error, setError] = useState(''); const [isPreview, setIsPreview] = useState(false); - // Guzik „gość" pokazujemy tylko na preview/localhost (adres brancha zawiera „-git-"). + // Guzik „gość" pokazujemy na preview i lokalnie (każdy adres *.vercel.app oraz localhost). + // Na własnej domenie produkcyjnej się nie pokaże. useEffect(() => { const h = window.location.hostname; - setIsPreview(h.includes('-git-') || h.includes('localhost') || h.startsWith('127.')); + setIsPreview(h.endsWith('.vercel.app') || h.includes('localhost') || h.startsWith('127.')); }, []); async function sendCode(e: React.FormEvent) { From 0aa7a1133a3f7d139486d755304f27441c84d84c Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 22 Jun 2026 20:18:51 +0000 Subject: [PATCH 020/117] Perf: drop per-frame blur on scrolling cards (smoother scroll) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Karty listy (.event-rich) — najliczniejsze i scrollowane — zamienione na „smoked glass" bez backdrop-filter, więc nie ma rozmycia liczonego co klatkę przy scrollu. Prawdziwy blur zostaje tylko na nielicznych elementach (CTA, formularz, baner) i zmniejszony do 12px/150%. Wygląd zachowany, scroll lekki. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_017ErbidN4HCXywidwUdDcbf --- src/app/globals.css | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index 6146c5f..e7c2a2d 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -465,25 +465,31 @@ img.avatar { display: inline-block; } } /* Recepta szkła: półprzezroczyste tło + rozmycie/saturacja + krawędź + mokry odblask. */ -.glass-page .event-rich, .glass-page .card, .glass-page .empty-state, .glass-page .tip-banner { background: rgba(255, 255, 255, 0.05); border-color: rgba(255, 255, 255, 0.10); - -webkit-backdrop-filter: blur(18px) saturate(180%); - backdrop-filter: blur(18px) saturate(180%); + -webkit-backdrop-filter: blur(12px) saturate(150%); + backdrop-filter: blur(12px) saturate(150%); box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.18), 0 20px 60px rgba(0, 0, 0, 0.5); } -.glass-page .event-rich:hover, .glass-page .card:hover { background: rgba(255, 255, 255, 0.08); border-color: rgba(255, 255, 255, 0.14); } +/* Karty listy: „smoked glass" BEZ backdrop-filter → płynny scroll (zero rozmycia per-klatka). */ +.glass-page .event-rich { + background: rgba(18, 20, 34, 0.44); + border: 1px solid rgba(255, 255, 255, 0.10); + box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.16), 0 18px 50px rgba(0, 0, 0, 0.5); +} +.glass-page .event-rich:hover { background: rgba(26, 28, 44, 0.52); border-color: rgba(255, 255, 255, 0.14); } + /* Szklisty CTA zamiast pełnego gradientu */ .glass-page .cta-gradient { background: rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.16); - -webkit-backdrop-filter: blur(18px) saturate(160%); - backdrop-filter: blur(18px) saturate(160%); + -webkit-backdrop-filter: blur(12px) saturate(150%); + backdrop-filter: blur(12px) saturate(150%); box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.22); color: #fff; } From 68d29670b3473f7e3595ada02049d0892711726f Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 22 Jun 2026 20:24:42 +0000 Subject: [PATCH 021/117] Add beveled edges + corner glints to glass (less flat) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Statyczna głębia bez kosztu przy scrollu: fazowana krawędź (inset jasny górno-lewy + ciemny dolno-prawy), refleksy światła w narożnikach i lekka barwna refrakcja przy dolnej krawędzi kart. Dotyczy kart listy oraz pozostałych szklanych powierzchni i CTA. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_017ErbidN4HCXywidwUdDcbf --- src/app/globals.css | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index e7c2a2d..60d3722 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -472,17 +472,33 @@ img.avatar { display: inline-block; } border-color: rgba(255, 255, 255, 0.10); -webkit-backdrop-filter: blur(12px) saturate(150%); backdrop-filter: blur(12px) saturate(150%); - box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.18), 0 20px 60px rgba(0, 0, 0, 0.5); + box-shadow: + inset 1px 1px 0 rgba(255, 255, 255, 0.22), + inset -1px -1px 1px rgba(0, 0, 0, 0.35), + 0 20px 60px rgba(0, 0, 0, 0.5); } .glass-page .card:hover { background: rgba(255, 255, 255, 0.08); border-color: rgba(255, 255, 255, 0.14); } /* Karty listy: „smoked glass" BEZ backdrop-filter → płynny scroll (zero rozmycia per-klatka). */ .glass-page .event-rich { - background: rgba(18, 20, 34, 0.44); + background: + radial-gradient(60% 55% at 0% 0%, rgba(255, 255, 255, 0.10), transparent 60%), + radial-gradient(45% 40% at 100% 0%, rgba(255, 255, 255, 0.06), transparent 60%), + radial-gradient(55% 50% at 100% 100%, rgba(99, 102, 241, 0.08), transparent 62%), + rgba(18, 20, 34, 0.46); border: 1px solid rgba(255, 255, 255, 0.10); - box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.16), 0 18px 50px rgba(0, 0, 0, 0.5); + box-shadow: + inset 1px 1px 0 rgba(255, 255, 255, 0.22), + inset -1px -1px 1px rgba(0, 0, 0, 0.40), + 0 18px 50px rgba(0, 0, 0, 0.5); +} +.glass-page .event-rich:hover { + border-color: rgba(255, 255, 255, 0.16); + box-shadow: + inset 1px 1px 0 rgba(255, 255, 255, 0.30), + inset -1px -1px 1px rgba(0, 0, 0, 0.40), + 0 22px 60px rgba(0, 0, 0, 0.55); } -.glass-page .event-rich:hover { background: rgba(26, 28, 44, 0.52); border-color: rgba(255, 255, 255, 0.14); } /* Szklisty CTA zamiast pełnego gradientu */ .glass-page .cta-gradient { @@ -490,7 +506,9 @@ img.avatar { display: inline-block; } border: 1px solid rgba(255, 255, 255, 0.16); -webkit-backdrop-filter: blur(12px) saturate(150%); backdrop-filter: blur(12px) saturate(150%); - box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.22); + box-shadow: + inset 1px 1px 0 rgba(255, 255, 255, 0.30), + inset -1px -1px 1px rgba(0, 0, 0, 0.25); color: #fff; } .glass-page .cta-gradient:hover { background: rgba(255, 255, 255, 0.18); } From 799e6aa9408f6cf34919ad08d2bb1eb86d1841a6 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 22 Jun 2026 20:29:06 +0000 Subject: [PATCH 022/117] Restore card blur; calmer, side-weighted aurora MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Przywrócono backdrop-filter (frosted) na kartach listy — z zachowaniem fazowanej krawędzi i glintów. W zamian zorza wyciszona (niższe alfy + opacity 0.55) i zepchnięta na boki (pasma przy lewej i prawej krawędzi, środek spokojniejszy). Rozmycie dodatkowo zmiękcza zorzę za kartami. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_017ErbidN4HCXywidwUdDcbf --- src/app/globals.css | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index 60d3722..66ac1c9 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -426,28 +426,28 @@ img.avatar { display: inline-block; } } /* Zorza polarna: pionowe, miękkie kurtyny światła (maska po bokach, blend „screen"). */ -.aurora { position: absolute; left: -20%; right: -20%; top: -10%; height: 120%; opacity: 0.8; } +.aurora { position: absolute; left: -25%; right: -25%; top: -10%; height: 120%; opacity: 0.55; } .aurora-band { - position: absolute; top: 0; bottom: 0; width: 44%; + position: absolute; top: 0; bottom: 0; width: 46%; mix-blend-mode: screen; will-change: transform; -webkit-mask-image: linear-gradient(to right, transparent, #000 35%, #000 65%, transparent); mask-image: linear-gradient(to right, transparent, #000 35%, #000 65%, transparent); } -/* Jasna część gradientu jest na środku (≈48%) → zorza siedzi w centrum, nie tylko u góry. */ +/* Wyciszona zorza zepchnięta na boki — środek (treść) spokojniejszy. */ .aurora-band.b1 { - left: 0%; - background: linear-gradient(to top, transparent 4%, rgba(34, 197, 94, 0.22) 30%, rgba(45, 212, 191, 0.40) 50%, rgba(99, 102, 241, 0.22) 76%, transparent 96%); + left: -10%; + background: linear-gradient(to top, transparent 6%, rgba(34, 197, 94, 0.16) 30%, rgba(45, 212, 191, 0.30) 50%, rgba(99, 102, 241, 0.16) 76%, transparent 96%); animation: aurora1 20s ease-in-out infinite alternate; } .aurora-band.b2 { - left: 30%; - background: linear-gradient(to top, transparent 6%, rgba(45, 212, 191, 0.32) 42%, rgba(168, 85, 247, 0.30) 74%, transparent 94%); + left: 64%; + background: linear-gradient(to top, transparent 6%, rgba(45, 212, 191, 0.24) 44%, rgba(168, 85, 247, 0.26) 78%, transparent 96%); animation: aurora2 25s ease-in-out infinite alternate; } .aurora-band.b3 { - left: 58%; - background: linear-gradient(to top, transparent 8%, rgba(56, 189, 248, 0.28) 46%, rgba(124, 58, 237, 0.24) 78%, transparent 96%); + left: 28%; + background: linear-gradient(to top, transparent 12%, rgba(56, 189, 248, 0.12) 48%, rgba(124, 58, 237, 0.12) 80%, transparent 94%); animation: aurora3 17s ease-in-out infinite alternate; } @keyframes aurora1 { from { transform: translateX(-15%) skewX(-11deg) scaleY(1); } to { transform: translateX(16%) skewX(8deg) scaleY(1.14); } } @@ -479,14 +479,16 @@ img.avatar { display: inline-block; } } .glass-page .card:hover { background: rgba(255, 255, 255, 0.08); border-color: rgba(255, 255, 255, 0.14); } -/* Karty listy: „smoked glass" BEZ backdrop-filter → płynny scroll (zero rozmycia per-klatka). */ +/* Karty listy: matowe szkło (frosted) + fazowana krawędź i glinty w rogach. */ .glass-page .event-rich { background: - radial-gradient(60% 55% at 0% 0%, rgba(255, 255, 255, 0.10), transparent 60%), - radial-gradient(45% 40% at 100% 0%, rgba(255, 255, 255, 0.06), transparent 60%), - radial-gradient(55% 50% at 100% 100%, rgba(99, 102, 241, 0.08), transparent 62%), - rgba(18, 20, 34, 0.46); + radial-gradient(60% 55% at 0% 0%, rgba(255, 255, 255, 0.12), transparent 60%), + radial-gradient(45% 40% at 100% 0%, rgba(255, 255, 255, 0.07), transparent 60%), + radial-gradient(55% 50% at 100% 100%, rgba(99, 102, 241, 0.10), transparent 62%), + rgba(14, 16, 28, 0.28); border: 1px solid rgba(255, 255, 255, 0.10); + -webkit-backdrop-filter: blur(12px) saturate(150%); + backdrop-filter: blur(12px) saturate(150%); box-shadow: inset 1px 1px 0 rgba(255, 255, 255, 0.22), inset -1px -1px 1px rgba(0, 0, 0, 0.40), From 7cb1a0a7dfc204a8ab07389acdc2768a0c722429 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 22 Jun 2026 20:33:35 +0000 Subject: [PATCH 023/117] Add edge refraction to glass cards; nudge aurora up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refrakcja: chromatyczne rozszczepienie na krawędziach (chłodny błękit vs fiolet) przez kolorowe inset-cienie + cienki, tęczowo przesunięty rant (gradientowy border przez mask-composite). Aurora odrobinę mocniejsza (opacity 0.55 → 0.63). Wszystko statyczne — bez kosztu przy scrollu. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_017ErbidN4HCXywidwUdDcbf --- src/app/globals.css | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/app/globals.css b/src/app/globals.css index 66ac1c9..cb419ad 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -426,7 +426,7 @@ img.avatar { display: inline-block; } } /* Zorza polarna: pionowe, miękkie kurtyny światła (maska po bokach, blend „screen"). */ -.aurora { position: absolute; left: -25%; right: -25%; top: -10%; height: 120%; opacity: 0.55; } +.aurora { position: absolute; left: -25%; right: -25%; top: -10%; height: 120%; opacity: 0.63; } .aurora-band { position: absolute; top: 0; bottom: 0; width: 46%; mix-blend-mode: screen; @@ -492,13 +492,30 @@ img.avatar { display: inline-block; } box-shadow: inset 1px 1px 0 rgba(255, 255, 255, 0.22), inset -1px -1px 1px rgba(0, 0, 0, 0.40), + inset 3px 3px 9px rgba(120, 200, 255, 0.11), + inset -3px -3px 9px rgba(185, 135, 255, 0.11), 0 18px 50px rgba(0, 0, 0, 0.5); } +/* Tęczowo przesunięty rant — światło załamane na krawędzi szkła (refrakcja). */ +.glass-page .event-rich::after { + content: ''; + position: absolute; inset: 0; + border-radius: inherit; + padding: 1px; + background: linear-gradient(135deg, rgba(130, 210, 255, 0.40), rgba(255, 255, 255, 0) 38%, rgba(255, 255, 255, 0) 62%, rgba(190, 140, 255, 0.34)); + -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); + -webkit-mask-composite: xor; + mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); + mask-composite: exclude; + pointer-events: none; +} .glass-page .event-rich:hover { border-color: rgba(255, 255, 255, 0.16); box-shadow: inset 1px 1px 0 rgba(255, 255, 255, 0.30), inset -1px -1px 1px rgba(0, 0, 0, 0.40), + inset 3px 3px 9px rgba(120, 200, 255, 0.14), + inset -3px -3px 9px rgba(185, 135, 255, 0.14), 0 22px 60px rgba(0, 0, 0, 0.55); } From f0e7e072fa18f87df8bfb4fa797cc2cbc1754b93 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 22 Jun 2026 20:37:47 +0000 Subject: [PATCH 024/117] Refine aurora palette; let cards pick up aurora color MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mniej „AI": neonowy zielony/cyan zastąpione stonowaną, analogiczną gamą (przygaszony błękit → indygo → fiolet → kurzowy róż), też w poświacie bazy. Karty mieszają się z aurorą: niższe własne przyciemnienie (0.28 → 0.20) i wyższa saturacja rozmycia (do 195%) → glass tintuje się kolorem zorzy za sobą. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_017ErbidN4HCXywidwUdDcbf --- src/app/globals.css | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index cb419ad..899cdb5 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -421,7 +421,7 @@ img.avatar { display: inline-block; } position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; /* Nocne niebo + delikatna poświata zorzy nad horyzontem. */ background: - radial-gradient(120% 70% at 50% 125%, rgba(45, 212, 191, 0.08), transparent 60%), + radial-gradient(120% 70% at 50% 125%, rgba(76, 112, 162, 0.07), transparent 60%), linear-gradient(180deg, #070815 0%, #05060e 55%, #04040a 100%); } @@ -437,17 +437,17 @@ img.avatar { display: inline-block; } /* Wyciszona zorza zepchnięta na boki — środek (treść) spokojniejszy. */ .aurora-band.b1 { left: -10%; - background: linear-gradient(to top, transparent 6%, rgba(34, 197, 94, 0.16) 30%, rgba(45, 212, 191, 0.30) 50%, rgba(99, 102, 241, 0.16) 76%, transparent 96%); + background: linear-gradient(to top, transparent 6%, rgba(72, 116, 168, 0.16) 30%, rgba(88, 112, 182, 0.30) 50%, rgba(110, 100, 176, 0.18) 76%, transparent 96%); animation: aurora1 20s ease-in-out infinite alternate; } .aurora-band.b2 { left: 64%; - background: linear-gradient(to top, transparent 6%, rgba(45, 212, 191, 0.24) 44%, rgba(168, 85, 247, 0.26) 78%, transparent 96%); + background: linear-gradient(to top, transparent 6%, rgba(118, 110, 190, 0.22) 44%, rgba(178, 124, 168, 0.24) 78%, transparent 96%); animation: aurora2 25s ease-in-out infinite alternate; } .aurora-band.b3 { left: 28%; - background: linear-gradient(to top, transparent 12%, rgba(56, 189, 248, 0.12) 48%, rgba(124, 58, 237, 0.12) 80%, transparent 94%); + background: linear-gradient(to top, transparent 12%, rgba(90, 120, 174, 0.12) 48%, rgba(126, 112, 168, 0.12) 80%, transparent 94%); animation: aurora3 17s ease-in-out infinite alternate; } @keyframes aurora1 { from { transform: translateX(-15%) skewX(-11deg) scaleY(1); } to { transform: translateX(16%) skewX(8deg) scaleY(1.14); } } @@ -470,8 +470,8 @@ img.avatar { display: inline-block; } .glass-page .tip-banner { background: rgba(255, 255, 255, 0.05); border-color: rgba(255, 255, 255, 0.10); - -webkit-backdrop-filter: blur(12px) saturate(150%); - backdrop-filter: blur(12px) saturate(150%); + -webkit-backdrop-filter: blur(12px) saturate(175%); + backdrop-filter: blur(12px) saturate(175%); box-shadow: inset 1px 1px 0 rgba(255, 255, 255, 0.22), inset -1px -1px 1px rgba(0, 0, 0, 0.35), @@ -485,10 +485,10 @@ img.avatar { display: inline-block; } radial-gradient(60% 55% at 0% 0%, rgba(255, 255, 255, 0.12), transparent 60%), radial-gradient(45% 40% at 100% 0%, rgba(255, 255, 255, 0.07), transparent 60%), radial-gradient(55% 50% at 100% 100%, rgba(99, 102, 241, 0.10), transparent 62%), - rgba(14, 16, 28, 0.28); + rgba(14, 16, 28, 0.20); border: 1px solid rgba(255, 255, 255, 0.10); - -webkit-backdrop-filter: blur(12px) saturate(150%); - backdrop-filter: blur(12px) saturate(150%); + -webkit-backdrop-filter: blur(12px) saturate(195%); + backdrop-filter: blur(12px) saturate(195%); box-shadow: inset 1px 1px 0 rgba(255, 255, 255, 0.22), inset -1px -1px 1px rgba(0, 0, 0, 0.40), @@ -523,8 +523,8 @@ img.avatar { display: inline-block; } .glass-page .cta-gradient { background: rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.16); - -webkit-backdrop-filter: blur(12px) saturate(150%); - backdrop-filter: blur(12px) saturate(150%); + -webkit-backdrop-filter: blur(12px) saturate(175%); + backdrop-filter: blur(12px) saturate(175%); box-shadow: inset 1px 1px 0 rgba(255, 255, 255, 0.30), inset -1px -1px 1px rgba(0, 0, 0, 0.25); From 871a37b51f5290ce080b08986aa0465b8dfecf7b Mon Sep 17 00:00:00 2001 From: uncleeai Date: Wed, 24 Jun 2026 19:17:00 +0200 Subject: [PATCH 025/117] style: premium glassmorphic design, morphing card, animations and fixes --- .gitignore | 9 + public/BG/dark abstract.mp4 | Bin 0 -> 233164 bytes src/app/event/[id]/page.tsx | 81 ++---- src/app/globals.css | 451 ++++++++++++++++++++--------- src/app/page.tsx | 420 +++++++++++++++++++-------- src/components/GlassBackground.tsx | 67 ++++- src/lib/types.ts | 36 +++ supabase/schema.sql | 2 +- 8 files changed, 746 insertions(+), 320 deletions(-) create mode 100644 public/BG/dark abstract.mp4 diff --git a/.gitignore b/.gitignore index 0fb3267..fe6b85d 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,12 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +# test files +/gemini-code-*.html +/test_ssr.html + +# large video assets +/public/BG/*.mp4 +!/public/BG/dark abstract.mp4 +/public/BG.mp4 diff --git a/public/BG/dark abstract.mp4 b/public/BG/dark abstract.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..d1fea921d0dd1160b70dc1b0079667d6b124396a GIT binary patch literal 233164 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 z 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®$(vg=PexrnJMPbkoJ%Nl(0=! zQx=5lblP)GqNn6Hx57w9;;X3%6_l@!T?Ne`vz`NN(sSm@>bJD9;4LM;5jBM9L?-Mz zu}_>uOG8?O=}5h$e2YdErzN$Y^!PV3C7y*JW-1G_h{1iri;wuxw=6LagsQ%VrLrtK zgIED~UGKmRxFr3*Z(~^^@x$vv}Z!|)<(Br_L(dK)J{`Gyf|t|7FWDG$Ok2?cra~W z7|8BJ7Pq|Y3GrvqQE(tH_2WzXd#5BG+QC|^j}V-xHkgnPh$H$X2OE1JvR4;LRhKfG zL&c!-qef8PpdP6OHm!eaP{QF$tzWAp{pkMKzBWECMmv>xfF$T*E+H4ESHg?~4#3~n z!G9rGj4?KXodWve9Qd=LIo{caEhNQESY4HGcsK%{mr*A*N5xe7UIaCMrjz~}LUEVy zr+Yx2_&;o15s81cy40=TPC}cltbBh%z9)1cY~z!31qZik5p~EFF}(?1m&&-znu2fz zxpt_CnM)-Sc3`Ce^?x`0|AMg?OIkzmb}i_l8qR|Xc<1bWEA60J;&2D=+bjE*-zn?& zO!S40f8zl~f9v4 zNYT=-q5_3fz}}?Y|M^-ZKJezLCu3dl3Nu4AF$7LKB|p3{`E(^=@PDcDyShrE7gV}4pkQVfFR!{rAvUvvUfz^Bj>kTx@ZzD7JeqvuZrm1o; zgqE>b&O^n+cq>j%s>8d2g@fV2h%XFp;rWbuJP{&7S)T4#^K{=Fq*=-g3C)_p^VL(Q zFf`CCek$>yYY#pq);z(G_2{}C=k-rzJ!#r(@nGy|2)Aey(iLop@A1@7wz_*%FlPrTZmyDz10*npQ@0?in<7L%25d_XqD0v(H_@AMp(|+;!1~J?+golL@7EzVZZHI?e^4}-4wOyk+fEqHO=3g)t2gxy!GjhZo z=*?S>Lx^$p3fv3IS!ajDU1b)~kOMdkbXI=lozb_6P=PKm)FRw%i~Zs3HWa^!{^5EAMfvq?ba?NzN=puC>b!Rp}g>sqzN^ zzK{UdsJ|4eMg#S~6e|F@l+@Q=#LX8wr$?#p0DR(4AF4FI8yGoaTwjCjFI%tpzq;vV zw-*BdP2FK#?Y*XQN#ADO$O5=q=bL%T%LLhzaL&<7?_G!;qjV_>jlSPDf8#;! zxD$atHBaXsJJKF7H9u-(wPS_%P4wN>vR?9&H`jv)e=dvqf`{1TWhC&ZbfkFB>k#UX z6TW+?DCSe3#tGr`pxXH5Byg}Qq2VqlB3TT^wcm5Rd`GU98iHlTOa`8H0s7ltFz}U< zY{|Li!T0qQu|Onh)PMA@M`_`64iI$4QBiSYH|TN~NsLejc5jgR3sELA)K_j>ARLX! zV46i}g2hm|o6w)b<8O-K8x#nw*yiHycmkFos|r*O)Ce2gkJcsL%bY741p3xl!Xwf3 zDDtFPE)lgB8f>$qI28{A+wRsZ@e_LMy?OIea6Z5oynMidAMcxHu?{1d3&1(bcE7p@__?)N2zoEm$M zt;z%fb#rhDcO1YRj8*WL`JWW6XN<5HVT(lHwI?AH7BjQlK)bbLEHq(4UWPDu-s#1in)ss*DqUB{!>C#+MC(sg*k6fq)Uh)3nDS%dPWhek%xL^T*?)T+as^G%LQzT9k-l0WSsP=nNQL@SyUQea|q?{Ib%Q-G>ux zXRq*iP#UC`(kR^asz*eHP~czb2=H&xl2u(07?AQ0qX`bG1B0;w*>d#Q+R~rM~6v?8=K5NrNqr=$c<^%U5IaQg)Wwg3BK3HHT|xh-?Y zAcf-^H}On3Hs$ojhM_dTGe5yH)1h zhxgAM%gXO~UAoH_YK=?s|-Ab=rnf4Mb1*vW>Zi7ZsVu^LV*xAGfVeY04mX*5UddU*a?lLM_y zk&Y3m;{T!C93IqTIAV&Yt0G6#^R1Hq988f_;(-E<0a}s*7c_IU8*r@nn!iw;9_-*b ze2)*#VZl@`3GW+MbTNIvkU!AQ5$K^k5|lgawqD-+NUYor5km|5Y!UNd~=F>XY6>f3gU zGQpJ~%!Pi5IaAFDqws+K=56U4)gy3x2V;Q literal 0 HcmV?d00001 diff --git a/src/app/event/[id]/page.tsx b/src/app/event/[id]/page.tsx index 55cb092..c19c443 100644 --- a/src/app/event/[id]/page.tsx +++ b/src/app/event/[id]/page.tsx @@ -5,10 +5,11 @@ import Link from 'next/link'; import { useRouter } from 'next/navigation'; import { supabase } from '@/lib/supabaseClient'; import { useAuth } from '@/lib/auth'; +import { getConfirmedSlot } from '@/lib/types'; import type { Availability, EventRow, Profile, Slot, Vote } from '@/lib/types'; -import { SLOT_PRESETS } from '@/lib/slotPresets'; import { Avatar, AvatarStack, type Person } from '@/components/Avatar'; import { IconPin } from '@/components/icons'; +import GlassBackground from '@/components/GlassBackground'; const CHOICES: { value: Availability; label: string; cls: string }[] = [ { value: 'yes', label: 'Mogę', cls: 'active-yes' }, @@ -183,21 +184,7 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> } } - async function confirmSlot(slotId: string, startsAt: string) { - await supabase - .from('events') - .update({ confirmed_slot_id: slotId, confirmed_at: startsAt }) - .eq('id', eventId); - load(); - } - - async function unconfirmSlot() { - await supabase - .from('events') - .update({ confirmed_slot_id: null, confirmed_at: null }) - .eq('id', eventId); - load(); - } + // confirmed_slot_id and confirmed_at are now computed dynamically on the client async function deleteEvent() { if (!window.confirm('Usunąć cały wypad? Znikną wszystkie terminy i głosy. Tego nie da się cofnąć.')) return; @@ -250,6 +237,11 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> const maxYes = useMemo(() => Math.max(0, ...stats.map((s) => s.yes)), [stats]); + const { confirmedSlotId, confirmedAt } = useMemo(() => { + const { slotId, confirmedAt } = getConfirmedSlot(slots, votes); + return { confirmedSlotId: slotId, confirmedAt }; + }, [slots, votes]); + const profileById = useMemo(() => new Map(members.map((m) => [m.id, m])), [members]); // Uczestnicy, którzy oddali jakikolwiek głos — z awatarami (do stosu na górze). @@ -270,11 +262,12 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> return members.filter((m) => !voted.has(m.id)).map((m) => m.display_name); }, [members, votes]); - if (loading) return

Wczytuję…

; + if (loading) return

Wczytuję…

; if (notFound) { return ( -
+
+

Nie znaleziono

Ten wypad nie istnieje albo link jest nieprawidłowy.

@@ -285,7 +278,8 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> const isOrganizer = !event?.created_by_user_id || event.created_by_user_id === userId; return ( -
+
+ ‹ Wszystkie wypady
@@ -298,8 +292,8 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> {event?.created_by &&

Organizuje: {event.created_by}

}
- {event?.confirmed_at && ( -
✅ Ustalono: {formatSlot(event.confirmed_at)}
+ {confirmedAt && ( +
✅ Ustalono: {formatSlot(confirmedAt)}
)}
@@ -332,18 +326,14 @@ export default function EventPage({ params }: { params: Promise<{ id: string }>

Proponowane terminy

- {isOrganizer - ? 'Jako organizator możesz „ustalić" finalny termin — wskoczy wtedy na oś czasu.' - : event?.created_by - ? `Finalny termin ustala organizator (${event.created_by}). Ty zaznacz, kiedy możesz.` - : 'Zaznacz przy każdym terminie, kiedy możesz.'} + Ustalony termin to ten, na który pasuje najwięcej osób (w przypadku remisu decyduje wcześniejszy termin). Zaznacz przy każdym terminie, kiedy możesz.

{stats.length === 0 && (

Brak terminów. Dodaj pierwszy poniżej.

)} {stats.map(({ slot, yes, maybe, no, mine, votes: slotVotes }) => { - const isConfirmed = event?.confirmed_slot_id === slot.id; + const isConfirmed = confirmedSlotId === slot.id; const isBest = yes > 0 && yes === maxYes; const canDelete = isOrganizer || slot.created_by_user_id === userId; return ( @@ -407,34 +397,11 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> })}
)} - - {isOrganizer && ( -
- {isConfirmed ? ( - - ) : ( - - )} -
- )}
); })} -
- {SLOT_PRESETS.map((p) => ( - - ))} -
+
/>
-
- {isOrganizer && ( - - )} +
+ +
+
); } diff --git a/src/app/globals.css b/src/app/globals.css index 899cdb5..3437006 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,26 +1,29 @@ :root { - --bg: #0a0b12; - --card: #15161e; - --card-2: #1c1e28; - --text: #f2f3f7; - --muted: #9499a8; - --border: rgba(255, 255, 255, 0.09); - --border-strong: rgba(255, 255, 255, 0.16); - --primary: #5b57f2; - --primary-hover: #6f6cf6; + --bg: #050505; + --card: rgba(255, 255, 255, 0.03); + --card-2: rgba(255, 255, 255, 0.05); + --text: rgba(255, 255, 255, 0.9); + --muted: rgba(255, 255, 255, 0.55); + --border: rgba(255, 255, 255, 0.08); + --border-strong: rgba(255, 255, 255, 0.15); + --primary: rgba(255, 255, 255, 0.12); + --primary-hover: rgba(255, 255, 255, 0.18); --yes: #30d158; --maybe: #ffd60a; --no: #ff453a; - --radius: 18px; - --radius-sm: 12px; - --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 10px 30px rgba(0, 0, 0, 0.18); + --radius: 24px; + --radius-sm: 16px; + --shadow: 0 20px 40px rgba(0, 0, 0, 0.5); /* Ciemny motyw również dla kontrolek natywnych (picker daty, scrollbary) na iOS. */ color-scheme: dark; } * { box-sizing: border-box; -webkit-tap-highlight-color: transparent; } -html { -webkit-text-size-adjust: 100%; } +html { + -webkit-text-size-adjust: 100%; + scrollbar-gutter: stable; +} html, body { margin: 0; @@ -107,7 +110,7 @@ button.ghost { } button.ghost:hover { background: #262833; border-color: var(--border-strong); } -button.ghost.danger { color: var(--no); border-color: rgba(255, 69, 58, 0.35); background: rgba(255, 69, 58, 0.08); } +button.ghost.danger { color: var(--no); border-color: rgba(255, 69, 58, 0.35); background: rgba(255, 15, 2, 0.08); } button.ghost.danger:hover { background: rgba(255, 69, 58, 0.14); border-color: var(--no); } .chips { gap: 8px; } @@ -185,12 +188,24 @@ button.chip { min-height: 40px; padding: 9px 14px; font-size: 0.85rem; font-weig padding: 10px 8px; } .choices button:hover { background: rgba(255, 255, 255, 0.05); } -.choices button.active-yes { background: var(--yes); color: #04210d; } -.choices button.active-maybe { background: var(--maybe); color: #3b2f04; } -.choices button.active-no { background: var(--no); color: #fff; } -.choices button.active-yes:hover { background: var(--yes); } -.choices button.active-maybe:hover { background: var(--maybe); } -.choices button.active-no:hover { background: var(--no); } +.choices button.active-yes { + background: rgba(48, 209, 88, 0.18); + color: #5eff84; + box-shadow: inset 0 0 0 1px rgba(48, 209, 88, 0.4), 0 0 12px rgba(48, 209, 88, 0.2); +} +.choices button.active-maybe { + background: rgba(255, 214, 10, 0.15); + color: #ffdf3d; + box-shadow: inset 0 0 0 1px rgba(255, 214, 10, 0.35), 0 0 12px rgba(255, 214, 10, 0.15); +} +.choices button.active-no { + background: rgba(255, 69, 58, 0.18); + color: #ff6b63; + box-shadow: inset 0 0 0 1px rgba(255, 69, 58, 0.4), 0 0 12px rgba(255, 69, 58, 0.2); +} +.choices button.active-yes:hover { background: rgba(48, 209, 88, 0.25); } +.choices button.active-maybe:hover { background: rgba(255, 214, 10, 0.22); } +.choices button.active-no:hover { background: rgba(255, 69, 58, 0.25); } .voters { font-size: 0.82rem; color: var(--muted); margin-top: 10px; display: flex; flex-wrap: wrap; gap: 6px 12px; } .voters .name { color: var(--text); } @@ -210,7 +225,7 @@ button.chip { min-height: 40px; padding: 9px 14px; font-size: 0.85rem; font-weig letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); - margin: 26px 4px 8px; + margin: 14px 4px 8px; } .section-label.faded { color: #6a6f80; } @@ -306,25 +321,45 @@ button.chip { min-height: 40px; padding: 9px 14px; font-size: 0.85rem; font-weig /* Wybór awatara (setup) */ .avatar-picker { display: grid; grid-template-columns: repeat(auto-fill, minmax(46px, 1fr)); gap: 8px; } .avatar-option { - background: var(--card-2); border: 1px solid var(--border); border-radius: 12px; - font-size: 1.4rem; padding: 8px 0; min-height: 48px; color: inherit; font-weight: 400; + background: rgba(255, 255, 255, 0.05); + border: 1px solid rgba(255, 255, 255, 0.08); + border-radius: var(--radius-sm); + font-size: 1.4rem; + padding: 8px 0; + min-height: 48px; + color: inherit; + font-weight: 400; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1); +} +.avatar-option:hover:not(:disabled) { + background: rgba(255, 255, 255, 0.12); + border-color: rgba(255, 255, 255, 0.2); + transform: scale(1.05); +} +.avatar-option:active:not(:disabled) { + transform: scale(0.95); } -.avatar-option:hover { background: #262833; } .avatar-option.selected { - border-color: var(--primary); + border-color: #5b57f2; box-shadow: 0 0 0 2px rgba(91, 87, 242, 0.4); - background: rgba(91, 87, 242, 0.12); + background: rgba(91, 87, 242, 0.15); } /* Gradientowy CTA */ .cta-gradient { width: 100%; - background: linear-gradient(135deg, #6d6af6, #4f46e5); - box-shadow: 0 8px 24px rgba(91, 87, 242, 0.35); + background: rgba(255, 255, 255, 0.12); + border: 1px solid rgba(255, 255, 255, 0.15); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 10px 20px rgba(0, 0, 0, 0.2); padding: 15px 18px; font-size: 1.02rem; + border-radius: var(--radius-sm); } -.cta-gradient:hover { background: linear-gradient(135deg, #7b78f8, #5a51ea); } +.cta-gradient:hover { background: rgba(255, 255, 255, 0.18); } /* Karta wypadu (bogata) */ .event-rich { @@ -352,6 +387,7 @@ button.chip { min-height: 40px; padding: 9px 14px; font-size: 0.85rem; font-weig /* Pasek postępu głosowania */ .progress-wrap { margin-top: 12px; display: flex; align-items: center; gap: 10px; } +.progress-inline-wrap { display: flex; align-items: center; gap: 10px; flex: 1; margin-left: 8px; } .progress { flex: 1; height: 7px; border-radius: 999px; background: rgba(255, 255, 255, 0.08); overflow: hidden; } .progress-bar { height: 100%; border-radius: 999px; transition: width 0.3s ease; } .progress-label { font-size: 0.8rem; font-weight: 600; white-space: nowrap; } @@ -369,26 +405,39 @@ img.avatar { display: inline-block; } position: fixed; inset: 0; z-index: 100; display: flex; align-items: center; justify-content: center; padding: 20px; - background: rgba(0, 0, 0, 0.55); - -webkit-backdrop-filter: blur(6px); - backdrop-filter: blur(6px); + background: rgba(0, 0, 0, 0.45); + -webkit-backdrop-filter: blur(8px); + backdrop-filter: blur(8px); } .profile-modal { position: relative; width: 100%; max-width: 360px; - background: var(--card); border: 1px solid var(--border); - border-radius: 20px; box-shadow: var(--shadow); + background: rgba(22, 18, 30, 0.65); + border: 1px solid rgba(255, 255, 255, 0.15); + border-radius: 24px; + box-shadow: 0 30px 60px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.15); + -webkit-backdrop-filter: blur(35px) saturate(220%); + backdrop-filter: blur(35px) saturate(220%); padding: 28px 20px 20px; text-align: center; } .modal-close { position: absolute; top: 12px; right: 12px; - width: 34px; height: 34px; padding: 0; + width: 32px; height: 32px; padding: 0; display: inline-flex; align-items: center; justify-content: center; - background: var(--card-2); border: 1px solid var(--border); color: var(--muted); - border-radius: 50%; font-size: 0.9rem; font-weight: 500; + background: rgba(255, 255, 255, 0.06); border: 1px solid rgba(255, 255, 255, 0.08); color: var(--muted); + border-radius: 50%; font-size: 0.8rem; font-weight: 500; + transition: all 0.2s ease; +} +.modal-close:hover { + background: rgba(255, 255, 255, 0.15); + border-color: rgba(255, 255, 255, 0.2); + color: #fff; + transform: scale(1.05); +} +.modal-close:active { + transform: scale(0.95); } -.modal-close:hover { background: #262833; color: var(--text); } .avatar-xl-wrap { position: relative; display: inline-block; margin-bottom: 16px; } .avatar-camera { @@ -396,13 +445,68 @@ img.avatar { display: inline-block; } width: 36px; height: 36px; padding: 0; display: inline-flex; align-items: center; justify-content: center; border-radius: 50%; font-size: 1rem; - background: var(--primary); border: 3px solid var(--card); color: #fff; + background: rgba(255, 255, 255, 0.15); border: 3px solid rgb(22, 18, 30); color: #fff; + transition: all 0.2s ease; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); +} +.avatar-camera:hover { + background: rgba(255, 255, 255, 0.25); + transform: scale(1.05); +} +.avatar-camera:active { + transform: scale(0.95); } -.avatar-camera:hover { background: var(--primary-hover); } -.profile-emoji-row { display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px; margin-bottom: 18px; } +.profile-emoji-row { display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; margin-bottom: 18px; } .profile-modal .field { text-align: left; } +.profile-modal label { + color: rgba(255, 255, 255, 0.7); + font-weight: 500; +} + +/* Custom stylings for inputs and buttons inside .profile-modal for maximum legibility */ +.profile-modal input[type="text"] { + background: rgba(0, 0, 0, 0.25); + border: 1px solid rgba(255, 255, 255, 0.12); + color: #fff; + transition: all 0.2s ease; +} + +.profile-modal input[type="text"]:focus { + background: rgba(0, 0, 0, 0.35); + border-color: rgba(255, 255, 255, 0.3); + box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.1); +} + +.profile-modal button.ghost { + background: rgba(255, 255, 255, 0.08); + border: 1px solid rgba(255, 255, 255, 0.12); + color: #fff; + font-weight: 600; + transition: all 0.2s ease; +} + +.profile-modal button.ghost:hover:not(:disabled) { + background: rgba(255, 255, 255, 0.15); + border-color: rgba(255, 255, 255, 0.22); +} + +.profile-modal button.ghost:disabled { + opacity: 0.35; +} + +.profile-modal button.ghost.danger { + background: rgba(255, 69, 58, 0.15); + border: 1px solid rgba(255, 69, 58, 0.3); + color: #ff453a; +} + +.profile-modal button.ghost.danger:hover { + background: rgba(255, 69, 58, 0.25); + border-color: #ff453a; +} + /* Baner z poradą */ .tip-banner { display: flex; align-items: center; gap: 12px; @@ -419,128 +523,107 @@ img.avatar { display: inline-block; } .glass-bg { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; - /* Nocne niebo + delikatna poświata zorzy nad horyzontem. */ - background: - radial-gradient(120% 70% at 50% 125%, rgba(76, 112, 162, 0.07), transparent 60%), - linear-gradient(180deg, #070815 0%, #05060e 55%, #04040a 100%); -} - -/* Zorza polarna: pionowe, miękkie kurtyny światła (maska po bokach, blend „screen"). */ -.aurora { position: absolute; left: -25%; right: -25%; top: -10%; height: 120%; opacity: 0.63; } -.aurora-band { - position: absolute; top: 0; bottom: 0; width: 46%; - mix-blend-mode: screen; - will-change: transform; - -webkit-mask-image: linear-gradient(to right, transparent, #000 35%, #000 65%, transparent); - mask-image: linear-gradient(to right, transparent, #000 35%, #000 65%, transparent); -} -/* Wyciszona zorza zepchnięta na boki — środek (treść) spokojniejszy. */ -.aurora-band.b1 { - left: -10%; - background: linear-gradient(to top, transparent 6%, rgba(72, 116, 168, 0.16) 30%, rgba(88, 112, 182, 0.30) 50%, rgba(110, 100, 176, 0.18) 76%, transparent 96%); - animation: aurora1 20s ease-in-out infinite alternate; -} -.aurora-band.b2 { - left: 64%; - background: linear-gradient(to top, transparent 6%, rgba(118, 110, 190, 0.22) 44%, rgba(178, 124, 168, 0.24) 78%, transparent 96%); - animation: aurora2 25s ease-in-out infinite alternate; -} -.aurora-band.b3 { - left: 28%; - background: linear-gradient(to top, transparent 12%, rgba(90, 120, 174, 0.12) 48%, rgba(126, 112, 168, 0.12) 80%, transparent 94%); - animation: aurora3 17s ease-in-out infinite alternate; -} -@keyframes aurora1 { from { transform: translateX(-15%) skewX(-11deg) scaleY(1); } to { transform: translateX(16%) skewX(8deg) scaleY(1.14); } } -@keyframes aurora2 { from { transform: translateX(14%) skewX(10deg) scaleY(1.1); } to { transform: translateX(-16%) skewX(-9deg) scaleY(0.92); } } -@keyframes aurora3 { from { transform: translateX(-13%) skewX(-8deg) scaleY(1.06); } to { transform: translateX(15%) skewX(12deg) scaleY(1.18); } } -@media (prefers-reduced-motion: reduce) { - .aurora-band { animation: none; } + background: #050505; } + +/* Wideo w tle (Apple Glassmorphism Video Background) */ +.glass-video { + transform: scale(1.3); + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; + filter: blur(60px); + opacity: 0.5; + z-index: 0; +} + .glass-grain { position: absolute; inset: 0; - opacity: 0.05; + opacity: 0.04; mix-blend-mode: soft-light; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); background-size: 140px 140px; + z-index: 1; } -/* Recepta szkła: półprzezroczyste tło + rozmycie/saturacja + krawędź + mokry odblask. */ +/* Recepta szkła Apple (Apple Glassmorphism): bg-white/[0.03] + blur(30px) + saturate(200%) */ .glass-page .card, .glass-page .empty-state, .glass-page .tip-banner { - background: rgba(255, 255, 255, 0.05); - border-color: rgba(255, 255, 255, 0.10); - -webkit-backdrop-filter: blur(12px) saturate(175%); - backdrop-filter: blur(12px) saturate(175%); + background: rgba(255, 255, 255, 0.03); + border: 1px solid rgba(255, 255, 255, 0.08); + -webkit-backdrop-filter: blur(30px) saturate(200%); + backdrop-filter: blur(30px) saturate(200%); box-shadow: - inset 1px 1px 0 rgba(255, 255, 255, 0.22), - inset -1px -1px 1px rgba(0, 0, 0, 0.35), - 0 20px 60px rgba(0, 0, 0, 0.5); + inset 0 1px 0 rgba(255, 255, 255, 0.15), + 0 20px 40px rgba(0, 0, 0, 0.4); } -.glass-page .card:hover { background: rgba(255, 255, 255, 0.08); border-color: rgba(255, 255, 255, 0.14); } +.glass-page .card:hover { background: rgba(255, 255, 255, 0.05); } -/* Karty listy: matowe szkło (frosted) + fazowana krawędź i glinty w rogach. */ +/* Szklane karty wydarzeń */ .glass-page .event-rich { - background: - radial-gradient(60% 55% at 0% 0%, rgba(255, 255, 255, 0.12), transparent 60%), - radial-gradient(45% 40% at 100% 0%, rgba(255, 255, 255, 0.07), transparent 60%), - radial-gradient(55% 50% at 100% 100%, rgba(99, 102, 241, 0.10), transparent 62%), - rgba(14, 16, 28, 0.20); - border: 1px solid rgba(255, 255, 255, 0.10); - -webkit-backdrop-filter: blur(12px) saturate(195%); - backdrop-filter: blur(12px) saturate(195%); + background: rgba(255, 255, 255, 0.03); + border: 1px solid rgba(255, 255, 255, 0.08); + -webkit-backdrop-filter: blur(30px) saturate(200%); + backdrop-filter: blur(30px) saturate(150%); box-shadow: - inset 1px 1px 0 rgba(255, 255, 255, 0.22), - inset -1px -1px 1px rgba(0, 0, 0, 0.40), - inset 3px 3px 9px rgba(120, 200, 255, 0.11), - inset -3px -3px 9px rgba(185, 135, 255, 0.11), - 0 18px 50px rgba(0, 0, 0, 0.5); -} -/* Tęczowo przesunięty rant — światło załamane na krawędzi szkła (refrakcja). */ -.glass-page .event-rich::after { - content: ''; - position: absolute; inset: 0; - border-radius: inherit; - padding: 1px; - background: linear-gradient(135deg, rgba(130, 210, 255, 0.40), rgba(255, 255, 255, 0) 38%, rgba(255, 255, 255, 0) 62%, rgba(190, 140, 255, 0.34)); - -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); - -webkit-mask-composite: xor; - mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); - mask-composite: exclude; - pointer-events: none; + inset 0 1px 0 rgba(255, 255, 255, 0.15), + 0 20px 40px rgba(0, 0, 0, 0.4); } .glass-page .event-rich:hover { - border-color: rgba(255, 255, 255, 0.16); - box-shadow: - inset 1px 1px 0 rgba(255, 255, 255, 0.30), - inset -1px -1px 1px rgba(0, 0, 0, 0.40), - inset 3px 3px 9px rgba(120, 200, 255, 0.14), - inset -3px -3px 9px rgba(185, 135, 255, 0.14), - 0 22px 60px rgba(0, 0, 0, 0.55); + background: rgba(255, 255, 255, 0.06); + border-color: rgba(255, 255, 255, 0.12); } -/* Szklisty CTA zamiast pełnego gradientu */ +/* Biały szklany przycisk główny (CTA) */ .glass-page .cta-gradient { background: rgba(255, 255, 255, 0.12); - border: 1px solid rgba(255, 255, 255, 0.16); - -webkit-backdrop-filter: blur(12px) saturate(175%); - backdrop-filter: blur(12px) saturate(175%); + border: 1px solid rgba(255, 255, 255, 0.15); + -webkit-backdrop-filter: blur(20px) saturate(150%); + backdrop-filter: blur(20px) saturate(150%); box-shadow: - inset 1px 1px 0 rgba(255, 255, 255, 0.30), - inset -1px -1px 1px rgba(0, 0, 0, 0.25); + inset 0 1px 0 rgba(255, 255, 255, 0.25), + 0 10px 20px rgba(0, 0, 0, 0.2); color: #fff; + transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, transform 0.06s ease; +} +.glass-page .cta-gradient:hover { + background: rgba(255, 255, 255, 0.18); + border-color: rgba(255, 255, 255, 0.22); } -.glass-page .cta-gradient:hover { background: rgba(255, 255, 255, 0.18); } .glass-page .section-label { color: rgba(255, 255, 255, 0.5); letter-spacing: 0.12em; } -/* Pasek postępu: ciemny „żelowy" tor, kolorowy wskaźnik (sygnał %) zostaje */ +/* Karta terminu w wersji szklanej */ +.glass-page .slot { + background: rgba(255, 255, 255, 0.03); + border: 1px solid rgba(255, 255, 255, 0.08); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08); +} +.glass-page .slot.winner { + border-color: rgba(48, 209, 88, 0.35); + box-shadow: inset 0 0 0 1px rgba(48, 209, 88, 0.35); +} +.glass-page .slot.confirmed { + border-color: rgba(48, 209, 88, 0.5); + box-shadow: inset 0 0 0 1px rgba(48, 209, 88, 0.5); +} + +/* Szklany, ciemny tor paska postępu */ .glass-page .progress { background: rgba(0, 0, 0, 0.4); - border: 1px solid rgba(255, 255, 255, 0.04); + border: 1px solid rgba(255, 255, 255, 0.03); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5); } +/* Biały świecący pasek postępu */ +.glass-page .progress-bar { + background: rgba(255, 255, 255, 0.85) !important; + box-shadow: 0 0 8px rgba(255, 255, 255, 0.4); +} + /* Mokry połysk na górnej krawędzi — jaśniejszy w środku, zanikający po bokach. */ .glass-page .event-rich, .glass-page .card, @@ -557,6 +640,112 @@ img.avatar { display: inline-block; } position: absolute; top: 0; left: 14%; right: 14%; height: 1px; - background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.35), transparent); + background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.25), transparent); pointer-events: none; } + +/* Animacja rozwijania formularza nowego wypadu */ +.form-collapse { + display: grid; + grid-template-rows: 0fr; + transition: grid-template-rows 0.42s cubic-bezier(0.25, 1, 0.5, 1), + opacity 0.35s ease-in-out, + margin-top 0.42s cubic-bezier(0.25, 1, 0.5, 1), + margin-bottom 0.42s cubic-bezier(0.25, 1, 0.5, 1); + opacity: 0; + overflow: hidden; + margin-top: 0; + margin-bottom: 0; +} +.form-collapse.open { + grid-template-rows: 1fr; + opacity: 1; + margin-top: 16px; + margin-bottom: 16px; +} +.form-collapse > form, +.form-collapse > div { + min-height: 0; +} +.form-collapse .card, +.form-collapse .empty-state { + margin-bottom: 0; + /* Wyłączamy backdrop-filter w zamkniętym stanie, żeby uniknąć przeskoku koloru */ + -webkit-backdrop-filter: none; + backdrop-filter: none; + transition: backdrop-filter 0.3s ease 0.35s, -webkit-backdrop-filter 0.3s ease 0.35s; +} +.form-collapse.open .card, +.form-collapse.open .empty-state { + /* Włączamy backdrop-filter z opóźnieniem — dopiero po zakończeniu rozwijania grida */ + -webkit-backdrop-filter: blur(30px) saturate(200%); + backdrop-filter: blur(30px) saturate(200%); +} + +/* Animacja zawartości (wygładzenie pojawiania się) */ +.form-collapse form > *, +.form-collapse .empty-state > * { + opacity: 0; + transform: translateY(-8px); + /* Szybkie wygaszanie bez opóźnienia przy zamykaniu */ + transition: opacity 0.2s ease-in, transform 0.2s ease-in; +} +.form-collapse.open form > *, +.form-collapse.open .empty-state > * { + opacity: 1; + transform: translateY(0); + /* Płynne wejście z lekkim opóźnieniem przy otwieraniu */ + transition: opacity 0.3s ease-out 0.08s, transform 0.35s cubic-bezier(0.25, 1, 0.5, 1) 0.08s; +} + +/* Logo i branding w nagłówku (bezpieczne klasy przed AdBlockami) */ +.app-title-group { + display: flex !important; + align-items: center !important; + gap: 10px !important; + user-select: none; + opacity: 1 !important; + visibility: visible !important; +} + +.app-title-icon { + width: 36px !important; + height: 36px !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + background: rgba(255, 255, 255, 0.04) !important; + border: 1px solid rgba(255, 255, 255, 0.12) !important; + border-radius: 11px !important; + color: #ffffff !important; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.12) !important; + transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1) !important; + opacity: 1 !important; + visibility: visible !important; +} + +.app-title-icon svg { + display: block !important; + color: #ffffff !important; +} + +.app-title-group:hover .app-title-icon { + background: rgba(255, 255, 255, 0.08) !important; + border-color: rgba(255, 255, 255, 0.18) !important; + transform: scale(1.05) !important; +} + +.app-title-text { + font-size: 1.25rem !important; + font-weight: 700 !important; + letter-spacing: -0.022em !important; + color: #ffffff !important; + opacity: 1 !important; + visibility: visible !important; + display: inline-block !important; +} + +.welcome-section h1 { + letter-spacing: -0.025em !important; +} + diff --git a/src/app/page.tsx b/src/app/page.tsx index 1b5ca68..e516a81 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,12 +1,12 @@ 'use client'; -import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; import { supabase } from '@/lib/supabaseClient'; import { useAuth } from '@/lib/auth'; +import { getConfirmedSlot } from '@/lib/types'; import type { EventRow, Slot, Vote, Profile } from '@/lib/types'; -import { SLOT_PRESETS } from '@/lib/slotPresets'; import { AvatarStack, type Person } from '@/components/Avatar'; import ProfileMenu from '@/components/ProfileMenu'; import GlassBackground from '@/components/GlassBackground'; @@ -43,10 +43,20 @@ export default function Home() { const [showForm, setShowForm] = useState(false); const [title, setTitle] = useState(''); const [location, setLocation] = useState(''); - const [proposedSlots, setProposedSlots] = useState(['']); + const [startsAt, setStartsAt] = useState(''); const [busy, setBusy] = useState(false); const [error, setError] = useState(''); + const titleInputRef = useRef(null); + + useEffect(() => { + if (showForm && titleInputRef.current) { + setTimeout(() => { + titleInputRef.current?.focus(); + }, 100); + } + }, [showForm]); + const load = useCallback(async () => { const [{ data: ev }, { data: sl }, { data: vo }, { data: pr }] = await Promise.all([ supabase.from('events').select('*').order('created_at', { ascending: false }), @@ -77,7 +87,7 @@ export default function Home() { async function createEvent(e: React.FormEvent) { e.preventDefault(); - if (!title.trim() || busy) return; + if (!title.trim() || !startsAt || busy) return; setBusy(true); setError(''); @@ -98,16 +108,13 @@ export default function Home() { return; } - const slotRows = proposedSlots - .filter((s) => s) - .map((s) => ({ + if (startsAt) { + await supabase.from('slots').insert({ event_id: data.id, - starts_at: new Date(s).toISOString(), + starts_at: new Date(startsAt).toISOString(), created_by: displayName, created_by_user_id: userId, - })); - if (slotRows.length > 0) { - await supabase.from('slots').insert(slotRows); + }); } router.push(`/event/${data.id}`); @@ -118,17 +125,54 @@ export default function Home() { const open: EventRow[] = []; const upcoming: EventRow[] = []; const past: EventRow[] = []; + + const slotsByEvent = new Map(); + for (const s of slots) { + const arr = slotsByEvent.get(s.event_id) ?? []; + arr.push(s); + slotsByEvent.set(s.event_id, arr); + } + const votesByEvent = new Map(); + for (const v of votes) { + const arr = votesByEvent.get(v.event_id) ?? []; + arr.push(v); + votesByEvent.set(v.event_id, arr); + } + + const confirmedDateMap = new Map(); + for (const ev of events) { - if (!ev.confirmed_at) open.push(ev); - else if (new Date(ev.confirmed_at).getTime() >= now) upcoming.push(ev); - else past.push(ev); + const evSlots = slotsByEvent.get(ev.id) ?? []; + const evVotes = votesByEvent.get(ev.id) ?? []; + const { confirmedAt } = getConfirmedSlot(evSlots, evVotes); + + if (!confirmedAt) { + open.push(ev); + } else { + confirmedDateMap.set(ev.id, confirmedAt); + if (new Date(confirmedAt).getTime() >= now) { + upcoming.push(ev); + } else { + past.push(ev); + } + } } - upcoming.sort((a, b) => new Date(a.confirmed_at!).getTime() - new Date(b.confirmed_at!).getTime()); - past.sort((a, b) => new Date(b.confirmed_at!).getTime() - new Date(a.confirmed_at!).getTime()); + + upcoming.sort((a, b) => { + const da = new Date(confirmedDateMap.get(a.id)!).getTime(); + const db = new Date(confirmedDateMap.get(b.id)!).getTime(); + return da - db; + }); + + past.sort((a, b) => { + const da = new Date(confirmedDateMap.get(a.id)!).getTime(); + const db = new Date(confirmedDateMap.get(b.id)!).getTime(); + return db - da; + }); + return { open, upcoming, past }; - }, [events]); + }, [events, slots, votes]); - // Agregaty per wypad: głosujący (z awatarami), % paczki, reprezentatywna data. const aggByEvent = useMemo(() => { const profileById = new Map(profiles.map((p) => [p.id, p])); const slotsBy = new Map(); @@ -147,7 +191,8 @@ export default function Home() { const result = new Map(); for (const ev of events) { const seen = new Map(); - for (const v of votesBy.get(ev.id) ?? []) { + const evVotes = votesBy.get(ev.id) ?? []; + for (const v of evVotes) { const key = v.user_id ?? `name:${v.participant_name}`; if (seen.has(key)) continue; const prof = v.user_id ? profileById.get(v.user_id) : undefined; @@ -158,7 +203,8 @@ export default function Home() { const evSlots = (slotsBy.get(ev.id) ?? []) .slice() .sort((a, b) => new Date(a.starts_at).getTime() - new Date(b.starts_at).getTime()); - const dateIso = ev.confirmed_at ?? evSlots[0]?.starts_at ?? null; + const { confirmedAt } = getConfirmedSlot(evSlots, evVotes); + const dateIso = confirmedAt ?? evSlots[0]?.starts_at ?? null; result.set(ev.id, { voters, percent, dateIso }); } return result; @@ -167,108 +213,229 @@ export default function Home() { return (
-
- Cześć, {displayName} - -
+
+ {/* Logo */} +
+ + + + + + +
- - - {showForm && ( -
-

Nowy wypad

-
- - setTitle(e.target.value)} - autoFocus - /> + {/* Nazwa + powitanie */} +
+
+ Planner
-
- - setLocation(e.target.value)} - /> +
+ Hej, {displayName} 👋
+
+ + +
+ + {events.length > 0 && ( + + )} + + {events.length > 0 && ( +
+ +

Nowy wypad

+
+ + setTitle(e.target.value)} + ref={titleInputRef} + /> +
+
+ + setLocation(e.target.value)} + /> +
+ +
+ + setStartsAt(e.target.value)} + style={{ flex: 1, minWidth: 200 }} + required + /> +
+ + {error &&

{error}

} + + +
+ )} -
- -
- {SLOT_PRESETS.map((p) => ( + {loading &&

Wczytuję…

} + + {!loading && events.length === 0 && ( +
+ {/* Sekcja 1: Brak wypadów (Empty State) */} +
+
+ {[ +
+ +
, +

Brak wypadów

, +

+ Zaproponuj pierwszy termin i wyślij znajomym. +

, , + ].map((child, i) => ( +
- + {p.label} - + {child} +
))}
- {proposedSlots.map((slot, i) => ( -
- - setProposedSlots((prev) => prev.map((s, j) => (j === i ? e.target.value : s))) - } - style={{ flex: 1, minWidth: 200 }} - /> - {proposedSlots.length > 1 && ( +
+ + {/* Sekcja 2: Formularz — kaskadowy fade-in od lewej */} +
+
+
+ {[ +

Nowy wypad

, +
+ + setTitle(e.target.value)} + ref={titleInputRef} + /> +
, +
+ + setLocation(e.target.value)} + /> +
, +
+ + setStartsAt(e.target.value)} + style={{ flex: 1, minWidth: 200 }} + required + /> +
, + error ?

{error}

: null, + , - )} -
- ))} - + Anuluj + , + ].filter(Boolean).map((child, i) => ( +
+ {child} +
+ ))} + +
- - {error &&

{error}

} - - - )} - - {loading &&

Wczytuję…

} - - {!loading && events.length === 0 && !showForm && ( -
-
🗓️
-

Brak wypadów

-

Zaproponuj pierwszy termin i wyślij znajomym.

-
)} @@ -341,24 +508,27 @@ function EventCard({ ev, agg, variant }: { ev: EventRow; agg: Agg; variant: 'ope ) : ( Nikt jeszcze nie głosował )} - - {variant === 'past' && ✓ Zakończony} - {variant === 'upcoming' && Ustalony} -
- {variant === 'open' && ( -
-
-
+ {variant === 'open' ? ( +
+
+
+
+ + {agg.percent}% zagłosowało +
- - {agg.percent}% zagłosowało - -
- )} + ) : ( + <> + + {variant === 'past' && ✓ Zakończony} + {variant === 'upcoming' && Ustalony} + + )} +
); } diff --git a/src/components/GlassBackground.tsx b/src/components/GlassBackground.tsx index f89cd28..bf7a291 100644 --- a/src/components/GlassBackground.tsx +++ b/src/components/GlassBackground.tsx @@ -1,12 +1,67 @@ -// Tło „Liquid Glass" — falujące kurtyny zorzy polarnej + subtelne ziarno. +import { useEffect, useRef } from 'react'; + +// Tło „Liquid Glass" w stylu Apple — wyciszone, zoptymalizowane wideo + rozmycie i nasycenie w CSS. export default function GlassBackground() { + const videoRef = useRef(null); + + useEffect(() => { + const video = videoRef.current; + if (!video) return; + + // Wyłączamy wbudowany loop, aby kontrolować kierunek za pomocą JavaScript + video.loop = false; + + let direction = 1; // 1 = w przód, -1 = w tył + let lastTime = performance.now(); + let frameId: number; + + const updatePlay = (now: number) => { + const delta = (now - lastTime) / 1000; + lastTime = now; + + if (video.duration) { + if (direction === 1) { + // Odtwarzanie w przód: pozwalamy przeglądarce odtwarzać naturalnie + if (video.paused) { + video.play().catch(() => {}); + } + // Gdy zbliżamy się do końca, zmieniamy kierunek + if (video.currentTime >= video.duration - 0.1) { + direction = -1; + video.pause(); + } + } else { + // Odtwarzanie w tył: cofamy currentTime o delta czasowy + let target = video.currentTime - delta; + if (target <= 0.1) { + target = 0.1; + direction = 1; + video.play().catch(() => {}); + } + video.currentTime = target; + } + } + + frameId = requestAnimationFrame(updatePlay); + }; + + frameId = requestAnimationFrame(updatePlay); + + return () => { + cancelAnimationFrame(frameId); + }; + }, []); + return ( ) : ( <> {variant === 'past' && ✓ Zakończony} - {variant === 'upcoming' && Ustalony} + {variant === 'upcoming' && Jest termin} )}
From 9e1db4f0725f03213af688a3119defd1e0a539ce Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 24 Jun 2026 18:41:19 +0000 Subject: [PATCH 036/117] =?UTF-8?q?Losuj=20docinek=20przy=20ka=C5=BCdym=20?= =?UTF-8?q?wej=C5=9Bciu=20+=20kaskadowa=20animacja=20formularza=20nowego?= =?UTF-8?q?=20wypadu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Docinek: zamiast stałego per wypad losujemy raz na wejście (useMemo), żeby pokazywały się różne warianty (też 'Te cweluchy się nie piszą') - Formularz '+ Nowy wypad' dostaje schodkową kaskadę pól (nth-child delays), taką jak w stanie pustym przy dodawaniu pierwszego wypadu Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MF3pEjMiVuE3XnzgNeXfR2 --- src/app/event/[id]/page.tsx | 9 ++------- src/app/globals.css | 9 +++++++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/app/event/[id]/page.tsx b/src/app/event/[id]/page.tsx index 7dc1c75..0a0d3d3 100644 --- a/src/app/event/[id]/page.tsx +++ b/src/app/event/[id]/page.tsx @@ -12,7 +12,7 @@ import { IconPin, IconCalendar, IconCheck } from '@/components/icons'; import GlassBackground from '@/components/GlassBackground'; import DateTimeInput from '@/components/DateTimeInput'; -// Docinki dla tych, co jeszcze się nie zapisali — losowane, ale stabilne per wypad. +// Docinki dla tych, co jeszcze się nie zapisali — losowane przy każdym wejściu. const NAG_TEXTS = [ 'Te cweluchy się nie piszą', 'Olali temat', @@ -20,11 +20,6 @@ const NAG_TEXTS = [ 'Wciąż się obijają', 'Mają to w nosie', ]; -function pickNag(id: string): string { - let h = 0; - for (let i = 0; i < id.length; i++) h = (h * 31 + id.charCodeAt(i)) | 0; - return NAG_TEXTS[Math.abs(h) % NAG_TEXTS.length]; -} const CHOICES: { value: Availability; label: string; cls: string }[] = [ { value: 'yes', label: 'Wchodzę', cls: 'active-yes' }, @@ -264,7 +259,7 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> const memberCount = members.length; const votedCount = participantsPeople.length; const votedPct = memberCount > 0 ? Math.min(100, Math.round((votedCount / memberCount) * 100)) : 0; - const nag = pickNag(eventId); + const nag = useMemo(() => NAG_TEXTS[Math.floor(Math.random() * NAG_TEXTS.length)], []); return (
diff --git a/src/app/globals.css b/src/app/globals.css index de490c0..1d2a7f0 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -760,6 +760,15 @@ img.avatar { display: inline-block; } transition: opacity 0.3s ease-out 0.08s, transform 0.35s cubic-bezier(0.25, 1, 0.5, 1) 0.08s; } +/* Kaskada pól po kolei — jak w stanie pustym przy pierwszym wypadzie */ +.form-collapse.open form > *:nth-child(1) { transition-delay: 0.12s; } +.form-collapse.open form > *:nth-child(2) { transition-delay: 0.19s; } +.form-collapse.open form > *:nth-child(3) { transition-delay: 0.26s; } +.form-collapse.open form > *:nth-child(4) { transition-delay: 0.33s; } +.form-collapse.open form > *:nth-child(5) { transition-delay: 0.40s; } +.form-collapse.open form > *:nth-child(6) { transition-delay: 0.47s; } +.form-collapse.open form > *:nth-child(7) { transition-delay: 0.54s; } + /* Logo i branding w nagłówku (bezpieczne klasy przed AdBlockami) */ .app-title-group { display: flex !important; From e41956310b2290db5f2d6d9ca1e5e964a2ad81ad Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 24 Jun 2026 18:44:45 +0000 Subject: [PATCH 037/117] =?UTF-8?q?Napraw=20crash=20strony=20wypadu:=20hoo?= =?UTF-8?q?k=20useMemo=20wo=C5=82any=20warunkowo=20po=20wczesnym=20return?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nag był obliczany useMemo po 'if (loading) return', więc przy przejściu loading true->false rosła liczba hooków i React się wywalał. Przeniesiono useMemo nad wczesne returny, do reszty hooków. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MF3pEjMiVuE3XnzgNeXfR2 --- src/app/event/[id]/page.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/event/[id]/page.tsx b/src/app/event/[id]/page.tsx index 0a0d3d3..83fbae9 100644 --- a/src/app/event/[id]/page.tsx +++ b/src/app/event/[id]/page.tsx @@ -235,6 +235,9 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> return Array.from(seen.values()); }, [votes, profileById]); + // Docinek losowany raz na zamontowanie strony (nie miga przy live-update). + const nag = useMemo(() => NAG_TEXTS[Math.floor(Math.random() * NAG_TEXTS.length)], []); + // Kto z paczki nie oddał jeszcze żadnego głosu w tym wypadzie. const missingVoters = useMemo(() => { const voted = new Set(votes.map((v) => v.user_id).filter(Boolean)); @@ -259,7 +262,6 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> const memberCount = members.length; const votedCount = participantsPeople.length; const votedPct = memberCount > 0 ? Math.min(100, Math.round((votedCount / memberCount) * 100)) : 0; - const nag = useMemo(() => NAG_TEXTS[Math.floor(Math.random() * NAG_TEXTS.length)], []); return (
From dce93f075a53bffd9432010dfa67601c4fa012a0 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 24 Jun 2026 18:47:35 +0000 Subject: [PATCH 038/117] =?UTF-8?q?Napraw=20kwadratowy=20r=C3=B3g=20karty?= =?UTF-8?q?=20formularza=20nowego=20wypadu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .form-collapse ma overflow:hidden bez border-radius, więc prostokątne przycięcie w połączeniu z backdrop-filter karty pokazywało kwadrat w zaokrąglonym rogu. Dodano border-radius na kontenerze zwijania. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MF3pEjMiVuE3XnzgNeXfR2 --- src/app/globals.css | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index 1d2a7f0..770c73a 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -710,12 +710,15 @@ img.avatar { display: inline-block; } .form-collapse { display: grid; grid-template-rows: 0fr; - transition: grid-template-rows 0.42s cubic-bezier(0.25, 1, 0.5, 1), - opacity 0.35s ease-in-out, - margin-top 0.42s cubic-bezier(0.25, 1, 0.5, 1), + transition: grid-template-rows 0.42s cubic-bezier(0.25, 1, 0.5, 1), + opacity 0.35s ease-in-out, + margin-top 0.42s cubic-bezier(0.25, 1, 0.5, 1), margin-bottom 0.42s cubic-bezier(0.25, 1, 0.5, 1); opacity: 0; overflow: hidden; + /* Zaokrąglone przycięcie rodzica — inaczej prostokątny clip + szklany blur karty + daje kwadratowy róg wystający spod zaokrąglenia */ + border-radius: var(--radius); margin-top: 0; margin-bottom: 0; } From 61a7aac4d977db25105842454d9acb2457d0e883 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 24 Jun 2026 18:56:42 +0000 Subject: [PATCH 039/117] =?UTF-8?q?Dodaj=20kierunkowe=20przej=C5=9Bcia=20m?= =?UTF-8?q?i=C4=99dzy=20stronami=20(iOS=20slide)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Włącz experimental.viewTransition w next.config - Komponent PageTransition owijający treść strony w React z mapą enter/exit dla typów nav-forward / nav-back - transitionTypes na linkach: wejście w wypad = nav-forward (slide z prawej), powrót do listy = nav-back (slide z lewej); router.push też taguje forward - CSS kierunkowych slajdów + poszanowanie prefers-reduced-motion - Typy canary Reacta (ViewTransition) włączone przez referencję w d.ts Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MF3pEjMiVuE3XnzgNeXfR2 --- next.config.mjs | 7 ++++- src/app/event/[id]/page.tsx | 7 +++-- src/app/globals.css | 47 +++++++++++++++++++++++++++++++ src/app/page.tsx | 7 +++-- src/components/PageTransition.tsx | 18 ++++++++++++ src/types/react-canary.d.ts | 4 +++ 6 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 src/components/PageTransition.tsx create mode 100644 src/types/react-canary.d.ts diff --git a/next.config.mjs b/next.config.mjs index 4678774..20f5b95 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,4 +1,9 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {}; +const nextConfig = { + experimental: { + // Włącza integrację React View Transitions — animacje przejść między stronami. + viewTransition: true, + }, +}; export default nextConfig; diff --git a/src/app/event/[id]/page.tsx b/src/app/event/[id]/page.tsx index 83fbae9..31503f6 100644 --- a/src/app/event/[id]/page.tsx +++ b/src/app/event/[id]/page.tsx @@ -10,6 +10,7 @@ import type { Availability, EventRow, Profile, Slot, Vote } from '@/lib/types'; import { Avatar, AvatarStack, type Person } from '@/components/Avatar'; import { IconPin, IconCalendar, IconCheck } from '@/components/icons'; import GlassBackground from '@/components/GlassBackground'; +import PageTransition from '@/components/PageTransition'; import DateTimeInput from '@/components/DateTimeInput'; // Docinki dla tych, co jeszcze się nie zapisali — losowane przy każdym wejściu. @@ -252,7 +253,7 @@ export default function EventPage({ params }: { params: Promise<{ id: string }>

Nie znaleziono

Ten wypad nie istnieje albo link jest nieprawidłowy.

- +
); } @@ -266,7 +267,8 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> return (
- ‹ Wszystkie wypady + + ‹ Wszystkie wypady

{event?.title}

@@ -414,6 +416,7 @@ export default function EventPage({ params }: { params: Promise<{ id: string }>
+
); } diff --git a/src/app/globals.css b/src/app/globals.css index 770c73a..9e27639 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -706,6 +706,53 @@ img.avatar { display: inline-block; } pointer-events: none; } +/* ===== Przejścia między stronami (iOS-owy slide) ===== */ +/* Wrapper zawartości strony — kontener animowany przez View Transitions. */ +.page-transition { min-height: 100%; } + +/* Wejście „w głąb" (nav-forward): stara strona jedzie w lewo, nowa wjeżdża z prawej. */ +::view-transition-old(.nav-forward) { + --slide: -28%; + animation: 180ms ease-in both vt-fade reverse, + 420ms cubic-bezier(0.32, 0.72, 0, 1) both vt-slide reverse; +} +::view-transition-new(.nav-forward) { + --slide: 28%; + animation: 240ms ease-out 120ms both vt-fade, + 420ms cubic-bezier(0.32, 0.72, 0, 1) both vt-slide; +} + +/* Powrót (nav-back): odwrotnie — nowa wjeżdża z lewej, stara odjeżdża w prawo. */ +::view-transition-old(.nav-back) { + --slide: 28%; + animation: 180ms ease-in both vt-fade reverse, + 420ms cubic-bezier(0.32, 0.72, 0, 1) both vt-slide reverse; +} +::view-transition-new(.nav-back) { + --slide: -28%; + animation: 240ms ease-out 120ms both vt-fade, + 420ms cubic-bezier(0.32, 0.72, 0, 1) both vt-slide; +} + +@keyframes vt-slide { + from { translate: var(--slide); } + to { translate: 0; } +} +@keyframes vt-fade { + from { opacity: 0; } + to { opacity: 1; } +} + +/* Szanuj „ogranicz ruch" — bez przesuwania, natychmiastowa zamiana. */ +@media (prefers-reduced-motion: reduce) { + ::view-transition-old(*), + ::view-transition-new(*), + ::view-transition-group(*) { + animation-duration: 0s !important; + animation-delay: 0s !important; + } +} + /* Animacja rozwijania formularza nowego wypadu */ .form-collapse { display: grid; diff --git a/src/app/page.tsx b/src/app/page.tsx index 0eb8b34..c01dd82 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -10,6 +10,7 @@ import type { EventRow, Slot, Vote, Profile } from '@/lib/types'; import { AvatarStack, type Person } from '@/components/Avatar'; import ProfileMenu from '@/components/ProfileMenu'; import GlassBackground from '@/components/GlassBackground'; +import PageTransition from '@/components/PageTransition'; import DateTimeInput from '@/components/DateTimeInput'; import { IconCalendar, IconClock, IconPin, IconChevron, IconBulb } from '@/components/icons'; @@ -118,7 +119,7 @@ export default function Home() { }); } - router.push(`/event/${data.id}`); + router.push(`/event/${data.id}`, { transitionTypes: ['nav-forward'] }); } const { open, upcoming, past } = useMemo(() => { @@ -214,6 +215,7 @@ export default function Home() { return (
+
{/* Logo */}
Im więcej osób da znać, tym łatwiej trafić w dobry termin.
)} +
); } @@ -476,7 +479,7 @@ function Section({ function EventCard({ ev, agg, variant }: { ev: EventRow; agg: Agg; variant: 'open' | 'upcoming' | 'past' }) { return ( - +
{ev.title} diff --git a/src/components/PageTransition.tsx b/src/components/PageTransition.tsx new file mode 100644 index 0000000..8cfabfe --- /dev/null +++ b/src/components/PageTransition.tsx @@ -0,0 +1,18 @@ +'use client'; + +import { ViewTransition } from 'react'; + +// Owija zawartość strony w animację przejścia kierunkowego (iOS-owy slide): +// wejście w wypad jedzie z prawej, powrót — z lewej. Kierunek niesie `transitionTypes` +// z /router (nav-forward / nav-back); bez typu (np. back przeglądarki) brak animacji. +export default function PageTransition({ children }: { children: React.ReactNode }) { + return ( + +
{children}
+
+ ); +} diff --git a/src/types/react-canary.d.ts b/src/types/react-canary.d.ts new file mode 100644 index 0000000..1ca1973 --- /dev/null +++ b/src/types/react-canary.d.ts @@ -0,0 +1,4 @@ +// Włącza typy z kanału canary Reacta (m.in. ViewTransition), które w App Routerze +// dostarcza Next przez swój wbudowany build Reacta. Sam moduł 'react/canary' nie +// istnieje w runtime — to wyłącznie referencja typów (nie trafia do bundla). +/// From 048cb3e35ff37bc184ec1db558770870bb7900bf Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 24 Jun 2026 19:08:06 +0000 Subject: [PATCH 040/117] =?UTF-8?q?Przej=C5=9Bcia=20stron:=20r=C4=99czne?= =?UTF-8?q?=20startViewTransition=20zamiast=20eksperymentalnej=20integracj?= =?UTF-8?q?i=20React?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Provider w layoucie (nie odmontowuje się przy nawigacji) owija router.push w document.startViewTransition i kończy animację po zmianie pathname - Kierunek przez data-vt na ; CSS animuje ::view-transition-old/new(root) (forward: nowa z prawej na wierzchu; back: bieżąca zjeżdża w prawo, odsłania poprzednią) - Linki/karty wołają useTransitionNavigate (z obsługą Cmd/Ctrl-klik i reduced-motion) - Usunięto experimental.viewTransition, komponent PageTransition i typy canary Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MF3pEjMiVuE3XnzgNeXfR2 --- next.config.mjs | 7 +-- src/app/event/[id]/page.tsx | 23 ++++++---- src/app/globals.css | 55 +++++++++-------------- src/app/layout.tsx | 5 ++- src/app/page.tsx | 22 ++++++--- src/components/PageTransition.tsx | 18 -------- src/lib/transition.tsx | 75 +++++++++++++++++++++++++++++++ src/types/react-canary.d.ts | 4 -- 8 files changed, 132 insertions(+), 77 deletions(-) delete mode 100644 src/components/PageTransition.tsx create mode 100644 src/lib/transition.tsx delete mode 100644 src/types/react-canary.d.ts diff --git a/next.config.mjs b/next.config.mjs index 20f5b95..4678774 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,9 +1,4 @@ /** @type {import('next').NextConfig} */ -const nextConfig = { - experimental: { - // Włącza integrację React View Transitions — animacje przejść między stronami. - viewTransition: true, - }, -}; +const nextConfig = {}; export default nextConfig; diff --git a/src/app/event/[id]/page.tsx b/src/app/event/[id]/page.tsx index 31503f6..105de35 100644 --- a/src/app/event/[id]/page.tsx +++ b/src/app/event/[id]/page.tsx @@ -2,7 +2,6 @@ import { use, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import Link from 'next/link'; -import { useRouter } from 'next/navigation'; import { supabase } from '@/lib/supabaseClient'; import { useAuth } from '@/lib/auth'; import { getConfirmedSlot } from '@/lib/types'; @@ -10,8 +9,8 @@ import type { Availability, EventRow, Profile, Slot, Vote } from '@/lib/types'; import { Avatar, AvatarStack, type Person } from '@/components/Avatar'; import { IconPin, IconCalendar, IconCheck } from '@/components/icons'; import GlassBackground from '@/components/GlassBackground'; -import PageTransition from '@/components/PageTransition'; import DateTimeInput from '@/components/DateTimeInput'; +import { useTransitionNavigate } from '@/lib/transition'; // Docinki dla tych, co jeszcze się nie zapisali — losowane przy każdym wejściu. const NAG_TEXTS = [ @@ -40,7 +39,7 @@ function formatSlot(iso: string): string { export default function EventPage({ params }: { params: Promise<{ id: string }> }) { const { id: eventId } = use(params); - const router = useRouter(); + const navigate = useTransitionNavigate(); const { userId, displayName } = useAuth(); const [event, setEvent] = useState(null); @@ -198,7 +197,7 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> window.alert('Nie udało się usunąć wypadu.'); return; } - router.push('/'); + navigate('/', 'back'); } const stats = useMemo(() => { @@ -253,7 +252,7 @@ export default function EventPage({ params }: { params: Promise<{ id: string }>

Nie znaleziono

Ten wypad nie istnieje albo link jest nieprawidłowy.

- + { if (e.metaKey || e.ctrlKey || e.shiftKey || e.button !== 0) return; e.preventDefault(); navigate('/', 'back'); }}> ); } @@ -267,8 +266,17 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> return (
- - ‹ Wszystkie wypady + { + if (e.metaKey || e.ctrlKey || e.shiftKey || e.button !== 0) return; + e.preventDefault(); + navigate('/', 'back'); + }} + > + ‹ Wszystkie wypady +

{event?.title}

@@ -416,7 +424,6 @@ export default function EventPage({ params }: { params: Promise<{ id: string }>
- ); } diff --git a/src/app/globals.css b/src/app/globals.css index 9e27639..8f7c19f 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -707,49 +707,38 @@ img.avatar { display: inline-block; } } /* ===== Przejścia między stronami (iOS-owy slide) ===== */ -/* Wrapper zawartości strony — kontener animowany przez View Transitions. */ -.page-transition { min-height: 100%; } +/* Kierunek niesie atrybut data-vt na (ustawiany w TransitionProvider). + Animujemy snapshoty całej strony: ::view-transition-old/new(root). */ +:root::view-transition-group(root) { animation-duration: 380ms; } -/* Wejście „w głąb" (nav-forward): stara strona jedzie w lewo, nowa wjeżdża z prawej. */ -::view-transition-old(.nav-forward) { - --slide: -28%; - animation: 180ms ease-in both vt-fade reverse, - 420ms cubic-bezier(0.32, 0.72, 0, 1) both vt-slide reverse; +/* Wejście „w głąb" (forward): stara jedzie lekko w lewo, nowa wjeżdża z prawej (na wierzchu). */ +:root[data-vt="forward"]::view-transition-old(root) { + animation: 380ms cubic-bezier(0.32, 0.72, 0, 1) both vt-out-left; } -::view-transition-new(.nav-forward) { - --slide: 28%; - animation: 240ms ease-out 120ms both vt-fade, - 420ms cubic-bezier(0.32, 0.72, 0, 1) both vt-slide; +:root[data-vt="forward"]::view-transition-new(root) { + z-index: 2; + animation: 380ms cubic-bezier(0.32, 0.72, 0, 1) both vt-in-right; } -/* Powrót (nav-back): odwrotnie — nowa wjeżdża z lewej, stara odjeżdża w prawo. */ -::view-transition-old(.nav-back) { - --slide: 28%; - animation: 180ms ease-in both vt-fade reverse, - 420ms cubic-bezier(0.32, 0.72, 0, 1) both vt-slide reverse; +/* Powrót (back): bieżąca strona zjeżdża w prawo (na wierzchu) i odsłania poprzednią z lewej. */ +:root[data-vt="back"]::view-transition-old(root) { + z-index: 2; + animation: 380ms cubic-bezier(0.32, 0.72, 0, 1) both vt-out-right; } -::view-transition-new(.nav-back) { - --slide: -28%; - animation: 240ms ease-out 120ms both vt-fade, - 420ms cubic-bezier(0.32, 0.72, 0, 1) both vt-slide; +:root[data-vt="back"]::view-transition-new(root) { + animation: 380ms cubic-bezier(0.32, 0.72, 0, 1) both vt-in-left; } -@keyframes vt-slide { - from { translate: var(--slide); } - to { translate: 0; } -} -@keyframes vt-fade { - from { opacity: 0; } - to { opacity: 1; } -} +@keyframes vt-in-right { from { transform: translateX(100%); } to { transform: translateX(0); } } +@keyframes vt-in-left { from { transform: translateX(-25%); } to { transform: translateX(0); } } +@keyframes vt-out-left { from { transform: translateX(0); } to { transform: translateX(-25%); } } +@keyframes vt-out-right { from { transform: translateX(0); } to { transform: translateX(100%); } } /* Szanuj „ogranicz ruch" — bez przesuwania, natychmiastowa zamiana. */ @media (prefers-reduced-motion: reduce) { - ::view-transition-old(*), - ::view-transition-new(*), - ::view-transition-group(*) { - animation-duration: 0s !important; - animation-delay: 0s !important; + :root::view-transition-old(root), + :root::view-transition-new(root) { + animation: none !important; } } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index b0c5e3f..f49b1bf 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -2,6 +2,7 @@ import type { Metadata, Viewport } from 'next'; import { Analytics } from '@vercel/analytics/next'; import { SpeedInsights } from '@vercel/speed-insights/next'; import { AuthProvider } from '@/lib/auth'; +import { TransitionProvider } from '@/lib/transition'; import './globals.css'; export const metadata: Metadata = { @@ -24,7 +25,9 @@ export default function RootLayout({ children }: { children: React.ReactNode })
- {children} + + {children} +
diff --git a/src/app/page.tsx b/src/app/page.tsx index c01dd82..cee686a 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -2,7 +2,6 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import Link from 'next/link'; -import { useRouter } from 'next/navigation'; import { supabase } from '@/lib/supabaseClient'; import { useAuth } from '@/lib/auth'; import { getConfirmedSlot } from '@/lib/types'; @@ -10,8 +9,8 @@ import type { EventRow, Slot, Vote, Profile } from '@/lib/types'; import { AvatarStack, type Person } from '@/components/Avatar'; import ProfileMenu from '@/components/ProfileMenu'; import GlassBackground from '@/components/GlassBackground'; -import PageTransition from '@/components/PageTransition'; import DateTimeInput from '@/components/DateTimeInput'; +import { useTransitionNavigate } from '@/lib/transition'; import { IconCalendar, IconClock, IconPin, IconChevron, IconBulb } from '@/components/icons'; function fmtDate(iso: string): string { @@ -33,7 +32,7 @@ type Agg = { voters: Person[]; percent: number; dateIso: string | null }; const EMPTY_AGG: Agg = { voters: [], percent: 0, dateIso: null }; export default function Home() { - const router = useRouter(); + const navigate = useTransitionNavigate(); const { userId, displayName } = useAuth(); const [events, setEvents] = useState([]); @@ -119,7 +118,7 @@ export default function Home() { }); } - router.push(`/event/${data.id}`, { transitionTypes: ['nav-forward'] }); + navigate(`/event/${data.id}`, 'forward'); } const { open, upcoming, past } = useMemo(() => { @@ -215,7 +214,6 @@ export default function Home() { return (
-
{/* Logo */}
Im więcej osób da znać, tym łatwiej trafić w dobry termin.
)} -
); } @@ -478,8 +475,19 @@ function Section({ } function EventCard({ ev, agg, variant }: { ev: EventRow; agg: Agg; variant: 'open' | 'upcoming' | 'past' }) { + const navigate = useTransitionNavigate(); + const href = `/event/${ev.id}`; return ( - + { + // Pozwól na otwieranie w nowej karcie (Cmd/Ctrl/środkowy przycisk); inaczej animowany slide. + if (e.metaKey || e.ctrlKey || e.shiftKey || e.button !== 0) return; + e.preventDefault(); + navigate(href, 'forward'); + }} + >
{ev.title} diff --git a/src/components/PageTransition.tsx b/src/components/PageTransition.tsx deleted file mode 100644 index 8cfabfe..0000000 --- a/src/components/PageTransition.tsx +++ /dev/null @@ -1,18 +0,0 @@ -'use client'; - -import { ViewTransition } from 'react'; - -// Owija zawartość strony w animację przejścia kierunkowego (iOS-owy slide): -// wejście w wypad jedzie z prawej, powrót — z lewej. Kierunek niesie `transitionTypes` -// z /router (nav-forward / nav-back); bez typu (np. back przeglądarki) brak animacji. -export default function PageTransition({ children }: { children: React.ReactNode }) { - return ( - -
{children}
-
- ); -} diff --git a/src/lib/transition.tsx b/src/lib/transition.tsx new file mode 100644 index 0000000..4efc484 --- /dev/null +++ b/src/lib/transition.tsx @@ -0,0 +1,75 @@ +'use client'; + +import { createContext, useCallback, useContext, useEffect, useRef } from 'react'; +import { usePathname, useRouter } from 'next/navigation'; + +type Direction = 'forward' | 'back'; +type NavigateFn = (href: string, dir: Direction) => void; + +const Ctx = createContext(null); + +type DocWithVT = Document & { + startViewTransition?: (cb: () => void | Promise) => { finished: Promise }; +}; + +// Provider żyje w layoucie (nie odmontowuje się przy nawigacji), dzięki czemu może +// dokończyć animację już po zamontowaniu nowej strony. Mechanizm: +// 1) ustawiamy kierunek na , 2) startViewTransition robi snapshot starej strony, +// 3) router.push renderuje nową; gdy zmieni się pathname, rozwiązujemy obietnicę, by przeglądarka +// zrobiła snapshot nowej strony i odpaliła slajd (CSS w globals.css). +export function TransitionProvider({ children }: { children: React.ReactNode }) { + const router = useRouter(); + const pathname = usePathname(); + const resolveRef = useRef<(() => void) | null>(null); + + useEffect(() => { + if (resolveRef.current) { + resolveRef.current(); + resolveRef.current = null; + } + }, [pathname]); + + const navigate = useCallback( + (href, dir) => { + const doc = document as DocWithVT; + const reduce = + typeof window !== 'undefined' && + window.matchMedia('(prefers-reduced-motion: reduce)').matches; + + if (!doc.startViewTransition || reduce) { + router.push(href); + return; + } + + document.documentElement.dataset.vt = dir; + const transition = doc.startViewTransition( + () => + new Promise((resolve) => { + resolveRef.current = resolve; + router.push(href); + // Bezpiecznik: jeśli nawigacja nie zmieni ścieżki, nie wieszaj animacji. + setTimeout(() => { + if (resolveRef.current === resolve) { + resolveRef.current = null; + resolve(); + } + }, 600); + }), + ); + transition.finished.finally(() => { + if (document.documentElement.dataset.vt === dir) { + delete document.documentElement.dataset.vt; + } + }); + }, + [router], + ); + + return {children}; +} + +export function useTransitionNavigate(): NavigateFn { + const fn = useContext(Ctx); + if (!fn) throw new Error('useTransitionNavigate musi być użyte wewnątrz TransitionProvider'); + return fn; +} diff --git a/src/types/react-canary.d.ts b/src/types/react-canary.d.ts deleted file mode 100644 index 1ca1973..0000000 --- a/src/types/react-canary.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Włącza typy z kanału canary Reacta (m.in. ViewTransition), które w App Routerze -// dostarcza Next przez swój wbudowany build Reacta. Sam moduł 'react/canary' nie -// istnieje w runtime — to wyłącznie referencja typów (nie trafia do bundla). -/// From 84612a5e3bcbb12eec604e1c1237b0d2f3360d6d Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 24 Jun 2026 19:15:02 +0000 Subject: [PATCH 041/117] =?UTF-8?q?Optymalizacja=20wydajno=C5=9Bci=20t?= =?UTF-8?q?=C5=82a=20i=20animacji=20(g=C5=82=C3=B3wnie=20iOS)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GlassBackground: natywna pętla zamiast per-klatkowego seeku currentTime (najcięższy koszt na iOS); pauza wideo gdy karta w tle - Hoist tła do layoutu — jedna persystentna instancja zamiast remountu i reloadu wideo przy każdej nawigacji (płynniejsze też przejścia stron) - Wideo na własnej warstwie GPU (translateZ/will-change), blur 60px -> 44px (wygląd ~ten sam, taniej) - contain: layout paint na .form-collapse — animacja rozwijania nie reflowuje całej listy wypadów Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MF3pEjMiVuE3XnzgNeXfR2 --- src/app/event/[id]/page.tsx | 5 +-- src/app/globals.css | 13 +++++-- src/app/layout.tsx | 2 ++ src/app/page.tsx | 2 -- src/components/GlassBackground.tsx | 56 ++++++++---------------------- 5 files changed, 29 insertions(+), 49 deletions(-) diff --git a/src/app/event/[id]/page.tsx b/src/app/event/[id]/page.tsx index 105de35..0051e0e 100644 --- a/src/app/event/[id]/page.tsx +++ b/src/app/event/[id]/page.tsx @@ -8,7 +8,6 @@ import { getConfirmedSlot } from '@/lib/types'; import type { Availability, EventRow, Profile, Slot, Vote } from '@/lib/types'; import { Avatar, AvatarStack, type Person } from '@/components/Avatar'; import { IconPin, IconCalendar, IconCheck } from '@/components/icons'; -import GlassBackground from '@/components/GlassBackground'; import DateTimeInput from '@/components/DateTimeInput'; import { useTransitionNavigate } from '@/lib/transition'; @@ -244,12 +243,11 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> return members.filter((m) => !voted.has(m.id)).map((m) => m.display_name); }, [members, votes]); - if (loading) return

Wczytuję…

; + if (loading) return

Wczytuję…

; if (notFound) { return (
-

Nie znaleziono

Ten wypad nie istnieje albo link jest nieprawidłowy.

{ if (e.metaKey || e.ctrlKey || e.shiftKey || e.button !== 0) return; e.preventDefault(); navigate('/', 'back'); }}> @@ -265,7 +263,6 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> return (
- +
{children} diff --git a/src/app/page.tsx b/src/app/page.tsx index cee686a..1ab6531 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -8,7 +8,6 @@ import { getConfirmedSlot } from '@/lib/types'; import type { EventRow, Slot, Vote, Profile } from '@/lib/types'; import { AvatarStack, type Person } from '@/components/Avatar'; import ProfileMenu from '@/components/ProfileMenu'; -import GlassBackground from '@/components/GlassBackground'; import DateTimeInput from '@/components/DateTimeInput'; import { useTransitionNavigate } from '@/lib/transition'; import { IconCalendar, IconClock, IconPin, IconChevron, IconBulb } from '@/components/icons'; @@ -213,7 +212,6 @@ export default function Home() { return (
-
{/* Logo */}
(null); @@ -8,48 +13,15 @@ export default function GlassBackground() { const video = videoRef.current; if (!video) return; - // Wyłączamy wbudowany loop, aby kontrolować kierunek za pomocą JavaScript - video.loop = false; - - let direction = 1; // 1 = w przód, -1 = w tył - let lastTime = performance.now(); - let frameId: number; - - const updatePlay = (now: number) => { - const delta = (now - lastTime) / 1000; - lastTime = now; - - if (video.duration) { - if (direction === 1) { - // Odtwarzanie w przód: pozwalamy przeglądarce odtwarzać naturalnie - if (video.paused) { - video.play().catch(() => {}); - } - // Gdy zbliżamy się do końca, zmieniamy kierunek - if (video.currentTime >= video.duration - 0.1) { - direction = -1; - video.pause(); - } - } else { - // Odtwarzanie w tył: cofamy currentTime o delta czasowy - let target = video.currentTime - delta; - if (target <= 0.1) { - target = 0.1; - direction = 1; - video.play().catch(() => {}); - } - video.currentTime = target; - } - } - - frameId = requestAnimationFrame(updatePlay); - }; - - frameId = requestAnimationFrame(updatePlay); + const tryPlay = () => video.play().catch(() => {}); + tryPlay(); // niektóre Safari nie startują autoplay bez jawnego play() - return () => { - cancelAnimationFrame(frameId); + const onVisibility = () => { + if (document.hidden) video.pause(); + else tryPlay(); }; + document.addEventListener('visibilitychange', onVisibility); + return () => document.removeEventListener('visibilitychange', onVisibility); }, []); return ( @@ -59,7 +31,9 @@ export default function GlassBackground() { src="/BG/dark abstract.mp4" autoPlay muted + loop playsInline + preload="auto" className="glass-video" />
From b2bd94b62fa9b4ba665ce9341ac600f9e719b9ff Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 24 Jun 2026 19:19:41 +0000 Subject: [PATCH 042/117] =?UTF-8?q?Napraw=20t=C5=82o=20po=20hoistcie:=20au?= =?UTF-8?q?rora=20zn=C3=B3w=20za=20ca=C5=82=C4=85=20tre=C5=9Bci=C4=85,=20n?= =?UTF-8?q?ie=20tylko=20pod=20panelem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Po przeniesieniu tła do body z-index:-1 chował je za nieprzezroczystym tłem body (aurora widoczna tylko poniżej treści). Tło na z-index:0, .container z treścią na z-index:1 — aurora wypełnia ekran za zawartością jak wcześniej. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MF3pEjMiVuE3XnzgNeXfR2 --- src/app/globals.css | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index 1b8b89a..2fa23e8 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -40,6 +40,9 @@ html, body { .container { max-width: 680px; margin: 0 auto; + /* Nad globalnym tłem (.glass-bg z-index:0), nad nieprzezroczystym tłem body. */ + position: relative; + z-index: 1; /* Marginesy + bezpieczne obszary iOS (notch, pasek home) w trybie standalone. */ padding: calc(28px + env(safe-area-inset-top)) calc(20px + env(safe-area-inset-right)) @@ -582,9 +585,9 @@ img.avatar { display: inline-block; } .glass-page { position: relative; z-index: 1; } .glass-bg { - /* z-index: -1 trzyma tło za CAŁĄ zawartością .glass-page (też niepozycjonowanym - nagłówkiem), inaczej pozycjonowane tło zasłaniałoby tytuł i przycisk udostępniania */ - position: fixed; inset: 0; z-index: -1; pointer-events: none; overflow: hidden; + /* Globalne tło na z-index:0 (nad nieprzezroczystym tłem body); cała treść siedzi + w .container z z-index:1, więc jest nad aurorą. */ + position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; background: #050505; } From 83616a3aecd285135ded017c316cc29c0ee02e4d Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 24 Jun 2026 19:32:44 +0000 Subject: [PATCH 043/117] =?UTF-8?q?Perf:=20zdejmij=20backdrop-filter=20z?= =?UTF-8?q?=20powtarzanych=20kart=20listy=20wypad=C3=B3w?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rozmycie szkła nad odtwarzanym wideo przelicza się co klatkę dla każdej karty. Karty listy (.event-rich) powtarzają się N razy — zamiast frostowania dają teraz ciemne półprzezroczyste tło (panel). Duże karty i CTA zostają szklane. Duży zysk na głównym ekranie przy minimalnej zmianie wyglądu. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MF3pEjMiVuE3XnzgNeXfR2 --- src/app/globals.css | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index 2fa23e8..540e3e0 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -635,16 +635,17 @@ img.avatar { display: inline-block; } /* Szklane karty wydarzeń */ .glass-page .event-rich { - background: rgba(255, 255, 255, 0.03); + /* Bez backdrop-filter: karty listy powtarzają się N razy, a rozmycie nad + odtwarzanym wideo przelicza się co klatkę dla każdej z nich. Zamiast frostowania + ciemne półprzezroczyste tło — czyta się jak panel, wygląd zbliżony, koszt ~zerowy. */ + background: rgba(13, 13, 17, 0.55); border: 1px solid rgba(255, 255, 255, 0.08); - -webkit-backdrop-filter: blur(30px) saturate(200%); - backdrop-filter: blur(30px) saturate(150%); box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.15), + inset 0 1px 0 rgba(255, 255, 255, 0.12), 0 20px 40px rgba(0, 0, 0, 0.4); } .glass-page .event-rich:hover { - background: rgba(255, 255, 255, 0.06); + background: rgba(26, 26, 32, 0.6); border-color: rgba(255, 255, 255, 0.12); } From cd90cb4ee3081075dee14cdf1ddc737cada0dfb7 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 24 Jun 2026 19:40:00 +0000 Subject: [PATCH 044/117] =?UTF-8?q?Dodaj=20prze=C5=82=C4=85cznik=20animowa?= =?UTF-8?q?nego=20t=C5=82a=20w=20menu=20profilu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - BackgroundProvider (kontekst + zapamiętywanie w localStorage) - GlassBackground respektuje preferencję (wyłączone = brak wideo, czarne tło) - Przełącznik (iOS-owy switch) w modalu profilu, pod wyborem awatara - Wyłączenie tła wyraźnie odciąża słabsze urządzenia (brak dekodu/blura wideo, szkło nad statycznym tłem liczone raz zamiast co klatkę) Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MF3pEjMiVuE3XnzgNeXfR2 --- src/app/globals.css | 30 +++++++++++++++++++++ src/app/layout.tsx | 15 ++++++----- src/components/GlassBackground.tsx | 8 +++++- src/components/ProfileMenu.tsx | 19 ++++++++++++++ src/lib/background.tsx | 42 ++++++++++++++++++++++++++++++ 5 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 src/lib/background.tsx diff --git a/src/app/globals.css b/src/app/globals.css index 540e3e0..2bbae8c 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -523,6 +523,36 @@ img.avatar { display: inline-block; } .profile-emoji-row { display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; margin-bottom: 18px; } .profile-modal .field { text-align: left; } +/* Wiersz ustawienia (np. przełącznik tła) */ +.setting-row { + display: flex; align-items: center; gap: 12px; + text-align: left; margin-bottom: 18px; +} +.setting-text { flex: 1; min-width: 0; } +.setting-title { display: block; font-weight: 500; color: rgba(255, 255, 255, 0.9); } +.setting-sub { display: block; font-size: 0.78rem; color: var(--muted); margin-top: 1px; } + +/* Przełącznik w stylu iOS */ +.switch { + flex-shrink: 0; + width: 50px; height: 30px; padding: 0; + border-radius: 999px; + background: rgba(255, 255, 255, 0.14); + border: 1px solid rgba(255, 255, 255, 0.12); + position: relative; + transition: background 0.2s ease; +} +.switch.on { background: var(--yes); border-color: transparent; } +.switch-knob { + position: absolute; top: 50%; left: 3px; + width: 24px; height: 24px; border-radius: 50%; + background: #fff; + transform: translateY(-50%); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4); + transition: left 0.2s cubic-bezier(0.25, 1, 0.5, 1); +} +.switch.on .switch-knob { left: 23px; } + .profile-modal label { color: rgba(255, 255, 255, 0.7); font-weight: 500; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 9bec874..a22c401 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -3,6 +3,7 @@ import { Analytics } from '@vercel/analytics/next'; import { SpeedInsights } from '@vercel/speed-insights/next'; import { AuthProvider } from '@/lib/auth'; import { TransitionProvider } from '@/lib/transition'; +import { BackgroundProvider } from '@/lib/background'; import GlassBackground from '@/components/GlassBackground'; import './globals.css'; @@ -25,12 +26,14 @@ export default function RootLayout({ children }: { children: React.ReactNode }) return ( - -
- - {children} - -
+ + +
+ + {children} + +
+
diff --git a/src/components/GlassBackground.tsx b/src/components/GlassBackground.tsx index bd50ef2..3b5ab42 100644 --- a/src/components/GlassBackground.tsx +++ b/src/components/GlassBackground.tsx @@ -1,15 +1,19 @@ 'use client'; import { useEffect, useRef } from 'react'; +import { useBackground } from '@/lib/background'; // Tło „Liquid Glass" — wyciszone wideo + rozmycie/nasycenie w CSS. // Pętla natywna (loop) zamiast ręcznego cofania `currentTime` co klatkę — to ostatnie // było bardzo kosztowne na iOS (per-klatkowy seek = ciągłe dekodowanie, zabierało wątek // główny innym animacjom). Pauzujemy też wideo, gdy karta jest w tle. +// Można je całkiem wyłączyć (przełącznik w menu profilu) dla maksymalnej wydajności. export default function GlassBackground() { + const { enabled } = useBackground(); const videoRef = useRef(null); useEffect(() => { + if (!enabled) return; const video = videoRef.current; if (!video) return; @@ -22,7 +26,9 @@ export default function GlassBackground() { }; document.addEventListener('visibilitychange', onVisibility); return () => document.removeEventListener('visibilitychange', onVisibility); - }, []); + }, [enabled]); + + if (!enabled) return null; return ( +
+
+ Animowane tło + Wyłącz dla lepszej płynności +
+ +
+
diff --git a/src/lib/background.tsx b/src/lib/background.tsx new file mode 100644 index 0000000..582a1e6 --- /dev/null +++ b/src/lib/background.tsx @@ -0,0 +1,42 @@ +'use client'; + +import { createContext, useCallback, useContext, useEffect, useState } from 'react'; + +type BackgroundCtx = { enabled: boolean; toggle: () => void }; +const Ctx = createContext(null); +const KEY = 'planner-bg-enabled'; + +// Preferencja włączenia animowanego tła (wideo). Domyślnie wł.; zapamiętywana w localStorage. +// Wideo jest kosztowne (dekoduje się + rozmywa co klatkę i zmusza szkło do ciągłego +// przeliczania), więc wyłączenie tła wyraźnie odciąża słabsze urządzenia. +export function BackgroundProvider({ children }: { children: React.ReactNode }) { + const [enabled, setEnabled] = useState(true); + + useEffect(() => { + try { + if (localStorage.getItem(KEY) === '0') setEnabled(false); + } catch { + /* brak dostępu do localStorage — zostaje domyślne wł. */ + } + }, []); + + const toggle = useCallback(() => { + setEnabled((v) => { + const next = !v; + try { + localStorage.setItem(KEY, next ? '1' : '0'); + } catch { + /* ignorujemy */ + } + return next; + }); + }, []); + + return {children}; +} + +export function useBackground(): BackgroundCtx { + const ctx = useContext(Ctx); + if (!ctx) throw new Error('useBackground musi być użyte wewnątrz BackgroundProvider'); + return ctx; +} From cb2df2734b59134d4a34aba81b28b67313c9ea19 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 24 Jun 2026 19:54:47 +0000 Subject: [PATCH 045/117] =?UTF-8?q?P=C5=82ynniejsze=20rozwijanie=20formula?= =?UTF-8?q?rza:=20karta=20bez=20backdrop-filter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Duża karta formularza nowego wypadu rozmywała tło co klatkę w trakcie animacji wysokości — zamiana na ciemny kryjący panel (jak karty listy) usuwa ten koszt. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MF3pEjMiVuE3XnzgNeXfR2 --- src/app/globals.css | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index 2bbae8c..48f621a 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -814,16 +814,12 @@ img.avatar { display: inline-block; } .form-collapse .card, .form-collapse .empty-state { margin-bottom: 0; - /* Wyłączamy backdrop-filter w zamkniętym stanie, żeby uniknąć przeskoku koloru */ + /* Bez backdrop-filter: duża szklana karta liczyłaby rozmycie tła co klatkę + dokładnie w trakcie animacji wysokości — to psuło płynność rozwijania. + Zamiast frostu ciemny, kryjący panel. */ + background: rgba(16, 16, 20, 0.9); -webkit-backdrop-filter: none; backdrop-filter: none; - transition: backdrop-filter 0.3s ease 0.35s, -webkit-backdrop-filter 0.3s ease 0.35s; -} -.form-collapse.open .card, -.form-collapse.open .empty-state { - /* Włączamy backdrop-filter z opóźnieniem — dopiero po zakończeniu rozwijania grida */ - -webkit-backdrop-filter: blur(30px) saturate(200%); - backdrop-filter: blur(30px) saturate(200%); } /* Animacja zawartości (wygładzenie pojawiania się) */ From 591d61f0f5ad5a72e25914594bd048f8d44037a5 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 24 Jun 2026 20:00:38 +0000 Subject: [PATCH 046/117] =?UTF-8?q?Przywr=C3=B3=C4=87=20szklany=20wygl?= =?UTF-8?q?=C4=85d=20karty=20formularza=20nowego=20wypadu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To była percepcja, nie realny lag — wracamy do backdrop-filter. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MF3pEjMiVuE3XnzgNeXfR2 --- src/app/globals.css | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index 48f621a..2bbae8c 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -814,12 +814,16 @@ img.avatar { display: inline-block; } .form-collapse .card, .form-collapse .empty-state { margin-bottom: 0; - /* Bez backdrop-filter: duża szklana karta liczyłaby rozmycie tła co klatkę - dokładnie w trakcie animacji wysokości — to psuło płynność rozwijania. - Zamiast frostu ciemny, kryjący panel. */ - background: rgba(16, 16, 20, 0.9); + /* Wyłączamy backdrop-filter w zamkniętym stanie, żeby uniknąć przeskoku koloru */ -webkit-backdrop-filter: none; backdrop-filter: none; + transition: backdrop-filter 0.3s ease 0.35s, -webkit-backdrop-filter 0.3s ease 0.35s; +} +.form-collapse.open .card, +.form-collapse.open .empty-state { + /* Włączamy backdrop-filter z opóźnieniem — dopiero po zakończeniu rozwijania grida */ + -webkit-backdrop-filter: blur(30px) saturate(200%); + backdrop-filter: blur(30px) saturate(200%); } /* Animacja zawartości (wygładzenie pojawiania się) */ From 9ce501efe673875c7f6dd29f6b64f16cd53513dd Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 24 Jun 2026 20:00:38 +0000 Subject: [PATCH 047/117] =?UTF-8?q?Cache=20danych:=20natychmiastowe=20otwi?= =?UTF-8?q?eranie=20wypad=C3=B3w=20(dane=20z=20dashboardu)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Lekki singleton w pamięci (dataCache): dashboard zapisuje komplet danych, strona wypadu seeduje z niego stan na start -> brak 'Wczytuję...' przy wejściu z listy - Strona wypadu po świeżym load() odświeża cache (mergeEventData), więc powrót na listę pokazuje aktualne dane - Dashboard też seeduje z cache (instant powrót) - Realtime i load() bez zmian — głosy/zmiany dalej aktualizują się na żywo; cache to tylko zaliczka na render, nie zamiennik pobierania Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MF3pEjMiVuE3XnzgNeXfR2 --- src/app/event/[id]/page.tsx | 23 +++++++++++++---- src/app/page.tsx | 26 ++++++++++++------- src/lib/dataCache.ts | 51 +++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 14 deletions(-) create mode 100644 src/lib/dataCache.ts diff --git a/src/app/event/[id]/page.tsx b/src/app/event/[id]/page.tsx index 0051e0e..07143c4 100644 --- a/src/app/event/[id]/page.tsx +++ b/src/app/event/[id]/page.tsx @@ -10,6 +10,7 @@ import { Avatar, AvatarStack, type Person } from '@/components/Avatar'; import { IconPin, IconCalendar, IconCheck } from '@/components/icons'; import DateTimeInput from '@/components/DateTimeInput'; import { useTransitionNavigate } from '@/lib/transition'; +import { getCache, mergeEventData } from '@/lib/dataCache'; // Docinki dla tych, co jeszcze się nie zapisali — losowane przy każdym wejściu. const NAG_TEXTS = [ @@ -41,11 +42,15 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> const navigate = useTransitionNavigate(); const { userId, displayName } = useAuth(); - const [event, setEvent] = useState(null); - const [slots, setSlots] = useState([]); - const [votes, setVotes] = useState([]); - const [members, setMembers] = useState([]); - const [loading, setLoading] = useState(true); + // Seed z cache dashboardu (jeśli wchodzimy z listy) — wypad pokazuje się natychmiast, + // a load() poniżej i tak dociąga świeże dane i podpina realtime. + const seed = getCache(); + const seedEvent = seed?.events.find((e) => e.id === eventId) ?? null; + const [event, setEvent] = useState(seedEvent); + const [slots, setSlots] = useState(() => seed?.slots.filter((s) => s.event_id === eventId) ?? []); + const [votes, setVotes] = useState(() => seed?.votes.filter((v) => v.event_id === eventId) ?? []); + const [members, setMembers] = useState(() => seed?.profiles ?? []); + const [loading, setLoading] = useState(!seedEvent); const [notFound, setNotFound] = useState(false); const [newSlot, setNewSlot] = useState(''); @@ -98,6 +103,14 @@ export default function EventPage({ params }: { params: Promise<{ id: string }> } } setVotes(merged); + + // Odśwież cache tego wypadu, by powrót na listę pokazał aktualne dane. + mergeEventData(eventId, { + event: ev as EventRow, + slots: (sl ?? []) as Slot[], + votes: dbVotes, + profiles: (pr ?? []) as Profile[], + }); } setLoading(false); }, [eventId, userId, displayName]); diff --git a/src/app/page.tsx b/src/app/page.tsx index 1ab6531..11c7c2e 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -10,6 +10,7 @@ import { AvatarStack, type Person } from '@/components/Avatar'; import ProfileMenu from '@/components/ProfileMenu'; import DateTimeInput from '@/components/DateTimeInput'; import { useTransitionNavigate } from '@/lib/transition'; +import { getCache, setCache } from '@/lib/dataCache'; import { IconCalendar, IconClock, IconPin, IconChevron, IconBulb } from '@/components/icons'; function fmtDate(iso: string): string { @@ -34,11 +35,13 @@ export default function Home() { const navigate = useTransitionNavigate(); const { userId, displayName } = useAuth(); - const [events, setEvents] = useState([]); - const [slots, setSlots] = useState([]); - const [votes, setVotes] = useState([]); - const [profiles, setProfiles] = useState([]); - const [loading, setLoading] = useState(true); + // Seed z cache (jeśli wracamy z wypadu) — lista pojawia się od razu, bez „Wczytuję…". + const cached = getCache(); + const [events, setEvents] = useState(() => cached?.events ?? []); + const [slots, setSlots] = useState(() => cached?.slots ?? []); + const [votes, setVotes] = useState(() => cached?.votes ?? []); + const [profiles, setProfiles] = useState(() => cached?.profiles ?? []); + const [loading, setLoading] = useState(() => !cached); const [showForm, setShowForm] = useState(false); const [title, setTitle] = useState(''); @@ -64,10 +67,15 @@ export default function Home() { supabase.from('votes').select('*'), supabase.from('profiles').select('*'), ]); - setEvents((ev ?? []) as EventRow[]); - setSlots((sl ?? []) as Slot[]); - setVotes((vo ?? []) as Vote[]); - setProfiles((pr ?? []) as Profile[]); + const events = (ev ?? []) as EventRow[]; + const slots = (sl ?? []) as Slot[]; + const votes = (vo ?? []) as Vote[]; + const profiles = (pr ?? []) as Profile[]; + setEvents(events); + setSlots(slots); + setVotes(votes); + setProfiles(profiles); + setCache({ events, slots, votes, profiles }); // zaliczka dla strony wypadu setLoading(false); }, []); diff --git a/src/lib/dataCache.ts b/src/lib/dataCache.ts new file mode 100644 index 0000000..8445134 --- /dev/null +++ b/src/lib/dataCache.ts @@ -0,0 +1,51 @@ +import type { EventRow, Slot, Vote, Profile } from './types'; + +// Lekki cache w pamięci (singleton po stronie klienta). Dashboard ładuje komplet danych; +// strona wypadu odczytuje je na start, by pokazać się natychmiast — a potem i tak +// rewaliduje przez własne load() + realtime, więc dane pozostają świeże i na żywo. +// To wyłącznie „zaliczka" na otwarcie, nie zamiennik pobierania. + +export type AppData = { + events: EventRow[]; + slots: Slot[]; + votes: Vote[]; + profiles: Profile[]; +}; + +let cache: AppData | null = null; + +export function getCache(): AppData | null { + return cache; +} + +export function setCache(data: AppData): void { + cache = data; +} + +function upsertEvent(events: EventRow[], ev: EventRow): EventRow[] { + const rest = events.filter((e) => e.id !== ev.id); + return [...rest, ev]; +} + +// Po świeżym pobraniu danych jednego wypadu odśwież ich kopię w cache, +// żeby powrót na listę nie pokazał starych głosów/terminów. +export function mergeEventData( + eventId: string, + data: { event: EventRow | null; slots: Slot[]; votes: Vote[]; profiles: Profile[] }, +): void { + if (!cache) { + cache = { + events: data.event ? [data.event] : [], + slots: [...data.slots], + votes: [...data.votes], + profiles: [...data.profiles], + }; + return; + } + cache = { + events: data.event ? upsertEvent(cache.events, data.event) : cache.events, + slots: [...cache.slots.filter((s) => s.event_id !== eventId), ...data.slots], + votes: [...cache.votes.filter((v) => v.event_id !== eventId), ...data.votes], + profiles: data.profiles.length ? data.profiles : cache.profiles, + }; +} From 58f2f4b204013cd56743125b2385c555c54c3ef6 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 25 Jun 2026 04:09:20 +0000 Subject: [PATCH 048/117] =?UTF-8?q?Pe=C5=82na=20szeroko=C5=9B=C4=87=20przy?= =?UTF-8?q?cisku=20'Utw=C3=B3rz=20wypad'=20(by=C5=82=20sizowany=20do=20tre?= =?UTF-8?q?=C5=9Bci)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MF3pEjMiVuE3XnzgNeXfR2 --- src/app/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index 11c7c2e..514b330 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -294,7 +294,7 @@ export default function Home() {
{error &&

{error}

} - From 08d3a67c49ae03e541ece5bfcc9938b404583f08 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 25 Jun 2026 04:12:50 +0000 Subject: [PATCH 049/117] =?UTF-8?q?Zamie=C5=84=20wideo=20t=C5=82a=20na=20a?= =?UTF-8?q?nimowany=20gradient=20aurora=20(CSS)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rozwiązuje przeskok na pętli i okazjonalny freeze wideo. Dwie warstwy radialnych gradientów animowane tylko transformem (GPU), pętla alternate = bezszwowa. Koszt znikomy, brak dekodowania wideo. Przełącznik tła w profilu działa jak dotąd. Plik wideo zostaje w repo na wypadek powrotu. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MF3pEjMiVuE3XnzgNeXfR2 --- src/app/globals.css | 50 ++++++++++++++++++++++-------- src/components/GlassBackground.tsx | 38 +++-------------------- 2 files changed, 41 insertions(+), 47 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index 2bbae8c..a4f47c9 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -621,24 +621,48 @@ img.avatar { display: inline-block; } background: #050505; } -/* Wideo w tle (Apple Glassmorphism Video Background) */ -.glass-video { - /* translateZ(0) promuje wideo na własną warstwę GPU — rozmycie kompozytuje się - taniej i nie wymusza przerysowań treści nad nim. */ - transform: translateZ(0) scale(1.3); +/* Tło „aurora" — animowany gradient CSS (zamiast wideo). + Ruch wyłącznie przez transform na dwóch warstwach (GPU); pętla alternate jest + bezszwowa, więc nie ma przeskoku ani freeze'u. */ +.glass-aurora { position: absolute; - inset: 0; - width: 100%; - height: 100%; - object-fit: cover; - /* Nieco mniejszy promień rozmycia (było 60px) — przy scale 1.3 i opacity 0.5 - wygląd praktycznie ten sam, a koszt na iOS zauważalnie niższy. */ - filter: blur(44px); - opacity: 0.5; + inset: -25%; z-index: 0; + opacity: 0.55; +} +.glass-aurora::before, +.glass-aurora::after { + content: ''; + position: absolute; + inset: 0; + background-repeat: no-repeat; will-change: transform; backface-visibility: hidden; } +.glass-aurora::before { + background: + radial-gradient(42% 50% at 24% 30%, rgba(124, 77, 255, 0.50), transparent 70%), + radial-gradient(46% 56% at 82% 22%, rgba(34, 102, 204, 0.42), transparent 70%); + animation: aurora-drift-1 24s ease-in-out infinite alternate; +} +.glass-aurora::after { + background: + radial-gradient(48% 56% at 72% 78%, rgba(255, 64, 160, 0.42), transparent 70%), + radial-gradient(42% 50% at 18% 76%, rgba(90, 60, 210, 0.40), transparent 70%); + animation: aurora-drift-2 30s ease-in-out infinite alternate; +} +@keyframes aurora-drift-1 { + from { transform: translate3d(-6%, -4%, 0) scale(1.05); } + to { transform: translate3d(6%, 6%, 0) scale(1.18); } +} +@keyframes aurora-drift-2 { + from { transform: translate3d(5%, 5%, 0) scale(1.12); } + to { transform: translate3d(-6%, -6%, 0) scale(1.04); } +} +@media (prefers-reduced-motion: reduce) { + .glass-aurora::before, + .glass-aurora::after { animation: none; } +} .glass-grain { position: absolute; inset: 0; diff --git a/src/components/GlassBackground.tsx b/src/components/GlassBackground.tsx index 3b5ab42..ac5bbeb 100644 --- a/src/components/GlassBackground.tsx +++ b/src/components/GlassBackground.tsx @@ -1,47 +1,17 @@ 'use client'; -import { useEffect, useRef } from 'react'; import { useBackground } from '@/lib/background'; -// Tło „Liquid Glass" — wyciszone wideo + rozmycie/nasycenie w CSS. -// Pętla natywna (loop) zamiast ręcznego cofania `currentTime` co klatkę — to ostatnie -// było bardzo kosztowne na iOS (per-klatkowy seek = ciągłe dekodowanie, zabierało wątek -// główny innym animacjom). Pauzujemy też wideo, gdy karta jest w tle. -// Można je całkiem wyłączyć (przełącznik w menu profilu) dla maksymalnej wydajności. +// Tło „aurora" — animowany gradient CSS zamiast wideo. Pętla bezszwowa (animacja +// alternate, zero przeskoku), nigdy się nie freezuje, a ruch idzie wyłącznie przez +// transform (GPU) — koszt znikomy. Można je wyłączyć (przełącznik w menu profilu). export default function GlassBackground() { const { enabled } = useBackground(); - const videoRef = useRef(null); - - useEffect(() => { - if (!enabled) return; - const video = videoRef.current; - if (!video) return; - - const tryPlay = () => video.play().catch(() => {}); - tryPlay(); // niektóre Safari nie startują autoplay bez jawnego play() - - const onVisibility = () => { - if (document.hidden) video.pause(); - else tryPlay(); - }; - document.addEventListener('visibilitychange', onVisibility); - return () => document.removeEventListener('visibilitychange', onVisibility); - }, [enabled]); - if (!enabled) return null; return (
+ {event?.description && ( +

{event.description}

+ )} + {slots.length > 0 && (
diff --git a/src/app/globals.css b/src/app/globals.css index b3956f8..938ef10 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -86,6 +86,27 @@ input:focus { } input::placeholder { color: #6a6f80; } +textarea { + width: 100%; + padding: 13px 15px; + background: var(--card-2); + color: var(--text); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + font-size: 1rem; + font-family: inherit; + line-height: 1.5; + resize: vertical; + min-height: 84px; + transition: border-color 0.15s ease, box-shadow 0.15s ease; +} +textarea:focus { + outline: none; + border-color: var(--primary); + box-shadow: 0 0 0 3px rgba(91, 87, 242, 0.25); +} +textarea::placeholder { color: #6a6f80; } + /* Input daty z własnym placeholderem (iOS nie pokazuje nic w pustym datetime-local) */ .dt-field { position: relative; display: flex; width: 100%; } .dt-field > input { width: 100%; text-align: center; } @@ -463,6 +484,19 @@ img.avatar { display: inline-block; } .profile-trigger:hover { background: none; } .profile-trigger:active { transform: scale(0.94); } +/* Przycisk ustawień (koło zębate) obok avatara */ +.settings-trigger { + width: 38px; height: 38px; padding: 0; + display: inline-flex; align-items: center; justify-content: center; + border-radius: 50%; + background: var(--card-2); + border: 1px solid var(--border); + color: var(--muted); + flex-shrink: 0; +} +.settings-trigger:hover { background: #262833; color: var(--text); border-color: var(--border-strong); } +.settings-trigger:active { transform: scale(0.94); } + /* Modal profilu (wyśrodkowany, rozmyte tło) */ .profile-overlay { position: fixed; inset: 0; z-index: 100; @@ -775,6 +809,19 @@ body.login-active .glass-bg { display: none; } pointer-events: none; } +/* Opis wypadu na stronie wydarzenia */ +.event-description { + margin: 0 0 18px; + padding: 14px 16px; + background: rgba(255, 255, 255, 0.03); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + color: rgba(255, 255, 255, 0.78); + font-size: 0.92rem; + line-height: 1.5; + white-space: pre-line; +} + /* Toast „nowy wypad" — pływający baner na dole, klik otwiera wypad. */ .toast { position: fixed; diff --git a/src/app/page.tsx b/src/app/page.tsx index 90f5794..464bd9b 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -8,6 +8,7 @@ import { getConfirmedSlot } from '@/lib/types'; import type { EventRow, Slot, Vote, Profile } from '@/lib/types'; import { AvatarStack, type Person } from '@/components/Avatar'; import ProfileMenu from '@/components/ProfileMenu'; +import SettingsMenu from '@/components/SettingsMenu'; import DateTimeInput from '@/components/DateTimeInput'; import { useTransitionNavigate } from '@/lib/transition'; import { getCache, setCache } from '@/lib/dataCache'; @@ -46,6 +47,7 @@ export default function Home() { const [showForm, setShowForm] = useState(false); const [title, setTitle] = useState(''); const [location, setLocation] = useState(''); + const [description, setDescription] = useState(''); const [startsAt, setStartsAt] = useState(''); const [busy, setBusy] = useState(false); const [error, setError] = useState(''); @@ -109,6 +111,7 @@ export default function Home() { .insert({ title: title.trim(), location: location.trim() || null, + description: description.trim() || null, created_by: displayName, created_by_user_id: userId, }) @@ -253,7 +256,10 @@ export default function Home() {
- +
+ + +
{events.length > 0 && ( @@ -288,6 +294,17 @@ export default function Home() { />
+
+ +