Skip to content

Commit 59127c8

Browse files
committed
frontend: rotate default currency on account summary
to improve UX, we'd like to enable rotating default currency on account summary. This is done by: - creating DefaultCurrencyRotator component - reused that component in rates.tsx and chart.tsx - onClick, runs `rotateFiat` (`RatesContext`). - reinitialize chart on change `defaultCurrency` (`RatesContext`)
1 parent 73494c9 commit 59127c8

File tree

7 files changed

+68
-25
lines changed

7 files changed

+68
-25
lines changed

frontends/web/src/components/rates/rates.module.css

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,6 @@
1717
position: relative;
1818
}
1919

20-
.fiatRow {
21-
22-
}
23-
2420
.availableFiatAmount {
2521
padding-right: var(--space-quarter) !important;
2622
text-align: right;
@@ -33,8 +29,12 @@
3329
position: relative;
3430
}
3531

36-
.unitAction::after,
37-
.availableFiatUnit::after {
32+
.rotatable {
33+
position: relative;
34+
cursor: default;
35+
}
36+
37+
.rotatable::after {
3838
border-bottom: dotted 1px var(--color-softblack);
3939
content: "";
4040
position: absolute;
@@ -58,8 +58,3 @@
5858
}
5959
}
6060

61-
@media (max-width: 640px) {
62-
.availableFiatUnit::after {
63-
border-bottom: none;
64-
}
65-
}

frontends/web/src/components/rates/rates.tsx

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ function Conversion({
7070
alwaysShowAmounts = false
7171
}: TProvidedProps) {
7272

73-
const { rotateFiat, defaultCurrency, btcUnit } = useContext(RatesContext);
73+
const { defaultCurrency, btcUnit } = useContext(RatesContext);
7474

7575
let formattedAmount = <>{'---'}</>;
7676
let isAvailable = false;
@@ -92,7 +92,7 @@ function Conversion({
9292
<td className={unstyled ? '' : style.availableFiatAmount}>{formattedAmount}</td>
9393
{
9494
!noAction && (
95-
<td className={unstyled ? '' : style.availableFiatUnit} onClick={rotateFiat}>{activeUnit}</td>
95+
<DefaultCurrencyRotator activeUnit={activeUnit} className={unstyled ? '' : style.availableFiatUnit} />
9696
)
9797
}
9898
{
@@ -110,7 +110,7 @@ function Conversion({
110110
{' '}
111111
{
112112
!skipUnit && !noAction && (
113-
<span className={style.unitAction} onClick={rotateFiat}>{activeUnit}</span>
113+
<DefaultCurrencyRotator activeUnit={activeUnit} tableRow={false} className={style.unitAction} />
114114
)
115115
}
116116
{
@@ -122,6 +122,26 @@ function Conversion({
122122
);
123123
}
124124

125+
type TDefaultCurrencyRotator = {
126+
activeUnit?: ConversionUnit;
127+
className?: string;
128+
tableRow?: boolean;
129+
}
130+
131+
export const DefaultCurrencyRotator = ({
132+
activeUnit,
133+
className = '',
134+
tableRow = true
135+
}: TDefaultCurrencyRotator) => {
136+
const { rotateFiat, defaultCurrency } = useContext(RatesContext);
137+
const displayedCurrency = activeUnit ? activeUnit : defaultCurrency;
138+
const textStyle = `${className} ${style.rotatable}`;
139+
if (!tableRow) {
140+
return <span className={textStyle} onClick={rotateFiat}>{displayedCurrency}</span>;
141+
}
142+
return <td className={textStyle} onClick={rotateFiat}>{displayedCurrency}</td>;
143+
};
144+
125145
export const formattedCurrencies = currenciesWithDisplayName.map((fiat) => ({ label: `${fiat.displayName} (${fiat.currency})`, value: fiat.currency }));
126146

127147
export const FiatConversion = Conversion;

frontends/web/src/contexts/RatesContext.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type RatesContextProps = {
2222
defaultCurrency: Fiat;
2323
activeCurrencies: Fiat[];
2424
btcUnit?: BtcUnit;
25-
rotateFiat: () => void;
25+
rotateFiat: () => Promise<void>;
2626
selectFiat: (fiat: Fiat) => Promise<void>;
2727
updateDefaultFiat: (fiat: Fiat) => void;
2828
updateRatesConfig: () => Promise<void>;

frontends/web/src/contexts/RatesProvider.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,18 @@ export const RatesProvider = ({ children }: TProps) => {
4848
}
4949
};
5050

51-
const rotateFiat = () => {
51+
const rotateFiat = async () => {
5252
const index = activeCurrencies.indexOf(defaultCurrency);
5353
const fiat = activeCurrencies[(index + 1) % activeCurrencies.length];
54-
updateDefaultFiat(fiat);
54+
await updateDefaultFiat(fiat);
5555
};
5656

57-
const updateDefaultFiat = (fiat: Fiat) => {
57+
const updateDefaultFiat = async (fiat: Fiat) => {
5858
if (!activeCurrencies.includes(fiat)) {
5959
selectFiat(fiat);
6060
}
61+
await setConfig({ backend: { mainFiat: fiat } });
6162
setDefaultCurrency(fiat);
62-
setConfig({ backend: { mainFiat: fiat } });
6363
};
6464

6565
//this is a method to select a fiat to be

frontends/web/src/routes/account/summary/accountssummary.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { Guide } from '../../../components/guide/guide';
3434
import { HideAmountsButton } from '../../../components/hideamountsbutton/hideamountsbutton';
3535
import { AppContext } from '../../../contexts/AppContext';
3636
import { getAccountsByKeystore, isAmbiguiousName } from '../utils';
37+
import { RatesContext } from '../../../contexts/RatesContext';
3738

3839
type TProps = {
3940
accounts: accountApi.IAccount[];
@@ -52,6 +53,7 @@ export function AccountsSummary({
5253
const summaryReqTimerID = useRef<number>();
5354
const mounted = useMountedRef();
5455
const { hideAmounts } = useContext(AppContext);
56+
const { defaultCurrency } = useContext(RatesContext);
5557

5658
const accountsByKeystore = getAccountsByKeystore(accounts);
5759

@@ -138,17 +140,24 @@ export function AccountsSummary({
138140
}
139141
}, [getAccountSummary, mounted, onStatusChanged]);
140142

141-
// fetch accounts summary and balance on the first render.
142143
useEffect(() => {
144+
// for subscriptions and unsubscriptions
145+
// runs only on component mount and unmount.
143146
const subscriptions = [
144147
statusChanged(update),
145148
syncdone(update)
146149
];
150+
return () => unsubscribe(subscriptions);
151+
}, [update]);
152+
153+
154+
useEffect(() => {
155+
// handles fetching data and runs on component mount
156+
// & whenever any of the dependencies change.
147157
getAccountSummary();
148158
getAccountsBalance();
149159
getAccountsTotalBalance();
150-
return () => unsubscribe(subscriptions);
151-
}, [getAccountSummary, getAccountsBalance, getAccountsTotalBalance, update]);
160+
}, [getAccountSummary, getAccountsBalance, getAccountsTotalBalance, defaultCurrency]);
152161

153162
// update the timer to get a new account summary update when receiving the previous call result.
154163
useEffect(() => {

frontends/web/src/routes/account/summary/chart.module.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,14 @@
116116

117117
.totalValue {
118118
font-size: 2rem;
119+
display: flex;
120+
align-items: flex-end;
119121
}
120122

121123
.totalUnit {
122124
color: var(--color-secondary);
123125
display: inline-block;
126+
margin-bottom: 3px;
124127
font-size: 1.4rem;
125128
padding: 0 .25rem;
126129
}

frontends/web/src/routes/account/summary/chart.tsx

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ import { Amount } from '../../../components/amount/amount';
2424
import Filters from './filters';
2525
import { getDarkmode } from '../../../components/darkmode/darkmode';
2626
import { TChartDisplay, TChartFiltersProps } from './types';
27+
import { DefaultCurrencyRotator } from '../../../components/rates/rates';
2728
import styles from './chart.module.css';
28-
2929
export interface FormattedLineData extends LineData {
3030
formattedValue: string;
3131
}
@@ -56,7 +56,6 @@ type Props = ChartProps & TranslateProps;
5656
type FormattedData = {
5757
[key: number]: string;
5858
}
59-
6059
class Chart extends Component<Props, State> {
6160
private ref = createRef<HTMLDivElement>();
6261
private refToolTip = createRef<HTMLSpanElement>();
@@ -129,6 +128,10 @@ class Chart extends Component<Props, State> {
129128
}
130129
});
131130
}
131+
132+
if (this.props.data.chartFiat !== prev.data.chartFiat) {
133+
this.reinitializeChart();
134+
}
132135
}
133136

134137
private hasData = (): boolean => {
@@ -240,6 +243,19 @@ class Chart extends Component<Props, State> {
240243
}
241244
};
242245

246+
private reinitializeChart = () => {
247+
this.removeChart();
248+
this.createChart();
249+
};
250+
251+
private removeChart = () => {
252+
if (this.chart) {
253+
this.chart.remove();
254+
this.chart = undefined;
255+
window.removeEventListener('resize', this.onResize);
256+
}
257+
};
258+
243259
private onResize = () => {
244260
this.checkIfMobile();
245261
if (this.resizeTimerID) {
@@ -514,7 +530,7 @@ class Chart extends Component<Props, State> {
514530
<Skeleton minWidth="220px" />
515531
)}
516532
<span className={styles.totalUnit}>
517-
{chartTotal !== null && chartFiat}
533+
{chartTotal !== null && <DefaultCurrencyRotator tableRow={false}/>}
518534
</span>
519535
</div>
520536
{!showMobileTotalValue ?

0 commit comments

Comments
 (0)