Przełączanie walut w interfejsie
1) Zasady
1. Najpierw znaczenie, potem UI. Oddzielna waluta rachunku (prawda księgowa) z wyświetlania waluty (wygoda) i waluty transakcyjnej (rzeczywista konwersja pieniędzy).
2. Zero dwuznaczności. Pokaż kod + symbol zagrożony zamieszaniem ('US $', 'CA $', 'MXN',' R $ '). Dla ₴/₸/₼, zawsze dodawać kod w szczegółach.
3. Uczciwość kursu. Możesz zobaczyć: źródło kursu, moment ostatniej aktualizacji, czy prowizje/spread są zawarte.
4. Stabilność wejściowa. Przełączanie waluty nie powinno „przeskakiwać” wartości wejścia bez wyraźnej zgody (zwłaszcza w formie kursu/depozytu).
5. Lokalizacja formatów. Delimitery, spacje, znak waluty - przez lokalizację użytkownika; dokładność - według waluty.
2) Przełączanie modeli
Tylko wyświetlanie - Wszystkie obliczenia pozostają w walucie konta, interfejs użytkownika pokazuje odpowiednik w wybranej walucie. Użyj do katalogu, profilu, wymiaru.
Hybryda (miękka konwersja): wyświetlanie w wybranej walucie + potwierdzenie transakcji w walucie konta (pokaż obie).
Obsługa (przelicznik twardy): użytkownik zmienia walutę transakcji (depozyt/wypłata/kurs). Potrzebujemy wyraźnych kursów, prowizji, czasu utrwalenia.
Reguła: domyślnie - tylko wyświetlanie i włączanie konwersji „twardej” tylko w odpowiednich przepływach (gotówka, wypłata, przelew środków).
3) Sterowanie i rozmieszczenie
Przełącznik waluty w panelu nagłówka/profil (ikona „/€/$ ”lub kod waluty).
Selector: search by code/name/symbol; wybrane/częste waluty - top.
Wewnątrz formularzy (depozyt/oprocentowanie): kompaktowy selektor po prawej stronie pola kwoty, obok podpowiedzi „odpowiednik w XXX”.
Wzór mobilny: dolny arkusz z listą i wejściem do filtrowania.
html
<button aria-haspopup="listbox" aria-expanded="false" class="currency-switch">UAH</button>
<ul role="listbox" class="currency-menu" hidden>
<li role="option" aria-selected="true">UAH — ₴</li>
<li role="option">USD — US$</li>
<li role="option">EUR — €</li>
<li role="option">TRY — ₺</li>
</ul>
4) Formatowanie i dokładność
Jednostki niewielkie: Ilości przechowywane w całych jednostkach minimalnych (grosze, centy, satoshi).
Miejsca po przecinku według waluty:- 0: JPY, KRW, CLP
- 2: USD, EUR, UAH, TRY
- 3 +: niektóre waluty ZAR (2), KWD (3), krypto (4-8)
- Kryptowaluty: Pokaż do 8 znaków (dokładność dynamiczna, ale z niższą granicą czytelności).
- Cyfry tabeli: „font-variant-numeric: tabular-nums;” dla wyrównania kolumn.
js const fmt = (amountMinor, currency, locale) => {
const fraction = { JPY:0, KRW:0, KWD:3 }[currency]?? 2;
return new Intl.NumberFormat(locale, { style:'currency', currency, minimumFractionDigits:fraction, maximumFractionDigits:fraction })
.format(amountMinor / 10fraction);
};
fmt(200000, 'UAH', 'uk-UA'); // 2 000,00 ₴
5) Kursy i aktualizacje
Źródło: naprawić dostawcę kursu (wewnętrzny cennik/bank/FX-API).
Pamięć podręczna: Aktualizuj kursy z rozsądną częstotliwością (np. co 60-300 sekund) + dodatkowe aktualizacje na żądanie.
Czas utrwalenia: Wyświetlanie 'zaktualizowany N minut temu' i czas utrwalenia w kasie.
Spread/Komisja: Pokaż wyraźną linię: "Stawka 1 USD = 36. 60 UAH (w tym Spread 1. 5%)».
Zaokrąglenie: bank lub regularny - wybierz jeden i napraw go w polityce.
6) Tekst i wyjaśnienia UX
Odpowiednik: "52. 10 €" - obok kwoty, wyciszony kolor, zaktualizowany w czasie rzeczywistym.
Zastrzeżenia prawne: „Rzeczywista stawka i prowizja zostaną odnotowane w kroku potwierdzającym”.
Długie kody: użyj końcówek narzędzi/łańcucha wtórnego: „US $ - US dolar”.
Konwersja w koszyku: nie zmieniaj „całkowitej” bez wyjaśnienia; pokaż linię wyliczania.
7) Dostępność (A11y)
'role =' listbox/option '' w wyborze waluty.
Obsługa klawiatury: strzałki, Enter, Type-ahead według kodu/nazwy.
Czytanie dla SR: „Wyświetl walutę: UAH - hrywna ukraińska”.
Kolor i jedyne medium o znaczeniu (zawsze jest kod/tekst).
RTL: liczby/kody w 'dir = „ltr” wewnątrz łańcuchów arabskich.
8) Wydajność i buforowanie
Kursy - w pamięci + Przechowywanie z TTL (na przykład 5 minut).
Aktualizacje partii: przeliczanie odpowiedników w partiach (np. AnimationFrame, debunks 100-200 ms).
Nie uruchamiaj dodatkowego rerender listy, gdy kurs zmienia się <próg (na przykład 0. 1%).
9) Specyfika iGaming
Waluta rachunku - podstawowa sprawozdawczość (depozyty, saldo, historia).
kurs waluty: zazwyczaj = waluta rachunku; jeśli inny jest określony, pokaż podwójny blok: „Debetowane X XXX w USD (w UAH)”.
Ustalanie rozliczeń: Wygrane są przeliczane według kursu w momencie rozrachunku, a nie zakłady - należy to zobaczyć w szczegółach kuponu/historii.
Depozyt/wypłata: stopa i prowizja PSP/banku - w osobnej linii; ETA metodą.
Granice odpowiedzialnej gry: określone w walucie konta; Jeśli interfejs użytkownika jest w innej walucie, pokaż obie wartości.
Turnieje i nagrody: waluta funduszu nagrody jest ustalona; po wyświetleniu ekwiwalent jest przybliżony, oznaczony.
10) Antypattery
„Magiczna” zmiana wartości w polu wejścia podczas przełączania waluty - bez wyraźnej zgody.
Użyj jednego znaku „$” bez kodu kraju.
Ukryta prowizja w wiedzy (brak linii o rozprzestrzenianiu).
Mieszanie lokalnego i walutowego (format według „en-US” dla „UAH”).
Twarda precyzja „2 znaki” dla JPY/KRW lub „8 znaków” dla wszystkich kryptowalut.
Ponowne obliczenie historycznych transakcji „z mocą wsteczną” po obecnym kursie wymiany - bez znaku „ponowne obliczenie”.
11) Żetony systemu projektowania (przykład)
json
{
"currency": {
"default": "UAH",
"displayList": ["UAH","USD","EUR","TRY","PLN","BRL","MXN"],
"fractions": { "JPY":0, "KRW":0, "KWD":3, "BTC":8 },
"showCodeWithSymbol": ["USD","CAD","AUD","NZD"],
"approxPrefix": "≈ "
},
"format": {
"tabularNums": true,
"grouping": "locale",
"negative": "−"
},
"fx": {
"ttlSec": 300,
"changeThresholdPct": 0.1,
"showSpread": true
}
}
12) Snippety
Przełącznik walutowy (Reakcja, kontekst + Intl)
tsx import { createContext, useContext, useState, useMemo } from 'react';
type Cur = 'UAH' 'USD' 'EUR' 'TRY';
const CurrencyCtx = createContext<{cur:Cur,set:(c:Cur)=>void, rate:(from:Cur,to:Cur)=>number}>({cur:'UAH',set:()=>{},rate:()=>1});
export function CurrencyProvider({children}:{children:React.ReactNode}){
const [cur, set] = useState<Cur>('UAH');
// fx: получить из кэша/апи; здесь — заглушка const table = { UAH:{USD:0.027,EUR:0.025,TRY:0.89,UAH:1}, USD:{UAH:36.6,EUR:0.93,TRY:33.0,USD:1}, EUR:{UAH:39.2,USD:1.07,TRY:35.4,EUR:1}, TRY:{UAH:1.12,USD:0.030,EUR:0.028,TRY:1} };
const rate = (from:Cur,to:Cur)=> table[from][to];
const value = useMemo(()=>({cur, set, rate}),[cur]);
return <CurrencyCtx.Provider value={value}>{children}</CurrencyCtx.Provider>;
}
export function useCurrency(){ return useContext(CurrencyCtx); }
export function Money({minor, iso}:{minor:number, iso:Cur}){
const { cur, rate } = useCurrency();
const fraction = { JPY:0, KRW:0, KWD:3 }[cur as any]?? 2;
const v = (minor/10fraction) rate(iso, cur);
return <span style={{fontVariantNumeric:'tabular-nums'}}>{new Intl.NumberFormat(undefined,{style:'currency',currency:cur, minimumFractionDigits:fraction, maximumFractionDigits:fraction}).format(v)}</span>;
}
Podwójny wyświetlacz (konwersja operacyjna)
html
<div class="amount">
<label>Сумма депозита</label>
<div class="row">
<input type="number" inputmode="decimal" aria-describedby="fxnote">
<select aria-label="Валюта операции">
<option>USD</option><option>EUR</option><option>UAH</option>
</select>
</div>
<small id="fxnote">≈ 2 000,00 ₴ · Курс будет зафиксирован на следующем шаге</small>
</div>
13) Metryka
Opóźnienie FX: czas od przejścia waluty do aktualizacji wszystkich pól (cel ≤ 150 ms).
Wskaźnik poprawności: udział wezwań do wsparcia w „nieprawidłowych kwotach” (<0. 2%).
Wyświetlanie vs niedopasowanie konta: zdarzenia, w których użytkownik myli waluty (niższe wskazówki).
Wskazówki dotyczące kursu CTR: kliknięcia na „Więcej o kursie/prowizji”.
Rabat pieniężny przy konwersji: udział niepowodzeń związanych z „nagłą” zmianą kwoty.
14) Lista kontrolna QA
Znaczenie i przejrzystość
- Waluta rachunku i/lub transakcji jest widoczna wszędzie.
- $ pokazuje kod kraju (US $, CA $, itp.).
- Istnieje linia dotycząca stawki, daty aktualizacji i spreadu/prowizji.
Format i dokładność
- Miejsca po przecinku według waluty (JPY = 0, KWD = 3, krypta = do 8).
- Numer/waluta locale odpowiada językowi UI.
- Historyczne transakcje nie są ponownie obliczane „według bieżącego kursu wymiany” bez oznaczania.
Zachowanie
- Wymiana waluty nie zmienia wpisu bez potwierdzenia.
- Ekwiwalent „na” jest aktualizowany płynnie i szybko.
- Waluta selektor jest klawiatura dostępna, Typ-ahead działa.
iGaming-specyfiki
- W kuponie: opłata/wygrana i ich waluta są podpisywane, kurs ustalania jest podany.
- W okresie do: PSP/opłaty bankowe są widoczne oddzielnie.
- W granicach: obie wartości są wyświetlane (konto i wyświetlane).
RTL/A11y
- Kody/kwoty są poprawnie odczytywane w RTL ('dir = „ltr” dla numerów).
- Wskaźniki kontrastu i ostrości odpowiadają AA.
15) Dokumentacja w systemie projektowym
Komponenty: 'Ekran', 'Pieniądze', 'FxNote', 'Kwota'.
Precyzyjna/zaokrąglająca polityka i pojedyncza funkcja formatowania.
Zasady: „kiedy wyświetlanie tylko”, „kiedy twarde konwersja”, „jak pokazać rozprzestrzenianie”.
Odniesienie do waluty: kod, symbol, cyfry, kolizje znaków regionalnych.
Galeria Do/Don: „$ without code”, auto skok wejście, ukryte prowizje.
Krótkie podsumowanie
Przełączanie walut to nie tylko selektor. Jest to jasny model pieniędzy (waluta konta vs wyświetlacz vs operacja), uczciwy kurs z prowizją, poprawne formatowanie przez lokalne i ostrożne zachowanie pól wejściowych. Naprawić zasady w systemie projektowania, zautomatyzować formatowanie i buforowanie kursów - a użytkownicy będą pewnie pracować z kwotami, nie wątpić w liczby i nie tracić pieniędzy na „niewidoczne” spready.