h5先关
This commit is contained in:
parent
3fa9222b99
commit
9a9dfce9ba
@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
||||||
<title>Manager Center</title>
|
<title>Manager Center</title>
|
||||||
<link rel="stylesheet" href="./style.css?v=20260624-0100" />
|
<link rel="stylesheet" href="./style.css?v=20260625-0100" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="manager-center" aria-label="Manager Center" data-i18n-aria="page_label" data-loading="true">
|
<div class="manager-center" aria-label="Manager Center" data-i18n-aria="page_label" data-loading="true">
|
||||||
@ -39,35 +39,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="card search-card">
|
<section class="card action-card" id="actionCard" aria-label="Manager actions">
|
||||||
<div class="section-head">
|
<button class="action-item" id="addBDLeaderButton" type="button">
|
||||||
<h2 data-i18n="user">User</h2>
|
|
||||||
</div>
|
|
||||||
<form class="search-form" id="searchForm" autocomplete="off">
|
|
||||||
<input id="accountInput" type="text" inputmode="text" placeholder="Enter user ID or account" data-i18n-placeholder="user_search_placeholder" />
|
|
||||||
<button id="searchButton" type="submit" data-i18n="search">Search</button>
|
|
||||||
</form>
|
|
||||||
<div class="form-status" id="searchStatus" role="status" hidden></div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="card target-card" id="targetCard" hidden>
|
|
||||||
<div class="avatar-shell">
|
|
||||||
<img id="targetAvatar" alt="" hidden />
|
|
||||||
<span id="targetAvatarFallback">U</span>
|
|
||||||
</div>
|
|
||||||
<div class="profile-copy">
|
|
||||||
<div class="eyebrow" data-i18n="target_user">Target User</div>
|
|
||||||
<div class="name" id="targetName">-</div>
|
|
||||||
<div class="meta" id="targetUid">UID: -</div>
|
|
||||||
<div class="pill-row">
|
|
||||||
<span class="status-pill" id="targetAccountStatus">-</span>
|
|
||||||
<span class="status-pill" id="targetCountryStatus">-</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="card action-card" id="actionCard" hidden>
|
|
||||||
<button class="action-item" id="addBDLeaderButton" type="button" disabled>
|
|
||||||
<span class="action-item-icon" aria-hidden="true">
|
<span class="action-item-icon" aria-hidden="true">
|
||||||
<svg viewBox="0 0 24 24">
|
<svg viewBox="0 0 24 24">
|
||||||
<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" />
|
<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" />
|
||||||
@ -83,7 +56,7 @@
|
|||||||
<path d="m9 6 6 6-6 6" />
|
<path d="m9 6 6 6-6 6" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button class="action-item" id="countryEntryButton" type="button" disabled>
|
<button class="action-item" id="countryEntryButton" type="button">
|
||||||
<span class="action-item-icon" aria-hidden="true">
|
<span class="action-item-icon" aria-hidden="true">
|
||||||
<svg viewBox="0 0 24 24">
|
<svg viewBox="0 0 24 24">
|
||||||
<circle cx="12" cy="12" r="9" />
|
<circle cx="12" cy="12" r="9" />
|
||||||
@ -116,7 +89,7 @@
|
|||||||
<path d="m9 6 6 6-6 6" />
|
<path d="m9 6 6 6-6 6" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button class="action-item is-danger" id="banEntryButton" type="button" disabled>
|
<button class="action-item is-danger" id="banEntryButton" type="button">
|
||||||
<span class="action-item-icon" aria-hidden="true">
|
<span class="action-item-icon" aria-hidden="true">
|
||||||
<svg viewBox="0 0 24 24">
|
<svg viewBox="0 0 24 24">
|
||||||
<circle cx="12" cy="12" r="9" />
|
<circle cx="12" cy="12" r="9" />
|
||||||
@ -130,7 +103,7 @@
|
|||||||
<path d="m9 6 6 6-6 6" />
|
<path d="m9 6 6 6-6 6" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button class="action-item" id="unbanEntryButton" type="button" disabled>
|
<button class="action-item" id="unbanEntryButton" type="button">
|
||||||
<span class="action-item-icon" aria-hidden="true">
|
<span class="action-item-icon" aria-hidden="true">
|
||||||
<svg viewBox="0 0 24 24">
|
<svg viewBox="0 0 24 24">
|
||||||
<path d="M12 3 20 7v5c0 5-3.4 8-8 9-4.6-1-8-4-8-9V7l8-4Z" />
|
<path d="M12 3 20 7v5c0 5-3.4 8-8 9-4.6-1-8-4-8-9V7l8-4Z" />
|
||||||
@ -144,25 +117,31 @@
|
|||||||
<path d="m9 6 6 6-6 6" />
|
<path d="m9 6 6 6-6 6" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
<button class="action-item" id="bdLeaderListButton" type="button">
|
||||||
|
<span class="action-item-icon" aria-hidden="true">
|
||||||
|
<svg viewBox="0 0 24 24">
|
||||||
|
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
|
||||||
|
<circle cx="9" cy="7" r="4" />
|
||||||
|
<path d="M23 21v-2a4 4 0 0 0-3-3.87" />
|
||||||
|
<path d="M16 3.13a4 4 0 0 1 0 7.75" />
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span class="action-item-copy">
|
||||||
|
<span class="action-item-title" data-i18n="bd_leaders">BD Leaders</span>
|
||||||
|
<span class="action-item-subtitle" id="bdLeaderSummary">0</span>
|
||||||
|
</span>
|
||||||
|
<svg class="action-item-arrow" viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="m9 6 6 6-6 6" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
</section>
|
</section>
|
||||||
|
<div class="form-status" id="pageStatus" role="status" hidden></div>
|
||||||
<section class="card bd-leader-card">
|
|
||||||
<div class="section-head">
|
|
||||||
<div>
|
|
||||||
<h2 data-i18n="bd_leaders">BD Leaders</h2>
|
|
||||||
<div class="section-subtitle" id="bdLeaderCount">0</div>
|
|
||||||
</div>
|
|
||||||
<button class="text-button" id="refreshBDLeaderButton" type="button" data-i18n="refresh">Refresh</button>
|
|
||||||
</div>
|
|
||||||
<div class="form-status" id="bdLeaderStatus" role="status" hidden></div>
|
|
||||||
<div class="bd-leader-list" id="bdLeaderList"></div>
|
|
||||||
</section>
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<div class="modal-mask" id="countryModal" role="dialog" aria-modal="true" aria-labelledby="countryModalTitle" hidden>
|
<div class="modal-mask" id="actionModal" role="dialog" aria-modal="true" aria-labelledby="actionModalTitle" hidden>
|
||||||
<section class="modal-sheet">
|
<section class="modal-sheet">
|
||||||
<div class="modal-head">
|
<div class="modal-head">
|
||||||
<h2 id="countryModalTitle" data-i18n="change_country">Change Country</h2>
|
<h2 id="actionModalTitle">-</h2>
|
||||||
<button class="modal-close" type="button" data-modal-close aria-label="Close" data-i18n-aria="close">
|
<button class="modal-close" type="button" data-modal-close aria-label="Close" data-i18n-aria="close">
|
||||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
<path d="M6 6 18 18M18 6 6 18" />
|
<path d="M6 6 18 18M18 6 6 18" />
|
||||||
@ -170,106 +149,111 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<label class="field-label" id="countryLabelText" data-i18n="select_country">Select country</label>
|
<form class="search-form modal-search-form" id="modalSearchForm" autocomplete="off">
|
||||||
<div class="current-country" id="currentCountryText">-</div>
|
<input id="modalAccountInput" type="text" inputmode="text" placeholder="Enter user ID or account" data-i18n-placeholder="user_search_placeholder" />
|
||||||
<div class="custom-select" id="countrySelect" data-value="">
|
<button id="modalSearchButton" type="submit" data-i18n="search">Search</button>
|
||||||
<button
|
</form>
|
||||||
class="custom-select-button"
|
<div class="form-status" id="modalSearchStatus" role="status" hidden></div>
|
||||||
id="countryButton"
|
|
||||||
type="button"
|
|
||||||
aria-expanded="false"
|
|
||||||
aria-haspopup="listbox"
|
|
||||||
aria-labelledby="countryLabelText countrySelectedLabel"
|
|
||||||
>
|
|
||||||
<span id="countrySelectedLabel">-</span>
|
|
||||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
|
||||||
<path d="m7 9 5 5 5-5" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<div class="custom-select-menu" id="countryMenu" role="listbox" aria-labelledby="countryLabelText" hidden></div>
|
|
||||||
</div>
|
|
||||||
<button class="primary-action" id="changeCountryButton" type="button" disabled data-i18n="change_country">Change Country</button>
|
|
||||||
<div class="form-status" id="countryStatus" role="status" hidden></div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="modal-mask" id="giftModal" role="dialog" aria-modal="true" aria-labelledby="giftModalTitle" hidden>
|
<section class="target-card modal-target-card" id="targetCard" hidden>
|
||||||
<section class="modal-sheet">
|
<div class="avatar-shell">
|
||||||
<div class="modal-head">
|
<img id="targetAvatar" alt="" hidden />
|
||||||
<h2 id="giftModalTitle" data-i18n="gift_props">Gift Props</h2>
|
<span id="targetAvatarFallback">U</span>
|
||||||
<button class="modal-close" type="button" data-modal-close aria-label="Close" data-i18n-aria="close">
|
|
||||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
|
||||||
<path d="M6 6 18 18M18 6 6 18" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<label class="field-label" id="propsTypeLabelText" data-i18n="gift_type">Gift Type</label>
|
|
||||||
<div class="custom-select" id="propsTypeSelect" data-value="RIDE">
|
|
||||||
<button
|
|
||||||
class="custom-select-button"
|
|
||||||
id="propsTypeButton"
|
|
||||||
type="button"
|
|
||||||
aria-expanded="false"
|
|
||||||
aria-haspopup="listbox"
|
|
||||||
aria-labelledby="propsTypeLabelText propsTypeSelectedLabel"
|
|
||||||
>
|
|
||||||
<span id="propsTypeSelectedLabel">Ride</span>
|
|
||||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
|
||||||
<path d="m7 9 5 5 5-5" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<div class="custom-select-menu" id="propsTypeMenu" role="listbox" aria-labelledby="propsTypeLabelText" hidden>
|
|
||||||
<button type="button" role="option" data-value="RIDE" data-i18n="prop_type_ride">Ride</button>
|
|
||||||
<button type="button" role="option" data-value="NOBLE_VIP" data-i18n="prop_type_noble_vip">Noble VIP</button>
|
|
||||||
<button type="button" role="option" data-value="AVATAR_FRAME" data-i18n="prop_type_avatar_frame">Avatar Frame</button>
|
|
||||||
<button type="button" role="option" data-value="BADGE" data-i18n="prop_type_badge">Badge</button>
|
|
||||||
<button type="button" role="option" data-value="CHAT_BUBBLE" data-i18n="prop_type_chat_bubble">Chat Bubble</button>
|
|
||||||
<button type="button" role="option" data-value="DATA_CARD" data-i18n="prop_type_data_card">Profile Card</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="profile-copy">
|
||||||
|
<div class="eyebrow" data-i18n="target_user">Target User</div>
|
||||||
|
<div class="name" id="targetName">-</div>
|
||||||
|
<div class="meta" id="targetUid">UID: -</div>
|
||||||
|
<div class="pill-row">
|
||||||
|
<span class="status-pill" id="targetAccountStatus">-</span>
|
||||||
|
<span class="status-pill" id="targetCountryStatus">-</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div class="operation-panel" id="addBDLeaderPanel" hidden>
|
||||||
|
<button class="primary-action" id="addBDLeaderConfirmButton" type="button" disabled data-i18n="add_bd_leader">Add BD Leader</button>
|
||||||
|
<div class="form-status" id="addBDLeaderStatus" role="status" hidden></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="props-status" id="propsStatus" role="status" hidden></div>
|
|
||||||
<div class="props-list" id="propsList"></div>
|
|
||||||
<button class="primary-action" id="sendPropsButton" type="button" disabled data-i18n="send">Send</button>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="modal-mask" id="banModal" role="dialog" aria-modal="true" aria-labelledby="banModalTitle" hidden>
|
<div class="operation-panel" id="countryPanel" hidden>
|
||||||
<section class="modal-sheet">
|
<label class="field-label" id="countryLabelText" data-i18n="select_country">Select country</label>
|
||||||
<div class="modal-head">
|
<div class="current-country" id="currentCountryText">-</div>
|
||||||
<h2 id="banModalTitle" data-i18n="ban_user">Ban User</h2>
|
<div class="custom-select" id="countrySelect" data-value="">
|
||||||
<button class="modal-close" type="button" data-modal-close aria-label="Close" data-i18n-aria="close">
|
<button
|
||||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
class="custom-select-button"
|
||||||
<path d="M6 6 18 18M18 6 6 18" />
|
id="countryButton"
|
||||||
</svg>
|
type="button"
|
||||||
</button>
|
aria-expanded="false"
|
||||||
</div>
|
aria-haspopup="listbox"
|
||||||
<div class="modal-body">
|
aria-labelledby="countryLabelText countrySelectedLabel"
|
||||||
<span class="danger-chip" id="banEligibility">-</span>
|
>
|
||||||
<textarea id="banReason" maxlength="200" rows="3" placeholder="Ban reason" data-i18n-placeholder="ban_reason"></textarea>
|
<span id="countrySelectedLabel">-</span>
|
||||||
<button class="danger-action" id="banButton" type="button" disabled data-i18n="ban">Ban</button>
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
<div class="form-status" id="banStatus" role="status" hidden></div>
|
<path d="m7 9 5 5 5-5" />
|
||||||
</div>
|
</svg>
|
||||||
</section>
|
</button>
|
||||||
</div>
|
<div class="custom-select-menu" id="countryMenu" role="listbox" aria-labelledby="countryLabelText" hidden></div>
|
||||||
|
</div>
|
||||||
|
<button class="primary-action" id="changeCountryButton" type="button" disabled data-i18n="change_country">Change Country</button>
|
||||||
|
<div class="form-status" id="countryStatus" role="status" hidden></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="modal-mask" id="unbanModal" role="dialog" aria-modal="true" aria-labelledby="unbanModalTitle" hidden>
|
<div class="operation-panel" id="giftPanel" hidden>
|
||||||
<section class="modal-sheet">
|
<label class="field-label" id="propsTypeLabelText" data-i18n="gift_type">Gift Type</label>
|
||||||
<div class="modal-head">
|
<div class="custom-select" id="propsTypeSelect" data-value="RIDE">
|
||||||
<h2 id="unbanModalTitle" data-i18n="unban_user">Unban User</h2>
|
<button
|
||||||
<button class="modal-close" type="button" data-modal-close aria-label="Close" data-i18n-aria="close">
|
class="custom-select-button"
|
||||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
id="propsTypeButton"
|
||||||
<path d="M6 6 18 18M18 6 6 18" />
|
type="button"
|
||||||
</svg>
|
aria-expanded="false"
|
||||||
</button>
|
aria-haspopup="listbox"
|
||||||
</div>
|
aria-labelledby="propsTypeLabelText propsTypeSelectedLabel"
|
||||||
<div class="modal-body">
|
>
|
||||||
<span class="danger-chip" id="unbanEligibility">-</span>
|
<span id="propsTypeSelectedLabel">Ride</span>
|
||||||
<textarea id="unbanReason" maxlength="200" rows="3" placeholder="Unban reason" data-i18n-placeholder="unban_reason"></textarea>
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
<button class="primary-action" id="unbanButton" type="button" disabled data-i18n="unban">Unban</button>
|
<path d="m7 9 5 5 5-5" />
|
||||||
<div class="form-status" id="unbanStatus" role="status" hidden></div>
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div class="custom-select-menu" id="propsTypeMenu" role="listbox" aria-labelledby="propsTypeLabelText" hidden>
|
||||||
|
<button type="button" role="option" data-value="RIDE" data-i18n="prop_type_ride">Ride</button>
|
||||||
|
<button type="button" role="option" data-value="NOBLE_VIP" data-i18n="prop_type_noble_vip">Noble VIP</button>
|
||||||
|
<button type="button" role="option" data-value="AVATAR_FRAME" data-i18n="prop_type_avatar_frame">Avatar Frame</button>
|
||||||
|
<button type="button" role="option" data-value="BADGE" data-i18n="prop_type_badge">Badge</button>
|
||||||
|
<button type="button" role="option" data-value="CHAT_BUBBLE" data-i18n="prop_type_chat_bubble">Chat Bubble</button>
|
||||||
|
<button type="button" role="option" data-value="DATA_CARD" data-i18n="prop_type_data_card">Profile Card</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="props-status" id="propsStatus" role="status" hidden></div>
|
||||||
|
<div class="props-list" id="propsList"></div>
|
||||||
|
<button class="primary-action" id="sendPropsButton" type="button" disabled data-i18n="send">Send</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="operation-panel" id="banPanel" hidden>
|
||||||
|
<span class="danger-chip" id="banEligibility">-</span>
|
||||||
|
<textarea id="banReason" maxlength="200" rows="3" placeholder="Ban reason" data-i18n-placeholder="ban_reason"></textarea>
|
||||||
|
<button class="danger-action" id="banButton" type="button" disabled data-i18n="ban">Ban</button>
|
||||||
|
<div class="form-status" id="banStatus" role="status" hidden></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="operation-panel" id="unbanPanel" hidden>
|
||||||
|
<span class="danger-chip" id="unbanEligibility">-</span>
|
||||||
|
<textarea id="unbanReason" maxlength="200" rows="3" placeholder="Unban reason" data-i18n-placeholder="unban_reason"></textarea>
|
||||||
|
<button class="primary-action" id="unbanButton" type="button" disabled data-i18n="unban">Unban</button>
|
||||||
|
<div class="form-status" id="unbanStatus" role="status" hidden></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="operation-panel" id="bdLeaderPanel" hidden>
|
||||||
|
<div class="section-head">
|
||||||
|
<div>
|
||||||
|
<h2 data-i18n="bd_leaders">BD Leaders</h2>
|
||||||
|
<div class="section-subtitle" id="bdLeaderCount">0</div>
|
||||||
|
</div>
|
||||||
|
<button class="text-button" id="refreshBDLeaderButton" type="button" data-i18n="refresh">Refresh</button>
|
||||||
|
</div>
|
||||||
|
<div class="form-status" id="bdLeaderStatus" role="status" hidden></div>
|
||||||
|
<div class="bd-leader-list" id="bdLeaderList"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
@ -280,6 +264,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="toast" id="toast" role="status" hidden></div>
|
<div class="toast" id="toast" role="status" hidden></div>
|
||||||
</div>
|
</div>
|
||||||
<script src="./script.js?v=20260624-0100" defer></script>
|
<script src="./script.js?v=20260625-0100" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -349,6 +349,7 @@
|
|||||||
const state = {
|
const state = {
|
||||||
manager: null,
|
manager: null,
|
||||||
target: null,
|
target: null,
|
||||||
|
activeAction: "",
|
||||||
features: defaultFeatures(),
|
features: defaultFeatures(),
|
||||||
propsType: defaultPropsType,
|
propsType: defaultPropsType,
|
||||||
props: [],
|
props: [],
|
||||||
@ -363,6 +364,54 @@
|
|||||||
addingBDLeader: false
|
addingBDLeader: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const actionConfigs = {
|
||||||
|
addBDLeader: {
|
||||||
|
titleKey: "add_bd_leader",
|
||||||
|
disabledKey: "add_bd_leader_disabled",
|
||||||
|
feature: "addBdLeader",
|
||||||
|
panel: "#addBDLeaderPanel",
|
||||||
|
status: "#addBDLeaderStatus",
|
||||||
|
needsUser: true
|
||||||
|
},
|
||||||
|
changeCountry: {
|
||||||
|
titleKey: "change_country",
|
||||||
|
disabledKey: "change_country_disabled",
|
||||||
|
feature: "changeCountry",
|
||||||
|
panel: "#countryPanel",
|
||||||
|
status: "#countryStatus",
|
||||||
|
needsUser: true
|
||||||
|
},
|
||||||
|
giftProps: {
|
||||||
|
titleKey: "gift_props",
|
||||||
|
disabledKey: "gift_props_disabled",
|
||||||
|
feature: "giftProps",
|
||||||
|
panel: "#giftPanel",
|
||||||
|
status: "#propsStatus",
|
||||||
|
needsUser: true
|
||||||
|
},
|
||||||
|
banUser: {
|
||||||
|
titleKey: "ban_user",
|
||||||
|
disabledKey: "ban_user_disabled",
|
||||||
|
feature: "banUser",
|
||||||
|
panel: "#banPanel",
|
||||||
|
status: "#banStatus",
|
||||||
|
needsUser: true
|
||||||
|
},
|
||||||
|
unbanUser: {
|
||||||
|
titleKey: "unban_user",
|
||||||
|
disabledKey: "unban_user_disabled",
|
||||||
|
feature: "unbanUser",
|
||||||
|
panel: "#unbanPanel",
|
||||||
|
status: "#unbanStatus",
|
||||||
|
needsUser: true
|
||||||
|
},
|
||||||
|
bdLeaders: {
|
||||||
|
titleKey: "bd_leaders",
|
||||||
|
panel: "#bdLeaderPanel",
|
||||||
|
needsUser: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const params = readURLParams();
|
const params = readURLParams();
|
||||||
let currentLang = normalizeLanguage(params.get("lang"));
|
let currentLang = normalizeLanguage(params.get("lang"));
|
||||||
let currentMessages = fallbackMessages[currentLang] || fallbackMessages.en;
|
let currentMessages = fallbackMessages[currentLang] || fallbackMessages.en;
|
||||||
@ -414,7 +463,7 @@
|
|||||||
if (window.location.protocol === "file:") return fallbackMessages[normalizedLang];
|
if (window.location.protocol === "file:") return fallbackMessages[normalizedLang];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`./locales/${normalizedLang}.json?v=20260624-0100`, { cache: "no-store" });
|
const response = await fetch(`./locales/${normalizedLang}.json?v=20260625-0100`, { cache: "no-store" });
|
||||||
if (response.ok) return await response.json();
|
if (response.ok) return await response.json();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return fallbackMessages[normalizedLang];
|
return fallbackMessages[normalizedLang];
|
||||||
@ -570,6 +619,7 @@
|
|||||||
renderCountrySelect();
|
renderCountrySelect();
|
||||||
renderManager(state.manager);
|
renderManager(state.manager);
|
||||||
renderTarget();
|
renderTarget();
|
||||||
|
renderActionModal();
|
||||||
renderProps();
|
renderProps();
|
||||||
renderBDLeaders();
|
renderBDLeaders();
|
||||||
updateActionState();
|
updateActionState();
|
||||||
@ -723,6 +773,47 @@
|
|||||||
document.body.classList.toggle("is-modal-open", Boolean(document.querySelector(".modal-mask:not([hidden])")));
|
document.body.classList.toggle("is-modal-open", Boolean(document.querySelector(".modal-mask:not([hidden])")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function activeConfig() {
|
||||||
|
return actionConfigs[state.activeAction] || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearActionStatuses() {
|
||||||
|
setStatus($("#modalSearchStatus"), "");
|
||||||
|
Object.values(actionConfigs).forEach((config) => {
|
||||||
|
if (config.status) setStatus($(config.status), "");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearActionModalForm() {
|
||||||
|
const input = $("#modalAccountInput");
|
||||||
|
if (input) input.value = "";
|
||||||
|
const banReason = $("#banReason");
|
||||||
|
const unbanReason = $("#unbanReason");
|
||||||
|
if (banReason) banReason.value = "";
|
||||||
|
if (unbanReason) unbanReason.value = "";
|
||||||
|
state.target = null;
|
||||||
|
state.selectedCountryId = "";
|
||||||
|
renderTarget();
|
||||||
|
clearActionStatuses();
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderActionModal() {
|
||||||
|
const config = activeConfig();
|
||||||
|
const title = $("#actionModalTitle");
|
||||||
|
if (title) title.textContent = config ? message(config.titleKey) : "-";
|
||||||
|
|
||||||
|
const needsUser = config?.needsUser !== false;
|
||||||
|
const searchForm = $("#modalSearchForm");
|
||||||
|
const modalTarget = $("#targetCard");
|
||||||
|
if (searchForm) searchForm.hidden = !needsUser;
|
||||||
|
if (modalTarget && !needsUser) modalTarget.hidden = true;
|
||||||
|
|
||||||
|
Object.values(actionConfigs).forEach((item) => {
|
||||||
|
const panel = $(item.panel);
|
||||||
|
if (panel) panel.hidden = item !== config || (item.needsUser !== false && !state.target);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function setModalOpen(selector, open) {
|
function setModalOpen(selector, open) {
|
||||||
const modal = $(selector);
|
const modal = $(selector);
|
||||||
if (!modal) return;
|
if (!modal) return;
|
||||||
@ -739,77 +830,56 @@
|
|||||||
document.querySelectorAll(".modal-mask").forEach((modal) => {
|
document.querySelectorAll(".modal-mask").forEach((modal) => {
|
||||||
modal.hidden = true;
|
modal.hidden = true;
|
||||||
});
|
});
|
||||||
|
state.activeAction = "";
|
||||||
|
state.target = null;
|
||||||
setPropsTypeMenuOpen(false);
|
setPropsTypeMenuOpen(false);
|
||||||
setCountryMenuOpen(false);
|
setCountryMenuOpen(false);
|
||||||
|
renderTarget();
|
||||||
syncModalState();
|
syncModalState();
|
||||||
}
|
}
|
||||||
|
|
||||||
function openGiftModal() {
|
function openActionModal(action) {
|
||||||
if (!featureEnabled("giftProps")) {
|
const config = actionConfigs[action];
|
||||||
showToast(message("gift_props_disabled"));
|
if (!config) return;
|
||||||
|
if (config.feature && !featureEnabled(config.feature)) {
|
||||||
|
showToast(message(config.disabledKey));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!state.target) {
|
|
||||||
showToast(message("enter_user"));
|
state.activeAction = action;
|
||||||
return;
|
clearActionModalForm();
|
||||||
}
|
renderActionModal();
|
||||||
setModalOpen("#giftModal", true);
|
setModalOpen("#actionModal", true);
|
||||||
updateActionState();
|
updateActionState();
|
||||||
|
|
||||||
|
if (action === "giftProps" && !state.props.length) {
|
||||||
|
loadProps().catch((error) => {
|
||||||
|
setStatus($("#propsStatus"), friendlyError(error), "error");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (action === "bdLeaders") {
|
||||||
|
renderBDLeaders();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.setTimeout(() => {
|
||||||
|
if (config.needsUser !== false) $("#modalAccountInput")?.focus();
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function openCountryModal() {
|
function openGiftModal() {
|
||||||
if (!featureEnabled("changeCountry")) {
|
openActionModal("giftProps");
|
||||||
showToast(message("change_country_disabled"));
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!state.target) {
|
|
||||||
showToast(message("enter_user"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setStatus($("#countryStatus"), "");
|
function openCountryModal() {
|
||||||
const currentCountryText = $("#currentCountryText");
|
openActionModal("changeCountry");
|
||||||
if (currentCountryText) currentCountryText.textContent = `${message("current_country")}: ${displayCountryText(state.target)}`;
|
|
||||||
state.selectedCountryId = String(state.target.countryId || matchingCountryId(state.target) || "");
|
|
||||||
setModalOpen("#countryModal", true);
|
|
||||||
renderCountrySelect();
|
|
||||||
updateActionState();
|
|
||||||
|
|
||||||
if (!state.countries.length) {
|
|
||||||
try {
|
|
||||||
await loadCountries();
|
|
||||||
} catch (error) {
|
|
||||||
setStatus($("#countryStatus"), friendlyError(error), "error");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function openBanModal() {
|
function openBanModal() {
|
||||||
if (!featureEnabled("banUser")) {
|
openActionModal("banUser");
|
||||||
showToast(message("ban_user_disabled"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!state.target) {
|
|
||||||
showToast(message("enter_user"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setStatus($("#banStatus"), "");
|
|
||||||
setModalOpen("#banModal", true);
|
|
||||||
updateActionState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function openUnbanModal() {
|
function openUnbanModal() {
|
||||||
if (!featureEnabled("unbanUser")) {
|
openActionModal("unbanUser");
|
||||||
showToast(message("unban_user_disabled"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!state.target) {
|
|
||||||
showToast(message("enter_user"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setStatus($("#unbanStatus"), "");
|
|
||||||
setModalOpen("#unbanModal", true);
|
|
||||||
updateActionState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function closePage() {
|
function closePage() {
|
||||||
@ -943,6 +1013,13 @@
|
|||||||
return message("bd_leader_count", "{count} BD Leaders").replace("{count}", new Intl.NumberFormat("en-US").format(Number(count) || 0));
|
return message("bd_leader_count", "{count} BD Leaders").replace("{count}", new Intl.NumberFormat("en-US").format(Number(count) || 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatBDLeaderSummary() {
|
||||||
|
const countText = formatBDLeaderCount(state.bdLeaders.length);
|
||||||
|
const firstLeader = state.bdLeaders[0];
|
||||||
|
if (!firstLeader) return countText;
|
||||||
|
return `${countText} - ${userIDText(firstLeader)}`;
|
||||||
|
}
|
||||||
|
|
||||||
function formatDateTime(value) {
|
function formatDateTime(value) {
|
||||||
if (!value) return "";
|
if (!value) return "";
|
||||||
const date = new Date(value);
|
const date = new Date(value);
|
||||||
@ -973,18 +1050,15 @@
|
|||||||
|
|
||||||
function renderTarget() {
|
function renderTarget() {
|
||||||
const card = $("#targetCard");
|
const card = $("#targetCard");
|
||||||
const actionCard = $("#actionCard");
|
|
||||||
if (!state.target) {
|
if (!state.target) {
|
||||||
if (card) card.hidden = true;
|
if (card) card.hidden = true;
|
||||||
if (actionCard) actionCard.hidden = true;
|
renderActionModal();
|
||||||
closeModals();
|
|
||||||
updateActionState();
|
updateActionState();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const target = state.target;
|
const target = state.target;
|
||||||
if (card) card.hidden = false;
|
if (card) card.hidden = false;
|
||||||
if (actionCard) actionCard.hidden = false;
|
|
||||||
$("#targetName").textContent = displayName(target);
|
$("#targetName").textContent = displayName(target);
|
||||||
$("#targetUid").textContent = userIDText(target);
|
$("#targetUid").textContent = userIDText(target);
|
||||||
$("#targetAccountStatus").textContent = target.accountStatus || "-";
|
$("#targetAccountStatus").textContent = target.accountStatus || "-";
|
||||||
@ -1002,6 +1076,28 @@
|
|||||||
unbanEligibility.classList.toggle("is-danger", !canUnban);
|
unbanEligibility.classList.toggle("is-danger", !canUnban);
|
||||||
}
|
}
|
||||||
renderAvatar("#targetAvatar", "#targetAvatarFallback", target.userAvatar, displayName(target), "U");
|
renderAvatar("#targetAvatar", "#targetAvatarFallback", target.userAvatar, displayName(target), "U");
|
||||||
|
renderActionModal();
|
||||||
|
updateActionState();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function prepareActiveActionAfterTarget() {
|
||||||
|
if (!state.target) return;
|
||||||
|
|
||||||
|
if (state.activeAction === "changeCountry") {
|
||||||
|
const currentCountryText = $("#currentCountryText");
|
||||||
|
if (currentCountryText) currentCountryText.textContent = `${message("current_country")}: ${displayCountryText(state.target)}`;
|
||||||
|
state.selectedCountryId = String(state.target.countryId || matchingCountryId(state.target) || "");
|
||||||
|
renderCountrySelect();
|
||||||
|
if (!state.countries.length) {
|
||||||
|
await loadCountries();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.activeAction === "giftProps") {
|
||||||
|
renderProps();
|
||||||
|
}
|
||||||
|
|
||||||
updateActionState();
|
updateActionState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1071,7 +1167,10 @@
|
|||||||
function renderBDLeaders() {
|
function renderBDLeaders() {
|
||||||
const list = $("#bdLeaderList");
|
const list = $("#bdLeaderList");
|
||||||
const count = $("#bdLeaderCount");
|
const count = $("#bdLeaderCount");
|
||||||
if (count) count.textContent = formatBDLeaderCount(state.bdLeaders.length);
|
const summary = $("#bdLeaderSummary");
|
||||||
|
const leaderCountText = formatBDLeaderCount(state.bdLeaders.length);
|
||||||
|
if (count) count.textContent = leaderCountText;
|
||||||
|
if (summary) summary.textContent = formatBDLeaderSummary();
|
||||||
if (!list) return;
|
if (!list) return;
|
||||||
|
|
||||||
list.replaceChildren();
|
list.replaceChildren();
|
||||||
@ -1116,10 +1215,7 @@
|
|||||||
name.textContent = displayName(leader);
|
name.textContent = displayName(leader);
|
||||||
const meta = document.createElement("span");
|
const meta = document.createElement("span");
|
||||||
meta.className = "bd-leader-meta";
|
meta.className = "bd-leader-meta";
|
||||||
const metaItems = [userIDText(leader)];
|
meta.textContent = userIDText(leader);
|
||||||
if (leader.regionId) metaItems.push(leader.regionId);
|
|
||||||
if (leader.originSys) metaItems.push(leader.originSys);
|
|
||||||
meta.textContent = metaItems.join(" · ");
|
|
||||||
copy.append(name, meta);
|
copy.append(name, meta);
|
||||||
|
|
||||||
const time = document.createElement("span");
|
const time = document.createElement("span");
|
||||||
@ -1138,14 +1234,16 @@
|
|||||||
const giftEntryButton = $("#giftEntryButton");
|
const giftEntryButton = $("#giftEntryButton");
|
||||||
const banEntryButton = $("#banEntryButton");
|
const banEntryButton = $("#banEntryButton");
|
||||||
const unbanEntryButton = $("#unbanEntryButton");
|
const unbanEntryButton = $("#unbanEntryButton");
|
||||||
|
const bdLeaderListButton = $("#bdLeaderListButton");
|
||||||
const refreshBDLeaderButton = $("#refreshBDLeaderButton");
|
const refreshBDLeaderButton = $("#refreshBDLeaderButton");
|
||||||
|
const addBDLeaderConfirmButton = $("#addBDLeaderConfirmButton");
|
||||||
const sendButton = $("#sendPropsButton");
|
const sendButton = $("#sendPropsButton");
|
||||||
const changeCountryButton = $("#changeCountryButton");
|
const changeCountryButton = $("#changeCountryButton");
|
||||||
const banButton = $("#banButton");
|
const banButton = $("#banButton");
|
||||||
const unbanButton = $("#unbanButton");
|
const unbanButton = $("#unbanButton");
|
||||||
if (addBDLeaderButton) {
|
if (addBDLeaderButton) {
|
||||||
const disabledByFeature = !featureEnabled("addBdLeader");
|
const disabledByFeature = !featureEnabled("addBdLeader");
|
||||||
addBDLeaderButton.disabled = disabledByFeature || !state.target || state.addingBDLeader || isTargetBDLeader();
|
addBDLeaderButton.disabled = disabledByFeature || state.addingBDLeader;
|
||||||
addBDLeaderButton.classList.toggle("is-feature-disabled", disabledByFeature);
|
addBDLeaderButton.classList.toggle("is-feature-disabled", disabledByFeature);
|
||||||
const title = addBDLeaderButton.querySelector(".action-item-title");
|
const title = addBDLeaderButton.querySelector(".action-item-title");
|
||||||
if (title) {
|
if (title) {
|
||||||
@ -1156,33 +1254,38 @@
|
|||||||
}
|
}
|
||||||
if (giftEntryButton) {
|
if (giftEntryButton) {
|
||||||
const disabledByFeature = !featureEnabled("giftProps");
|
const disabledByFeature = !featureEnabled("giftProps");
|
||||||
giftEntryButton.disabled = disabledByFeature || !state.target;
|
giftEntryButton.disabled = disabledByFeature;
|
||||||
giftEntryButton.classList.toggle("is-feature-disabled", disabledByFeature);
|
giftEntryButton.classList.toggle("is-feature-disabled", disabledByFeature);
|
||||||
const title = giftEntryButton.querySelector(".action-item-title");
|
const title = giftEntryButton.querySelector(".action-item-title");
|
||||||
if (title) title.textContent = disabledByFeature ? message("gift_props_disabled") : message("gift_props");
|
if (title) title.textContent = disabledByFeature ? message("gift_props_disabled") : message("gift_props");
|
||||||
}
|
}
|
||||||
if (countryEntryButton) {
|
if (countryEntryButton) {
|
||||||
const disabledByFeature = !featureEnabled("changeCountry");
|
const disabledByFeature = !featureEnabled("changeCountry");
|
||||||
countryEntryButton.disabled = disabledByFeature || !state.target || state.countriesLoading || state.changingCountry;
|
countryEntryButton.disabled = disabledByFeature || state.changingCountry;
|
||||||
countryEntryButton.classList.toggle("is-feature-disabled", disabledByFeature);
|
countryEntryButton.classList.toggle("is-feature-disabled", disabledByFeature);
|
||||||
const title = countryEntryButton.querySelector(".action-item-title");
|
const title = countryEntryButton.querySelector(".action-item-title");
|
||||||
if (title) title.textContent = disabledByFeature ? message("change_country_disabled") : message("change_country");
|
if (title) title.textContent = disabledByFeature ? message("change_country_disabled") : message("change_country");
|
||||||
}
|
}
|
||||||
if (banEntryButton) {
|
if (banEntryButton) {
|
||||||
const disabledByFeature = !featureEnabled("banUser");
|
const disabledByFeature = !featureEnabled("banUser");
|
||||||
banEntryButton.disabled = disabledByFeature || !state.target;
|
banEntryButton.disabled = disabledByFeature;
|
||||||
banEntryButton.classList.toggle("is-feature-disabled", disabledByFeature);
|
banEntryButton.classList.toggle("is-feature-disabled", disabledByFeature);
|
||||||
const title = banEntryButton.querySelector(".action-item-title");
|
const title = banEntryButton.querySelector(".action-item-title");
|
||||||
if (title) title.textContent = disabledByFeature ? message("ban_user_disabled") : message("ban_user");
|
if (title) title.textContent = disabledByFeature ? message("ban_user_disabled") : message("ban_user");
|
||||||
}
|
}
|
||||||
if (unbanEntryButton) {
|
if (unbanEntryButton) {
|
||||||
const disabledByFeature = !featureEnabled("unbanUser");
|
const disabledByFeature = !featureEnabled("unbanUser");
|
||||||
unbanEntryButton.disabled = disabledByFeature || !state.target;
|
unbanEntryButton.disabled = disabledByFeature;
|
||||||
unbanEntryButton.classList.toggle("is-feature-disabled", disabledByFeature);
|
unbanEntryButton.classList.toggle("is-feature-disabled", disabledByFeature);
|
||||||
const title = unbanEntryButton.querySelector(".action-item-title");
|
const title = unbanEntryButton.querySelector(".action-item-title");
|
||||||
if (title) title.textContent = disabledByFeature ? message("unban_user_disabled") : message("unban_user");
|
if (title) title.textContent = disabledByFeature ? message("unban_user_disabled") : message("unban_user");
|
||||||
}
|
}
|
||||||
|
if (bdLeaderListButton) bdLeaderListButton.disabled = state.bdLeadersLoading;
|
||||||
if (refreshBDLeaderButton) refreshBDLeaderButton.disabled = state.bdLeadersLoading;
|
if (refreshBDLeaderButton) refreshBDLeaderButton.disabled = state.bdLeadersLoading;
|
||||||
|
if (addBDLeaderConfirmButton) {
|
||||||
|
addBDLeaderConfirmButton.disabled = !featureEnabled("addBdLeader") || !state.target || state.addingBDLeader || isTargetBDLeader();
|
||||||
|
addBDLeaderConfirmButton.textContent = state.addingBDLeader ? message("adding_bd_leader") : message("add_bd_leader");
|
||||||
|
}
|
||||||
if (sendButton) sendButton.disabled = !featureEnabled("giftProps") || !state.target || !state.selectedPropsId;
|
if (sendButton) sendButton.disabled = !featureEnabled("giftProps") || !state.target || !state.selectedPropsId;
|
||||||
if (changeCountryButton) {
|
if (changeCountryButton) {
|
||||||
const currentID = String(state.target?.countryId || matchingCountryId(state.target) || "");
|
const currentID = String(state.target?.countryId || matchingCountryId(state.target) || "");
|
||||||
@ -1252,26 +1355,29 @@
|
|||||||
|
|
||||||
async function searchUser(event) {
|
async function searchUser(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const input = $("#accountInput");
|
const input = $("#modalAccountInput");
|
||||||
|
const status = $("#modalSearchStatus");
|
||||||
|
const button = $("#modalSearchButton");
|
||||||
const account = String(input?.value || "").trim();
|
const account = String(input?.value || "").trim();
|
||||||
if (!account) {
|
if (!account) {
|
||||||
setStatus($("#searchStatus"), message("enter_user"), "error");
|
setStatus(status, message("enter_user"), "error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#searchButton").disabled = true;
|
button.disabled = true;
|
||||||
setStatus($("#searchStatus"), message("searching"));
|
setStatus(status, message("searching"));
|
||||||
try {
|
try {
|
||||||
const body = await requestGoJSON(endpointSearchUser(account));
|
const body = await requestGoJSON(endpointSearchUser(account));
|
||||||
state.target = body?.user || body || null;
|
state.target = body?.user || body || null;
|
||||||
renderTarget();
|
renderTarget();
|
||||||
setStatus($("#searchStatus"), "");
|
await prepareActiveActionAfterTarget();
|
||||||
|
setStatus(status, "");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
state.target = null;
|
state.target = null;
|
||||||
renderTarget();
|
renderTarget();
|
||||||
setStatus($("#searchStatus"), friendlyError(error), "error");
|
setStatus(status, friendlyError(error), "error");
|
||||||
} finally {
|
} finally {
|
||||||
$("#searchButton").disabled = false;
|
button.disabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1280,13 +1386,18 @@
|
|||||||
showToast(message("add_bd_leader_disabled"));
|
showToast(message("add_bd_leader_disabled"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!state.target || state.addingBDLeader) return;
|
if (!state.target) {
|
||||||
|
setStatus($("#addBDLeaderStatus"), message("enter_user"), "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (state.addingBDLeader) return;
|
||||||
if (isTargetBDLeader()) {
|
if (isTargetBDLeader()) {
|
||||||
showToast(message("user_already_bd_leader"));
|
setStatus($("#addBDLeaderStatus"), message("user_already_bd_leader"), "error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.addingBDLeader = true;
|
state.addingBDLeader = true;
|
||||||
|
setStatus($("#addBDLeaderStatus"), message("adding_bd_leader"));
|
||||||
updateActionState();
|
updateActionState();
|
||||||
try {
|
try {
|
||||||
await requestGoJSON(endpointBDLeaders(), {
|
await requestGoJSON(endpointBDLeaders(), {
|
||||||
@ -1295,10 +1406,12 @@
|
|||||||
userId: displayUserID(state.target)
|
userId: displayUserID(state.target)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
setStatus($("#addBDLeaderStatus"), "");
|
||||||
|
closeModals();
|
||||||
showToast(message("add_bd_leader_success"));
|
showToast(message("add_bd_leader_success"));
|
||||||
await loadBDLeaders();
|
await loadBDLeaders();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showToast(friendlyError(error));
|
setStatus($("#addBDLeaderStatus"), friendlyError(error), "error");
|
||||||
} finally {
|
} finally {
|
||||||
state.addingBDLeader = false;
|
state.addingBDLeader = false;
|
||||||
updateActionState();
|
updateActionState();
|
||||||
@ -1310,7 +1423,11 @@
|
|||||||
showToast(message("gift_props_disabled"));
|
showToast(message("gift_props_disabled"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!state.target || !state.selectedPropsId) return;
|
if (!state.target) {
|
||||||
|
setStatus($("#propsStatus"), message("enter_user"), "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!state.selectedPropsId) return;
|
||||||
|
|
||||||
const button = $("#sendPropsButton");
|
const button = $("#sendPropsButton");
|
||||||
button.disabled = true;
|
button.disabled = true;
|
||||||
@ -1322,7 +1439,7 @@
|
|||||||
propsId: state.selectedPropsId
|
propsId: state.selectedPropsId
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
setModalOpen("#giftModal", false);
|
closeModals();
|
||||||
showToast(message("send_success"));
|
showToast(message("send_success"));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showToast(friendlyError(error));
|
showToast(friendlyError(error));
|
||||||
@ -1336,6 +1453,10 @@
|
|||||||
setStatus($("#banStatus"), message("ban_user_disabled"), "error");
|
setStatus($("#banStatus"), message("ban_user_disabled"), "error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!state.target) {
|
||||||
|
setStatus($("#banStatus"), message("enter_user"), "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!canBanTarget(state.target)) return;
|
if (!canBanTarget(state.target)) return;
|
||||||
|
|
||||||
const button = $("#banButton");
|
const button = $("#banButton");
|
||||||
@ -1351,8 +1472,8 @@
|
|||||||
});
|
});
|
||||||
state.target.accountStatus = "ARCHIVE";
|
state.target.accountStatus = "ARCHIVE";
|
||||||
renderTarget();
|
renderTarget();
|
||||||
setModalOpen("#banModal", false);
|
|
||||||
setStatus($("#banStatus"), "");
|
setStatus($("#banStatus"), "");
|
||||||
|
closeModals();
|
||||||
showToast(message("ban_success"));
|
showToast(message("ban_success"));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setStatus($("#banStatus"), friendlyError(error), "error");
|
setStatus($("#banStatus"), friendlyError(error), "error");
|
||||||
@ -1366,6 +1487,10 @@
|
|||||||
setStatus($("#unbanStatus"), message("unban_user_disabled"), "error");
|
setStatus($("#unbanStatus"), message("unban_user_disabled"), "error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!state.target) {
|
||||||
|
setStatus($("#unbanStatus"), message("enter_user"), "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!canUnbanTarget(state.target)) return;
|
if (!canUnbanTarget(state.target)) return;
|
||||||
|
|
||||||
const button = $("#unbanButton");
|
const button = $("#unbanButton");
|
||||||
@ -1381,8 +1506,8 @@
|
|||||||
});
|
});
|
||||||
state.target.accountStatus = "NORMAL";
|
state.target.accountStatus = "NORMAL";
|
||||||
renderTarget();
|
renderTarget();
|
||||||
setModalOpen("#unbanModal", false);
|
|
||||||
setStatus($("#unbanStatus"), "");
|
setStatus($("#unbanStatus"), "");
|
||||||
|
closeModals();
|
||||||
showToast(message("unban_success"));
|
showToast(message("unban_success"));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setStatus($("#unbanStatus"), friendlyError(error), "error");
|
setStatus($("#unbanStatus"), friendlyError(error), "error");
|
||||||
@ -1392,7 +1517,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function changeUserCountry() {
|
async function changeUserCountry() {
|
||||||
if (!state.target) return;
|
if (!state.target) {
|
||||||
|
setStatus($("#countryStatus"), message("enter_user"), "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!featureEnabled("changeCountry")) {
|
if (!featureEnabled("changeCountry")) {
|
||||||
setStatus($("#countryStatus"), message("change_country_disabled"), "error");
|
setStatus($("#countryStatus"), message("change_country_disabled"), "error");
|
||||||
return;
|
return;
|
||||||
@ -1415,8 +1543,8 @@
|
|||||||
});
|
});
|
||||||
state.target = body?.user || state.target;
|
state.target = body?.user || state.target;
|
||||||
renderTarget();
|
renderTarget();
|
||||||
setModalOpen("#countryModal", false);
|
|
||||||
setStatus($("#countryStatus"), "");
|
setStatus($("#countryStatus"), "");
|
||||||
|
closeModals();
|
||||||
showToast(message("country_changed"));
|
showToast(message("country_changed"));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setStatus($("#countryStatus"), friendlyError(error), "error");
|
setStatus($("#countryStatus"), friendlyError(error), "error");
|
||||||
@ -1467,7 +1595,8 @@
|
|||||||
setPropsTypeMenuOpen(false);
|
setPropsTypeMenuOpen(false);
|
||||||
setCountryMenuOpen(false);
|
setCountryMenuOpen(false);
|
||||||
});
|
});
|
||||||
$("#addBDLeaderButton")?.addEventListener("click", addBDLeader);
|
$("#addBDLeaderButton")?.addEventListener("click", () => openActionModal("addBDLeader"));
|
||||||
|
$("#bdLeaderListButton")?.addEventListener("click", () => openActionModal("bdLeaders"));
|
||||||
$("#refreshBDLeaderButton")?.addEventListener("click", () => {
|
$("#refreshBDLeaderButton")?.addEventListener("click", () => {
|
||||||
loadBDLeaders().catch((error) => {
|
loadBDLeaders().catch((error) => {
|
||||||
showToast(friendlyError(error));
|
showToast(friendlyError(error));
|
||||||
@ -1510,7 +1639,8 @@
|
|||||||
setCountryMenuOpen(false);
|
setCountryMenuOpen(false);
|
||||||
closeModals();
|
closeModals();
|
||||||
});
|
});
|
||||||
$("#searchForm")?.addEventListener("submit", searchUser);
|
$("#modalSearchForm")?.addEventListener("submit", searchUser);
|
||||||
|
$("#addBDLeaderConfirmButton")?.addEventListener("click", addBDLeader);
|
||||||
$("#sendPropsButton")?.addEventListener("click", sendProps);
|
$("#sendPropsButton")?.addEventListener("click", sendProps);
|
||||||
$("#banButton")?.addEventListener("click", banUser);
|
$("#banButton")?.addEventListener("click", banUser);
|
||||||
$("#unbanButton")?.addEventListener("click", unbanUser);
|
$("#unbanButton")?.addEventListener("click", unbanUser);
|
||||||
@ -1523,7 +1653,7 @@
|
|||||||
await applyLanguage(currentLang);
|
await applyLanguage(currentLang);
|
||||||
if (!readRawParam("token")) {
|
if (!readRawParam("token")) {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setStatus($("#searchStatus"), message("missing_token"), "error");
|
setStatus($("#pageStatus"), message("missing_token"), "error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -278,19 +278,22 @@ button:disabled {
|
|||||||
|
|
||||||
.action-card {
|
.action-card {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 4px;
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
padding: 6px;
|
gap: 10px;
|
||||||
|
padding: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-item {
|
.action-item {
|
||||||
|
position: relative;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 42px minmax(0, 1fr) 24px;
|
grid-template-columns: 44px minmax(0, 1fr);
|
||||||
gap: 10px;
|
gap: 8px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 58px;
|
min-height: 112px;
|
||||||
|
border: 1px solid var(--line);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
padding: 8px;
|
padding: 12px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@ -313,8 +316,8 @@ button:disabled {
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 42px;
|
width: 44px;
|
||||||
height: 42px;
|
height: 44px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: #e7f8f4;
|
background: #e7f8f4;
|
||||||
color: var(--primary-dark);
|
color: var(--primary-dark);
|
||||||
@ -338,6 +341,8 @@ button:disabled {
|
|||||||
|
|
||||||
.action-item-copy {
|
.action-item-copy {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
gap: 4px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,8 +354,19 @@ button:disabled {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.action-item-subtitle {
|
||||||
|
overflow: hidden;
|
||||||
|
color: var(--muted);
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 800;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
.action-item-arrow {
|
.action-item-arrow {
|
||||||
justify-self: end;
|
position: absolute;
|
||||||
|
top: 14px;
|
||||||
|
right: 12px;
|
||||||
color: #9aa4af;
|
color: #9aa4af;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,6 +410,10 @@ button:disabled {
|
|||||||
.bd-leader-list {
|
.bd-leader-list {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
max-height: min(54vh, 420px);
|
||||||
|
overflow-y: auto;
|
||||||
|
padding-right: 2px;
|
||||||
|
overscroll-behavior: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bd-leader-row {
|
.bd-leader-row {
|
||||||
@ -814,6 +834,11 @@ textarea:focus {
|
|||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-target-card,
|
||||||
|
.operation-panel {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.modal-body textarea {
|
.modal-body textarea {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user