475 lines
16 KiB
Svelte
475 lines
16 KiB
Svelte
<script>
|
||
import { browser } from "$app/environment";
|
||
import { getAuthInfo, makeAuthHeaderForAxios } from "$lib/auth/Auth.js";
|
||
import { makePost } from "$lib/tools/requests/requests.js";
|
||
import { sayError } from "$lib/tools/toaster/Toaster.js";
|
||
import { redirect } from "$lib/tools/url/URLTools.js";
|
||
import Pagination from "$lib/ui-components/pagination.svelte";
|
||
|
||
export let data;
|
||
let { userData } = data;
|
||
let { token } = data;
|
||
|
||
let userInfoReloading = false;
|
||
|
||
const orderStatusMap = {
|
||
"1": "Ожидает исполнения",
|
||
"2": "Время заявки истекло",
|
||
"3": "Исполнена",
|
||
};
|
||
|
||
async function deleteUser() {
|
||
const result = await makePost(
|
||
"deleteUser",
|
||
{
|
||
token: token,
|
||
},
|
||
makeAuthHeaderForAxios(getAuthInfo()?.a)
|
||
);
|
||
if (result.status === 401) {
|
||
sayError("Данные авторизации устарели");
|
||
// window.location.href = "/";
|
||
redirect("/admin/");
|
||
return;
|
||
}
|
||
if (result.error) {
|
||
sayError("Не удалось удалить пользователя");
|
||
return;
|
||
}
|
||
redirect("/admin/userslist");
|
||
}
|
||
|
||
async function reloadUserInfo() {
|
||
userInfoReloading = true;
|
||
const userResult = await makePost(
|
||
"getUser",
|
||
{
|
||
token: token,
|
||
},
|
||
makeAuthHeaderForAxios(getAuthInfo()?.a)
|
||
);
|
||
if (userResult.status === 401) {
|
||
userInfoReloading = false;
|
||
sayError("Данные авторизации устарели");
|
||
redirect("/admin/");
|
||
return;
|
||
}
|
||
if (userResult.error) {
|
||
userInfoReloading = false;
|
||
sayError("Не удалось настроить пользователя");
|
||
return;
|
||
}
|
||
userData = userResult.data;
|
||
userInfoReloading = false;
|
||
}
|
||
|
||
let userOrders = [];
|
||
let numPagesUserOrders = 1;
|
||
let currentPageUserOrders = 1;
|
||
let disablePagesUserOrders = false;
|
||
let ordersFilter = "1";
|
||
async function getUserOrders() {
|
||
disablePagesUserOrders = true;
|
||
const result = await makePost(
|
||
"admin/getUserOrders",
|
||
{
|
||
token: token,
|
||
page: currentPageUserOrders,
|
||
// orderBy: "id",
|
||
statuses_to_send: Number(ordersFilter),
|
||
},
|
||
makeAuthHeaderForAxios(getAuthInfo()?.a)
|
||
);
|
||
if (result.status === 401) {
|
||
sayError("Данные авторизации устарели");
|
||
// window.location.href = "/";
|
||
redirect("/admin/");
|
||
disablePagesUserOrders = false;
|
||
return;
|
||
}
|
||
if (result.error) {
|
||
sayError("Не удалось получить ордеры пользователя");
|
||
disablePagesUserOrders = false;
|
||
return;
|
||
}
|
||
userOrders = result.data.data;
|
||
if(!Array.isArray(userOrders)) userOrders = [];
|
||
numPagesUserOrders = Number(result.data?.pages);
|
||
if (numPagesUserOrders === 0) numPagesUserOrders = 1;
|
||
console.log(result.data);
|
||
disablePagesUserOrders = false;
|
||
}
|
||
|
||
let reqsCurrentPage = 1;
|
||
let reqsMaxPage = 1;
|
||
let userRequisites = [];
|
||
async function getUserRequisites() {
|
||
const result = await makePost(
|
||
"admin/getRequisite",
|
||
{
|
||
page: Number(reqsCurrentPage),
|
||
token: token,
|
||
},
|
||
makeAuthHeaderForAxios(getAuthInfo()?.a)
|
||
);
|
||
if (result.status === 401) {
|
||
sayError("Данные авторизации устарели");
|
||
redirect("/admin/");
|
||
return;
|
||
}
|
||
if (result.error) {
|
||
sayError("Не удалось получить реквизиты пользователя");
|
||
return;
|
||
}
|
||
userRequisites = result.data.data;
|
||
if(!Array.isArray(userDeposits)) userRequisites = [];
|
||
reqsMaxPage = Number(result.data.pages);
|
||
console.log(result.data);
|
||
}
|
||
|
||
let userDeposits = [];
|
||
let numOfPagesUserDeposits = 1;
|
||
let currentPageUserDeposits = 1;
|
||
let disablePagesUserDeposits = false;
|
||
const depoStatusMap = {
|
||
"0": "Активна",
|
||
"1": "Завершена",
|
||
"2": "Отклонена"
|
||
};
|
||
///api/v1/admin/getUserDeposits
|
||
async function getUserDeposits() {
|
||
disablePagesUserDeposits = true;
|
||
const result = await makePost(
|
||
"admin/getUserDeposits",
|
||
{
|
||
token: token,
|
||
page: 1,
|
||
},
|
||
makeAuthHeaderForAxios(getAuthInfo()?.a)
|
||
);
|
||
if (result.status === 401) {
|
||
sayError("Данные авторизации устарели");
|
||
redirect("/admin/");
|
||
disablePagesUserDeposits = false;
|
||
return;
|
||
}
|
||
if (result.error) {
|
||
sayError("Не удалось получить депозиты пользователя");
|
||
disablePagesUserDeposits = false;
|
||
return;
|
||
}
|
||
userDeposits = result.data.deposits;
|
||
if(!Array.isArray(userDeposits)) userDeposits = [];
|
||
numPagesUserOrders = result.data.pages;
|
||
disablePagesUserDeposits = false;
|
||
// console.log(result.data, 'depos');
|
||
}
|
||
|
||
$: if(browser || Number(ordersFilter) > -999) getUserOrders();
|
||
|
||
if (browser) {
|
||
getUserOrders();
|
||
getUserRequisites();
|
||
getUserDeposits();
|
||
}
|
||
|
||
let findFieldValue = "";
|
||
let showLoadingFind = false;
|
||
let showFoundedOrderWindow = false;
|
||
async function findOrder() {
|
||
showLoadingFind = true;
|
||
const res = await makePost("admin/find", {
|
||
|
||
}, makeAuthHeaderForAxios(getAuthInfo()?.a));
|
||
}
|
||
showLoadingFind = false;
|
||
const orderTypesMap = {
|
||
"card": "Карта",
|
||
"sbp": "СБП",
|
||
"clearing_account": "По номеру счёта"
|
||
}
|
||
</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 p-4 rounded-box bg-base-300">
|
||
<div class="flex gap-2 p-2 items-center text-lg">
|
||
<p class="font-bold">Токен:</p>
|
||
<p class="text-info">{token}</p>
|
||
</div>
|
||
<div class="flex gap-2 p-2 items-center text-lg">
|
||
<p class="font-bold">Имя и фамилия:</p>
|
||
<p class="text-info">{userData.name} {userData.surname}</p>
|
||
</div>
|
||
<div class="flex gap-2 p-2 items-center text-lg">
|
||
<p class="font-bold">Валюта:</p>
|
||
<p class="text-info">{userData?.code}</p>
|
||
</div>
|
||
<div class="flex gap-2 p-2 items-center text-lg">
|
||
<p class="font-bold">Баланс:</p>
|
||
<p class="text-info">{Number(userData.balance)/1e6} USDT</p>
|
||
</div>
|
||
<div class="flex gap-2 p-2 items-center text-lg">
|
||
<p class="font-bold">Заморожено:</p>
|
||
<p class="text-info">{userData?.insurance} USDT</p>
|
||
</div>
|
||
<div class="flex gap-2 p-2 items-center text-lg">
|
||
<p class="font-bold">Ставка:</p>
|
||
<p class="text-info">{userData.bid} %</p>
|
||
</div>
|
||
<div class="flex gap-2 p-2 items-center text-lg">
|
||
<p class="font-bold">Ставка на выплаты:</p>
|
||
<p class="text-info">{userData.payout_bid} %</p>
|
||
</div>
|
||
<div class="flex gap-2 p-2 items-center text-lg flex-wrap">
|
||
<p class="font-bold">Кошелёк пополнения:</p>
|
||
<p class="text-info text-sm">{userData.deposit_address}</p>
|
||
</div>
|
||
<div class="flex gap-2 p-2 items-center text-lg">
|
||
<p class="font-bold">Торговля:</p>
|
||
<p class={userData["can_trade"] === "t" ? "text-primary" : "text-error"}>
|
||
{userData["can_trade"] === "t" ? "Активна" : "Отключена"}
|
||
</p>
|
||
</div>
|
||
<div class="w-full flex gap-4 mt-8">
|
||
<button
|
||
class="btn btn-neutral w-[100px]"
|
||
on:click={() => {
|
||
reloadUserInfo();
|
||
}}
|
||
disabled={userInfoReloading}
|
||
>
|
||
{#if !userInfoReloading}
|
||
{"Обновить"}
|
||
{:else}
|
||
<span class="loading loading-spinner"></span>
|
||
{/if}
|
||
</button>
|
||
<a
|
||
href={window.location.pathname.replace("profile", "change")}
|
||
class="btn btn-info">Изменить</a
|
||
>
|
||
<button
|
||
on:click={() => {
|
||
deleteUser();
|
||
}}
|
||
class="btn btn-error ml-auto">Удалить</button
|
||
>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flex items-center gap-4">
|
||
<div class="bg-accent rounded-[4px] w-[10px] h-full"></div>
|
||
<h1 class="text-2xl font-semibold">Реквизиты пользователя</h1>
|
||
<button disabled class="btn btn-accent">Добавить реквизит</button>
|
||
</div>
|
||
<div class="w-full flex flex-col p-4 rounded-box bg-base-300">
|
||
<div class="w-full flex flex-col justify-center items-center">
|
||
<Pagination
|
||
totalPages={reqsMaxPage}
|
||
pageChangedCallback={(n) => {
|
||
reqsCurrentPage = n;
|
||
getUserRequisites();
|
||
}}
|
||
disableButtons={false}
|
||
css={"btn-neutral mt-2"}
|
||
/>
|
||
<p class="opacity-50 text-xs mt-1">Всего страниц: {reqsMaxPage}</p>
|
||
</div>
|
||
</div>
|
||
<div class="w-full flex flex-col p-4 rounded-box bg-base-300">
|
||
<div class="overflow-x-auto mt-4">
|
||
<table class="table">
|
||
<!-- head -->
|
||
<thead>
|
||
<tr>
|
||
<th>ID</th>
|
||
<th>Статус</th>
|
||
<th>Банк</th>
|
||
<th>СБП</th>
|
||
<th>Карта</th>
|
||
<th>Телефон</th>
|
||
<th>Имя</th>
|
||
<th>Девайс</th>
|
||
<th>Объем {userData.code}</th>
|
||
<th>Лимит {userData.code}</th>
|
||
<th>Опции</th>
|
||
<!-- <th></th> -->
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{#each userRequisites as requisite}
|
||
<tr class="hover:bg-neutral group">
|
||
<td class="font-semibold">{requisite["id"]}</td>
|
||
<td class=""
|
||
>{requisite["status"] === "t" ? "активен" : "отключен"}</td
|
||
>
|
||
<td>{requisite["bank_name"]}</td>
|
||
<td>{requisite["is_sbp"] === "t" ? "да" : "нет"}</td>
|
||
<td>{requisite["cardnumber"]}</td>
|
||
<td>{requisite["phone"]}</td>
|
||
<td>{requisite["name"]}</td>
|
||
<td>{requisite["device_uuid"]}</td>
|
||
<td>{requisite["daily_volume"]}</td>
|
||
<td>{requisite["daily_volume_limit"]}</td>
|
||
<td class="flex gap-2">
|
||
<a
|
||
href={"/admin/user/edit/req/" + token + "/" + requisite["id"] + "_" + userData.code}
|
||
class="btn btn-info">Изменить</a
|
||
>
|
||
<button class="btn btn-error">Удалить</button>
|
||
</td>
|
||
</tr>
|
||
{/each}
|
||
</tbody>
|
||
</table>
|
||
</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 p-4 rounded-box bg-base-300"></div> -->
|
||
|
||
<div class="flex items-center gap-4">
|
||
<div class="bg-accent rounded-[4px] w-[10px] h-full"></div>
|
||
<h1 class="text-2xl font-semibold">Текущие заявки</h1>
|
||
<!-- <button href={"/user/neworder/"+token} disabled class="btn btn-accent">Добавить заявку</button> -->
|
||
</div>
|
||
<div class="w-full flex flex-col p-4 rounded-box bg-base-300">
|
||
<div class="w-full flex flex-col justify-center items-center">
|
||
<!-- <div class="flex items-center gap-2">
|
||
<input bind:value={findFieldValue} type="text" class="input input-bordered">
|
||
<button on:click={()=>{showFoundedOrderWindow = true;}} class="btn btn-outline">Найти</button>
|
||
</div> -->
|
||
<Pagination
|
||
totalPages={numPagesUserOrders}
|
||
pageChangedCallback={(n) => {
|
||
currentPageUserOrders = n;
|
||
getUserOrders();
|
||
}}
|
||
disableButtons={disablePagesUserOrders}
|
||
css={"btn-neutral mt-2"}
|
||
/>
|
||
<p class="opacity-50 text-xs mt-1">Всего страниц: {numPagesUserOrders}</p>
|
||
<select
|
||
bind:value={ordersFilter}
|
||
class="select select-bordered min-w-[230px] mt-2"
|
||
>
|
||
<!-- <option value="-1"> Все выплаты </option> -->
|
||
<option value="1"> {orderStatusMap["1"]} </option>
|
||
<option value="2"> {orderStatusMap["2"]} </option>
|
||
<option value="3"> {orderStatusMap["3"]} </option>
|
||
</select>
|
||
</div>
|
||
<div class="overflow-x-auto mt-4">
|
||
<table class="table">
|
||
<!-- head -->
|
||
<thead>
|
||
<tr>
|
||
<!-- <th>ID заявки</th> -->
|
||
<th>UUID</th>
|
||
<th>ID клиента</th>
|
||
<th>Статус</th>
|
||
<th>Сумма</th>
|
||
<th>Тип заявки</th>
|
||
<!-- <th>Курс</th> -->
|
||
<!-- <th>Название реквизита</th> -->
|
||
<!-- <th>СБП</th> -->
|
||
<th>Мерчант</th>
|
||
<th>Время создания</th>
|
||
<th>Время закрытия</th>
|
||
<!-- <th>Опции</th> -->
|
||
<!-- <th></th> -->
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{#each userOrders as order}
|
||
<tr class="hover:bg-neutral group">
|
||
<!-- <td class="font-semibold">{order["id"]}</td> -->
|
||
<td class="font-semibold">{order["uuid"]}</td>
|
||
<td class="font-semibold">{order["external_user_id"]}</td>
|
||
<td class="">{order["status"]}</td>
|
||
<td>{order["summa"]} {userData?.code}</td>
|
||
<td>{orderTypesMap[order["order_type"]]}</td>
|
||
<!-- <td>{order["rate"]} {userData?.code}</td> -->
|
||
<!-- <td>{order["is_sbp"] === "t" ? "да" : "нет"}</td> -->
|
||
<td>{order["merchant"]}</td>
|
||
<td>{order["creation_time"]}</td>
|
||
<td>{order["closetime"]}</td>
|
||
<!-- <td>
|
||
<button class="btn btn-outline">Закрыть ручками</button>
|
||
</td> -->
|
||
<!-- <td class="flex gap-2">
|
||
<a href="" class="btn btn-info">Изменить</a>
|
||
<button class="btn btn-error">Удалить</button>
|
||
</td> -->
|
||
</tr>
|
||
{/each}
|
||
</tbody>
|
||
</table>
|
||
</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 p-4 rounded-box bg-base-300">
|
||
<div class="w-full flex flex-col justify-center items-center">
|
||
<Pagination
|
||
totalPages={numOfPagesUserDeposits}
|
||
pageChangedCallback={(n) => {
|
||
currentPageUserDeposits = n;
|
||
getUserDeposits();
|
||
}}
|
||
disableButtons={disablePagesUserDeposits}
|
||
css={"btn-neutral"}
|
||
/>
|
||
<p class="opacity-50 text-xs mt-1">
|
||
Всего страниц: {numOfPagesUserDeposits}
|
||
</p>
|
||
</div>
|
||
<div class="overflow-x-auto mt-4">
|
||
<table class="table">
|
||
<!-- head -->
|
||
<thead>
|
||
<tr>
|
||
<th>Статус</th>
|
||
<th>Сумма</th>
|
||
<th>Время создания</th>
|
||
<!-- <th>Опции</th> -->
|
||
<!-- <th></th> -->
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{#each userDeposits as depo}
|
||
<tr class="hover:bg-neutral group">
|
||
<td class="">{depoStatusMap[depo["pending"]]}</td>
|
||
<td>{Number(depo["amount"])/1e6} USDT</td>
|
||
<td>{depo["creationtime"]}</td>
|
||
<!-- <td class="flex gap-2">
|
||
<a href="" class="btn btn-info">Изменить</a>
|
||
<button class="btn btn-error">Удалить</button>
|
||
</td> -->
|
||
</tr>
|
||
{/each}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<!-- {#if showFoundedOrderWindow}
|
||
<div class="fixed z-[1000] inset-0 flex justify-center items-center bg-black bg-opacity-50">
|
||
<div class="bg-base-100 rounded-md p-4 flex flex-col">
|
||
<button class="btn btn-outline" on:click={()=>{showFoundedOrderWindow = false;}}>Закрыть</button>
|
||
<button class="btn btn-outline" on:click={()=>{showFoundedOrderWindow = false;}}>Закрыть</button>
|
||
</div>
|
||
</div>
|
||
{/if} --> |