2024-11-05 13:40:37 +01:00
@using BTCPayServer.Abstractions.TagHelpers
@using BTCPayServer.Client.Models
@using BTCPayServer.TagHelpers
2022-04-12 09:55:10 +02:00
@model BTCPayServer.Components.StoreWalletBalance.StoreWalletBalanceViewModel
2024-11-05 13:40:37 +01:00
<div id="StoreWalletBalance-@Model.StoreId" class="widget store-wallet-balance">
2022-06-15 13:03:24 +05:30
<div class="d-flex gap-3 align-items-center justify-content-between mb-2">
2024-10-14 14:11:00 +09:00
<h6 text-translate="true">Wallet Balance</h6>
2022-06-15 13:03:24 +05:30
@if (Model.CryptoCode != Model.DefaultCurrency)
{
2022-07-04 04:03:16 +02:00
<div class="btn-group btn-group-sm gap-0 currency-toggle" role="group">
<input type="radio" class="btn-check" name="StoreWalletBalance-currency" id="StoreWalletBalance-currency_@Model.CryptoCode" value="@Model.CryptoCode" autocomplete="off" checked>
<label class="btn btn-outline-secondary px-2 py-1" for="StoreWalletBalance-currency_@Model.CryptoCode">@Model.CryptoCode</label>
<input type="radio" class="btn-check" name="StoreWalletBalance-currency" id="StoreWalletBalance-currency_@Model.DefaultCurrency" value="@Model.DefaultCurrency" autocomplete="off">
<label class="btn btn-outline-secondary px-2 py-1" for="StoreWalletBalance-currency_@Model.DefaultCurrency">@Model.DefaultCurrency</label>
2022-06-15 13:03:24 +05:30
</div>
}
</div>
2022-04-12 09:55:10 +02:00
<header class="mb-3">
2022-06-20 07:31:22 +02:00
@if (Model.Balance != null)
2022-06-15 13:03:24 +05:30
{
2023-05-30 09:48:58 +02:00
<div class="balance d-flex align-items-baseline gap-1">
2023-05-11 10:35:51 +02:00
<h3 class="d-inline-block me-1" data-balance="@Model.Balance" data-sensitive>@Model.Balance</h3>
2022-07-04 04:03:16 +02:00
<span class="text-secondary fw-semibold currency">@Model.CryptoCode</span>
2022-06-15 13:03:24 +05:30
</div>
2022-06-20 07:31:22 +02:00
}
@if (Model.Series != null)
{
2022-07-06 05:40:16 +02:00
<div class="btn-group only-for-js mt-1" role="group" aria-label="Period">
2024-11-05 13:40:37 +01:00
<input type="radio" class="btn-check" name="StoreWalletBalancePeriod-@Model.StoreId" id="StoreWalletBalancePeriodWeek-@Model.StoreId" value="@HistogramType.Week" @(Model.Type == HistogramType.Week ? "checked" : "")>
<label class="btn btn-link" for="StoreWalletBalancePeriodWeek-@Model.StoreId">1W</label>
<input type="radio" class="btn-check" name="StoreWalletBalancePeriod-@Model.StoreId" id="StoreWalletBalancePeriodMonth-@Model.StoreId" value="@HistogramType.Month" @(Model.Type == HistogramType.Month ? "checked" : "")>
<label class="btn btn-link" for="StoreWalletBalancePeriodMonth-@Model.StoreId">1M</label>
<input type="radio" class="btn-check" name="StoreWalletBalancePeriod-@Model.StoreId" id="StoreWalletBalancePeriodYear-@Model.StoreId" value="@HistogramType.Year" @(Model.Type == HistogramType.Year ? "checked" : "")>
<label class="btn btn-link" for="StoreWalletBalancePeriodYear-@Model.StoreId">1Y</label>
2022-06-15 13:03:24 +05:30
</div>
}
2022-04-12 09:55:10 +02:00
</header>
2022-06-20 07:31:22 +02:00
@if (Model.Series != null)
{
<div class="ct-chart"></div>
}
2024-11-05 13:40:37 +01:00
else if (Model.MissingWalletConfig)
2023-10-11 14:12:33 +02:00
{
<p>
2024-11-05 13:40:37 +01:00
We would like to show you a chart of your balance but you have not yet <a href="@Url.Action("SetupWallet", "UIStores", new { storeId = Model.StoreId, cryptoCode = Model.CryptoCode })">configured a wallet</a>.
2023-10-11 14:12:33 +02:00
</p>
}
2022-06-20 07:31:22 +02:00
else
{
<p>
We would like to show you a chart of your balance.
Please <a href="https://github.com/dgarage/NBXplorer/blob/master/docs/Postgres-Migration.md" target="_blank" rel="noreferrer noopener">migrate to the new NBXplorer backend</a>
for that data to become available.
</p>
}
2022-04-12 09:55:10 +02:00
<script>
(function () {
2024-11-05 13:40:37 +01:00
const storeId = @Safe.Json(Model.StoreId);
2022-06-15 13:03:24 +05:30
const cryptoCode = @Safe.Json(Model.CryptoCode);
const defaultCurrency = @Safe.Json(Model.DefaultCurrency);
const divisibility = @Safe.Json(Model.CurrencyData.Divisibility);
let data = { series: @Safe.Json(Model.Series), labels: @Safe.Json(Model.Labels), balance: @Safe.Json(Model.Balance) };
let rate = null;
2024-11-05 13:40:37 +01:00
2022-06-15 13:03:24 +05:30
const id = `StoreWalletBalance-${storeId}`;
2024-11-05 13:40:37 +01:00
const baseUrl = @Safe.Json(Url.Action("WalletHistogram", "UIWallets", new { walletId = Model.WalletId, type = HistogramType.Week }));
const valueTransform = value => rate ? DashboardUtils.displayDefaultCurrency(value, rate, defaultCurrency, divisibility) : value
const labelCount = 6
const tooltip = Chartist.plugins.tooltip2({
template: '<div class="chartist-tooltip-value">{{value}}</div><div class="chartist-tooltip-line"></div>',
offset: {
x: 0,
y: -16
},
valueTransformFunction(value, label) {
return valueTransform(value) + ' ' + (rate ? defaultCurrency : cryptoCode)
}
})
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat
const dateFormatter = new Intl.DateTimeFormat('default', { month: 'short', day: 'numeric' })
2022-06-15 13:03:24 +05:30
const chartOpts = {
fullWidth: true,
showArea: true,
axisY: {
2024-11-05 13:40:37 +01:00
showLabel: false,
offset: 0
},
plugins: [tooltip]
2022-06-15 13:03:24 +05:30
};
2024-11-05 13:40:37 +01:00
2022-04-12 09:55:10 +02:00
const render = data => {
2022-07-04 04:03:16 +02:00
let { series, labels } = data;
const currency = rate ? defaultCurrency : cryptoCode;
2024-11-05 13:40:37 +01:00
document.querySelectorAll(`#${id} .currency`).forEach(c => c.innerText = currency)
2022-07-04 04:03:16 +02:00
document.querySelectorAll(`#${id} [data-balance]`).forEach(c => {
const value = Number.parseFloat(c.dataset.balance);
2024-02-02 11:29:35 +01:00
c.innerText = valueTransform(value)
2022-07-04 04:03:16 +02:00
});
2022-06-20 07:31:22 +02:00
if (!series) return;
2024-11-05 13:40:37 +01:00
2022-04-12 09:55:10 +02:00
const min = Math.min(...series);
const max = Math.max(...series);
const low = Math.max(min - ((max - min) / 5), 0);
2024-11-05 13:40:37 +01:00
const renderOpts = Object.assign({}, chartOpts, { low, axisX: {
labelInterpolationFnc(date, i) {
return i % labelEvery === 0 ? dateFormatter.format(new Date(date)) : null
}
} });
const pointCount = series.length;
const labelEvery = pointCount / labelCount;
new Chartist.Line(`#${id} .ct-chart`, {
labels: labels,
2022-04-12 09:55:10 +02:00
series: [series]
2022-06-15 13:03:24 +05:30
}, renderOpts);
2022-04-12 09:55:10 +02:00
};
2024-11-05 13:40:37 +01:00
2022-04-12 09:55:10 +02:00
const update = async type => {
const url = baseUrl.replace(/\/week$/gi, `/${type}`);
const response = await fetch(url);
if (response.ok) {
2022-06-15 13:03:24 +05:30
data = await response.json();
render(data);
2022-04-12 09:55:10 +02:00
}
};
2024-11-05 13:40:37 +01:00
2022-06-15 13:03:24 +05:30
render(data);
2024-11-05 13:40:37 +01:00
function addEventListeners() {
2022-07-06 05:40:16 +02:00
delegate('change', `#${id} [name="StoreWalletBalancePeriod-${storeId}"]`, async e => {
2022-04-12 09:55:10 +02:00
const type = e.target.value;
await update(type);
})
2022-07-04 04:03:16 +02:00
delegate('change', `#${id} .currency-toggle input`, async e => {
2022-06-15 13:03:24 +05:30
const { target } = e;
if (target.value === defaultCurrency) {
2022-07-04 04:03:16 +02:00
rate = await DashboardUtils.fetchRate(`${cryptoCode}_${defaultCurrency}`);
if (rate) render(data);
2022-06-15 13:03:24 +05:30
} else {
rate = null;
render(data);
}
});
2024-11-05 13:40:37 +01:00
}
if (document.readyState === "loading") {
window.addEventListener("DOMContentLoaded", addEventListeners);
} else {
addEventListeners();
}
2022-04-12 09:55:10 +02:00
})();
</script>
</div>