@oasisomniverse/js 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +36 -0
- package/src/add-data.js +54 -0
- package/src/avatar-connect.js +126 -0
- package/src/avatar-wallet.js +60 -0
- package/src/coming-soon.js +35 -0
- package/src/confirmation.js +53 -0
- package/src/contact.js +84 -0
- package/src/cross-chain-management.js +36 -0
- package/src/edit-avatar.js +79 -0
- package/src/eggs.js +88 -0
- package/src/forgot-password.js +73 -0
- package/src/index.esm.js +15 -0
- package/src/index.js +15 -0
- package/src/karma-toast.js +50 -0
- package/src/load-data.js +56 -0
- package/src/login.js +154 -0
- package/src/manage-data.js +42 -0
- package/src/manage-eggs.js +41 -0
- package/src/manage-mission.js +42 -0
- package/src/manage-oasis-nft.js +41 -0
- package/src/message.js +57 -0
- package/src/navbar.js +80 -0
- package/src/oasis-modal.js +79 -0
- package/src/off-chain-management.js +36 -0
- package/src/provider-dropdown.js +87 -0
- package/src/purchase-oasis-nft.js +54 -0
- package/src/purchase-oasis-virtual-land-nft.js +54 -0
- package/src/reset-password.js +75 -0
- package/src/search-avatar.js +78 -0
- package/src/search-data.js +59 -0
- package/src/search-eggs.js +49 -0
- package/src/search-karma.js +48 -0
- package/src/search-mission.js +50 -0
- package/src/search-oasis-nft.js +49 -0
- package/src/search-profiles.js +50 -0
- package/src/seeds.js +83 -0
- package/src/signup.js +154 -0
- package/src/star-field.js +68 -0
- package/src/verify-email.js +77 -0
- package/src/view-achievements.js +42 -0
- package/src/view-avatar-karma.js +50 -0
- package/src/view-avatar.js +69 -0
- package/src/view-eggs.js +44 -0
- package/src/view-karma.js +41 -0
- package/src/view-leagues.js +41 -0
- package/src/view-mission.js +44 -0
- package/src/view-oasis-nft.js +46 -0
- package/src/view-tournaments.js +41 -0
- package/src/vote-karma.js +61 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OasisSearchAvatar — search avatars popup widget
|
|
3
|
+
* Usage: const w = new OasisSearchAvatar({ onSelect: (avatar) => {} }); w.open();
|
|
4
|
+
*/
|
|
5
|
+
class OasisSearchAvatar {
|
|
6
|
+
constructor({ container, apiUrl = 'https://api.web4.oasisomniverse.one', onSelect = null, onClose = null } = {}) {
|
|
7
|
+
this._apiUrl = apiUrl; this._onSelect = onSelect; this._onClose = onClose; this._overlay = null;
|
|
8
|
+
this._injectStyles();
|
|
9
|
+
if (container) this._render(container);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
_injectStyles() {
|
|
13
|
+
if (document.getElementById('oasis-popup-styles')) return;
|
|
14
|
+
const s = document.createElement('style'); s.id = 'oasis-popup-styles';
|
|
15
|
+
s.textContent = `.oasis-popup-overlay{position:fixed;inset:0;z-index:9000;background:rgba(0,0,0,.65);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .25s}.oasis-popup-overlay.is-open{opacity:1}.oasis-popup-modal{background:#0a1628;border:1px solid rgba(0,200,255,.2);border-radius:16px;box-shadow:0 24px 64px rgba(0,0,0,.6);width:90%;max-width:560px;max-height:90vh;overflow-y:auto;transform:translateY(16px);transition:transform .25s}.oasis-popup-overlay.is-open .oasis-popup-modal{transform:none}.oasis-popup-modal.lg{max-width:900px}.oasis-popup-header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-popup-title{font-family:'Orbitron',sans-serif;font-size:14px;font-weight:700;color:#00c8ff;letter-spacing:.08em}.oasis-popup-close{background:none;border:none;color:#7a9bbf;font-size:22px;cursor:pointer;padding:0;line-height:1}.oasis-popup-close:hover{color:#fff}.oasis-popup-body{padding:24px}.oasis-field{display:flex;flex-direction:column;gap:6px;margin-bottom:16px}.oasis-label{font-size:11px;font-weight:600;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase}.oasis-input,.oasis-select,.oasis-textarea{background:rgba(255,255,255,.05);border:1px solid rgba(0,200,255,.2);border-radius:8px;padding:10px 14px;color:#fff;font-size:14px;outline:none;transition:border-color .2s;width:100%;box-sizing:border-box}.oasis-input:focus,.oasis-select:focus,.oasis-textarea:focus{border-color:rgba(0,200,255,.5)}.oasis-textarea{resize:vertical;min-height:80px}.oasis-select option{background:#0a1628}.oasis-btn{background:linear-gradient(135deg,#00c8ff,#0080ff);border:none;border-radius:8px;color:#fff;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:11px 20px;cursor:pointer;transition:opacity .2s}.oasis-btn:hover{opacity:.85}.oasis-btn:disabled{opacity:.5;cursor:not-allowed}.oasis-btn-ghost{background:rgba(0,200,255,.1);border:1px solid rgba(0,200,255,.3);color:#00c8ff;border-radius:8px;font-size:12px;font-weight:600;padding:9px 16px;cursor:pointer}.oasis-btn-row{display:flex;gap:10px;justify-content:flex-end;margin-top:20px}.oasis-msg{border-radius:8px;padding:10px 14px;font-size:13px;margin-bottom:16px}.oasis-msg-error{background:rgba(255,80,80,.12);border:1px solid rgba(255,80,80,.3);color:#ff6b6b}.oasis-msg-success{background:rgba(0,200,100,.12);border:1px solid rgba(0,200,100,.3);color:#00c864}.oasis-grid-2{display:grid;grid-template-columns:1fr 1fr;gap:16px}.oasis-info-block{background:rgba(0,200,255,.05);border:1px solid rgba(0,200,255,.1);border-radius:10px;padding:16px;margin-bottom:12px}.oasis-info-label{font-size:10px;font-weight:600;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase;margin-bottom:4px}.oasis-info-value{color:#fff;font-size:14px;font-weight:500}.oasis-cs{text-align:center;padding:32px 16px}.oasis-cs-icon{font-size:48px;margin-bottom:12px}.oasis-cs h3{font-family:'Orbitron',sans-serif;font-size:15px;color:#00c8ff;margin:0 0 8px}.oasis-cs p{color:#7a9bbf;font-size:13px;margin:0}.oasis-table{width:100%;border-collapse:collapse;font-size:13px}.oasis-table th{text-align:left;padding:10px 12px;font-size:10px;font-weight:700;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-table td{padding:10px 12px;color:#fff;border-bottom:1px solid rgba(255,255,255,.05)}.oasis-table tr:hover td{background:rgba(0,200,255,.04)}.oasis-badge{display:inline-block;padding:3px 8px;border-radius:999px;font-size:10px;font-weight:700}.oasis-badge-blue{background:rgba(0,200,255,.15);color:#00c8ff}.oasis-badge-green{background:rgba(0,200,100,.15);color:#00c864}.oasis-badge-red{background:rgba(255,80,80,.15);color:#ff6b6b}.oasis-badge-yellow{background:rgba(255,200,0,.15);color:#ffc800}.oasis-search-row{display:flex;gap:10px;margin-bottom:16px}.oasis-search-row .oasis-input{flex:1}.oasis-stat-row{display:flex;gap:12px;margin-bottom:20px}.oasis-stat{flex:1;background:rgba(0,200,255,.05);border:1px solid rgba(0,200,255,.1);border-radius:10px;padding:14px;text-align:center}.oasis-stat-val{font-family:'Orbitron',sans-serif;font-size:20px;font-weight:700;color:#00c8ff}.oasis-stat-lbl{font-size:10px;color:#7a9bbf;margin-top:4px}.oasis-divider{border:none;border-top:1px solid rgba(0,200,255,.1);margin:16px 0}.oasis-section-title{font-size:11px;font-weight:700;color:#7a9bbf;letter-spacing:.08em;text-transform:uppercase;margin:0 0 12px}.oasis-radio-group{display:flex;gap:16px;margin-bottom:16px}.oasis-radio-label{display:flex;align-items:center;gap:8px;font-size:13px;color:#fff;cursor:pointer}.oasis-radio-label input[type=radio]{accent-color:#00c8ff}.oasis-link{background:none;border:none;color:#00c8ff;font-size:13px;cursor:pointer;padding:0;text-decoration:underline}.oasis-chat-area{background:rgba(0,0,0,.2);border:1px solid rgba(0,200,255,.1);border-radius:10px;height:220px;overflow-y:auto;padding:12px;margin-bottom:12px;display:flex;flex-direction:column;gap:8px}.oasis-chat-bubble{background:rgba(0,200,255,.1);border-radius:10px;padding:8px 12px;font-size:13px;color:#fff;max-width:75%}.oasis-chat-bubble.mine{background:rgba(0,128,255,.2);align-self:flex-end}.oasis-chat-input-row{display:flex;gap:8px}.oasis-chat-input-row .oasis-input{flex:1}`;
|
|
16
|
+
document.head.appendChild(s);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
open() {
|
|
20
|
+
if (this._overlay) return;
|
|
21
|
+
this._overlay = document.createElement('div');
|
|
22
|
+
this._overlay.className = 'oasis-popup-overlay';
|
|
23
|
+
this._overlay.innerHTML = `<div class="oasis-popup-modal">
|
|
24
|
+
<div class="oasis-popup-header"><span class="oasis-popup-title">Search Avatars</span><button class="oasis-popup-close">×</button></div>
|
|
25
|
+
<div class="oasis-popup-body">${this._buildBody()}</div>
|
|
26
|
+
</div>`;
|
|
27
|
+
this._overlay.querySelector('.oasis-popup-close').addEventListener('click', () => this.close());
|
|
28
|
+
this._overlay.addEventListener('click', e => { if (e.target === this._overlay) this.close(); });
|
|
29
|
+
document.body.appendChild(this._overlay);
|
|
30
|
+
requestAnimationFrame(() => this._overlay.classList.add('is-open'));
|
|
31
|
+
const btn = this._overlay.querySelector('#oasis-sa-btn');
|
|
32
|
+
const inp = this._overlay.querySelector('#oasis-sa-q');
|
|
33
|
+
btn.addEventListener('click', () => this._doSearch());
|
|
34
|
+
inp.addEventListener('keydown', e => { if (e.key === 'Enter') this._doSearch(); });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
_buildBody() {
|
|
38
|
+
return `
|
|
39
|
+
<div class="oasis-search-row">
|
|
40
|
+
<input class="oasis-input" id="oasis-sa-q" type="text" placeholder="Search by username or name…" />
|
|
41
|
+
<button class="oasis-btn" id="oasis-sa-btn" style="white-space:nowrap">Search</button>
|
|
42
|
+
</div>
|
|
43
|
+
<div id="oasis-sa-results"><p style="color:#7a9bbf;font-size:13px;text-align:center;margin:24px 0">Enter a name or username to search avatars.</p></div>
|
|
44
|
+
`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async _doSearch() {
|
|
48
|
+
const q = this._overlay.querySelector('#oasis-sa-q').value.trim();
|
|
49
|
+
const res = this._overlay.querySelector('#oasis-sa-results');
|
|
50
|
+
const btn = this._overlay.querySelector('#oasis-sa-btn');
|
|
51
|
+
if (!q) return;
|
|
52
|
+
btn.textContent = '…'; btn.disabled = true;
|
|
53
|
+
try {
|
|
54
|
+
const r = await fetch(`${this._apiUrl}/api/avatar/search?username=${encodeURIComponent(q)}`);
|
|
55
|
+
const data = await r.json();
|
|
56
|
+
const avatars = Array.isArray(data) ? data : (data.result || []);
|
|
57
|
+
if (!avatars.length) { res.innerHTML = '<p style="color:#7a9bbf;font-size:13px;text-align:center;margin:24px 0">No avatars found.</p>'; }
|
|
58
|
+
else {
|
|
59
|
+
res.innerHTML = `<table class="oasis-table"><thead><tr><th>Username</th><th>Name</th><th>Karma</th><th></th></tr></thead><tbody>${avatars.map(a => `<tr><td>${a.username || '—'}</td><td>${a.firstName || ''} ${a.lastName || ''}</td><td>${a.karma ?? 0}</td><td><button class="oasis-badge oasis-badge-blue" data-id="${a.id}">Select</button></td></tr>`).join('')}</tbody></table>`;
|
|
60
|
+
res.querySelectorAll('[data-id]').forEach(b => b.addEventListener('click', () => { if (this._onSelect) this._onSelect(avatars.find(a => a.id === b.dataset.id)); this.close(); }));
|
|
61
|
+
}
|
|
62
|
+
} catch { res.innerHTML = '<p style="color:#ff6b6b;font-size:13px;text-align:center;margin:24px 0">Search failed. Please try again.</p>'; }
|
|
63
|
+
btn.textContent = 'Search'; btn.disabled = false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
close() {
|
|
67
|
+
if (!this._overlay) return;
|
|
68
|
+
const el = this._overlay; this._overlay = null;
|
|
69
|
+
el.classList.remove('is-open');
|
|
70
|
+
el.addEventListener('transitionend', () => el.remove(), { once: true });
|
|
71
|
+
if (this._onClose) this._onClose();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
_render(container) { container.innerHTML = `<div class="oasis-popup-body">${this._buildBody()}</div>`; }
|
|
75
|
+
destroy() { this.close(); }
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
window.OasisSearchAvatar = OasisSearchAvatar;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OasisSearchData — search OASIS data store popup widget
|
|
3
|
+
* Usage: const w = new OasisSearchData({ onSelect: (item) => {} }); w.open();
|
|
4
|
+
*/
|
|
5
|
+
class OasisSearchData {
|
|
6
|
+
constructor({ container, apiUrl = 'https://api.web4.oasisomniverse.one', onSelect = null, onClose = null } = {}) {
|
|
7
|
+
this._apiUrl = apiUrl; this._onSelect = onSelect; this._onClose = onClose; this._overlay = null;
|
|
8
|
+
this._injectStyles(); if (container) this._render(container);
|
|
9
|
+
}
|
|
10
|
+
_injectStyles() {
|
|
11
|
+
if (document.getElementById('oasis-popup-styles')) return;
|
|
12
|
+
const s = document.createElement('style'); s.id = 'oasis-popup-styles';
|
|
13
|
+
s.textContent = `.oasis-popup-overlay{position:fixed;inset:0;z-index:9000;background:rgba(0,0,0,.65);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .25s}.oasis-popup-overlay.is-open{opacity:1}.oasis-popup-modal{background:#0a1628;border:1px solid rgba(0,200,255,.2);border-radius:16px;box-shadow:0 24px 64px rgba(0,0,0,.6);width:90%;max-width:700px;max-height:90vh;overflow-y:auto;transform:translateY(16px);transition:transform .25s}.oasis-popup-overlay.is-open .oasis-popup-modal{transform:none}.oasis-popup-header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-popup-title{font-family:'Orbitron',sans-serif;font-size:14px;font-weight:700;color:#00c8ff;letter-spacing:.08em}.oasis-popup-close{background:none;border:none;color:#7a9bbf;font-size:22px;cursor:pointer;padding:0;line-height:1}.oasis-popup-close:hover{color:#fff}.oasis-popup-body{padding:24px}.oasis-field{display:flex;flex-direction:column;gap:6px;margin-bottom:16px}.oasis-label{font-size:11px;font-weight:600;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase}.oasis-input,.oasis-select,.oasis-textarea{background:rgba(255,255,255,.05);border:1px solid rgba(0,200,255,.2);border-radius:8px;padding:10px 14px;color:#fff;font-size:14px;outline:none;transition:border-color .2s;width:100%;box-sizing:border-box}.oasis-input:focus,.oasis-select:focus{border-color:rgba(0,200,255,.5)}.oasis-select option{background:#0a1628}.oasis-btn{background:linear-gradient(135deg,#00c8ff,#0080ff);border:none;border-radius:8px;color:#fff;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:11px 20px;cursor:pointer;transition:opacity .2s}.oasis-btn:hover{opacity:.85}.oasis-btn:disabled{opacity:.5;cursor:not-allowed}.oasis-msg{border-radius:8px;padding:10px 14px;font-size:13px;margin-bottom:16px}.oasis-msg-error{background:rgba(255,80,80,.12);border:1px solid rgba(255,80,80,.3);color:#ff6b6b}.oasis-table{width:100%;border-collapse:collapse;font-size:13px}.oasis-table th{text-align:left;padding:10px 12px;font-size:10px;font-weight:700;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-table td{padding:10px 12px;color:#fff;border-bottom:1px solid rgba(255,255,255,.05)}.oasis-table tr:hover td{background:rgba(0,200,255,.04)}.oasis-badge{display:inline-block;padding:3px 8px;border-radius:999px;font-size:10px;font-weight:700}.oasis-badge-blue{background:rgba(0,200,255,.15);color:#00c8ff}.oasis-badge-green{background:rgba(0,200,100,.15);color:#00c864}.oasis-search-row{display:flex;gap:10px;margin-bottom:16px}.oasis-search-row .oasis-input{flex:1}.oasis-cs{text-align:center;padding:32px 16px}.oasis-cs-icon{font-size:48px;margin-bottom:12px}.oasis-cs h3{font-family:'Orbitron',sans-serif;font-size:15px;color:#00c8ff;margin:0 0 8px}.oasis-cs p{color:#7a9bbf;font-size:13px;margin:0}`;
|
|
14
|
+
document.head.appendChild(s);
|
|
15
|
+
}
|
|
16
|
+
open() {
|
|
17
|
+
if (this._overlay) return;
|
|
18
|
+
this._overlay = document.createElement('div');
|
|
19
|
+
this._overlay.className = 'oasis-popup-overlay';
|
|
20
|
+
this._overlay.innerHTML = `<div class="oasis-popup-modal"><div class="oasis-popup-header"><span class="oasis-popup-title">Search Data</span><button class="oasis-popup-close">×</button></div><div class="oasis-popup-body">${this._buildBody()}</div></div>`;
|
|
21
|
+
this._overlay.querySelector('.oasis-popup-close').addEventListener('click', () => this.close());
|
|
22
|
+
this._overlay.addEventListener('click', e => { if (e.target === this._overlay) this.close(); });
|
|
23
|
+
document.body.appendChild(this._overlay);
|
|
24
|
+
requestAnimationFrame(() => this._overlay.classList.add('is-open'));
|
|
25
|
+
const btn = this._overlay.querySelector('#oasis-sd-btn');
|
|
26
|
+
btn.addEventListener('click', () => this._doSearch());
|
|
27
|
+
this._overlay.querySelector('#oasis-sd-q').addEventListener('keydown', e => { if (e.key === 'Enter') this._doSearch(); });
|
|
28
|
+
}
|
|
29
|
+
_buildBody() {
|
|
30
|
+
return `<div class="oasis-search-row">
|
|
31
|
+
<input class="oasis-input" id="oasis-sd-q" type="text" placeholder="Search by key or value…" />
|
|
32
|
+
<select class="oasis-select" id="oasis-sd-prov" style="width:auto;flex-shrink:0"><option value="">All Providers</option><option value="holochain">Holochain</option><option value="ethereum">Ethereum</option><option value="ipfs">IPFS</option><option value="mongodb">MongoDB</option></select>
|
|
33
|
+
<button class="oasis-btn" id="oasis-sd-btn" style="white-space:nowrap">Search</button>
|
|
34
|
+
</div>
|
|
35
|
+
<div id="oasis-sd-results"><p style="color:#7a9bbf;font-size:13px;text-align:center;margin:24px 0">Enter a query to search the OASIS data store.</p></div>`;
|
|
36
|
+
}
|
|
37
|
+
async _doSearch() {
|
|
38
|
+
const q = this._overlay.querySelector('#oasis-sd-q').value.trim();
|
|
39
|
+
const prov = this._overlay.querySelector('#oasis-sd-prov').value;
|
|
40
|
+
const res = this._overlay.querySelector('#oasis-sd-results');
|
|
41
|
+
const btn = this._overlay.querySelector('#oasis-sd-btn');
|
|
42
|
+
if (!q) return;
|
|
43
|
+
btn.textContent = '…'; btn.disabled = true;
|
|
44
|
+
try {
|
|
45
|
+
const url = `${this._apiUrl}/api/data/search?query=${encodeURIComponent(q)}${prov ? '&provider=' + prov : ''}`;
|
|
46
|
+
const r = await fetch(url);
|
|
47
|
+
const data = await r.json();
|
|
48
|
+
const items = Array.isArray(data) ? data : (data.result || []);
|
|
49
|
+
if (!items.length) res.innerHTML = '<p style="color:#7a9bbf;font-size:13px;text-align:center;margin:24px 0">No results found.</p>';
|
|
50
|
+
else res.innerHTML = `<table class="oasis-table"><thead><tr><th>Key</th><th>Provider</th><th>Modified</th><th></th></tr></thead><tbody>${items.map(i => `<tr><td>${i.key || '—'}</td><td><span class="oasis-badge oasis-badge-blue">${i.provider || '—'}</span></td><td>${i.modifiedDate ? new Date(i.modifiedDate).toLocaleDateString() : '—'}</td><td><button class="oasis-badge oasis-badge-green" data-idx="${items.indexOf(i)}">Select</button></td></tr>`).join('')}</tbody></table>`;
|
|
51
|
+
res.querySelectorAll('[data-idx]').forEach(b => b.addEventListener('click', () => { if (this._onSelect) this._onSelect(items[+b.dataset.idx]); this.close(); }));
|
|
52
|
+
} catch { res.innerHTML = '<div class="oasis-msg oasis-msg-error">Search failed.</div>'; }
|
|
53
|
+
btn.textContent = 'Search'; btn.disabled = false;
|
|
54
|
+
}
|
|
55
|
+
close() { if (!this._overlay) return; const el = this._overlay; this._overlay = null; el.classList.remove('is-open'); el.addEventListener('transitionend', () => el.remove(), { once: true }); if (this._onClose) this._onClose(); }
|
|
56
|
+
_render(c) { c.innerHTML = `<div class="oasis-popup-body">${this._buildBody()}</div>`; }
|
|
57
|
+
destroy() { this.close(); }
|
|
58
|
+
}
|
|
59
|
+
window.OasisSearchData = OasisSearchData;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OasisSearchEggs — search OASIS Eggs popup widget
|
|
3
|
+
* Usage: const w = new OasisSearchEggs({ onSelect: (egg) => {} }); w.open();
|
|
4
|
+
*/
|
|
5
|
+
class OasisSearchEggs {
|
|
6
|
+
constructor({ container, apiUrl = 'https://api.web4.oasisomniverse.one', onSelect = null, onClose = null } = {}) {
|
|
7
|
+
this._apiUrl = apiUrl; this._onSelect = onSelect; this._onClose = onClose; this._overlay = null;
|
|
8
|
+
this._injectStyles(); if (container) this._render(container);
|
|
9
|
+
}
|
|
10
|
+
_injectStyles() {
|
|
11
|
+
if (document.getElementById('oasis-popup-styles')) return;
|
|
12
|
+
const s = document.createElement('style'); s.id = 'oasis-popup-styles';
|
|
13
|
+
s.textContent = `.oasis-popup-overlay{position:fixed;inset:0;z-index:9000;background:rgba(0,0,0,.65);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .25s}.oasis-popup-overlay.is-open{opacity:1}.oasis-popup-modal{background:#0a1628;border:1px solid rgba(0,200,255,.2);border-radius:16px;box-shadow:0 24px 64px rgba(0,0,0,.6);width:90%;max-width:560px;max-height:90vh;overflow-y:auto;transform:translateY(16px);transition:transform .25s}.oasis-popup-overlay.is-open .oasis-popup-modal{transform:none}.oasis-popup-header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-popup-title{font-family:'Orbitron',sans-serif;font-size:14px;font-weight:700;color:#00c8ff;letter-spacing:.08em}.oasis-popup-close{background:none;border:none;color:#7a9bbf;font-size:22px;cursor:pointer;padding:0;line-height:1}.oasis-popup-close:hover{color:#fff}.oasis-popup-body{padding:24px}.oasis-input,.oasis-select{background:rgba(255,255,255,.05);border:1px solid rgba(0,200,255,.2);border-radius:8px;padding:10px 14px;color:#fff;font-size:14px;outline:none;transition:border-color .2s;width:100%;box-sizing:border-box}.oasis-input:focus,.oasis-select:focus{border-color:rgba(0,200,255,.5)}.oasis-select option{background:#0a1628}.oasis-btn{background:linear-gradient(135deg,#00c8ff,#0080ff);border:none;border-radius:8px;color:#fff;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:11px 20px;cursor:pointer;transition:opacity .2s}.oasis-btn:hover{opacity:.85}.oasis-btn:disabled{opacity:.5;cursor:not-allowed}.oasis-badge{display:inline-block;padding:3px 8px;border-radius:999px;font-size:10px;font-weight:700;cursor:pointer}.oasis-badge-blue{background:rgba(0,200,255,.15);color:#00c8ff}.oasis-badge-green{background:rgba(0,200,100,.15);color:#00c864}.oasis-badge-yellow{background:rgba(255,200,0,.15);color:#ffc800}.oasis-table{width:100%;border-collapse:collapse;font-size:13px}.oasis-table th{text-align:left;padding:10px 12px;font-size:10px;font-weight:700;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-table td{padding:10px 12px;color:#fff;border-bottom:1px solid rgba(255,255,255,.05)}.oasis-table tr:hover td{background:rgba(0,200,255,.04)}.oasis-search-row{display:flex;gap:10px;margin-bottom:16px}.oasis-search-row .oasis-input{flex:1}.oasis-cs{text-align:center;padding:32px 16px}.oasis-cs-icon{font-size:48px;margin-bottom:12px}.oasis-cs h3{font-family:'Orbitron',sans-serif;font-size:15px;color:#00c8ff;margin:0 0 8px}.oasis-cs p{color:#7a9bbf;font-size:13px;margin:0}`;
|
|
14
|
+
document.head.appendChild(s);
|
|
15
|
+
}
|
|
16
|
+
open() {
|
|
17
|
+
if (this._overlay) return;
|
|
18
|
+
this._overlay = document.createElement('div');
|
|
19
|
+
this._overlay.className = 'oasis-popup-overlay';
|
|
20
|
+
this._overlay.innerHTML = `<div class="oasis-popup-modal"><div class="oasis-popup-header"><span class="oasis-popup-title">Search Eggs</span><button class="oasis-popup-close">×</button></div><div class="oasis-popup-body">${this._buildBody()}</div></div>`;
|
|
21
|
+
this._overlay.querySelector('.oasis-popup-close').addEventListener('click', () => this.close());
|
|
22
|
+
this._overlay.addEventListener('click', e => { if (e.target === this._overlay) this.close(); });
|
|
23
|
+
document.body.appendChild(this._overlay);
|
|
24
|
+
requestAnimationFrame(() => this._overlay.classList.add('is-open'));
|
|
25
|
+
this._overlay.querySelector('#oasis-se-btn').addEventListener('click', () => this._doSearch());
|
|
26
|
+
}
|
|
27
|
+
_buildBody() {
|
|
28
|
+
return `<div class="oasis-search-row"><input class="oasis-input" id="oasis-se-q" type="text" placeholder="Search eggs by name or type…" /><button class="oasis-btn" id="oasis-se-btn">Search</button></div><div id="oasis-se-results"><p style="color:#7a9bbf;font-size:13px;text-align:center;margin:24px 0">Search the OASIS Egg registry.</p></div>`;
|
|
29
|
+
}
|
|
30
|
+
async _doSearch() {
|
|
31
|
+
const q = this._overlay.querySelector('#oasis-se-q').value.trim();
|
|
32
|
+
const res = this._overlay.querySelector('#oasis-se-results');
|
|
33
|
+
const btn = this._overlay.querySelector('#oasis-se-btn');
|
|
34
|
+
btn.textContent = '…'; btn.disabled = true;
|
|
35
|
+
try {
|
|
36
|
+
const r = await fetch(`${this._apiUrl}/api/avatar/eggs/search?query=${encodeURIComponent(q)}`);
|
|
37
|
+
const data = await r.json();
|
|
38
|
+
const eggs = Array.isArray(data) ? data : (data.result || []);
|
|
39
|
+
if (!eggs.length) res.innerHTML = '<p style="color:#7a9bbf;font-size:13px;text-align:center;margin:24px 0">No eggs found.</p>';
|
|
40
|
+
else res.innerHTML = `<table class="oasis-table"><thead><tr><th>Name</th><th>Type</th><th>Status</th><th></th></tr></thead><tbody>${eggs.map((e,i)=>`<tr><td>${e.name||'Egg'}</td><td><span class="oasis-badge oasis-badge-blue">${e.eggType||'Unknown'}</span></td><td><span class="oasis-badge ${e.isHatched?'oasis-badge-green':'oasis-badge-yellow'}">${e.isHatched?'Hatched':'Incubating'}</span></td><td><button class="oasis-badge oasis-badge-blue" data-i="${i}">Select</button></td></tr>`).join('')}</tbody></table>`;
|
|
41
|
+
res.querySelectorAll('[data-i]').forEach(b=>b.addEventListener('click',()=>{if(this._onSelect)this._onSelect(eggs[+b.dataset.i]);this.close();}));
|
|
42
|
+
} catch { res.innerHTML = '<p style="color:#ff6b6b;font-size:13px;text-align:center;margin:24px 0">Search failed.</p>'; }
|
|
43
|
+
btn.textContent = 'Search'; btn.disabled = false;
|
|
44
|
+
}
|
|
45
|
+
close() { if (!this._overlay) return; const el = this._overlay; this._overlay = null; el.classList.remove('is-open'); el.addEventListener('transitionend', () => el.remove(), { once: true }); if (this._onClose) this._onClose(); }
|
|
46
|
+
_render(c) { c.innerHTML = `<div class="oasis-popup-body">${this._buildBody()}</div>`; }
|
|
47
|
+
destroy() { this.close(); }
|
|
48
|
+
}
|
|
49
|
+
window.OasisSearchEggs = OasisSearchEggs;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OasisSearchKarma — search karma transactions popup widget
|
|
3
|
+
* Usage: const w = new OasisSearchKarma({ onSelect: (item) => {} }); w.open();
|
|
4
|
+
*/
|
|
5
|
+
class OasisSearchKarma {
|
|
6
|
+
constructor({ container, apiUrl = 'https://api.web4.oasisomniverse.one', onSelect = null, onClose = null } = {}) {
|
|
7
|
+
this._apiUrl = apiUrl; this._onSelect = onSelect; this._onClose = onClose; this._overlay = null;
|
|
8
|
+
this._injectStyles(); if (container) this._render(container);
|
|
9
|
+
}
|
|
10
|
+
_injectStyles() {
|
|
11
|
+
if (document.getElementById('oasis-popup-styles')) return;
|
|
12
|
+
const s = document.createElement('style'); s.id = 'oasis-popup-styles';
|
|
13
|
+
s.textContent = `.oasis-popup-overlay{position:fixed;inset:0;z-index:9000;background:rgba(0,0,0,.65);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .25s}.oasis-popup-overlay.is-open{opacity:1}.oasis-popup-modal{background:#0a1628;border:1px solid rgba(0,200,255,.2);border-radius:16px;box-shadow:0 24px 64px rgba(0,0,0,.6);width:90%;max-width:600px;max-height:90vh;overflow-y:auto;transform:translateY(16px);transition:transform .25s}.oasis-popup-overlay.is-open .oasis-popup-modal{transform:none}.oasis-popup-header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-popup-title{font-family:'Orbitron',sans-serif;font-size:14px;font-weight:700;color:#00c8ff;letter-spacing:.08em}.oasis-popup-close{background:none;border:none;color:#7a9bbf;font-size:22px;cursor:pointer;padding:0;line-height:1}.oasis-popup-close:hover{color:#fff}.oasis-popup-body{padding:24px}.oasis-input,.oasis-select{background:rgba(255,255,255,.05);border:1px solid rgba(0,200,255,.2);border-radius:8px;padding:10px 14px;color:#fff;font-size:14px;outline:none;transition:border-color .2s;width:100%;box-sizing:border-box}.oasis-input:focus,.oasis-select:focus{border-color:rgba(0,200,255,.5)}.oasis-select option{background:#0a1628}.oasis-btn{background:linear-gradient(135deg,#00c8ff,#0080ff);border:none;border-radius:8px;color:#fff;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:11px 20px;cursor:pointer;transition:opacity .2s}.oasis-btn:hover{opacity:.85}.oasis-btn:disabled{opacity:.5;cursor:not-allowed}.oasis-badge{display:inline-block;padding:3px 8px;border-radius:999px;font-size:10px;font-weight:700;cursor:pointer}.oasis-badge-blue{background:rgba(0,200,255,.15);color:#00c8ff}.oasis-badge-green{background:rgba(0,200,100,.15);color:#00c864}.oasis-badge-yellow{background:rgba(255,200,0,.15);color:#ffc800}.oasis-table{width:100%;border-collapse:collapse;font-size:13px}.oasis-table th{text-align:left;padding:10px 12px;font-size:10px;font-weight:700;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-table td{padding:10px 12px;color:#fff;border-bottom:1px solid rgba(255,255,255,.05)}.oasis-table tr:hover td{background:rgba(0,200,255,.04)}.oasis-search-row{display:flex;gap:10px;margin-bottom:16px}.oasis-search-row .oasis-input{flex:1}.oasis-cs{text-align:center;padding:32px 16px}.oasis-cs-icon{font-size:48px;margin-bottom:12px}.oasis-cs h3{font-family:'Orbitron',sans-serif;font-size:15px;color:#00c8ff;margin:0 0 8px}.oasis-cs p{color:#7a9bbf;font-size:13px;margin:0}`;
|
|
14
|
+
document.head.appendChild(s);
|
|
15
|
+
}
|
|
16
|
+
open() {
|
|
17
|
+
if (this._overlay) return;
|
|
18
|
+
this._overlay = document.createElement('div');
|
|
19
|
+
this._overlay.className = 'oasis-popup-overlay';
|
|
20
|
+
this._overlay.innerHTML = `<div class="oasis-popup-modal"><div class="oasis-popup-header"><span class="oasis-popup-title">Search Karma</span><button class="oasis-popup-close">×</button></div><div class="oasis-popup-body">${this._buildBody()}</div></div>`;
|
|
21
|
+
this._overlay.querySelector('.oasis-popup-close').addEventListener('click', () => this.close());
|
|
22
|
+
this._overlay.addEventListener('click', e => { if (e.target === this._overlay) this.close(); });
|
|
23
|
+
document.body.appendChild(this._overlay);
|
|
24
|
+
requestAnimationFrame(() => this._overlay.classList.add('is-open'));
|
|
25
|
+
this._overlay.querySelector('#oasis-sk-btn').addEventListener('click', () => this._doSearch());
|
|
26
|
+
}
|
|
27
|
+
_buildBody() {
|
|
28
|
+
return `<div class="oasis-search-row"><input class="oasis-input" id="oasis-sk-q" type="text" placeholder="Search by avatar username…" /><button class="oasis-btn" id="oasis-sk-btn">Search</button></div><div id="oasis-sk-results"><p style="color:#7a9bbf;font-size:13px;text-align:center;margin:24px 0">Search karma by avatar or action.</p></div>`;
|
|
29
|
+
}
|
|
30
|
+
async _doSearch() {
|
|
31
|
+
const q = this._overlay.querySelector('#oasis-sk-q').value.trim();
|
|
32
|
+
const res = this._overlay.querySelector('#oasis-sk-results');
|
|
33
|
+
const btn = this._overlay.querySelector('#oasis-sk-btn');
|
|
34
|
+
btn.textContent = '…'; btn.disabled = true;
|
|
35
|
+
try {
|
|
36
|
+
const r = await fetch(`${this._apiUrl}/api/karma/search?query=${encodeURIComponent(q)}`);
|
|
37
|
+
const data = await r.json();
|
|
38
|
+
const items = Array.isArray(data) ? data : (data.result || []);
|
|
39
|
+
if (!items.length) res.innerHTML = '<p style="color:#7a9bbf;font-size:13px;text-align:center;margin:24px 0">No karma records found.</p>';
|
|
40
|
+
else res.innerHTML = `<table class="oasis-table"><thead><tr><th>Avatar</th><th>Action</th><th>⚡ Karma</th><th>Date</th></tr></thead><tbody>${items.map(i=>`<tr><td>${i.avatarUsername||'—'}</td><td>${i.karmaType||'—'}</td><td><span class="oasis-badge oasis-badge-blue">+${i.karmaAmount??0}</span></td><td>${i.date?new Date(i.date).toLocaleDateString():'—'}</td></tr>`).join('')}</tbody></table>`;
|
|
41
|
+
} catch { res.innerHTML = '<p style="color:#ff6b6b;font-size:13px;text-align:center;margin:24px 0">Search failed.</p>'; }
|
|
42
|
+
btn.textContent = 'Search'; btn.disabled = false;
|
|
43
|
+
}
|
|
44
|
+
close() { if (!this._overlay) return; const el = this._overlay; this._overlay = null; el.classList.remove('is-open'); el.addEventListener('transitionend', () => el.remove(), { once: true }); if (this._onClose) this._onClose(); }
|
|
45
|
+
_render(c) { c.innerHTML = `<div class="oasis-popup-body">${this._buildBody()}</div>`; }
|
|
46
|
+
destroy() { this.close(); }
|
|
47
|
+
}
|
|
48
|
+
window.OasisSearchKarma = OasisSearchKarma;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OasisSearchMission — search OASIS missions popup widget
|
|
3
|
+
* Usage: const w = new OasisSearchMission({ onSelect: (mission) => {} }); w.open();
|
|
4
|
+
*/
|
|
5
|
+
class OasisSearchMission {
|
|
6
|
+
constructor({ container, apiUrl = 'https://api.web4.oasisomniverse.one', onSelect = null, onClose = null } = {}) {
|
|
7
|
+
this._apiUrl = apiUrl; this._onSelect = onSelect; this._onClose = onClose; this._overlay = null;
|
|
8
|
+
this._injectStyles(); if (container) this._render(container);
|
|
9
|
+
}
|
|
10
|
+
_injectStyles() {
|
|
11
|
+
if (document.getElementById('oasis-popup-styles')) return;
|
|
12
|
+
const s = document.createElement('style'); s.id = 'oasis-popup-styles';
|
|
13
|
+
s.textContent = `.oasis-popup-overlay{position:fixed;inset:0;z-index:9000;background:rgba(0,0,0,.65);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .25s}.oasis-popup-overlay.is-open{opacity:1}.oasis-popup-modal{background:#0a1628;border:1px solid rgba(0,200,255,.2);border-radius:16px;box-shadow:0 24px 64px rgba(0,0,0,.6);width:90%;max-width:600px;max-height:90vh;overflow-y:auto;transform:translateY(16px);transition:transform .25s}.oasis-popup-overlay.is-open .oasis-popup-modal{transform:none}.oasis-popup-header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-popup-title{font-family:'Orbitron',sans-serif;font-size:14px;font-weight:700;color:#00c8ff;letter-spacing:.08em}.oasis-popup-close{background:none;border:none;color:#7a9bbf;font-size:22px;cursor:pointer;padding:0;line-height:1}.oasis-popup-close:hover{color:#fff}.oasis-popup-body{padding:24px}.oasis-input{background:rgba(255,255,255,.05);border:1px solid rgba(0,200,255,.2);border-radius:8px;padding:10px 14px;color:#fff;font-size:14px;outline:none;transition:border-color .2s;width:100%;box-sizing:border-box}.oasis-input:focus{border-color:rgba(0,200,255,.5)}.oasis-btn{background:linear-gradient(135deg,#00c8ff,#0080ff);border:none;border-radius:8px;color:#fff;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:11px 20px;cursor:pointer;transition:opacity .2s}.oasis-btn:hover{opacity:.85}.oasis-btn:disabled{opacity:.5;cursor:not-allowed}.oasis-badge{display:inline-block;padding:3px 8px;border-radius:999px;font-size:10px;font-weight:700;cursor:pointer}.oasis-badge-blue{background:rgba(0,200,255,.15);color:#00c8ff}.oasis-badge-green{background:rgba(0,200,100,.15);color:#00c864}.oasis-table{width:100%;border-collapse:collapse;font-size:13px}.oasis-table th{text-align:left;padding:10px 12px;font-size:10px;font-weight:700;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-table td{padding:10px 12px;color:#fff;border-bottom:1px solid rgba(255,255,255,.05)}.oasis-table tr:hover td{background:rgba(0,200,255,.04)}.oasis-search-row{display:flex;gap:10px;margin-bottom:16px}.oasis-search-row .oasis-input{flex:1}.oasis-cs{text-align:center;padding:32px 16px}.oasis-cs-icon{font-size:48px;margin-bottom:12px}.oasis-cs h3{font-family:'Orbitron',sans-serif;font-size:15px;color:#00c8ff;margin:0 0 8px}.oasis-cs p{color:#7a9bbf;font-size:13px;margin:0}`;
|
|
14
|
+
document.head.appendChild(s);
|
|
15
|
+
}
|
|
16
|
+
open() {
|
|
17
|
+
if (this._overlay) return;
|
|
18
|
+
this._overlay = document.createElement('div');
|
|
19
|
+
this._overlay.className = 'oasis-popup-overlay';
|
|
20
|
+
this._overlay.innerHTML = `<div class="oasis-popup-modal"><div class="oasis-popup-header"><span class="oasis-popup-title">Search Missions</span><button class="oasis-popup-close">×</button></div><div class="oasis-popup-body">${this._buildBody()}</div></div>`;
|
|
21
|
+
this._overlay.querySelector('.oasis-popup-close').addEventListener('click', () => this.close());
|
|
22
|
+
this._overlay.addEventListener('click', e => { if (e.target === this._overlay) this.close(); });
|
|
23
|
+
document.body.appendChild(this._overlay);
|
|
24
|
+
requestAnimationFrame(() => this._overlay.classList.add('is-open'));
|
|
25
|
+
this._overlay.querySelector('#oasis-sm-btn').addEventListener('click', () => this._doSearch());
|
|
26
|
+
this._overlay.querySelector('#oasis-sm-q').addEventListener('keydown', e => { if (e.key === 'Enter') this._doSearch(); });
|
|
27
|
+
}
|
|
28
|
+
_buildBody() {
|
|
29
|
+
return `<div class="oasis-search-row"><input class="oasis-input" id="oasis-sm-q" type="text" placeholder="Search missions…" /><button class="oasis-btn" id="oasis-sm-btn">Search</button></div><div id="oasis-sm-results"><p style="color:#7a9bbf;font-size:13px;text-align:center;margin:24px 0">Search for OASIS missions.</p></div>`;
|
|
30
|
+
}
|
|
31
|
+
async _doSearch() {
|
|
32
|
+
const q = this._overlay.querySelector('#oasis-sm-q').value.trim();
|
|
33
|
+
const res = this._overlay.querySelector('#oasis-sm-results');
|
|
34
|
+
const btn = this._overlay.querySelector('#oasis-sm-btn');
|
|
35
|
+
btn.textContent = '…'; btn.disabled = true;
|
|
36
|
+
try {
|
|
37
|
+
const r = await fetch(`${this._apiUrl}/api/mission/search?query=${encodeURIComponent(q)}`);
|
|
38
|
+
const data = await r.json();
|
|
39
|
+
const ms = Array.isArray(data) ? data : (data.result || []);
|
|
40
|
+
if (!ms.length) res.innerHTML = '<p style="color:#7a9bbf;font-size:13px;text-align:center;margin:24px 0">No missions found.</p>';
|
|
41
|
+
else res.innerHTML = `<table class="oasis-table"><thead><tr><th>Mission</th><th>Type</th><th>Karma</th><th></th></tr></thead><tbody>${ms.map((m,i)=>`<tr><td>${m.name||'—'}</td><td><span class="oasis-badge oasis-badge-blue">${m.missionType||'—'}</span></td><td>+${m.karmaReward??0} ⚡</td><td><button class="oasis-badge oasis-badge-green" data-i="${i}">Select</button></td></tr>`).join('')}</tbody></table>`;
|
|
42
|
+
res.querySelectorAll('[data-i]').forEach(b=>b.addEventListener('click',()=>{if(this._onSelect)this._onSelect(ms[+b.dataset.i]);this.close();}));
|
|
43
|
+
} catch { res.innerHTML = '<p style="color:#ff6b6b;font-size:13px;text-align:center;margin:24px 0">Search failed.</p>'; }
|
|
44
|
+
btn.textContent = 'Search'; btn.disabled = false;
|
|
45
|
+
}
|
|
46
|
+
close() { if (!this._overlay) return; const el = this._overlay; this._overlay = null; el.classList.remove('is-open'); el.addEventListener('transitionend', () => el.remove(), { once: true }); if (this._onClose) this._onClose(); }
|
|
47
|
+
_render(c) { c.innerHTML = `<div class="oasis-popup-body">${this._buildBody()}</div>`; }
|
|
48
|
+
destroy() { this.close(); }
|
|
49
|
+
}
|
|
50
|
+
window.OasisSearchMission = OasisSearchMission;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OasisSearchOasisNft — search OASIS NFTs popup widget
|
|
3
|
+
* Usage: const w = new OasisSearchOasisNft({ onSelect: (nft) => {} }); w.open();
|
|
4
|
+
*/
|
|
5
|
+
class OasisSearchOasisNft {
|
|
6
|
+
constructor({ container, apiUrl = 'https://api.web4.oasisomniverse.one', onSelect = null, onClose = null } = {}) {
|
|
7
|
+
this._apiUrl = apiUrl; this._onSelect = onSelect; this._onClose = onClose; this._overlay = null;
|
|
8
|
+
this._injectStyles(); if (container) this._render(container);
|
|
9
|
+
}
|
|
10
|
+
_injectStyles() {
|
|
11
|
+
if (document.getElementById('oasis-popup-styles')) return;
|
|
12
|
+
const s = document.createElement('style'); s.id = 'oasis-popup-styles';
|
|
13
|
+
s.textContent = `.oasis-popup-overlay{position:fixed;inset:0;z-index:9000;background:rgba(0,0,0,.65);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .25s}.oasis-popup-overlay.is-open{opacity:1}.oasis-popup-modal{background:#0a1628;border:1px solid rgba(0,200,255,.2);border-radius:16px;box-shadow:0 24px 64px rgba(0,0,0,.6);width:90%;max-width:640px;max-height:90vh;overflow-y:auto;transform:translateY(16px);transition:transform .25s}.oasis-popup-overlay.is-open .oasis-popup-modal{transform:none}.oasis-popup-header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-popup-title{font-family:'Orbitron',sans-serif;font-size:14px;font-weight:700;color:#00c8ff;letter-spacing:.08em}.oasis-popup-close{background:none;border:none;color:#7a9bbf;font-size:22px;cursor:pointer;padding:0;line-height:1}.oasis-popup-close:hover{color:#fff}.oasis-popup-body{padding:24px}.oasis-input,.oasis-select{background:rgba(255,255,255,.05);border:1px solid rgba(0,200,255,.2);border-radius:8px;padding:10px 14px;color:#fff;font-size:14px;outline:none;transition:border-color .2s;width:100%;box-sizing:border-box}.oasis-input:focus,.oasis-select:focus{border-color:rgba(0,200,255,.5)}.oasis-select option{background:#0a1628}.oasis-btn{background:linear-gradient(135deg,#00c8ff,#0080ff);border:none;border-radius:8px;color:#fff;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:11px 20px;cursor:pointer;transition:opacity .2s}.oasis-btn:hover{opacity:.85}.oasis-btn:disabled{opacity:.5;cursor:not-allowed}.oasis-badge{display:inline-block;padding:3px 8px;border-radius:999px;font-size:10px;font-weight:700;cursor:pointer}.oasis-badge-blue{background:rgba(0,200,255,.15);color:#00c8ff}.oasis-badge-green{background:rgba(0,200,100,.15);color:#00c864}.oasis-badge-yellow{background:rgba(255,200,0,.15);color:#ffc800}.oasis-nft-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:12px;margin-top:16px}.oasis-nft-card{background:rgba(0,200,255,.05);border:1px solid rgba(0,200,255,.1);border-radius:10px;padding:16px;text-align:center;cursor:pointer;transition:border-color .2s}.oasis-nft-card:hover{border-color:rgba(0,200,255,.4)}.oasis-nft-thumb{font-size:36px;margin-bottom:8px}.oasis-nft-card-name{font-size:12px;font-weight:700;color:#fff;margin-bottom:4px}.oasis-nft-price{font-size:11px;color:#00c8ff}.oasis-search-row{display:flex;gap:10px;margin-bottom:16px}.oasis-search-row .oasis-input{flex:1}.oasis-cs{text-align:center;padding:32px 16px}.oasis-cs-icon{font-size:48px;margin-bottom:12px}.oasis-cs h3{font-family:'Orbitron',sans-serif;font-size:15px;color:#00c8ff;margin:0 0 8px}.oasis-cs p{color:#7a9bbf;font-size:13px;margin:0}`;
|
|
14
|
+
document.head.appendChild(s);
|
|
15
|
+
}
|
|
16
|
+
open() {
|
|
17
|
+
if (this._overlay) return;
|
|
18
|
+
this._overlay = document.createElement('div');
|
|
19
|
+
this._overlay.className = 'oasis-popup-overlay';
|
|
20
|
+
this._overlay.innerHTML = `<div class="oasis-popup-modal"><div class="oasis-popup-header"><span class="oasis-popup-title">Search NFTs</span><button class="oasis-popup-close">×</button></div><div class="oasis-popup-body">${this._buildBody()}</div></div>`;
|
|
21
|
+
this._overlay.querySelector('.oasis-popup-close').addEventListener('click', () => this.close());
|
|
22
|
+
this._overlay.addEventListener('click', e => { if (e.target === this._overlay) this.close(); });
|
|
23
|
+
document.body.appendChild(this._overlay);
|
|
24
|
+
requestAnimationFrame(() => this._overlay.classList.add('is-open'));
|
|
25
|
+
this._overlay.querySelector('#oasis-snft-btn').addEventListener('click', () => this._doSearch());
|
|
26
|
+
this._overlay.querySelector('#oasis-snft-q').addEventListener('keydown', e => { if (e.key === 'Enter') this._doSearch(); });
|
|
27
|
+
}
|
|
28
|
+
_buildBody() {
|
|
29
|
+
return `<div class="oasis-search-row"><input class="oasis-input" id="oasis-snft-q" type="text" placeholder="Search by name, collection, or creator…" /><button class="oasis-btn" id="oasis-snft-btn">Search</button></div><div id="oasis-snft-results"><p style="color:#7a9bbf;font-size:13px;text-align:center;margin:24px 0">Search the OASIS NFT marketplace.</p></div>`;
|
|
30
|
+
}
|
|
31
|
+
async _doSearch() {
|
|
32
|
+
const q = this._overlay.querySelector('#oasis-snft-q').value.trim();
|
|
33
|
+
const res = this._overlay.querySelector('#oasis-snft-results');
|
|
34
|
+
const btn = this._overlay.querySelector('#oasis-snft-btn');
|
|
35
|
+
btn.textContent = '…'; btn.disabled = true;
|
|
36
|
+
try {
|
|
37
|
+
const r = await fetch(`${this._apiUrl}/api/nft/search?query=${encodeURIComponent(q)}`);
|
|
38
|
+
const data = await r.json();
|
|
39
|
+
const nfts = Array.isArray(data) ? data : (data.result || []);
|
|
40
|
+
if (!nfts.length) res.innerHTML = '<div class="oasis-cs"><div class="oasis-cs-icon">🖼️</div><p>No NFTs found.</p></div>';
|
|
41
|
+
else { res.innerHTML = `<div class="oasis-nft-grid">${nfts.map((n,i)=>`<div class="oasis-nft-card" data-i="${i}"><div class="oasis-nft-thumb">🖼️</div><div class="oasis-nft-card-name">${n.name||'NFT'}</div><div class="oasis-nft-price">${n.price||'—'} ${n.currency||'ETH'}</div></div>`).join('')}</div>`; res.querySelectorAll('[data-i]').forEach(b=>b.addEventListener('click',()=>{if(this._onSelect)this._onSelect(nfts[+b.dataset.i]);this.close();})); }
|
|
42
|
+
} catch { res.innerHTML = '<p style="color:#ff6b6b;font-size:13px;text-align:center;margin:24px 0">Search failed.</p>'; }
|
|
43
|
+
btn.textContent = 'Search'; btn.disabled = false;
|
|
44
|
+
}
|
|
45
|
+
close() { if (!this._overlay) return; const el = this._overlay; this._overlay = null; el.classList.remove('is-open'); el.addEventListener('transitionend', () => el.remove(), { once: true }); if (this._onClose) this._onClose(); }
|
|
46
|
+
_render(c) { c.innerHTML = `<div class="oasis-popup-body">${this._buildBody()}</div>`; }
|
|
47
|
+
destroy() { this.close(); }
|
|
48
|
+
}
|
|
49
|
+
window.OasisSearchOasisNft = OasisSearchOasisNft;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OasisSearchProfiles — search game profiles popup widget
|
|
3
|
+
* Usage: const w = new OasisSearchProfiles({ onSelect: (profile) => {} }); w.open();
|
|
4
|
+
*/
|
|
5
|
+
class OasisSearchProfiles {
|
|
6
|
+
constructor({ container, apiUrl = 'https://api.web4.oasisomniverse.one', onSelect = null, onClose = null } = {}) {
|
|
7
|
+
this._apiUrl = apiUrl; this._onSelect = onSelect; this._onClose = onClose; this._overlay = null;
|
|
8
|
+
this._injectStyles(); if (container) this._render(container);
|
|
9
|
+
}
|
|
10
|
+
_injectStyles() {
|
|
11
|
+
if (document.getElementById('oasis-popup-styles')) return;
|
|
12
|
+
const s = document.createElement('style'); s.id = 'oasis-popup-styles';
|
|
13
|
+
s.textContent = `.oasis-popup-overlay{position:fixed;inset:0;z-index:9000;background:rgba(0,0,0,.65);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .25s}.oasis-popup-overlay.is-open{opacity:1}.oasis-popup-modal{background:#0a1628;border:1px solid rgba(0,200,255,.2);border-radius:16px;box-shadow:0 24px 64px rgba(0,0,0,.6);width:90%;max-width:600px;max-height:90vh;overflow-y:auto;transform:translateY(16px);transition:transform .25s}.oasis-popup-overlay.is-open .oasis-popup-modal{transform:none}.oasis-popup-header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-popup-title{font-family:'Orbitron',sans-serif;font-size:14px;font-weight:700;color:#00c8ff;letter-spacing:.08em}.oasis-popup-close{background:none;border:none;color:#7a9bbf;font-size:22px;cursor:pointer;padding:0;line-height:1}.oasis-popup-close:hover{color:#fff}.oasis-popup-body{padding:24px}.oasis-input,.oasis-select{background:rgba(255,255,255,.05);border:1px solid rgba(0,200,255,.2);border-radius:8px;padding:10px 14px;color:#fff;font-size:14px;outline:none;transition:border-color .2s;width:100%;box-sizing:border-box}.oasis-input:focus{border-color:rgba(0,200,255,.5)}.oasis-btn{background:linear-gradient(135deg,#00c8ff,#0080ff);border:none;border-radius:8px;color:#fff;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:11px 20px;cursor:pointer;transition:opacity .2s}.oasis-btn:hover{opacity:.85}.oasis-btn:disabled{opacity:.5;cursor:not-allowed}.oasis-badge{display:inline-block;padding:3px 8px;border-radius:999px;font-size:10px;font-weight:700;cursor:pointer}.oasis-badge-blue{background:rgba(0,200,255,.15);color:#00c8ff}.oasis-badge-green{background:rgba(0,200,100,.15);color:#00c864}.oasis-table{width:100%;border-collapse:collapse;font-size:13px}.oasis-table th{text-align:left;padding:10px 12px;font-size:10px;font-weight:700;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase;border-bottom:1px solid rgba(0,200,255,.1)}.oasis-table td{padding:10px 12px;color:#fff;border-bottom:1px solid rgba(255,255,255,.05)}.oasis-table tr:hover td{background:rgba(0,200,255,.04)}.oasis-search-row{display:flex;gap:10px;margin-bottom:16px}.oasis-search-row .oasis-input{flex:1}.oasis-cs{text-align:center;padding:32px 16px}.oasis-cs-icon{font-size:48px;margin-bottom:12px}.oasis-cs h3{font-family:'Orbitron',sans-serif;font-size:15px;color:#00c8ff;margin:0 0 8px}.oasis-cs p{color:#7a9bbf;font-size:13px;margin:0}`;
|
|
14
|
+
document.head.appendChild(s);
|
|
15
|
+
}
|
|
16
|
+
open() {
|
|
17
|
+
if (this._overlay) return;
|
|
18
|
+
this._overlay = document.createElement('div');
|
|
19
|
+
this._overlay.className = 'oasis-popup-overlay';
|
|
20
|
+
this._overlay.innerHTML = `<div class="oasis-popup-modal"><div class="oasis-popup-header"><span class="oasis-popup-title">Search Profiles</span><button class="oasis-popup-close">×</button></div><div class="oasis-popup-body">${this._buildBody()}</div></div>`;
|
|
21
|
+
this._overlay.querySelector('.oasis-popup-close').addEventListener('click', () => this.close());
|
|
22
|
+
this._overlay.addEventListener('click', e => { if (e.target === this._overlay) this.close(); });
|
|
23
|
+
document.body.appendChild(this._overlay);
|
|
24
|
+
requestAnimationFrame(() => this._overlay.classList.add('is-open'));
|
|
25
|
+
this._overlay.querySelector('#oasis-sp-btn').addEventListener('click', () => this._doSearch());
|
|
26
|
+
this._overlay.querySelector('#oasis-sp-q').addEventListener('keydown', e => { if (e.key === 'Enter') this._doSearch(); });
|
|
27
|
+
}
|
|
28
|
+
_buildBody() {
|
|
29
|
+
return `<div class="oasis-search-row"><input class="oasis-input" id="oasis-sp-q" type="text" placeholder="Search game profiles…" /><button class="oasis-btn" id="oasis-sp-btn">Search</button></div><div id="oasis-sp-results"><p style="color:#7a9bbf;font-size:13px;text-align:center;margin:24px 0">Search OASIS game profiles.</p></div>`;
|
|
30
|
+
}
|
|
31
|
+
async _doSearch() {
|
|
32
|
+
const q = this._overlay.querySelector('#oasis-sp-q').value.trim();
|
|
33
|
+
const res = this._overlay.querySelector('#oasis-sp-results');
|
|
34
|
+
const btn = this._overlay.querySelector('#oasis-sp-btn');
|
|
35
|
+
btn.textContent = '…'; btn.disabled = true;
|
|
36
|
+
try {
|
|
37
|
+
const r = await fetch(`${this._apiUrl}/api/game/profiles/search?query=${encodeURIComponent(q)}`);
|
|
38
|
+
const data = await r.json();
|
|
39
|
+
const profiles = Array.isArray(data) ? data : (data.result || []);
|
|
40
|
+
if (!profiles.length) res.innerHTML = '<p style="color:#7a9bbf;font-size:13px;text-align:center;margin:24px 0">No profiles found.</p>';
|
|
41
|
+
else res.innerHTML = `<table class="oasis-table"><thead><tr><th>Username</th><th>Level</th><th>XP</th><th></th></tr></thead><tbody>${profiles.map((p,i)=>`<tr><td>${p.username||'—'}</td><td>${p.level??1}</td><td>${p.xp??0}</td><td><button class="oasis-badge oasis-badge-blue" data-i="${i}">View</button></td></tr>`).join('')}</tbody></table>`;
|
|
42
|
+
res.querySelectorAll('[data-i]').forEach(b=>b.addEventListener('click',()=>{if(this._onSelect)this._onSelect(profiles[+b.dataset.i]);this.close();}));
|
|
43
|
+
} catch { res.innerHTML = '<p style="color:#ff6b6b;font-size:13px;text-align:center;margin:24px 0">Search failed.</p>'; }
|
|
44
|
+
btn.textContent = 'Search'; btn.disabled = false;
|
|
45
|
+
}
|
|
46
|
+
close() { if (!this._overlay) return; const el = this._overlay; this._overlay = null; el.classList.remove('is-open'); el.addEventListener('transitionend', () => el.remove(), { once: true }); if (this._onClose) this._onClose(); }
|
|
47
|
+
_render(c) { c.innerHTML = `<div class="oasis-popup-body">${this._buildBody()}</div>`; }
|
|
48
|
+
destroy() { this.close(); }
|
|
49
|
+
}
|
|
50
|
+
window.OasisSearchProfiles = OasisSearchProfiles;
|
package/src/seeds.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OasisSeeds — standalone Seeds widget
|
|
3
|
+
* Usage: new OasisSeeds({ container: document.getElementById('seeds') })
|
|
4
|
+
*/
|
|
5
|
+
(function () {
|
|
6
|
+
const SEEDS = [
|
|
7
|
+
{ id: '1', name: 'Wisdom Seed', type: 'Spiritual', rarity: 'rare', karma: 50, planted: false },
|
|
8
|
+
{ id: '2', name: 'Healing Seed', type: 'Health', rarity: 'common', karma: 20, planted: false },
|
|
9
|
+
{ id: '3', name: 'Unity Seed', type: 'Community', rarity: 'epic', karma: 150, planted: false },
|
|
10
|
+
{ id: '4', name: 'Truth Seed', type: 'Knowledge', rarity: 'legendary', karma: 500, planted: false },
|
|
11
|
+
{ id: '5', name: 'Love Seed', type: 'Spiritual', rarity: 'common', karma: 30, planted: false },
|
|
12
|
+
{ id: '6', name: 'Peace Seed', type: 'Community', rarity: 'rare', karma: 75, planted: false },
|
|
13
|
+
];
|
|
14
|
+
const ICONS = { Spiritual: '✨', Health: '💚', Community: '🤝', Knowledge: '📖' };
|
|
15
|
+
const RARITY_COLORS = { common: '#7a9bbf', rare: '#5ba8ff', epic: '#b87fff', legendary: '#ffb43c' };
|
|
16
|
+
|
|
17
|
+
const CSS = `
|
|
18
|
+
.oasis-seeds-shell{font-family:'Rajdhani',sans-serif;display:flex;flex-direction:column;gap:20px}
|
|
19
|
+
.oasis-seeds-header{text-align:center}
|
|
20
|
+
.oasis-seeds-title{font-family:'Orbitron',sans-serif;font-size:20px;color:#fff;margin:0 0 6px}
|
|
21
|
+
.oasis-seeds-sub{font-size:13px;color:#7a9bbf;margin:0}
|
|
22
|
+
.oasis-seeds-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:16px}
|
|
23
|
+
.oasis-seed-card{background:rgba(255,255,255,.04);border:1px solid rgba(0,200,255,.15);border-radius:12px;padding:18px 14px;display:flex;flex-direction:column;align-items:center;gap:10px;transition:border-color .2s;cursor:default}
|
|
24
|
+
.oasis-seed-card:hover{border-color:rgba(0,200,255,.35)}
|
|
25
|
+
.oasis-seed-card.planted{border-color:rgba(72,220,130,.3);background:rgba(72,220,130,.04)}
|
|
26
|
+
.oasis-seed-rarity{font-size:10px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;border-radius:999px;padding:3px 10px;border:1px solid currentColor}
|
|
27
|
+
.oasis-seed-icon{font-size:36px}
|
|
28
|
+
.oasis-seed-name{font-family:'Orbitron',sans-serif;font-size:13px;color:#fff;text-align:center}
|
|
29
|
+
.oasis-seed-type{font-size:11px;color:#7a9bbf}
|
|
30
|
+
.oasis-seed-karma{font-size:12px;color:#48dc82;font-weight:600}
|
|
31
|
+
.oasis-seed-btn{width:100%;background:linear-gradient(135deg,#00c8ff,#0080ff);border:none;border-radius:7px;color:#fff;font-family:'Orbitron',sans-serif;font-size:11px;font-weight:700;letter-spacing:.08em;padding:8px;cursor:pointer;transition:opacity .2s}
|
|
32
|
+
.oasis-seed-btn:hover{opacity:.85}
|
|
33
|
+
.oasis-seed-planted{font-size:12px;color:#48dc82;font-weight:600}
|
|
34
|
+
`;
|
|
35
|
+
|
|
36
|
+
class OasisSeeds {
|
|
37
|
+
constructor({ container } = {}) {
|
|
38
|
+
this._container = typeof container === 'string' ? document.querySelector(container) : container;
|
|
39
|
+
if (!this._container) throw new Error('OasisSeeds: container not found');
|
|
40
|
+
if (!document.getElementById('oasis-seeds-styles')) {
|
|
41
|
+
const s = document.createElement('style'); s.id = 'oasis-seeds-styles'; s.textContent = CSS;
|
|
42
|
+
document.head.appendChild(s);
|
|
43
|
+
}
|
|
44
|
+
this._seeds = SEEDS.map(s => ({ ...s }));
|
|
45
|
+
this._render();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
_render() {
|
|
49
|
+
this._container.innerHTML = `
|
|
50
|
+
<div class="oasis-seeds-shell">
|
|
51
|
+
<div class="oasis-seeds-header">
|
|
52
|
+
<h2 class="oasis-seeds-title">🌱 Seeds</h2>
|
|
53
|
+
<p class="oasis-seeds-sub">Plant seeds to grow your OASIS avatar and earn karma.</p>
|
|
54
|
+
</div>
|
|
55
|
+
<div class="oasis-seeds-grid">
|
|
56
|
+
${this._seeds.map(s => `
|
|
57
|
+
<div class="oasis-seed-card${s.planted ? ' planted' : ''}" data-id="${s.id}">
|
|
58
|
+
<div class="oasis-seed-rarity" style="color:${RARITY_COLORS[s.rarity]};border-color:${RARITY_COLORS[s.rarity]}44">${s.rarity}</div>
|
|
59
|
+
<div class="oasis-seed-icon">${ICONS[s.type] || '🌱'}</div>
|
|
60
|
+
<div class="oasis-seed-name">${s.name}</div>
|
|
61
|
+
<div class="oasis-seed-type">${s.type}</div>
|
|
62
|
+
<div class="oasis-seed-karma">+${s.karma} Karma</div>
|
|
63
|
+
${s.planted
|
|
64
|
+
? '<div class="oasis-seed-planted">🌿 Growing…</div>'
|
|
65
|
+
: `<button class="oasis-seed-btn" data-plant="${s.id}">Plant Seed</button>`}
|
|
66
|
+
</div>`).join('')}
|
|
67
|
+
</div>
|
|
68
|
+
</div>`;
|
|
69
|
+
this._container.querySelectorAll('[data-plant]').forEach(btn => {
|
|
70
|
+
btn.addEventListener('click', () => { this._plant(btn.dataset.plant); });
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
_plant(id) {
|
|
75
|
+
const s = this._seeds.find(x => x.id === id);
|
|
76
|
+
if (s) { s.planted = true; this._render(); }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
destroy() { this._container.innerHTML = ''; }
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
window.OasisSeeds = OasisSeeds;
|
|
83
|
+
})();
|