Przejdź do głównej treści
Mateusz Miszczak

Case Studies

Wybrane obszary produkcyjne, które realizowałem w aplikacjach fintech, w dostarczaniu i infrastrukturze oraz na stronach opartych na CMS.

  1. 01Realtime · Fintech

    Interfejsy fintech w czasie rzeczywistym

    Frontend Engineer
    Panel partnera
    Fintech

    W kontekście tradingu nieaktualne ceny są gorsze niż ich brak.

    Pobrane raz

    Czekam na dane

    Strumień WebSocket

    Czekam na dane

    Odchylenie od rynku—
    Demo na żywo: BTC/USD strumieniowane z WebSocketu Krakena
    PROBLEM

    Wewnętrzny panel administracyjny nie zapewniał spójnego widoku kont klienta. Dane portfela, ceny aktywów i historia transakcji były rozproszone po osobnych ekranach, bez możliwości przechodzenia między poziomami ani inicjowania transakcji bezpośrednio z portfela klienta.

    PODEJŚCIE

    Zbudowałem wielopoziomowy widok portfela z animowanymi, wysuwanymi panelami kont, panelami szczegółów aktywów z ceną i historią transakcji oraz tabelami transakcji z filtrowaniem według typu. Zamiast odświeżać dane przy nawigacji, wartości portfela, ceny aktywów i zawartość tabel synchronizuję przez WebSockety, bo w kontekście tradingu nieaktualne ceny są gorsze niż ich brak. Wstępnie uzupełniam też portfel i aktywo, gdy transakcja jest uruchamiana z panelu aktywa, dzięki czemu kontekst, w którym użytkownik już jest, zostaje zachowany.

    REZULTAT

    Użytkownicy mogą teraz przejść od pełnego portfela klienta do konkretnego aktywa i uruchomić przepływ kupna lub sprzedaży bezpośrednio z panelu szczegółów aktywa, ze wstępnie uzupełnionym portfelem i aktywem. Wszystkie dane aktualizują się w czasie rzeczywistym, bez ręcznego odświeżania.

    • React
    • TypeScript
    • Redux Toolkit
    • React Query
    • REST API
    • WebSockets
  2. 02Przepływy finansowe

    Wieloetapowe przepływy finansowe

    Frontend Engineer
    Trading
    SEPA

    Żądanie zakończone kodem 200 nie oznacza, że środki zostały przeksięgowane.

    Transakcja

    1. 1Aktywo
    2. 2Kwota
    3. 3Podsumowanie
    4. Oczekuje
    5. Zrealizowane

    Wypłata

    1. 1Konto
    2. 2Kwota
    3. 3Potwierdź
    4. Przetwarzanie
    5. Zaksięgowane
    Dwa niezależne przepływy z własnymi stanami, każdy kończony zdarzeniem z backendu, a nie odpowiedzią HTTP
    PROBLEM

    Użytkownicy potrzebowali możliwości handlu aktywami i realizowania wypłat bankowych bezpośrednio w aplikacji. Oba przepływy wyglądają podobnie na poziomie interfejsu, ale mają zupełnie inną logikę biznesową, reguły walidacji, modele danych i stany operacji po stronie backendu, przez co wspólna implementacja byłaby niepraktyczna.

    PODEJŚCIE

    Celowo nie ujednoliciłem ich za jedną abstrakcją. Powierzchowne podobieństwo wymusiłoby rozgałęzienia warunkowe na każdym kroku, a oba przepływy nie mają powodu, by zmieniać się razem. Zamiast tego zbudowałem dwa niezależne, trzyetapowe przepływy: modal kupna i sprzedaży aktywów oraz system wypłat bankowych, każdy z własnymi schematami Zod, maszyną stanów i obsługą błędów. Oba reagują na rzeczywiste potwierdzenia z backendu przesyłane przez WebSockety, a nie tylko na odpowiedź na pierwsze żądanie, bo żądanie zakończone kodem 200 nie oznacza, że środki zostały przeksięgowane.

    REZULTAT

    Oba przepływy poprawnie obsługują przypadki brzegowe: nieudane transakcje, stany oczekujące i przerwy w połączeniu sieciowym. Dzięki temu, że są rozdzielone, każdy można zmieniać, testować i analizować bez ruszania drugiego, co już się opłaciło, gdy przepływ tradingowy zyskał bardziej zaawansowane typy zleceń.

    • React
    • TypeScript
    • React Query
    • REST API
    • WebSockets
    • Zod
  3. 03Systemy administracyjne

    Systemy administracyjne i onboarding klientów

    Frontend Engineer
    Panel administracyjny
    Portal partnera

    Operator nie powinien dowiadywać się o błędzie pięć kroków po jego popełnieniu.

    Walidacja przy wysyłce

    1. Tożsamość
    2. Adres
    3. Podatki
    4. Zgodność
    5. Dokumenty
    6. Podsumowanie

    Walidacja na każdym kroku

    1. Tożsamość
    2. Adres
    3. Podatki
    4. Zgodność
    5. Dokumenty
    6. Podsumowanie
    Onboarding klienta z błędem w pierwszym kroku
    PROBLEM

    Operacje administracyjne wymagały złożonych, wieloetapowych formularzy spełniających wymagania zgodności regulacyjnej. Wyszukiwanie w dużych zbiorach użytkowników wysyłało żądanie przy każdym naciśnięciu klawisza, bo nie było mechanizmu debounce.

    PODEJŚCIE

    Zaimplementowałem pełny cykl życia konta użytkownika: zmiany statusu, kontrolę dostępu, zamykanie kont i odzyskiwanie dostępu do konta. W ramach onboardingu klientów zbudowałem wieloetapowe formularze walidowane Zod i zintegrowałem ustrukturyzowane dane zgodności, walidując każdy krok po jego zakończeniu, a nie dopiero przy wysyłce, dzięki czemu operator nie dowiaduje się o błędzie pięć kroków po jego popełnieniu. Dodałem debounce 500 ms w polu wyszukiwania, dobrany tak, by był wystarczająco długi, aby wchłonąć pisanie, ale na tyle krótki, by wyniki wciąż wydawały się natychmiastowe.

    REZULTAT

    Wyszukiwanie przeszło z jednego żądania na znak do jednego na ukończoną frazę, ograniczając ruch zapytań o mniej więcej rząd wielkości przy typowym wyszukiwaniu. Wieloetapowe formularze onboardingu z walidacją Zod zapobiegają przesyłaniu nieprawidłowych danych i dają jasną informację zwrotną na każdym kroku, a cykl życia konta jest obsłużony od początku do końca, łącznie ze stanami brzegowymi, takimi jak odzyskiwanie dostępu do konta.

    • React
    • TypeScript
    • Redux Toolkit
    • REST API
    • WebSockets
    • Zod
  4. 04Podatki i compliance

    Zarządzanie podatkami i przepływy dokumentów

    Frontend Engineer
    Podatki
    Compliance

    Nigdy nie pokazuj klientowi statusu, który nie jest prawdziwy.

    Po wysłaniuOdpowiedź backendu

    UI optymistyczne

    Backend akceptuje

    Wysłano

    Tym razem trafione, ale tylko założeniem

    Backend odrzuca

    Wysłano

    Pokazano sukces, którego nie było

    UI potwierdzane przez backend

    Backend akceptuje

    Oczekuje

    Każdy pokazany status był prawdziwy

    Backend odrzuca

    Oczekuje

    Każdy pokazany status był prawdziwy

    Ten sam wniosek o dokument podatkowy przy obu odpowiedziach backendu
    PROBLEM

    Klienci potrzebowali wglądu w historię podatkową, wyboru roku podatkowego i zarządzania wnioskami o dokumenty podatkowe, ale interfejs nie miał mechanizmu synchronizacji ze stanami operacji po stronie backendu w trakcie wieloetapowych procesów. Po złożeniu wniosku brakowało wiarygodnej informacji, czy operacja się powiodła.

    PODEJŚCIE

    Zaimplementowałem widoki historii podatkowej klienta, wybór roku podatkowego, tabele dokumentów podatkowych oraz pełne przepływy tworzenia i edycji wniosków. Ponieważ dokumenty podatkowe są prawnie wiążące, każdy stan sterowałem rzeczywistymi potwierdzeniami z backendu przesyłanymi przez WebSockety, zamiast aktualizować optymistycznie, godząc się na nieco wolniej odczuwaną reakcję w zamian za to, że klient nigdy nie widzi statusu, który nie jest prawdziwy.

    REZULTAT

    Przepływ wniosków podatkowych obsługuje wszystkie stany pośrednie, od złożenia po potwierdzenie przez backend, bez odświeżania strony. Klienci widzą dokładny status na każdym etapie, a wsparcie nie odpowiada już na pytania o wnioski, które pozornie zostały wysłane, a jednak nie.

    • React
    • TypeScript
    • Redux Toolkit
    • React Query
    • WebSockets
    • Zod
  5. 05Marketing i CMS

    Wielojęzyczne strony landingowe i serwisy oparte na CMS

    Frontend Engineer
    Next.js
    Strapi
    Turborepo
    SEO
    Analityka

    Zmiana w logice zgód jest wprowadzana raz i nie może się rozjechać między serwisami.

    Nowy serwis marketingowy
    config={newSite}
    Rozwijany serwis marketingowy
    config={existingSite}

    Wspólny pakiet zgód i analityki

    Zgody i analityka, zmieniane w jednym miejscu

    Oba serwisy importują ten sam pakiet, każdy przekazuje tylko własną konfigurację
    PROBLEM

    Dwa wielojęzyczne serwisy marketingowe trzeba było utrzymywać w ramach wspólnego ekosystemu Turborepo, oba korzystające z treści zarządzanych w CMS, obsługi zgód cookie, Google Analytics i renderowania zależnego od wersji językowej. Jeden należało zbudować od podstaw, drugi rozwijać dalej, bez duplikowania wspólnej logiki frontendowej między nimi.

    PODEJŚCIE

    Zbudowałem od podstaw jeden wielojęzyczny serwis marketingowy w Next.js i kontynuowałem rozwój drugiego w tym samym monorepo, pracując z treściami Strapi, responsywnymi sekcjami landingowymi, animowanymi układami i renderowaniem zależnym od wersji językowej. Zamiast implementować zgody i analitykę dwa razy, wydzieliłem je do wspólnego pakietu Turborepo, z którego obie aplikacje korzystają przez jeden import i obiekt konfiguracyjny, dzięki czemu zmiana w logice zgód jest wprowadzana raz i nie może się rozjechać między serwisami.

    REZULTAT

    Pierwszy serwis został dostarczony od podstaw, z wieloma podstronami, animowanymi sekcjami i wielojęzycznymi treściami z CMS, a drugi jest nadal rozwijany na tej samej wspólnej architekturze. Żadna z aplikacji nie nosi własnej kopii logiki zgód, a nowe sekcje landingowe czy treści w kolejnych językach można dodawać bez ruszania kodu frontendu.

    • React
    • Next.js
    • TypeScript
    • Strapi CMS
    • Turborepo
    • Tailwind CSS
    • Framer Motion
    • Google Analytics
    • Cookie Consent
    • SEO
    • Responsive UI
Case Studies | Mateusz Miszczak