Steven
Steven9 min citire

Redesignul dashboard-ului în jurul unui singur grafic-val

GeekBye v1.8.2 a transformat dashboard-ul dintr-o telecomandă de înregistrare într-o vizualizare de analytics doar-citire — o bandă de statistici și un grafic-val pe 7 zile. Ambele elemente definitorii au fost a doua schiță, livrate la douăzeci de minute după primele schițe, în aceeași după-amiază.

Inginerie
Design
Dashboard
Lansări GeekBye
Redesignul dashboard-ului în jurul unui singur grafic-val

Unele lansări adaugă o funcționalitate. GeekBye v1.8.2 mai degrabă a eliminat una — iar eliminarea e povestea. Într-o singură după-amiază din februarie 2026, optsprezece commit-uri au transformat pagina principală a dashboard-ului dintr-o telecomandă de înregistrare într-o vizualizare de analytics doar-citire: patru statistici și un singur grafic de activitate. Pe drum a livrat un grafic cu bare care a trăit douăzeci și două de minute, o grilă de carduri de statistici care a trăit douăzeci și un val SVG făcut de mână care le-a înlocuit pe amândouă. Întreaga căutare e păstrată în timestamp-urile commit-urilor, care sunt cel mai bun fel de documentație de design care există.

Dashboard-ul a încetat să mai fie o telecomandă

Înainte de această lansare, pagina principală a dashboard-ului era un panou de control. Începea cu un card-hero — un widget mare de înregistrare cu un badge LIVE, butoane Pause/Resume/Stop, blob-uri de gradient și un hook useSessionState care lega totul de recorder. Dashboard-ul încerca să fie două lucruri deodată: locul unde îți privești întâlnirile și locul de unde controlezi recorder-ul. Două produse, un singur ecran, concurând în tăcere.

v1.8.2 a ales unul. A șters cardul-hero și legăturile useSessionState — inclusiv un efect care te ducea automat la pagina de detalii a unei întâlniri în clipa în care se termina o sesiune, exact genul de salt „util" care surprinde oamenii în mijlocul fluxului. Pornirea și ascunderea recorder-ului s-au mutat într-un simplu toggle din navbar (un buton reutilizat care a pierdut vreo o sută de linii trecând de la controler de sesiune la comutator on/off), susținut de un nou handler IPC navbar:hide. Ce a rămas a fost un dashboard care face un singur lucru: îți arată ce ai înregistrat. Doar-citire. Calm.

Există un mic bug omenesc în această tranziție care merită menționat, pentru că e genul de lucru pe care un redesign îl introduce pe tăcute și pe care un ochi bun îl prinde în aceeași oră. Cele două butoane noi din sidebar — Start și Hide — au fost livrate cu același icon generic de grilă, așa că erau identice vizual. Douăsprezece minute mai târziu, un follow-up i-a dat lui Start un icon de play, i-a dat lui Hide un icon de ochi tăiat și a colorat Hide în chihlimbar, astfel încât „fă aplicația să dispară" să se citească drept o acțiune deliberată, nu un geamăn neutru al lui „start". Icoanele sunt text. Două butoane care arată la fel spun același lucru, iar acestea nu însemnau același lucru.

Graficul cu bare care a trăit douăzeci și două de minute

Iată partea pe care o iubesc, și e complet lizibilă din git log. La 16:29:34 a aterizat prima schiță a redesignului: un grafic de activitate pe 7 zile desenat ca bare — coloane animate, o înălțime minimă ca zilele mici să rămână vizibile, un ciot estompat de 2 pixeli pentru zilele cu zero. Rezonabil. Convențional. Genul de grafic pe care îl alegi fără să te gândești.

La 16:51:21 — douăzeci și două de minute mai târziu — a fost șters. Commit-ul de înlocuire spune exact ce a făcut: „replace bar chart with smooth wave area chart for 7-day activity" (înlocuiește graficul cu bare cu un grafic-val neted de tip arie pentru activitatea pe 7 zile). Iar la 16:52:21, la un minut după, un alt commit a scos cardul rotunjit și bordura din jurul valului, „for cleaner look" (pentru un aspect mai curat).

De ce? Commit-urile spun doar ce s-a schimbat, așa că de ce-ul e o interpretare — dar forma datelor o face evidentă. E un tool în care un utilizator tipic are zero, una sau două întâlniri într-o zi oarecare. Șapte bare, majoritatea înalte de 2 pixeli, arată ca un teren aproape pustiu. Aceleași șapte numere desenate ca o arie continuă umplută arată ca un trend — un val blând care urcă acolo unde săptămâna a fost aglomerată. Nimic n-a fost falsificat; valorile de pe axa y sunt identice. Redesignul a ales pur și simplu codarea care lasă datele rare, dar oneste, să se citească drept o formă în loc de o absență.

Statisticile au primit același tratament pe același ceas. Prima schiță (16:29) a pus patru numere într-o grilă 2×4 de carduri. La 16:49 grila s-a comprimat într-o singură bandă de statistici inline — un singur rând cu bordură, cu separatoare fine, tipografie mai mică, un container în loc de patru. Cinci casete pe ecran (patru carduri plus un card de grafic) au devenit două (o bandă și un val). Următorul PR a adăugat încă un detaliu onest: eticheta „Total Time" a devenit „Time in Meetings" (Timp în întâlniri), pentru că total-de-ce era o întrebare legitimă pe care nimeni n-ar trebui să fie nevoit s-o pună.

Douăzeci de minute, de la prima schiță la cea finală, totul într-un singur pull request. Dacă acelea ar fi fost comprimate într-un singur commit „redesign dashboard", căutarea ar fi fost invizibilă. Pentru că n-au fost, poți urmări un designer convergând în timp real.

Valul, mecanic

Aici nu există nicio librărie de grafice. Valul e un SVG inline construit în JSX și merită o privire pentru că e o rețetă mică și onestă pe care o poți fura pentru orice sparkline.

Netezirea e trucul. Pentru fiecare pereche de puncte adiacente, calea folosește un segment cubic-bezier ale cărui două puncte de control stau la mijlocul orizontal dintre ele — cpx = (prev.x + curr.x) / 2 — cu punctele de control ținute la înălțimea proprie a fiecărui capăt. Asta e netezirea clasică cu tangentă plată: curba trece lin prin fiecare punct de date fără să depășească vreodată peste valoarea cea mai mare sau sub cea mai mică, ceea ce un spline Catmull-Rom naiv ar face. Pentru un grafic despre numărul de întâlniri, „nu desena niciodată o cocoașă care sugerează o valoare ce nu s-a întâmplat" nu e un moft; e corectitudine. Aria umplută e aceeași curbă închisă de-a lungul bazei și pictată cu un gradient vertical (cyan, estompându-se de la 30% la aproape nimic), iar linia se desenează singură printr-o animație framer-motion pathLength, de la stânga la dreapta.

Sub SVG e instalația de date, și e eroul tăcut. O nouă metodă getAggregateStats() din repository-ul de transcript rulează trei prepared statements pe tabela SQLite locală transcript_sessions: totalurile din toate timpurile (număr, durată însumată, durată medie), un număr pe șapte zile în mișcare și un bucket pe zi cu GROUP BY date(created_at). Apoi — și ăsta e detaliul care face graficul robust — o mică buclă JavaScript parcurge ultimele șapte zile calendaristice și completează (back-fill) fiecare zi pe care query-ul n-a returnat-o, împingând un zero. Graficul are deci garantat exact șapte puncte, întotdeauna.

Această garanție e ceea ce face cazurile-limită să dispară în loc să aibă nevoie de gardieni împrăștiați prin view. O săptămână goală? Șapte de zero, iar un Math.max(count, 1) pe numitor ține linia plată la bază în loc să împartă la zero. Un singur punct de date care ar face formula de spațiere pe x i / (n − 1) să producă NaN? Nu se poate întâmpla — repository-ul nu emite niciodată mai puțin de șapte. Etichetele zilelor săptămânii chiar parsează fiecare bucket la T12:00:00 în loc de miezul nopții gol, așa că un string YYYY-MM-DD nu alunecă în ziua precedentă într-un fus orar UTC-negativ. Repari forma datelor la sursă și codul de randare poate fi naiv intenționat.

Totul rămâne pe mașină. Query-ul de statistici citește baza de date locală, se întoarce printr-un canal IPC tipizat transcript:get-stats și se animează în patru numere care urcă (count-up) la montare. Nimic din istoricul întâlnirilor tale nu părăsește laptopul ca să deseneze acest grafic — ceea ce, pentru un tool care îți înregistrează conversațiile, e singurul mod acceptabil de a construi o vizualizare de analytics.

Încă un bug, pentru că redesignurile le trag la lumină

Împachetat în aceeași lansare era un fix care n-avea nimic de-a face cu dashboard-ul și totul de-a face cu genul de datorie peste care se împiedică un redesign. Stilizarea scrollbar-ului întunecat al aplicației derivase în două definiții CSS concurente ale aceleiași clase — una mai veche, mov, și una mai nouă, alb-pe-întunecat — iar care câștiga depindea de ordinea cascadei. Mai rău, doar elementele care își aminteau să adauge clasa erau stilizate; tot restul cădea înapoi pe scrollbar-ul deschis implicit, iar scrollbar-urile orizontale nu erau niciodată stilizate pentru că vechile reguli setau doar o lățime, niciodată o înălțime. Fix-ul a șters ambele definiții, a stilizat scrollbar-ul global pe fiecare element și a eliminat clasa acum moartă din cele zece componente care o purtaseră. E un diff de două linii repetat de zece ori — taxa neglamuroasă a faptului că ai stilizat același lucru de două ori și le-ai lăsat pe amândouă să supraviețuiască.

Trei lucruri pe care ni le-a predat această lansare

  1. Scade ca să te concentrezi. Dashboard-ul a devenit mai bun făcând mai puțin — pierzând controalele de înregistrare de care n-a avut niciodată nevoie și devenind un singur lucru clar. Un ecran care e și vizualizator, și telecomandă e alcătuit din două jumătăți de produs; alege unul și mută-l pe celălalt acolo unde îi e locul.
  2. Alege codarea pe care o merită datele tale. Numărătorile rare se citesc ca absență în bare și ca un trend într-un grafic de tip arie, pornind de la numere identice. Asta nu e cosmetizare — e alegerea formei oneste care lasă datele reale și subțiri să comunice.
  3. Garantează forma datelor din amonte. Bucla de completare-până-la-șapte e motivul pentru care codul graficului n-are verificări de null împrăștiate: împărțirea la zero, NaN-ul dintr-un singur punct și zilele lipsă dispar toate pentru că query-ul promite exact șapte bucket-uri. Randarea robustă începe cu un strat mai jos.

Pentru capitolul anterior al poveștii v1, patru lansări în douăzeci și șase de ore (v1.7.6–v1.8.1); iar pentru întregul arc, anatomia livrării de software până la perfecțiune.