This commit is contained in:
FIRST_NAME LAST_NAME 2025-10-17 13:03:06 +03:00
parent 9eb577750f
commit 938d345769
10 changed files with 366 additions and 139 deletions

View File

@ -18,7 +18,7 @@
showMenu = !showMenu; showMenu = !showMenu;
}} }}
tabindex="0" tabindex="0"
class="btn btn-ghost 2xl:hidden w-[54px] max-w-[54px] p-1" class="btn btn-ghost w-[54px] max-w-[54px] p-1"
> >
{#if !showMenu} {#if !showMenu}
<svg <svg
@ -45,7 +45,7 @@
{jwtDecode(getAuthInfo()?.a)?.role == "4" ? "Admin" : "Moder"} {jwtDecode(getAuthInfo()?.a)?.role == "4" ? "Admin" : "Moder"}
</p> </p>
</div> </div>
<div class="navbar-center hidden 2xl:flex font-semibold"> <div class="navbar-center hidden font-semibold">
<ul class="menu menu-horizontal px-1"> <ul class="menu menu-horizontal px-1">
<li> <li>
<a href="/admin/userslist">Пользователи</a> <a href="/admin/userslist">Пользователи</a>
@ -64,7 +64,6 @@
<li><a href="/admin/change-balance/0">Управление балансом</a></li> <li><a href="/admin/change-balance/0">Управление балансом</a></li>
<li><a href="/admin/refs">Рефералы</a></li> <li><a href="/admin/refs">Рефералы</a></li>
{/if} {/if}
<!-- <li><a>Item 3</a></li> -->
</ul> </ul>
</div> </div>
<div class="navbar-end"> <div class="navbar-end">
@ -85,7 +84,7 @@
</div> </div>
<div <div
class={"fixed inset-0 top-16 z-50 px-5 flex flex-col items-center justify-center bg-base-100 transition-all duration-150 2xl:hidden " + class={"fixed inset-0 top-16 z-50 px-5 flex flex-col items-center justify-center bg-base-100 transition-all duration-150 " +
(showMenu ? "" : "-translate-x-full")} (showMenu ? "" : "-translate-x-full")}
> >
<ul <ul
@ -254,6 +253,21 @@
<ChevronRightIcon /> <ChevronRightIcon />
</div> </div>
</li> </li>
<div
class="h-[1px] w-full bg-neutral flex-shrink-0 opacity-50 my-[5px]"
></div>
<li class="relative">
<a
class="text-lg"
on:click={() => {
showMenu = false;
}}
href="/admin/req">Реквизиты</a
>
<div class="absolute right-0 top-[2px] pointer-events-none">
<ChevronRightIcon />
</div>
</li>
{/if} {/if}
</ul> </ul>
</div> </div>

View File

@ -1,4 +1,4 @@
export const prerender = true; export const prerender = true;
export const ssr = false; export const ssr = false;
// console.log = () => {}; console.log = () => {};

View File

@ -35,7 +35,7 @@
<div <div
class="flex justify-center flex-shrink-0 w-full h-[calc(100vh-52px-68px)] mt-[68px] overflow-auto p-4" class="flex justify-center flex-shrink-0 w-full h-[calc(100vh-52px-68px)] mt-[68px] overflow-auto p-4"
> >
<div class="flex w-full md:max-w-[90%] lg:max-w-[1080px]"> <div class="flex w-full md:max-w-[90%] lg:max-w-[1560px]">
<slot /> <slot />
</div> </div>
</div> </div>

View File

@ -37,8 +37,8 @@
let external_user_idValue = ""; let external_user_idValue = "";
let searchValue = ""; let searchValue = "";
async function findDispute() { async function findDeposit() {
if (searchValue.length < 5 || showLoadingFind) return; if (searchValue.length < 1 || showLoadingFind) return;
showLoadingFind = true; showLoadingFind = true;
let sData = { let sData = {
@ -89,6 +89,7 @@
sayInfo("Заявка закрыта!"); sayInfo("Заявка закрыта!");
showLoadingRollback = false; showLoadingRollback = false;
showFoundedOrderWindow = false; showFoundedOrderWindow = false;
findDeposit();
} }
let showChangeSum = false; let showChangeSum = false;
@ -119,6 +120,7 @@
showLoadingChangeSum = false; showLoadingChangeSum = false;
showChangeSum = false; showChangeSum = false;
showFoundedOrderWindow = false; showFoundedOrderWindow = false;
findDeposit();
} }
async function changeSumWithoutBalance(uuid) { async function changeSumWithoutBalance(uuid) {
showLoadingChangeSum = true; showLoadingChangeSum = true;
@ -142,6 +144,7 @@
showLoadingChangeSum = false; showLoadingChangeSum = false;
showChangeSum = false; showChangeSum = false;
showFoundedOrderWindow = false; showFoundedOrderWindow = false;
findDeposit();
} }
let showLoadingSendCallback = false; let showLoadingSendCallback = false;
@ -190,12 +193,14 @@
sayInfo("Команда изменена"); sayInfo("Команда изменена");
changingTeam = false; changingTeam = false;
showChangeTeamWindow = false; showChangeTeamWindow = false;
showFoundedOrderWindow = false;
findDeposit();
} }
let img64 = ""; let img64 = "";
let qrCode = false; let qrCode = false;
$: if (selectedDispute && selectedDispute["cardnumber"].length > 16) { $: if (selectedDispute && selectedDispute["requisite_type"] === "p2p_qr") {
qrCode = true; qrCode = true;
QRCode.toDataURL(selectedDispute["cardnumber"], { QRCode.toDataURL(selectedDispute["cardnumber"], {
type: "image/jpeg", type: "image/jpeg",
@ -215,7 +220,7 @@
<div class="w-full flex flex-col p-4 rounded-box bg-base-300"> <div class="w-full flex flex-col p-4 rounded-box bg-base-300">
<input <input
bind:value={searchValue} bind:value={searchValue}
placeholder="UUID, External UUID или External User ID" placeholder="UUID, External UUID, Токен или External User ID"
type="text" type="text"
class="input input-bordered" class="input input-bordered"
/> />
@ -224,7 +229,7 @@
on:click={() => { on:click={() => {
maxDepositSearchPages = 1; maxDepositSearchPages = 1;
currentDepositSearchPage = 1; currentDepositSearchPage = 1;
findDispute(); findDeposit();
}} }}
class="btn btn-outline mt-2" class="btn btn-outline mt-2"
> >
@ -242,7 +247,7 @@
on:click={() => { on:click={() => {
if (currentDepositSearchPage <= 1) return; if (currentDepositSearchPage <= 1) return;
currentDepositSearchPage -= 1; currentDepositSearchPage -= 1;
findDispute(); findDeposit();
}} }}
> >
&lt; &lt;
@ -256,7 +261,7 @@
on:click={() => { on:click={() => {
if (currentDepositSearchPage >= maxDepositSearchPages) return; if (currentDepositSearchPage >= maxDepositSearchPages) return;
currentDepositSearchPage += 1; currentDepositSearchPage += 1;
findDispute(); findDeposit();
}} }}
> >
&gt; &gt;
@ -360,8 +365,8 @@
<p>{selectedDispute["name"]}</p> <p>{selectedDispute["name"]}</p>
{/if} {/if}
{#if selectedDispute["cardnumber"] !== ""} {#if selectedDispute["cardnumber"] !== ""}
{#if selectedDispute["cardnumber"].length <= 16} {#if selectedDispute["requisite_type"] !== "p2p_qr"}
<p class="text-sm mt-3">Карта</p> <p class="text-sm mt-3">Карта/CVU</p>
<p>{selectedDispute["cardnumber"]}</p> <p>{selectedDispute["cardnumber"]}</p>
{:else} {:else}
<p class="text-sm mt-3">QR</p> <p class="text-sm mt-3">QR</p>

View File

@ -496,7 +496,7 @@
bind:value={searchFilter} bind:value={searchFilter}
type="text" type="text"
class="input input-bordered max-w-full w-full rounded-[10px]" class="input input-bordered max-w-full w-full rounded-[10px]"
placeholder="UUID, External ID или Реквизит" placeholder="UUID, External UUID, Токен или External User ID"
/> />
<div class="flex gap-[5px]"> <div class="flex gap-[5px]">
<button <button

133
src/routes/req/+page.svelte Normal file
View File

@ -0,0 +1,133 @@
<script>
import { makeAuthHeaderForAxios, getAuthInfo } from "$lib/auth/Auth";
import { makePost } from "$lib/tools/requests/requests";
import { toValidNumberFormat } from "$lib/tools/strings/Strings";
import { sayError } from "$lib/tools/toaster/Toaster";
import { redirect } from "$lib/tools/url/URLTools";
import Pagination from "$lib/ui-components/pagination.svelte";
let searchValue = "";
let showLoadingFind = false;
let reqsCurrentPage = 1;
let reqsMaxPage = 1;
let userRequisites = [];
async function getUserRequisites() {
if (showLoadingFind) return;
showLoadingFind = true;
const result = await makePost(
"admin/getRequisite",
{
page: Number(reqsCurrentPage),
token: searchValue,
},
// @ts-ignore
makeAuthHeaderForAxios(getAuthInfo()?.a)
);
if (result.status === 401) {
sayError("Данные авторизации устарели");
redirect("/admin/");
showLoadingFind = false;
return;
}
if (result.error) {
sayError("Не удалось получить реквизиты пользователя");
showLoadingFind = false;
return;
}
userRequisites = result.data.data;
if (!Array.isArray(userRequisites)) userRequisites = [];
reqsMaxPage = Number(result.data.pages);
console.log(result.data);
showLoadingFind = false;
}
</script>
<div class="w-full flex flex-col gap-8">
<div class="w-full flex flex-col p-4 rounded-box bg-base-300">
<input
bind:value={searchValue}
placeholder="Токен пользователя"
type="text"
class="input input-bordered"
/>
<button
on:click={() => {
reqsMaxPage = 1;
reqsCurrentPage = 1;
getUserRequisites();
}}
class="btn btn-outline mt-2"
>
{#if showLoadingFind}
<span class="loading loading-dots loading-xs"></span>
{:else}
{"Найти реквизиты"}
{/if}
</button>
<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">
{#if showLoadingFind}
<span class="loading loading-md self-center"></span>
{:else}
<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></th> -->
</tr>
</thead>
<tbody>
{#each userRequisites as requisite}
<tr class="hover:bg-neutral group">
<td class="font-semibold">{requisite["uuid"]}</td>
<td class=""
>{requisite["is_hidden"] !== "t" ? "активен" : "отключен"}</td
>
<td>{requisite["bank_name"]}</td>
<td>{requisite["requisite_type"]}</td>
<td>{requisite["requisite"] ?? "-"}</td>
<td>{requisite["name"]}</td>
<td>{requisite["device_uuid"]}</td>
<!-- <td class="flex gap-2"> -->
<!-- <a
href={"/admin/user/edit/req/" +
requisite["token"] +
"/" +
requisite["uuid"] +
"_" +
requisite["code"]}
class="btn btn-info">Изменить</a
> -->
<!-- <button class="btn btn-error">Удалить</button> -->
<!-- </td> -->
</tr>
{/each}
</tbody>
</table>
</div>
{/if}
</div>
</div>

View File

@ -1,129 +1,129 @@
<script> <script>
// @ts-nocheck // @ts-nocheck
import { browser } from "$app/environment"; // import { browser } from "$app/environment";
import { getAuthInfo, makeAuthHeaderForAxios } from "$lib/auth/Auth.js"; // import { getAuthInfo, makeAuthHeaderForAxios } from "$lib/auth/Auth.js";
import { makeGet, makePost } from "$lib/tools/requests/requests.js"; // import { makeGet, makePost } from "$lib/tools/requests/requests.js";
import { sayError } from "$lib/tools/toaster/Toaster.js"; // import { sayError } from "$lib/tools/toaster/Toaster.js";
import { redirect } from "$lib/tools/url/URLTools.js"; // import { redirect } from "$lib/tools/url/URLTools.js";
export let data; // export let data;
let { reqID } = data; // let { reqID } = data;
let {currency} = data; // let { currency } = data;
let { token } = data; // let { token } = data;
let reqInfo = []; // let reqInfo = [];
let value_bankName; // let value_bankName;
let value_cardNumber; // let value_cardNumber;
let value_phone; // let value_phone;
let value_status; // let value_status;
let value_limit; // let value_limit;
let canChange = false; // let canChange = false;
$: reqInfo, bindValues(); // $: reqInfo, bindValues();
$: value_cardNumber, value_phone, value_status, checkFields(); // $: value_cardNumber, value_phone, value_status, checkFields();
function bindValues() { // function bindValues() {
value_bankName = reqInfo[0]?.bank_name; // value_bankName = reqInfo[0]?.bank_name;
value_cardNumber = reqInfo[0]?.cardnumber; // value_cardNumber = reqInfo[0]?.cardnumber;
value_phone = reqInfo[0]?.phone; // value_phone = reqInfo[0]?.phone;
value_status = reqInfo[0]?.status === "t"; // value_status = reqInfo[0]?.status === "t";
value_limit = Number(reqInfo[0]?.daily_volume_limit); // value_limit = Number(reqInfo[0]?.daily_volume_limit);
value_bankName = reqInfo[0]?.bank_id; // value_bankName = reqInfo[0]?.bank_id;
} // }
function checkFields() { // function checkFields() {
if (value_cardNumber?.length !== 16) { // if (value_cardNumber?.length !== 16) {
canChange = false; // canChange = false;
return; // return;
} // }
if (value_phone?.length < 6) { // if (value_phone?.length < 6) {
canChange = false; // canChange = false;
return; // return;
} // }
if (value_limit < 0) { // if (value_limit < 0) {
canChange = false; // canChange = false;
return; // return;
} // }
canChange = true; // canChange = true;
} // }
async function getReqInfo() { // async function getReqInfo() {
const result = await makePost( // const result = await makePost(
"getRequisite", // "getRequisite",
{ // {
token: token, // token: token,
}, // },
makeAuthHeaderForAxios(getAuthInfo()?.a) // makeAuthHeaderForAxios(getAuthInfo()?.a)
); // );
if (result.status === 401) { // if (result.status === 401) {
sayError("Данные авторизации устарели"); // sayError("Данные авторизации устарели");
// window.location.href = "/"; // // window.location.href = "/";
redirect("/admin/"); // redirect("/admin/");
return; // return;
} // }
if (result.error) { // if (result.error) {
sayError("Не удалось получить реквизиты пользователя"); // sayError("Не удалось получить реквизиты пользователя");
return; // return;
} // }
console.log(result.data); // console.log(result.data, reqID);
reqInfo = result.data.filter((s) => s.id === reqID); // reqInfo = result.data.filter((s) => s.uuid === reqID);
} // }
async function changeRequisite() { // async function changeRequisite() {
//changeRequisite // //changeRequisite
canChange = false; // canChange = false;
const result = await makePost( // const result = await makePost(
"changeRequisite", // "changeRequisite",
{ // {
...reqInfo[0], // ...reqInfo[0],
bankname: value_bankName, // bankname: value_bankName,
cardnumber: value_cardNumber, // cardnumber: value_cardNumber,
phone: value_phone, // phone: value_phone,
status: value_status ? "true" : "false", // status: value_status ? "true" : "false",
limit: value_limit.toString(), // limit: value_limit.toString(),
}, // },
makeAuthHeaderForAxios(getAuthInfo()?.a) // makeAuthHeaderForAxios(getAuthInfo()?.a)
); // );
if (result.status === 401) { // if (result.status === 401) {
sayError("Данные авторизации устарели"); // sayError("Данные авторизации устарели");
// window.location.href = "/"; // // window.location.href = "/";
redirect("/admin/"); // redirect("/admin/");
// canChange = true; // // canChange = true;
return; // return;
} // }
if (result.error) { // if (result.error) {
sayError("Не удалось изменить реквизит пользователя"); // sayError("Не удалось изменить реквизит пользователя");
canChange = true; // canChange = true;
return; // return;
} // }
document.getElementById("ref")?.click(); // document.getElementById("ref")?.click();
// canChange = true; // // canChange = true;
} // }
let activeBanks = []; // let activeBanks = [];
async function getActiveBanks() { // async function getActiveBanks() {
let res = await makeGet( // let res = await makeGet(
"client/banksList", // "client/banksList",
makeAuthHeaderForAxios(getAuthInfo()?.a) // makeAuthHeaderForAxios(getAuthInfo()?.a)
); // );
if (res.error) { // if (res.error) {
sayError("Не удалось получить банки. Ошибка #4143"); // sayError("Не удалось получить банки. Ошибка #4143");
} else { // } else {
console.log(res.data); // console.log(res.data);
activeBanks = res.data; // activeBanks = res.data;
} // }
} // }
if (browser) { // if (browser) {
getReqInfo(); // getReqInfo();
getActiveBanks(); // getActiveBanks();
} // }
</script> </script>
<div class="w-full flex flex-col gap-8"> <!-- <div class="w-full flex flex-col gap-8">
<div class="flex gap-4"> <div class="flex gap-4">
<div class="bg-accent rounded-[4px] w-[10px] h-full"></div> <div class="bg-accent rounded-[4px] w-[10px] h-full"></div>
<h1 class="text-2xl font-semibold">Изменение реквизита (ID: {reqID})</h1> <h1 class="text-2xl font-semibold">Изменение реквизита (ID: {reqID})</h1>
@ -138,9 +138,6 @@
{#each activeBanks as bank} {#each activeBanks as bank}
<option value={bank.id}>{bank.name}</option> <option value={bank.id}>{bank.name}</option>
{/each} {/each}
<!-- <option value="sber">Сбер</option> -->
<!-- <option value="2">Модератор</option>
<option value="4">Администратор</option> -->
</select> </select>
<label class="input input-bordered flex items-center gap-2"> <label class="input input-bordered flex items-center gap-2">
Номер карты Номер карты
@ -176,4 +173,4 @@
<a href={"/admin/user/profile/" + token} class="hidden" id="ref"></a> <a href={"/admin/user/profile/" + token} class="hidden" id="ref"></a>
{/each} {/each}
</div> </div>
</div> </div> -->

View File

@ -330,7 +330,7 @@
</div> </div>
</div> </div>
<div class="flex items-center gap-4"> <!-- <div class="flex items-center gap-4">
<div class="bg-accent rounded-[4px] w-[10px] h-full"></div> <div class="bg-accent rounded-[4px] w-[10px] h-full"></div>
<h1 class="text-2xl font-semibold">Реквизиты пользователя</h1> <h1 class="text-2xl font-semibold">Реквизиты пользователя</h1>
<button disabled class="btn btn-accent">Добавить реквизит</button> <button disabled class="btn btn-accent">Добавить реквизит</button>
@ -352,7 +352,6 @@
<div class="w-full flex flex-col p-4 rounded-box bg-base-300"> <div class="w-full flex flex-col p-4 rounded-box bg-base-300">
<div class="overflow-x-auto mt-4"> <div class="overflow-x-auto mt-4">
<table class="table"> <table class="table">
<!-- head -->
<thead> <thead>
<tr> <tr>
<th>ID</th> <th>ID</th>
@ -366,7 +365,6 @@
<th>Объем {userData.code}</th> <th>Объем {userData.code}</th>
<th>Лимит {userData.code}</th> <th>Лимит {userData.code}</th>
<th>Опции</th> <th>Опции</th>
<!-- <th></th> -->
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -401,7 +399,7 @@
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div> -->
<!-- <div class="flex gap-4"> <!-- <div class="flex gap-4">
<div class="bg-accent rounded-[4px] w-[10px] h-full"></div> <div class="bg-accent rounded-[4px] w-[10px] h-full"></div>

View File

@ -5,32 +5,66 @@
getAuthInfo, getAuthInfo,
makeAuthHeaderForAxios, makeAuthHeaderForAxios,
} from "$lib/auth/Auth"; } from "$lib/auth/Auth";
import { makeGet } from "$lib/tools/requests/requests"; import { makeGet, makePost } from "$lib/tools/requests/requests";
import { toValidNumberFormat } from "$lib/tools/strings/Strings"; import { toValidNumberFormat } from "$lib/tools/strings/Strings";
import { sayError } from "$lib/tools/toaster/Toaster"; import { sayError } from "$lib/tools/toaster/Toaster";
import { redirect } from "$lib/tools/url/URLTools"; import { redirect } from "$lib/tools/url/URLTools";
import Pagination from "$lib/ui-components/pagination.svelte";
let users = []; let users = [];
let usersReady = false; let usersReady = false;
let searchValue = "";
let showLoadingFind = false;
let maxPage = 1;
let currentPage = 1;
let selectedCur = "";
async function getUsers() { async function getUsers() {
if (showLoadingFind) return;
showLoadingFind = true;
if (checkAuthSync()) { if (checkAuthSync()) {
const result = await makeGet( const result = await makePost(
"getUsers", "getUsers",
{
...(searchValue !== "" ? { search_data: searchValue } : {}),
...(selectedCur === "" ? {} : { currency: selectedCur }),
page: currentPage,
},
makeAuthHeaderForAxios(getAuthInfo()?.a) makeAuthHeaderForAxios(getAuthInfo()?.a)
); );
users = result.data; users = result.data.data ?? [];
console.log(result);
usersReady = true; usersReady = true;
maxPage = Number(result.data.pages);
showLoadingFind = false;
// console.log(result); // console.log(result);
} else { } else {
sayError("Данные авторизации устарели"); sayError("Данные авторизации устарели");
// window.location.href = "/"; // window.location.href = "/";
redirect("/admin/"); redirect("/admin/");
showLoadingFind = false;
return; return;
} }
} }
let currencies = [];
async function getCurrencies() {
const res = await makeGet(
"admin/getCurrencies",
// @ts-ignore
makeAuthHeaderForAxios(getAuthInfo()?.a)
);
res.data.forEach((e) => {
currencies = [...currencies, e.code];
});
console.log(currencies);
}
if (browser) { if (browser) {
getCurrencies();
getUsers(); getUsers();
} }
</script> </script>
@ -40,9 +74,51 @@
<div class="bg-accent rounded-[4px] w-[10px] h-full"></div> <div class="bg-accent rounded-[4px] w-[10px] h-full"></div>
<h1 class="text-2xl font-semibold">Все пользователи</h1> <h1 class="text-2xl font-semibold">Все пользователи</h1>
</div> </div>
<div class="w-full flex flex-col p-4 rounded-box bg-base-300">
<div class="grid grid-cols-2 gap-4">
<input
bind:value={searchValue}
placeholder="Поиск..."
type="text"
class="input input-bordered"
/>
<select bind:value={selectedCur} class="select select-bordered">
<option value="">Все валюты</option>
{#each currencies as c}
<option value={c}>{c}</option>
{/each}
</select>
</div>
<button
on:click={() => {
maxPage = 1;
currentPage = 1;
getUsers();
}}
class="btn btn-outline mt-2"
>
{#if showLoadingFind}
<span class="loading loading-dots loading-xs"></span>
{:else}
{"Применить"}
{/if}
</button>
<div class="w-full flex flex-col justify-center items-center">
<Pagination
totalPages={maxPage}
pageChangedCallback={(n) => {
currentPage = n;
getUsers();
}}
disableButtons={false}
css={"btn-neutral mt-2"}
/>
<p class="opacity-50 text-xs mt-1">Всего страниц: {maxPage}</p>
</div>
</div>
<div class="w-full flex flex-col p-4 rounded-box bg-base-300"> <div class="w-full flex flex-col p-4 rounded-box bg-base-300">
<div class="overflow-x-auto"> <div class="overflow-x-auto">
{#if usersReady} {#if usersReady && !showLoadingFind}
<table class="table"> <table class="table">
<!-- head --> <!-- head -->
<thead> <thead>
@ -59,7 +135,10 @@
<tr class="hover:bg-neutral group"> <tr class="hover:bg-neutral group">
<th class="font-normal">{user["token"]}</th> <th class="font-normal">{user["token"]}</th>
<td class="font-semibold">{user["name"]} {user["surname"]}</td> <td class="font-semibold">{user["name"]} {user["surname"]}</td>
<td>{toValidNumberFormat(user["balance"])} {user["code"]}</td> <td
>{toValidNumberFormat(user["total_balance"])}
{user["code"]}</td
>
<td> <td>
<a <a
href={"/admin/user/profile/" + user["token"]} href={"/admin/user/profile/" + user["token"]}

View File

@ -37,6 +37,7 @@ const config = {
"/sms", "/sms",
"/withdrawals", "/withdrawals",
"/refs", "/refs",
"/req",
], ],
}, },
}, },