FIRST_NAME LAST_NAME ab93c78309 fixed charts
2025-01-10 13:37:30 +03:00

538 lines
16 KiB
Svelte
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script>
// @ts-nocheck
import { getAuthInfo, makeAuthHeaderForAxios } from "$lib/auth/Auth";
import { makePost } from "$lib/tools/requests/requests";
import { sayError, sayInfo } from "$lib/tools/toaster/Toaster";
import Pagination from "$lib/ui-components/pagination.svelte";
import { redirect } from "$lib/tools/url/URLTools";
import axios from "axios";
import { isStringEmptyOrSpaces } from "$lib/tools/strings/Strings";
import {
ChevronLeftIcon,
ChevronRightIcon,
CopyIcon,
} from "svelte-feather-icons";
import { se } from "date-fns/locale";
import Chart1 from "$lib/ui-components/chart1.svelte";
let merchants = [];
let value_merchantsFilter = "true";
let showMerchants = false;
let value_sumMerchant = 0;
// let value_geoMerchants = "1";
$: if (value_merchantsFilter.length > 0 || value_geoMerchants.length > 0) {
getMerchants();
}
async function getMerchants() {
showMerchants = false;
let res = await makePost(
"admin/merchants",
{
// id: Number(value_geoMerchants),
active: value_merchantsFilter === "true",
},
makeAuthHeaderForAxios(getAuthInfo()?.a)
);
// console.log(res);
merchants = res.data.data;
console.log(merchants);
if (Array.isArray(merchants) === false) {
merchants = [];
}
showMerchants = true;
selectedMerchant = "";
}
let selectedMerchant = "";
let value_startTime = "0";
let value_endTime = "0";
function checkTime() {
if (isStringEmptyOrSpaces(value_endTime) || value_endTime === "0") {
// showStats = true;
return;
}
if (isStringEmptyOrSpaces(value_startTime) || value_startTime === "0") {
// showStats = true;
return;
}
getStatistics();
}
$: value_startTime, value_endTime, checkTime();
let statsResult = {};
let showStats = false;
let disablePayButton = false;
let showPaySpin = false;
let merchantsGeos = [];
async function getStatistics() {
showStats = false;
let res = await makePost(
"admin/merchantPayouts",
{
date_from: new Date(value_startTime)
.toISOString()
.replace(".000Z", "Z"),
date_to: new Date(value_endTime).toISOString().replace(".000Z", "Z"),
merchant_id: Number(selectedMerchant),
},
makeAuthHeaderForAxios(getAuthInfo()?.a)
);
statsResult = res.data;
res = await makePost(
"admin/merchantsGeo",
{
id: Number(selectedMerchant),
},
makeAuthHeaderForAxios(getAuthInfo()?.a)
);
merchantsGeos = res.data.data;
console.log("geos", merchantsGeos);
showStats = true;
}
async function payToMerchant() {
if (value_sumMerchant <= 0) {
return;
}
showPaySpin = true;
disablePayButton = true;
let res = await makePost(
"admin/decreaseMerchantBalance",
{
id: selectedMerchant,
amount: value_sumMerchant + "",
},
makeAuthHeaderForAxios(getAuthInfo()?.a)
);
// console.log(res);
if (res.error) {
sayError("Что-то пошло не так");
showPaySpin = false;
disablePayButton = false;
return;
}
sayInfo("Успешно!");
showPaySpin = false;
disablePayButton = false;
getMerchants();
}
const settlesStatusMap = {
"0": "Открыт",
"1": "Закрыт",
};
let settles = [];
let showSettlesLoading = false;
let settlesFilter = "-1";
let settlesCurrentPage = 1;
let maxPages = 1;
$: if (selectedMerchant !== "") {
settlesCurrentPage = 1;
getMerchantSettles();
console.log(selectedMerchant);
}
$: if (settlesFilter.length > 0) {
settlesCurrentPage = 1;
getMerchantSettles();
}
async function getMerchantSettles() {
showSettlesLoading = true;
const res = await makePost(
"admin/loadSettles",
{
page: settlesCurrentPage,
status: settlesFilter === "-1" ? undefined : settlesFilter,
},
makeAuthHeaderForAxios(getAuthInfo()?.a)
);
if (res.error) {
showSettlesLoading = false;
sayError("Не удалось полуть сеттлы мерча");
return;
}
showSettlesLoading = false;
settles = res.data["data"] ?? [];
maxPages = Number(res.data["pages"]) ? Number(res.data["pages"]) : 1;
}
let showChangeSettleWindow = false;
let selectedSettleNewSum = 0;
let selectedSettleNewHash = "";
let selectedSettleId = "";
let showLoadingChangeSettle = false;
async function changeSettle(id) {
showLoadingChangeSettle = true;
const res = await makePost(
"admin/updateSettle",
{
id,
amount: selectedSettleNewSum.toString(),
tx_hash: selectedSettleNewHash,
},
makeAuthHeaderForAxios(getAuthInfo()?.a)
);
if (res.error) {
sayError("Не удалось изменить сеттл");
showLoadingChangeSettle = false;
return;
}
sayInfo("Сеттл изменён!");
showChangeSettleWindow = false;
showLoadingChangeSettle = false;
getMerchantSettles();
}
</script>
<div class="w-full flex flex-col gap-8">
<div class="flex gap-4">
<div class="bg-accent rounded-[4px] w-[10px] h-full"></div>
<h1 class="text-2xl font-semibold">Мерчанты</h1>
</div>
<div class="w-full flex flex-col bg-base-300 p-4 rounded-box">
<div class="flex flex-col p-2">
<!-- <p>Гео</p>
<select
bind:value={value_geoMerchants}
class="select select-bordered w-full text-base"
>
<option selected value="1">Киргизстан</option>
<option value="false">Неактивные</option>
</select> -->
</div>
<div class="flex flex-col p-2">
<p>Статус</p>
<select
bind:value={value_merchantsFilter}
class="select select-bordered w-full text-base"
>
<option selected value="true">Активные</option>
<option value="false">Неактивные</option>
</select>
</div>
<div class="overflow-x-auto mt-4 flex flex-col">
{#if showMerchants}
<table class="table">
<!-- head -->
<thead>
<tr>
<th>ID</th>
<th>Интеграция</th>
<th>Имя</th>
<!-- <th>Баланс (USDT)</th>
<th>Комиссия</th>
<th>Курс на выплаты</th> -->
</tr>
</thead>
<tbody>
{#each merchants as merch}
<tr
on:click={() => {
if (selectedMerchant !== merch["id"]) {
selectedMerchant = merch["id"];
getStatistics();
console.log(selectedMerchant);
}
}}
class={"group " +
(selectedMerchant === merch["id"]
? "bg-secondary text-black"
: "hover:bg-neutral")}
>
<td class="font-semibold">{merch["id"]}</td>
<td>{merch["integration_type"]}</td>
<td>{merch["name"]}</td>
<!-- <td>{merch["balance"]}</td>
<td>{merch["rate"]}%</td>
<td>{merch["payout_rate"]}</td> -->
</tr>
{/each}
</tbody>
</table>
{:else}
<span class="loading loading-spinner self-center mt-4"></span>
{/if}
</div>
</div>
<div class="flex gap-4">
<div class="bg-accent rounded-[4px] w-[10px] h-full"></div>
<h1 class="text-2xl font-semibold">Статистика</h1>
</div>
<div class="w-full flex flex-col bg-base-300 p-4 rounded-box">
{#if selectedMerchant === ""}
<p class="text-center">
Выберите мерчанта из таблицы, чтобы посмотреть его статистику
</p>
{:else}
<div class="flex flex-col p-2">
<div class="overflow-x-auto">
<table class="table">
<!-- head -->
<thead>
<tr>
<th>Регион</th>
<th>Статус</th>
<th>Баланс</th>
<!-- <th>Тип баланса</th> -->
<th>Pay In</th>
<th>Pay Out</th>
</tr>
</thead>
<tbody>
{#each merchantsGeos as merch}
<tr>
<td class="font-semibold">{merch["code"]}</td>
<td>{merch["is_active"] === "t" ? "Активен" : "Отключен"}</td>
<td
>{merch["balance"]}
{merch["balance_type"] === "0" ? "USDT" : merch["code"]}</td
>
<!-- <td>{merch["balance_type"] === "0" ? "crypto":"fiat"}</td> -->
<td>{merch["payin"]}%</td>
<td>{merch["payout"]}%</td>
</tr>
{/each}
</tbody>
</table>
</div>
<div class="mt-4"></div>
{#key merchantsGeos}
{#each merchantsGeos as merch}
<p class="text-2xl font-bold">Объем для региона {merch["code"]}:</p>
<Chart1
currencyCode={merch["code"]}
merchantId={selectedMerchant}
/>
{/each}
{/key}
<p class="mt-4 text-2xl font-bold">
Показать статистику за период для ID: {selectedMerchant}
</p>
<div class="mt-3">
C: <input
bind:value={value_startTime}
type="datetime-local"
class="input input-bordered input-sm max-w-[200px]"
/>
</div>
<div class="mt-1">
По: <input
bind:value={value_endTime}
type="datetime-local"
class="input input-bordered input-sm max-w-[200px]"
/>
</div>
{#if statsResult?.total !== undefined}
{#if showStats}
<p class="mt-4 text-lg text-primary">
Сумма по закрытым заявкам: {statsResult?.success} USDT
</p>
<p class="text-lg text-primary">
Сумма по поступившим заявкам: {statsResult?.total} USDT
</p>
{:else}
<span class="loading loading-spinner self-center mt-4"></span>
{/if}
{/if}
<!-- <p class="mt-4">Уменьшение баланса</p>
<input
bind:value={value_sumMerchant}
type="number"
class="input input-bordered max-w-[200px] mt-1"
/>
<button
on:click={() => {
payToMerchant();
}}
disabled={disablePayButton}
class="btn btn-secondary flex justify-center items-center mt-1"
>Уменьшить
{#if showPaySpin}
<span class="loading loading-spinner self-center"></span>
{/if}
</button> -->
</div>
<p class="text-2xl font-bold mt-4">Сеттлы</p>
<select
bind:value={settlesFilter}
class="select select-bordered max-w-[320px] self-center my-2"
>
<option value="-1">Все сеттлы</option>
<option value="0">Открытые</option>
<option value="1">Закрытые</option>
</select>
{#if showSettlesLoading}
<span class="loading loading-lg self-center mt-2" />
{:else}
<div class="overflow-x-auto">
<table class="table">
<thead>
<tr>
<th> Опции </th>
<th> ID </th>
<th> Статус </th>
<th> Мерчант </th>
<th> Регион </th>
<th> Сумма </th>
<th> Сумма сеттла от мерча</th>
<th> Адрес кошелька </th>
<th> Хэш транзакции </th>
<th> Время создания </th>
<th> Время закрытия </th>
</tr>
</thead>
<tbody>
{#each settles as settle}
<tr class="hover:bg-neutral group">
<td>
<button
on:click={() => {
selectedSettleNewSum = Number(settle["amount"]);
selectedSettleNewHash = settle["tx_hash"];
selectedSettleId = settle["id"];
showChangeSettleWindow = true;
}}
class="btn btn-info">Изменить</button
>
</td>
<td>
{settle["id"]}
</td>
<td>
{settlesStatusMap[settle["status"]]}
</td>
<td>
{settle["name"]}
</td>
<td>
{settle["code"]}
</td>
<td>
{settle["amount"]} USDT
</td>
<td>
{settle["merchant_amount"]} USDT
</td>
<td class="">
<p>{settle["settle_address"]}</p>
{#if settle["settle_address"].length > 2}
<button
on:click={() => {
navigator.clipboard.writeText(
settle["settle_address"]
);
sayInfo("Скопировано");
}}
class="btn btn-xs"><CopyIcon size={"12"} /></button
>
{/if}
</td>
<td class="">
<p>{settle["tx_hash"]}</p>
{#if settle["tx_hash"].length > 2}
<button
on:click={() => {
navigator.clipboard.writeText(settle["tx_hash"]);
sayInfo("Скопировано");
}}
class="btn btn-xs"><CopyIcon size={"12"} /></button
>
{/if}
</td>
<td>
{settle["creationtime"]}
</td>
<td>
{settle["closetime"]}
</td>
</tr>
{/each}
</tbody>
</table>
</div>
{/if}
<div class="flex w-full justify-center items-center mt-2">
<button
class="btn"
on:click={() => {
if (settlesCurrentPage <= 1) return;
settlesCurrentPage -= 1;
getMerchantSettles();
}}
>
<ChevronLeftIcon size={"24"} /></button
>
<div class="btn cursor-default hover:cursor-default">
Страница {settlesCurrentPage}
</div>
<button
class="btn"
on:click={() => {
if (settlesCurrentPage >= maxPages) return;
settlesCurrentPage += 1;
getMerchantSettles();
}}
>
<ChevronRightIcon size={"24"} />
</button>
</div>
<p class="text-sm opacity-50 self-center">Всего страниц: {maxPages}</p>
{/if}
</div>
</div>
{#if showChangeSettleWindow}
<div
class="fixed z-[100] inset-0 flex justify-center items-center bg-base-300 bg-opacity-90"
>
<div class="flex flex-col p-4 rounded-md bg-base-300">
<p>ID: {selectedSettleId}</p>
<p class="text-sm mt-4">Новая сумма (USDT)</p>
<input
bind:value={selectedSettleNewSum}
type="number"
class="input input-bordered"
/>
<p class="mt-4 text-sm">Новый хэш</p>
<input
bind:value={selectedSettleNewHash}
type="text"
class="input input-bordered"
/>
<button
on:click={() => {
changeSettle(selectedSettleId);
}}
class="btn btn-success mt-2"
>
{#if showLoadingChangeSettle}
<span class="loading loading-xs" />
{:else}
{"Сохранить изменения"}
{/if}
</button>
<button
on:click={() => {
showChangeSettleWindow = false;
}}
class="btn btn-outline mt-1">Отмена</button
>
</div>
</div>
{/if}