883 lines
28 KiB
HTML
883 lines
28 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover" />
|
|
<title>Recharge Agency</title>
|
|
<style>
|
|
:root {
|
|
--page-width: 512px;
|
|
--brown-990: #290e00;
|
|
--panel-brown: #5e3513;
|
|
--gold-line: #f7dd92;
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
html,
|
|
body {
|
|
margin: 0;
|
|
min-height: 100%;
|
|
background: var(--brown-990);
|
|
font-family:
|
|
-apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", Arial,
|
|
sans-serif;
|
|
}
|
|
|
|
body {
|
|
color: #fff7df;
|
|
padding-bottom: env(safe-area-inset-bottom);
|
|
}
|
|
|
|
.page {
|
|
width: min(100%, var(--page-width));
|
|
aspect-ratio: 1080 / 2410;
|
|
margin: 0 auto;
|
|
overflow: visible;
|
|
background: var(--brown-990);
|
|
}
|
|
|
|
.canvas {
|
|
position: relative;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: var(--brown-990);
|
|
overflow: visible;
|
|
}
|
|
|
|
.sr-only {
|
|
position: absolute;
|
|
width: 1px;
|
|
height: 1px;
|
|
padding: 0;
|
|
margin: -1px;
|
|
overflow: hidden;
|
|
clip: rect(0, 0, 0, 0);
|
|
white-space: nowrap;
|
|
border: 0;
|
|
}
|
|
|
|
.hero-scene {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
width: 100%;
|
|
height: 70.9959%;
|
|
overflow: hidden;
|
|
-webkit-mask: url("../../assets/recharge-agency-list/mask.svg") 0 0 / 100% 100% no-repeat;
|
|
mask: url("../../assets/recharge-agency-list/mask.svg") 0 0 / 100% 100% no-repeat;
|
|
}
|
|
|
|
.hero-layer {
|
|
position: absolute;
|
|
display: block;
|
|
max-width: none;
|
|
pointer-events: none;
|
|
user-select: none;
|
|
object-fit: cover;
|
|
}
|
|
|
|
.hero-layer.top-glow {
|
|
left: -16.3889%;
|
|
top: -2.9807%;
|
|
width: 132.7778%;
|
|
height: 45.7043%;
|
|
}
|
|
|
|
.hero-layer.palace {
|
|
left: 0;
|
|
top: -30.0994%;
|
|
width: 100%;
|
|
height: 133.2554%;
|
|
}
|
|
|
|
.hero-layer.figure {
|
|
left: 0;
|
|
top: -12.858%;
|
|
width: 100%;
|
|
height: 104.0327%;
|
|
}
|
|
|
|
.title-ribbon {
|
|
position: absolute;
|
|
left: 1.8519%;
|
|
top: 56.722%;
|
|
width: 96.2037%;
|
|
height: 4.6888%;
|
|
display: block;
|
|
max-width: none;
|
|
pointer-events: none;
|
|
user-select: none;
|
|
}
|
|
|
|
.content-panel {
|
|
position: absolute;
|
|
left: 5.3704%;
|
|
top: 63.0705%;
|
|
width: 89.1667%;
|
|
height: auto;
|
|
overflow: visible;
|
|
}
|
|
|
|
.agency-list {
|
|
width: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
overflow: visible;
|
|
}
|
|
|
|
.agency-row {
|
|
width: 100%;
|
|
aspect-ratio: 963 / 275;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 0 24px;
|
|
border: 1px solid var(--gold-line);
|
|
border-radius: 2.9076% / 10.1818%;
|
|
background: var(--panel-brown);
|
|
box-shadow:
|
|
inset 0 0 0 1px rgba(255, 214, 109, 0.16),
|
|
0 6px 18px rgba(38, 11, 0, 0.35);
|
|
}
|
|
|
|
.agency-avatar {
|
|
width: 52px;
|
|
height: 52px;
|
|
flex: 0 0 52px;
|
|
border-radius: 50%;
|
|
border: 1px solid rgba(255, 220, 136, 0.78);
|
|
background: rgba(46, 18, 0, 0.55);
|
|
object-fit: cover;
|
|
}
|
|
|
|
.agency-main {
|
|
min-width: 0;
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
}
|
|
|
|
.agency-name {
|
|
display: block;
|
|
color: #fff3cf;
|
|
font-size: 13px;
|
|
font-weight: 700;
|
|
line-height: 1.15;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.agency-meta {
|
|
margin-top: 4px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
color: rgba(255, 238, 195, 0.74);
|
|
font-size: 10px;
|
|
line-height: 1.15;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.agency-country {
|
|
margin-top: 4px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
color: rgba(255, 238, 195, 0.78);
|
|
font-size: 10px;
|
|
line-height: 1.15;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.agency-country-flag {
|
|
width: 13px;
|
|
height: 13px;
|
|
flex: 0 0 13px;
|
|
border-radius: 50%;
|
|
border: 1px solid rgba(255, 238, 195, 0.62);
|
|
object-fit: cover;
|
|
background: rgba(46, 18, 0, 0.6);
|
|
}
|
|
|
|
.agency-country-name {
|
|
min-width: 0;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.agency-flags {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 3px;
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
.agency-flag {
|
|
width: 16px;
|
|
height: 16px;
|
|
border-radius: 50%;
|
|
border: 1px solid rgba(255, 238, 195, 0.62);
|
|
object-fit: cover;
|
|
background: rgba(46, 18, 0, 0.6);
|
|
}
|
|
|
|
.agency-actions {
|
|
flex: 0 0 78px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
justify-content: center;
|
|
gap: 5px;
|
|
}
|
|
|
|
.agency-action {
|
|
appearance: none;
|
|
width: 78px;
|
|
height: 24px;
|
|
margin: 0;
|
|
padding: 0 7px;
|
|
border: 1px solid rgba(255, 222, 126, 0.72);
|
|
border-radius: 999px;
|
|
font-size: 10px;
|
|
font-weight: 800;
|
|
line-height: 1;
|
|
letter-spacing: 0;
|
|
white-space: nowrap;
|
|
cursor: pointer;
|
|
-webkit-tap-highlight-color: transparent;
|
|
box-shadow: 0 2px 8px rgba(38, 11, 0, 0.3);
|
|
}
|
|
|
|
.agency-action:active {
|
|
transform: translateY(1px);
|
|
}
|
|
|
|
.agency-action.whatsapp {
|
|
border-color: rgba(159, 255, 185, 0.84);
|
|
background: linear-gradient(180deg, #27c66a, #168a49);
|
|
color: #ffffff;
|
|
}
|
|
|
|
.agency-action.profile {
|
|
background: linear-gradient(180deg, #fff2a8, #efb43d);
|
|
color: #552300;
|
|
}
|
|
|
|
.agency-state {
|
|
min-height: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: rgba(255, 238, 195, 0.78);
|
|
font-size: 13px;
|
|
font-weight: 650;
|
|
text-align: center;
|
|
padding: 0 18px;
|
|
aspect-ratio: 963 / 275;
|
|
border: 1px solid var(--gold-line);
|
|
border-radius: 2.9076% / 10.1818%;
|
|
background: var(--panel-brown);
|
|
}
|
|
|
|
.bottom-frame {
|
|
position: absolute;
|
|
left: 1.8056%;
|
|
top: var(--bottom-frame-top, 91%);
|
|
width: 96.1574%;
|
|
height: 2.4066%;
|
|
display: block;
|
|
max-width: none;
|
|
pointer-events: none;
|
|
user-select: none;
|
|
transform: scaleY(-1);
|
|
transform-origin: center;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<main class="page" aria-labelledby="page-title">
|
|
<div class="canvas" data-node-id="220:1781">
|
|
<h1 id="page-title" class="sr-only">Recharge Agency</h1>
|
|
|
|
<div class="hero-scene" data-node-id="220:1782">
|
|
<img class="hero-layer top-glow" src="../../assets/recharge-agency-list/top-glow.png" alt="" />
|
|
<img class="hero-layer palace" src="../../assets/recharge-agency-list/palace-hall.png" alt="" />
|
|
<img class="hero-layer figure" src="../../assets/recharge-agency-list/title-figure.png" alt="" />
|
|
</div>
|
|
|
|
<img class="title-ribbon" src="../../assets/recharge-agency-list/title-ribbon.png" alt="Recharge Agency" />
|
|
|
|
<section class="content-panel" aria-label="Recharge agency list">
|
|
<div class="agency-list" data-agency-list>
|
|
<div class="agency-state">Loading agencies...</div>
|
|
</div>
|
|
</section>
|
|
|
|
<svg class="bottom-frame" aria-hidden="true" viewBox="0 0 1038.5 58" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M0 58L9 49V28L34 8H193.5L200 17.5H840.5L845.5 8H1005.5L1031 28.5V49L1038.5 58V25.5L1010 0H840.5L834.5 11.5H204L197 0H30L0 25.5V58Z" fill="url(#bottom-frame-gradient)" />
|
|
<defs>
|
|
<linearGradient id="bottom-frame-gradient" x1="0" y1="29" x2="1038.5" y2="29" gradientUnits="userSpaceOnUse">
|
|
<stop stop-color="#FFCC5A" />
|
|
<stop offset="0.1342" stop-color="#FAE47E" />
|
|
<stop offset="0.721154" stop-color="#FAE47E" />
|
|
<stop offset="1" stop-color="#FFCC5A" />
|
|
</linearGradient>
|
|
</defs>
|
|
</svg>
|
|
</div>
|
|
</main>
|
|
<script>
|
|
(function () {
|
|
const DEFAULT_API_BASE = "https://jvapi.haiyihy.com/";
|
|
const DEFAULT_API_PREFIX = "/go";
|
|
const SELF_PROFILE_ENDPOINT = "/team/member/profile";
|
|
const COUNTRY_CONFIG_ENDPOINT = "/sys/config/country";
|
|
const SELLER_ENDPOINT = "/app/h5/recharge-agency-list/sellers";
|
|
const DEFAULT_LIST_LIMIT = "500";
|
|
const DEFAULT_AVATAR = "../../assets/defaultAvatar-CdxWBK1k.png";
|
|
const query = new URLSearchParams(window.location.search || "");
|
|
const hashQuery = new URLSearchParams((window.location.hash.split("?")[1] || "").split("#")[0]);
|
|
const listNode = document.querySelector("[data-agency-list]");
|
|
const browserLang = typeof navigator !== "undefined" ? navigator.language : "en";
|
|
const currentLang = normalizeLanguage(readParam(["lang"]) || browserLang);
|
|
let countryFlagMap = Object.create(null);
|
|
|
|
function trimValue(value) {
|
|
return String(value || "").trim();
|
|
}
|
|
|
|
function readParam(names) {
|
|
for (const name of names) {
|
|
const fromQuery = trimValue(query.get(name));
|
|
if (fromQuery) return fromQuery;
|
|
const fromHash = trimValue(hashQuery.get(name));
|
|
if (fromHash) return fromHash;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
function readRawParam(name) {
|
|
const queries = [window.location.search.replace(/^\?/, "")];
|
|
if (window.location.hash.includes("?")) {
|
|
queries.push(window.location.hash.split("?")[1].split("#")[0]);
|
|
}
|
|
|
|
for (const rawQuery of queries) {
|
|
for (const part of rawQuery.split("&")) {
|
|
if (!part) continue;
|
|
const equalIndex = part.indexOf("=");
|
|
const rawKey = equalIndex >= 0 ? part.slice(0, equalIndex) : part;
|
|
const rawValue = equalIndex >= 0 ? part.slice(equalIndex + 1) : "";
|
|
let decodedKey = "";
|
|
try {
|
|
decodedKey = decodeURIComponent(rawKey);
|
|
} catch (_) {
|
|
continue;
|
|
}
|
|
if (decodedKey !== name) continue;
|
|
try {
|
|
return decodeURIComponent(rawValue.replace(/\+/g, "%2B"));
|
|
} catch (_) {
|
|
return rawValue;
|
|
}
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
function normalizeLanguage(lang) {
|
|
const value = trimValue(lang).toLowerCase();
|
|
if (value.startsWith("ar")) return "ar";
|
|
if (value.startsWith("tr")) return "tr";
|
|
if (value.startsWith("id")) return "id";
|
|
return "en";
|
|
}
|
|
|
|
function normalizeBaseURL(base) {
|
|
const value = trimValue(base) || DEFAULT_API_BASE;
|
|
return value.endsWith("/") ? value : value + "/";
|
|
}
|
|
|
|
function resolveAPIBase() {
|
|
const override = readParam(["apiBase", "api_base"]);
|
|
if (override) return normalizeBaseURL(override);
|
|
if (typeof window.HYAPP_API_BASE_URL === "string") {
|
|
return normalizeBaseURL(window.HYAPP_API_BASE_URL);
|
|
}
|
|
if (typeof window.__RECHARGE_AGENCY_API_BASE__ === "string") {
|
|
return normalizeBaseURL(window.__RECHARGE_AGENCY_API_BASE__);
|
|
}
|
|
return normalizeBaseURL(DEFAULT_API_BASE);
|
|
}
|
|
|
|
function resolveAPIPrefix(apiBase) {
|
|
const override = readParam(["apiPrefix", "api_prefix"]);
|
|
if (override) return override;
|
|
if (typeof window.__RECHARGE_AGENCY_API_PREFIX__ === "string") {
|
|
return trimValue(window.__RECHARGE_AGENCY_API_PREFIX__);
|
|
}
|
|
try {
|
|
return new URL(apiBase).origin === new URL(DEFAULT_API_BASE).origin ? DEFAULT_API_PREFIX : "";
|
|
} catch (_) {
|
|
return "";
|
|
}
|
|
}
|
|
|
|
function resolveGoAPIBase() {
|
|
const override = readParam(["goApiBase", "goBase", "go_api_base"]);
|
|
if (override) return normalizeBaseURL(override);
|
|
if (typeof window.HYAPP_GO_API_BASE_URL === "string") {
|
|
return normalizeBaseURL(window.HYAPP_GO_API_BASE_URL);
|
|
}
|
|
if (typeof window.__RECHARGE_AGENCY_GO_API_BASE__ === "string") {
|
|
return normalizeBaseURL(window.__RECHARGE_AGENCY_GO_API_BASE__);
|
|
}
|
|
const apiBase = resolveAPIBase();
|
|
const apiPrefix = resolveAPIPrefix(apiBase);
|
|
if (!apiPrefix) return apiBase;
|
|
return normalizeBaseURL(new URL(joinPath(apiPrefix).replace(/^\/+/, ""), apiBase).toString());
|
|
}
|
|
|
|
function joinPath() {
|
|
return "/" + Array.prototype.slice.call(arguments)
|
|
.map((part) => trimValue(part).replace(/^\/+|\/+$/g, ""))
|
|
.filter(Boolean)
|
|
.join("/");
|
|
}
|
|
|
|
function buildURL(baseURL, path) {
|
|
return new URL(trimValue(path).replace(/^\/+/, ""), normalizeBaseURL(baseURL));
|
|
}
|
|
|
|
function buildSellerURL() {
|
|
const url = buildURL(resolveGoAPIBase(), SELLER_ENDPOINT);
|
|
url.searchParams.set("cursor", readParam(["cursor"]) || "1");
|
|
url.searchParams.set("limit", readParam(["limit"]) || DEFAULT_LIST_LIMIT);
|
|
return url;
|
|
}
|
|
|
|
function normalizeAuthorization(value) {
|
|
const token = trimValue(value);
|
|
if (!token) return "";
|
|
return /^bearer\s+/i.test(token) ? token : "Bearer " + token;
|
|
}
|
|
|
|
function readAuthorization() {
|
|
const direct = readRawParam("Authorization") || readRawParam("authorization");
|
|
if (direct) return normalizeAuthorization(direct);
|
|
const token = readRawParam("token") || readRawParam("accessToken") || readRawParam("access_token");
|
|
if (token) return normalizeAuthorization(token);
|
|
if (typeof window.__RECHARGE_AGENCY_AUTHORIZATION__ === "string") {
|
|
return normalizeAuthorization(window.__RECHARGE_AGENCY_AUTHORIZATION__);
|
|
}
|
|
try {
|
|
return normalizeAuthorization(
|
|
window.localStorage.getItem("Authorization") ||
|
|
window.localStorage.getItem("authorization") ||
|
|
window.localStorage.getItem("token") ||
|
|
window.localStorage.getItem("accessToken")
|
|
);
|
|
} catch (_) {
|
|
return "";
|
|
}
|
|
}
|
|
|
|
function authHeadersFromAuthorization(authorization) {
|
|
return {
|
|
Accept: "application/json",
|
|
Authorization: authorization,
|
|
"req-lang": currentLang,
|
|
"req-client": "H5",
|
|
"req-version": "V2",
|
|
"req-zone": Intl.DateTimeFormat().resolvedOptions().timeZone || "Asia/Shanghai",
|
|
"req-app-intel": "version=1.0.0;build=1;model=H5;sysVersion=Web;channel=Web",
|
|
"req-sys-origin": "origin=ATYOU;originChild=ATYOU"
|
|
};
|
|
}
|
|
|
|
function clearList() {
|
|
while (listNode.firstChild) listNode.removeChild(listNode.firstChild);
|
|
}
|
|
|
|
function syncListLayout(count) {
|
|
const safeCount = Math.max(1, Number(count) || 1);
|
|
const listTop = 63.0705;
|
|
const cardHeight = 11.4108;
|
|
const cardGap = 1.16;
|
|
const bottomGap = 3.95;
|
|
const listHeight = safeCount * cardHeight + Math.max(0, safeCount - 1) * cardGap;
|
|
const bottomTop = Math.max(91, listTop + listHeight + bottomGap);
|
|
document.documentElement.style.setProperty("--bottom-frame-top", bottomTop.toFixed(4) + "%");
|
|
}
|
|
|
|
function renderState(message) {
|
|
syncListLayout(1);
|
|
clearList();
|
|
const node = document.createElement("div");
|
|
node.className = "agency-state";
|
|
node.textContent = message;
|
|
listNode.appendChild(node);
|
|
}
|
|
|
|
function compactNumber(value) {
|
|
const number = Number(value || 0);
|
|
if (!Number.isFinite(number) || number <= 0) return "";
|
|
if (number >= 1000000) return (number / 1000000).toFixed(1).replace(/\.0$/, "") + "M";
|
|
if (number >= 1000) return (number / 1000).toFixed(1).replace(/\.0$/, "") + "K";
|
|
return String(Math.trunc(number));
|
|
}
|
|
|
|
function createImage(className, src, fallback) {
|
|
const img = document.createElement("img");
|
|
img.className = className;
|
|
img.alt = "";
|
|
img.decoding = "async";
|
|
img.loading = "lazy";
|
|
img.src = trimValue(src) || fallback || "";
|
|
img.onerror = function () {
|
|
if (fallback && img.src.indexOf(fallback) === -1) {
|
|
img.src = fallback;
|
|
}
|
|
};
|
|
return img;
|
|
}
|
|
|
|
function isInAppWebView() {
|
|
return !!(
|
|
window.FlutterPageControl &&
|
|
typeof window.FlutterPageControl.postMessage === "function"
|
|
);
|
|
}
|
|
|
|
function sendToApp(message) {
|
|
if (!isInAppWebView()) {
|
|
console.warn("[AppBridge] FlutterPageControl is not available", message);
|
|
return false;
|
|
}
|
|
window.FlutterPageControl.postMessage(String(message));
|
|
return true;
|
|
}
|
|
|
|
function openUserProfile(uid) {
|
|
const safeUID = trimValue(uid).replace(/:/g, "");
|
|
if (!safeUID) return false;
|
|
return sendToApp("view_user_info:" + safeUID);
|
|
}
|
|
|
|
function normalizeWhatsapp(value) {
|
|
const raw = trimValue(value);
|
|
if (!raw) return "";
|
|
const linkMatch = raw.match(/(?:wa\.me\/|phone=)(\+?\d[\d\s().-]*)/i);
|
|
const phoneSource = linkMatch ? linkMatch[1] : ((raw.match(/\+?\d[\d\s().-]{5,}\d/) || [raw])[0]);
|
|
const digits = phoneSource.replace(/\D/g, "");
|
|
return digits.length >= 6 ? digits : "";
|
|
}
|
|
|
|
function buildWhatsappURL(value) {
|
|
const raw = trimValue(value);
|
|
if (/^https?:\/\/(?:wa\.me|api\.whatsapp\.com|www\.whatsapp\.com)\//i.test(raw)) {
|
|
return raw;
|
|
}
|
|
const phone = normalizeWhatsapp(raw);
|
|
return phone ? "https://wa.me/" + encodeURIComponent(phone) : "";
|
|
}
|
|
|
|
function openWhatsapp(value) {
|
|
const url = buildWhatsappURL(value);
|
|
if (!url) return false;
|
|
let opened = null;
|
|
if (typeof window.open === "function") {
|
|
opened = window.open(url, "_blank", "noopener");
|
|
}
|
|
if (!opened) {
|
|
window.location.href = url;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function createRow(item) {
|
|
item = normalizeSeller(item);
|
|
const row = document.createElement("article");
|
|
row.className = "agency-row";
|
|
row.dataset.userId = trimValue(item.userId);
|
|
|
|
row.appendChild(createImage("agency-avatar", item.userAvatar, DEFAULT_AVATAR));
|
|
|
|
const main = document.createElement("div");
|
|
main.className = "agency-main";
|
|
|
|
const name = document.createElement("span");
|
|
name.className = "agency-name";
|
|
name.textContent = item.userNickname || item.account || ("ID " + item.userId);
|
|
main.appendChild(name);
|
|
|
|
const meta = document.createElement("div");
|
|
meta.className = "agency-meta";
|
|
const count = compactNumber(item.transactionCount);
|
|
const metaParts = [];
|
|
metaParts.push("ID " + (item.account || item.userId));
|
|
if (count) metaParts.push(count + " orders");
|
|
meta.textContent = metaParts.join(" · ");
|
|
main.appendChild(meta);
|
|
|
|
if (item.countryName || item.countryFlag) {
|
|
const country = document.createElement("div");
|
|
country.className = "agency-country";
|
|
if (item.countryFlag) {
|
|
country.appendChild(createImage("agency-country-flag", item.countryFlag, ""));
|
|
}
|
|
const countryName = document.createElement("span");
|
|
countryName.className = "agency-country-name";
|
|
countryName.textContent = item.countryName || "";
|
|
country.appendChild(countryName);
|
|
main.appendChild(country);
|
|
}
|
|
row.appendChild(main);
|
|
|
|
const flags = document.createElement("div");
|
|
flags.className = "agency-flags";
|
|
const flagValues = (Array.isArray(item.nationalFlag) ? item.nationalFlag : []).slice(0, 3).filter(Boolean);
|
|
flagValues.forEach(function (flag) {
|
|
flags.appendChild(createImage("agency-flag", flag, ""));
|
|
});
|
|
if (flagValues.length) row.appendChild(flags);
|
|
|
|
const actions = document.createElement("div");
|
|
actions.className = "agency-actions";
|
|
const whatsapp = item.whatsapp || item.whatsApp || item.contactInfo;
|
|
if (normalizeWhatsapp(whatsapp)) {
|
|
const whatsappButton = document.createElement("button");
|
|
whatsappButton.type = "button";
|
|
whatsappButton.className = "agency-action whatsapp";
|
|
whatsappButton.textContent = "WhatsApp";
|
|
whatsappButton.setAttribute("aria-label", "Open WhatsApp");
|
|
whatsappButton.addEventListener("click", function (event) {
|
|
event.stopPropagation();
|
|
openWhatsapp(whatsapp);
|
|
});
|
|
actions.appendChild(whatsappButton);
|
|
}
|
|
|
|
const profileButton = document.createElement("button");
|
|
profileButton.type = "button";
|
|
profileButton.className = "agency-action profile";
|
|
profileButton.textContent = "Profile";
|
|
profileButton.setAttribute("aria-label", "Open user profile");
|
|
profileButton.addEventListener("click", function (event) {
|
|
event.stopPropagation();
|
|
openUserProfile(item.userId);
|
|
});
|
|
actions.appendChild(profileButton);
|
|
row.appendChild(actions);
|
|
|
|
return row;
|
|
}
|
|
|
|
function firstNonBlank() {
|
|
for (let index = 0; index < arguments.length; index += 1) {
|
|
const value = trimValue(arguments[index]);
|
|
if (value) return value;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
function normalizeFlagList(value) {
|
|
if (Array.isArray(value)) return value.map(trimValue).filter(Boolean);
|
|
const raw = trimValue(value);
|
|
return raw ? raw.split(",").map(trimValue).filter(Boolean) : [];
|
|
}
|
|
|
|
function normalizeLookupKey(value) {
|
|
return trimValue(value).toLowerCase().replace(/\s+/g, " ");
|
|
}
|
|
|
|
function addCountryFlag(map, key, flag) {
|
|
const normalizedKey = normalizeLookupKey(key);
|
|
const flagURL = trimValue(flag);
|
|
if (normalizedKey && flagURL && !map[normalizedKey]) {
|
|
map[normalizedKey] = flagURL;
|
|
}
|
|
}
|
|
|
|
function splitCountryRegion(countryName, regionCode) {
|
|
const country = trimValue(countryName);
|
|
const region = trimValue(regionCode);
|
|
if (!country) {
|
|
return { countryName: country, regionCode: region };
|
|
}
|
|
const parts = country.split(/\s+[-\u2013\u2014]\s+/).map(trimValue).filter(Boolean);
|
|
if (parts.length <= 1) {
|
|
return { countryName: country, regionCode: region };
|
|
}
|
|
return {
|
|
countryName: parts[0],
|
|
regionCode: parts.slice(1).join(" - ")
|
|
};
|
|
}
|
|
|
|
function buildCountryFlagMap(json) {
|
|
const body = json && (json.body || json.data || json);
|
|
const countries = [];
|
|
const pushCountries = function (value) {
|
|
if (Array.isArray(value)) {
|
|
value.forEach(function (country) { countries.push(country); });
|
|
}
|
|
};
|
|
pushCountries(body);
|
|
if (body && typeof body === "object") {
|
|
pushCountries(body.openCountry);
|
|
pushCountries(body.tops);
|
|
pushCountries(body.countries);
|
|
pushCountries(body.records);
|
|
pushCountries(body.list);
|
|
}
|
|
|
|
const map = Object.create(null);
|
|
countries.forEach(function (country) {
|
|
if (!country || typeof country !== "object") return;
|
|
const flag = firstNonBlank(country.nationalFlag, country.countryFlag, country.flag);
|
|
addCountryFlag(map, country.countryName, flag);
|
|
addCountryFlag(map, country.aliasName, flag);
|
|
addCountryFlag(map, country.enName, flag);
|
|
addCountryFlag(map, country.alphaTwo, flag);
|
|
addCountryFlag(map, country.alphaThree, flag);
|
|
addCountryFlag(map, country.countryCode, flag);
|
|
if (Array.isArray(country.countryCodeAliases)) {
|
|
country.countryCodeAliases.forEach(function (alias) {
|
|
addCountryFlag(map, alias, flag);
|
|
});
|
|
}
|
|
});
|
|
return map;
|
|
}
|
|
|
|
function findCountryFlag() {
|
|
for (let index = 0; index < arguments.length; index += 1) {
|
|
const key = normalizeLookupKey(arguments[index]);
|
|
if (key && countryFlagMap[key]) return countryFlagMap[key];
|
|
}
|
|
return "";
|
|
}
|
|
|
|
function normalizeSeller(item) {
|
|
const source = item || {};
|
|
const userBaseInfo = source.userBaseInfo || {};
|
|
const rawCountryName = firstNonBlank(source.countryName, userBaseInfo.countryName);
|
|
const countryRegion = splitCountryRegion(
|
|
rawCountryName,
|
|
firstNonBlank(source.regionCode, userBaseInfo.regionCode)
|
|
);
|
|
const countryCode = firstNonBlank(source.countryCode, userBaseInfo.countryCode);
|
|
const nationalFlag = normalizeFlagList(source.nationalFlag || source.nationalFlags);
|
|
const explicitCountryFlag = firstNonBlank(source.ownNationalFlag, source.countryFlag);
|
|
return {
|
|
id: firstNonBlank(source.id, userBaseInfo.id),
|
|
sysOrigin: firstNonBlank(source.sysOrigin, userBaseInfo.originSys),
|
|
userId: firstNonBlank(source.userId, source.uid, userBaseInfo.id),
|
|
account: firstNonBlank(
|
|
source.account,
|
|
userBaseInfo.ownSpecialId && userBaseInfo.ownSpecialId.account,
|
|
userBaseInfo.account
|
|
),
|
|
userAvatar: firstNonBlank(source.userAvatar, userBaseInfo.userAvatar),
|
|
userNickname: firstNonBlank(source.userNickname, userBaseInfo.userNickname, userBaseInfo.account),
|
|
countryCode: countryCode,
|
|
countryName: countryRegion.countryName,
|
|
regionCode: countryRegion.regionCode,
|
|
contactInfo: firstNonBlank(source.contactInfo, source.contact, source.phone),
|
|
whatsapp: firstNonBlank(source.whatsapp, source.whatsApp, source.contactInfo, source.contact, source.phone),
|
|
nationalFlag: nationalFlag,
|
|
ownNationalFlag: firstNonBlank(source.ownNationalFlag),
|
|
countryFlag: firstNonBlank(
|
|
explicitCountryFlag,
|
|
findCountryFlag(countryRegion.countryName, rawCountryName, countryCode),
|
|
nationalFlag[0]
|
|
),
|
|
transactionCount: source.transactionCount
|
|
};
|
|
}
|
|
|
|
function normalizePayload(json) {
|
|
const body = json && (json.body || json.data || json);
|
|
if (Array.isArray(body)) return body;
|
|
if (body && Array.isArray(body.records)) return body.records;
|
|
if (body && Array.isArray(body.list)) return body.list;
|
|
if (body && Array.isArray(body.items)) return body.items;
|
|
return [];
|
|
}
|
|
|
|
async function requestJSON(url, authorization) {
|
|
const response = await fetch(url.toString(), {
|
|
cache: "no-store",
|
|
headers: authHeadersFromAuthorization(authorization),
|
|
});
|
|
const json = await response.json().catch(function () { return {}; });
|
|
if (!response.ok || json.status === false) {
|
|
throw new Error(json.errorMsg || json.message || "Unable to load agencies.");
|
|
}
|
|
return json;
|
|
}
|
|
|
|
async function fetchSelfProfile(authorization) {
|
|
const json = await requestJSON(buildURL(resolveAPIBase(), SELF_PROFILE_ENDPOINT), authorization);
|
|
return json && (json.body || json.data || json);
|
|
}
|
|
|
|
async function fetchCountryConfig(authorization) {
|
|
try {
|
|
const json = await requestJSON(buildURL(resolveAPIBase(), COUNTRY_CONFIG_ENDPOINT), authorization);
|
|
countryFlagMap = buildCountryFlagMap(json);
|
|
} catch (_) {
|
|
countryFlagMap = Object.create(null);
|
|
}
|
|
}
|
|
|
|
async function fetchSellerList(authorization) {
|
|
const json = await requestJSON(buildSellerURL(), authorization);
|
|
return normalizePayload(json);
|
|
}
|
|
|
|
async function fetchAgencies() {
|
|
if (!listNode) return;
|
|
const authorization = readAuthorization();
|
|
if (!authorization) {
|
|
renderState("Open in app to view agencies.");
|
|
return;
|
|
}
|
|
try {
|
|
await fetchSelfProfile(authorization);
|
|
await fetchCountryConfig(authorization);
|
|
const records = await fetchSellerList(authorization);
|
|
if (!records.length) {
|
|
renderState("No agencies available.");
|
|
return;
|
|
}
|
|
syncListLayout(records.length);
|
|
clearList();
|
|
records.forEach(function (item) {
|
|
listNode.appendChild(createRow(item || {}));
|
|
});
|
|
} catch (error) {
|
|
renderState(error && error.message ? error.message : "Unable to load agencies.");
|
|
}
|
|
}
|
|
|
|
fetchAgencies();
|
|
})();
|
|
</script>
|
|
</body>
|
|
|
|
</html>
|