This commit is contained in:
name 2024-09-14 20:49:06 +03:00
parent 4c03956b46
commit 690db20eef
3 changed files with 282 additions and 19 deletions

21
package-lock.json generated
View File

@ -11,7 +11,8 @@
"axios": "^1.7.2", "axios": "^1.7.2",
"date-fns": "^3.6.0", "date-fns": "^3.6.0",
"jwt-decode": "^4.0.0", "jwt-decode": "^4.0.0",
"serialize-error": "^11.0.3" "serialize-error": "^11.0.3",
"svelte-feather-icons": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {
"@fontsource/fira-mono": "^4.5.10", "@fontsource/fira-mono": "^4.5.10",
@ -3000,6 +3001,24 @@
"svelte": "^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0" "svelte": "^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0"
} }
}, },
"node_modules/svelte-feather-icons": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/svelte-feather-icons/-/svelte-feather-icons-4.1.0.tgz",
"integrity": "sha512-fcTL4VzEN4BoccQJjKiui0b9DWEsmO6zGpI0tQTJbthRtNrYheoU487zyA1BD8rj9kj6jbKGmGVo7zbSdRvMvA==",
"license": "MIT",
"dependencies": {
"svelte": "^3.38.2"
}
},
"node_modules/svelte-feather-icons/node_modules/svelte": {
"version": "3.59.2",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.59.2.tgz",
"integrity": "sha512-vzSyuGr3eEoAtT/A6bmajosJZIUWySzY2CzB3w2pgPvnkUjGqlDnsNnA0PMO+mMAhuyMul6C2uuZzY6ELSkzyA==",
"license": "MIT",
"engines": {
"node": ">= 8"
}
},
"node_modules/svelte-hmr": { "node_modules/svelte-hmr": {
"version": "0.16.0", "version": "0.16.0",
"resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.16.0.tgz", "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.16.0.tgz",

View File

@ -30,6 +30,7 @@
"axios": "^1.7.2", "axios": "^1.7.2",
"date-fns": "^3.6.0", "date-fns": "^3.6.0",
"jwt-decode": "^4.0.0", "jwt-decode": "^4.0.0",
"serialize-error": "^11.0.3" "serialize-error": "^11.0.3",
"svelte-feather-icons": "^4.1.0"
} }
} }

View File

@ -8,6 +8,12 @@
import { redirect } from "$lib/tools/url/URLTools"; import { redirect } from "$lib/tools/url/URLTools";
import axios from "axios"; import axios from "axios";
import { isStringEmptyOrSpaces } from "$lib/tools/strings/Strings"; import { isStringEmptyOrSpaces } from "$lib/tools/strings/Strings";
import {
ChevronLeftIcon,
ChevronRightIcon,
CopyIcon,
} from "svelte-feather-icons";
import { se } from "date-fns/locale";
let merchants = []; let merchants = [];
let value_merchantsFilter = "true"; let value_merchantsFilter = "true";
@ -39,13 +45,11 @@
let value_endTime = "0"; let value_endTime = "0";
function checkTime() { function checkTime() {
if (isStringEmptyOrSpaces(value_endTime) || value_endTime === "0") if (isStringEmptyOrSpaces(value_endTime) || value_endTime === "0") {
{
// showStats = true; // showStats = true;
return; return;
} }
if (isStringEmptyOrSpaces(value_startTime) || value_startTime === "0") if (isStringEmptyOrSpaces(value_startTime) || value_startTime === "0") {
{
// showStats = true; // showStats = true;
return; return;
} }
@ -77,16 +81,21 @@
} }
async function payToMerchant() { async function payToMerchant() {
if(value_sumMerchant <= 0) {return;} if (value_sumMerchant <= 0) {
return;
}
showPaySpin = true; showPaySpin = true;
disablePayButton = true; disablePayButton = true;
let res = await makePost("admin/decreaseMerchantBalance", { let res = await makePost(
id: selectedMerchant, "admin/decreaseMerchantBalance",
amount: value_sumMerchant+"" {
}, makeAuthHeaderForAxios(getAuthInfo()?.a)); id: selectedMerchant,
amount: value_sumMerchant + "",
},
makeAuthHeaderForAxios(getAuthInfo()?.a),
);
// console.log(res); // console.log(res);
if(res.error) if (res.error) {
{
sayError("Что-то пошло не так"); sayError("Что-то пошло не так");
showPaySpin = false; showPaySpin = false;
disablePayButton = false; disablePayButton = false;
@ -97,6 +106,79 @@
disablePayButton = false; disablePayButton = false;
getMerchants(); getMerchants();
} }
const settlesStatusMap = {
"0": "Открыт",
"1": "Закрыт",
};
let settles = [];
let showSettlesLoading = false;
let settlesFilter = "-1";
let settlesCurrentPage = 1;
let maxPages = 1;
$: if (selectedMerchant !== "") {
settlesCurrentPage = 1;
getMerchantSettles();
}
$: 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> </script>
<div class="w-full flex flex-col gap-8"> <div class="w-full flex flex-col gap-8">
@ -200,15 +282,176 @@
bind:value={value_sumMerchant} bind:value={value_sumMerchant}
type="number" type="number"
class="input input-bordered max-w-[200px] mt-1" class="input input-bordered max-w-[200px] mt-1"
> />
<button on:click={()=>{ <button
on:click={() => {
payToMerchant(); payToMerchant();
}} disabled={disablePayButton} class="btn btn-secondary flex justify-center items-center mt-1">Уменьшить }}
{#if showPaySpin} disabled={disablePayButton}
class="btn btn-secondary flex justify-center items-center mt-1"
>Уменьшить
{#if showPaySpin}
<span class="loading loading-spinner self-center"></span> <span class="loading loading-spinner self-center"></span>
{/if} {/if}
</button> </button>
</div> </div>
<p class="text-xl 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>
</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["code"]}
</td>
<td>
{settle["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} {/if}
</div> </div>
</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}