@oasisomniverse/vue 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.
Files changed (117) hide show
  1. package/package.json +37 -0
  2. package/src/components/Avatar/AvatarWallet.vue +29 -0
  3. package/src/components/Avatar/EditAvatar.vue +21 -0
  4. package/src/components/Avatar/SearchAvatar.vue +24 -0
  5. package/src/components/Avatar/ViewAvatar.vue +19 -0
  6. package/src/components/AvatarConnect/AvatarConnect.vue +64 -0
  7. package/src/components/AvatarProfile/AvatarProfile.vue +123 -0
  8. package/src/components/ComingSoon/ComingSoon.vue +14 -0
  9. package/src/components/Confirmation/Confirmation.vue +18 -0
  10. package/src/components/Contact/Contact.vue +40 -0
  11. package/src/components/DataScreen/AddData.vue +26 -0
  12. package/src/components/DataScreen/CrossChainManagement.vue +14 -0
  13. package/src/components/DataScreen/LoadData.vue +24 -0
  14. package/src/components/DataScreen/ManageData.vue +14 -0
  15. package/src/components/DataScreen/OffChainManagement.vue +14 -0
  16. package/src/components/DataScreen/SearchData.vue +24 -0
  17. package/src/components/Eggs/Eggs.vue +40 -0
  18. package/src/components/Eggs/ManageEggs.vue +14 -0
  19. package/src/components/Eggs/SearchEggs.vue +24 -0
  20. package/src/components/Eggs/ViewEggs.vue +20 -0
  21. package/src/components/ForgotPassword/ForgotPassword.vue +71 -0
  22. package/src/components/Game/Game.vue +29 -0
  23. package/src/components/Game/SearchProfiles.vue +24 -0
  24. package/src/components/Game/ViewAchievements.vue +25 -0
  25. package/src/components/Game/ViewLeagues.vue +25 -0
  26. package/src/components/Game/ViewTournaments.vue +27 -0
  27. package/src/components/HyperDrive/HyperDrive.vue +46 -0
  28. package/src/components/Karma/SearchKarma.vue +24 -0
  29. package/src/components/Karma/ViewAvatarKarma.vue +20 -0
  30. package/src/components/Karma/ViewKarma.vue +30 -0
  31. package/src/components/Karma/VoteKarma.vue +26 -0
  32. package/src/components/KarmaPanel/KarmaPanel.vue +71 -0
  33. package/src/components/KarmaToast/KarmaToast.vue +29 -0
  34. package/src/components/Login/Login.vue +90 -0
  35. package/src/components/Map/Add2dObjectMap.vue +23 -0
  36. package/src/components/Map/Add3dObjectMap.vue +24 -0
  37. package/src/components/Map/AddQuestToMap.vue +22 -0
  38. package/src/components/Map/DownloadOurWorld.vue +18 -0
  39. package/src/components/Map/ManageMap.vue +14 -0
  40. package/src/components/Map/Map.vue +38 -0
  41. package/src/components/Map/PlotRouteOnMap.vue +25 -0
  42. package/src/components/Map/SearchMap.vue +24 -0
  43. package/src/components/Map/ViewGlobal3dMap.vue +14 -0
  44. package/src/components/Map/ViewHalonsOnMap.vue +27 -0
  45. package/src/components/Map/ViewOappOnMap.vue +14 -0
  46. package/src/components/Map/ViewQuestOnMap.vue +20 -0
  47. package/src/components/MenuMessage/MenuMessage.vue +72 -0
  48. package/src/components/Message/Message.vue +50 -0
  49. package/src/components/Messaging/Messaging.vue +44 -0
  50. package/src/components/Mission/ManageMission.vue +14 -0
  51. package/src/components/Mission/Mission.vue +32 -0
  52. package/src/components/Mission/SearchMission.vue +24 -0
  53. package/src/components/Mission/ViewMission.vue +21 -0
  54. package/src/components/NFT/ContactPopup.vue +36 -0
  55. package/src/components/NFT/ManageOasisNft.vue +14 -0
  56. package/src/components/NFT/NFT.vue +36 -0
  57. package/src/components/NFT/PurchaseOasisNft.vue +21 -0
  58. package/src/components/NFT/PurchaseOasisVirtualLandNft.vue +23 -0
  59. package/src/components/NFT/SearchOasisNft.vue +30 -0
  60. package/src/components/NFT/Solana.vue +27 -0
  61. package/src/components/NFT/ViewOasisNft.vue +20 -0
  62. package/src/components/NavBar/NavBar.vue +71 -0
  63. package/src/components/OApp/CreateOAPP.vue +31 -0
  64. package/src/components/OApp/DeployOAPP.vue +23 -0
  65. package/src/components/OApp/DownloadOurWorld.vue +18 -0
  66. package/src/components/OApp/EditOAPP.vue +21 -0
  67. package/src/components/OApp/InstallOAPP.vue +23 -0
  68. package/src/components/OApp/LaunchOAPP.vue +19 -0
  69. package/src/components/OApp/ManageOAPP.vue +14 -0
  70. package/src/components/OApp/OApp.vue +40 -0
  71. package/src/components/OApp/SearchOAPP.vue +30 -0
  72. package/src/components/ONET/ONET.vue +40 -0
  73. package/src/components/ONODE/ONODE.vue +42 -0
  74. package/src/components/OasisModal/OasisModal.vue +36 -0
  75. package/src/components/Provider/ActivityPub.vue +14 -0
  76. package/src/components/Provider/CompareProviderSpeeds.vue +32 -0
  77. package/src/components/Provider/Eosio.vue +14 -0
  78. package/src/components/Provider/Ethereum.vue +14 -0
  79. package/src/components/Provider/Holochain.vue +14 -0
  80. package/src/components/Provider/Ipfs.vue +14 -0
  81. package/src/components/Provider/ManageAutoFailOver.vue +14 -0
  82. package/src/components/Provider/ManageAutoReplicaton.vue +14 -0
  83. package/src/components/Provider/ManageLoadBalancing.vue +14 -0
  84. package/src/components/Provider/ManageProviders.vue +27 -0
  85. package/src/components/Provider/MongoDb.vue +14 -0
  86. package/src/components/Provider/Neo4j.vue +14 -0
  87. package/src/components/Provider/SearchProviders.vue +24 -0
  88. package/src/components/Provider/Seeds.vue +14 -0
  89. package/src/components/Provider/Solid.vue +14 -0
  90. package/src/components/Provider/SqlLite.vue +14 -0
  91. package/src/components/Provider/ThreeFold.vue +14 -0
  92. package/src/components/Provider/ViewProviderStats.vue +27 -0
  93. package/src/components/Provider/ViewProviders.vue +30 -0
  94. package/src/components/ProviderDropdown/ProviderDropdown.vue +34 -0
  95. package/src/components/Providers/Providers.vue +30 -0
  96. package/src/components/Quest/ManageQuest.vue +14 -0
  97. package/src/components/Quest/Quest.vue +35 -0
  98. package/src/components/Quest/SearchQuest.vue +30 -0
  99. package/src/components/Quest/ViewQuest.vue +23 -0
  100. package/src/components/ResetPassword/ResetPassword.vue +39 -0
  101. package/src/components/SearchAvatars/SearchAvatars.vue +42 -0
  102. package/src/components/Seeds/AcceptInvite.vue +26 -0
  103. package/src/components/Seeds/DonateSeeds.vue +34 -0
  104. package/src/components/Seeds/ManageSeeds.vue +14 -0
  105. package/src/components/Seeds/PayWithSeeds.vue +34 -0
  106. package/src/components/Seeds/RewardSeeds.vue +20 -0
  107. package/src/components/Seeds/SearchSeeds.vue +18 -0
  108. package/src/components/Seeds/Seeds.vue +37 -0
  109. package/src/components/Seeds/SendInvite.vue +34 -0
  110. package/src/components/Seeds/ViewOrganizations.vue +27 -0
  111. package/src/components/Seeds/ViewSeeds.vue +34 -0
  112. package/src/components/Settings/Settings.vue +52 -0
  113. package/src/components/Signup/Signup.vue +121 -0
  114. package/src/components/StarField/StarField.vue +55 -0
  115. package/src/components/VerifyEmail/VerifyEmail.vue +21 -0
  116. package/src/components/Wallet/Wallet.vue +41 -0
  117. package/src/index.ts +143 -0
@@ -0,0 +1,23 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ const emit = defineEmits<{ close: []; submit: [{ name: string; lat: string; lng: string; imageUrl: string }] }>()
4
+ const form = ref({ name: '', lat: '', lng: '', imageUrl: '' })
5
+ function handleSubmit() { emit('submit', { ...form.value }) }
6
+ </script>
7
+ <template>
8
+ <div class="p-shell">
9
+ <h2 class="p-title">🗺️ Add 2D Object to Map</h2>
10
+ <form class="p-form" @submit.prevent="handleSubmit">
11
+ <div class="p-row"><label class="p-label">Object Name</label><input class="p-input" v-model="form.name" placeholder="Name this object" /></div>
12
+ <div class="p-row p-row--2col">
13
+ <div><label class="p-label">Latitude</label><input class="p-input" v-model="form.lat" placeholder="0.000000" /></div>
14
+ <div><label class="p-label">Longitude</label><input class="p-input" v-model="form.lng" placeholder="0.000000" /></div>
15
+ </div>
16
+ <div class="p-row"><label class="p-label">Image URL</label><input class="p-input" v-model="form.imageUrl" placeholder="https://..." /></div>
17
+ <div class="p-actions"><button class="p-btn-cancel" type="button" @click="emit('close')">Cancel</button><button class="p-btn" type="submit">Add to Map</button></div>
18
+ </form>
19
+ </div>
20
+ </template>
21
+ <style scoped>
22
+ .p-shell{display:flex;flex-direction:column;gap:20px;padding:24px 20px}.p-title{font-family:'Orbitron',sans-serif;font-size:18px;color:#fff;margin:0}.p-form{display:flex;flex-direction:column;gap:14px}.p-row{display:flex;flex-direction:column;gap:6px}.p-row--2col{display:grid;grid-template-columns:1fr 1fr;gap:12px}.p-row--2col>div{display:flex;flex-direction:column;gap:6px}.p-label{font-size:12px;color:#7a9bbf;font-weight:600;letter-spacing:.05em}.p-input{background:rgba(255,255,255,.06);border:1px solid rgba(0,200,255,.2);border-radius:8px;color:#fff;font-size:14px;padding:10px 12px;width:100%;box-sizing:border-box;outline:none;transition:border-color .2s}.p-input:focus{border-color:rgba(0,200,255,.5)}.p-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:4px}.p-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:10px 24px;cursor:pointer;transition:opacity .2s}.p-btn:hover{opacity:.85}.p-btn-cancel{background:transparent;border:1px solid rgba(0,200,255,.3);border-radius:8px;color:#00c8ff;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:10px 24px;cursor:pointer}
23
+ </style>
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ const emit = defineEmits<{ close: []; submit: [{ name: string; lat: string; lng: string; alt: string; modelUrl: string }] }>()
4
+ const form = ref({ name: '', lat: '', lng: '', alt: '', modelUrl: '' })
5
+ function handleSubmit() { emit('submit', { ...form.value }) }
6
+ </script>
7
+ <template>
8
+ <div class="p-shell">
9
+ <h2 class="p-title">🌐 Add 3D Object to Map</h2>
10
+ <form class="p-form" @submit.prevent="handleSubmit">
11
+ <div class="p-row"><label class="p-label">Object Name</label><input class="p-input" v-model="form.name" placeholder="Name this 3D object" /></div>
12
+ <div class="p-row p-row--3col">
13
+ <div><label class="p-label">Latitude</label><input class="p-input" v-model="form.lat" placeholder="0.000000" /></div>
14
+ <div><label class="p-label">Longitude</label><input class="p-input" v-model="form.lng" placeholder="0.000000" /></div>
15
+ <div><label class="p-label">Altitude (m)</label><input class="p-input" v-model="form.alt" placeholder="0" /></div>
16
+ </div>
17
+ <div class="p-row"><label class="p-label">3D Model URL (.glb / .gltf)</label><input class="p-input" v-model="form.modelUrl" placeholder="https://..." /></div>
18
+ <div class="p-actions"><button class="p-btn-cancel" type="button" @click="emit('close')">Cancel</button><button class="p-btn" type="submit">Add to Map</button></div>
19
+ </form>
20
+ </div>
21
+ </template>
22
+ <style scoped>
23
+ .p-shell{display:flex;flex-direction:column;gap:20px;padding:24px 20px}.p-title{font-family:'Orbitron',sans-serif;font-size:18px;color:#fff;margin:0}.p-form{display:flex;flex-direction:column;gap:14px}.p-row{display:flex;flex-direction:column;gap:6px}.p-row--3col{display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px}.p-row--3col>div{display:flex;flex-direction:column;gap:6px}.p-label{font-size:12px;color:#7a9bbf;font-weight:600;letter-spacing:.05em}.p-input{background:rgba(255,255,255,.06);border:1px solid rgba(0,200,255,.2);border-radius:8px;color:#fff;font-size:14px;padding:10px 12px;width:100%;box-sizing:border-box;outline:none;transition:border-color .2s}.p-input:focus{border-color:rgba(0,200,255,.5)}.p-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:4px}.p-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:10px 24px;cursor:pointer;transition:opacity .2s}.p-btn:hover{opacity:.85}.p-btn-cancel{background:transparent;border:1px solid rgba(0,200,255,.3);border-radius:8px;color:#00c8ff;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:10px 24px;cursor:pointer}
24
+ </style>
@@ -0,0 +1,22 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ const emit = defineEmits<{ close: []; submit: [{ questId: string; lat: string; lng: string }] }>()
4
+ const form = ref({ questId: '', lat: '', lng: '' })
5
+ function handleSubmit() { emit('submit', { ...form.value }) }
6
+ </script>
7
+ <template>
8
+ <div class="p-shell">
9
+ <h2 class="p-title">🗺️ Add Quest to Map</h2>
10
+ <form class="p-form" @submit.prevent="handleSubmit">
11
+ <div class="p-row"><label class="p-label">Quest ID</label><input class="p-input" v-model="form.questId" placeholder="Enter quest ID" /></div>
12
+ <div class="p-row p-row--2col">
13
+ <div><label class="p-label">Latitude</label><input class="p-input" v-model="form.lat" placeholder="0.000000" /></div>
14
+ <div><label class="p-label">Longitude</label><input class="p-input" v-model="form.lng" placeholder="0.000000" /></div>
15
+ </div>
16
+ <div class="p-actions"><button class="p-btn-cancel" type="button" @click="emit('close')">Cancel</button><button class="p-btn" type="submit">Add Quest</button></div>
17
+ </form>
18
+ </div>
19
+ </template>
20
+ <style scoped>
21
+ .p-shell{display:flex;flex-direction:column;gap:20px;padding:24px 20px}.p-title{font-family:'Orbitron',sans-serif;font-size:18px;color:#fff;margin:0}.p-form{display:flex;flex-direction:column;gap:14px}.p-row{display:flex;flex-direction:column;gap:6px}.p-row--2col{display:grid;grid-template-columns:1fr 1fr;gap:12px}.p-row--2col>div{display:flex;flex-direction:column;gap:6px}.p-label{font-size:12px;color:#7a9bbf;font-weight:600;letter-spacing:.05em}.p-input{background:rgba(255,255,255,.06);border:1px solid rgba(0,200,255,.2);border-radius:8px;color:#fff;font-size:14px;padding:10px 12px;width:100%;box-sizing:border-box;outline:none;transition:border-color .2s}.p-input:focus{border-color:rgba(0,200,255,.5)}.p-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:4px}.p-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:10px 24px;cursor:pointer;transition:opacity .2s}.p-btn:hover{opacity:.85}.p-btn-cancel{background:transparent;border:1px solid rgba(0,200,255,.3);border-radius:8px;color:#00c8ff;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:10px 24px;cursor:pointer}
22
+ </style>
@@ -0,0 +1,18 @@
1
+ <script setup lang="ts">
2
+ const emit = defineEmits<{ close: []; download: [] }>()
3
+ </script>
4
+ <template>
5
+ <div class="p-shell">
6
+ <div class="p-icon">🌍</div>
7
+ <h2 class="p-title">Download Our World</h2>
8
+ <p class="p-body">Download the full Our World map for offline use, including all quest locations, 3D objects, and HolON data embedded in the terrain.</p>
9
+ <div class="p-size">Estimated size: <strong>2.4 GB</strong></div>
10
+ <div class="p-actions">
11
+ <button class="p-btn-cancel" type="button" @click="emit('close')">Cancel</button>
12
+ <button class="p-btn" @click="emit('download')">Download</button>
13
+ </div>
14
+ </div>
15
+ </template>
16
+ <style scoped>
17
+ .p-shell{display:flex;flex-direction:column;align-items:center;gap:16px;padding:32px 20px;text-align:center}.p-icon{font-size:54px}.p-title{font-family:'Orbitron',sans-serif;font-size:18px;color:#fff;margin:0}.p-body{font-size:14px;color:#a8bfd8;line-height:1.6;margin:0;max-width:360px}.p-size{font-size:13px;color:#7a9bbf;background:rgba(0,200,255,.06);border:1px solid rgba(0,200,255,.15);border-radius:8px;padding:8px 16px}.p-actions{display:flex;gap:12px}.p-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 28px;cursor:pointer;transition:opacity .2s}.p-btn:hover{opacity:.85}.p-btn-cancel{background:transparent;border:1px solid rgba(0,200,255,.3);border-radius:8px;color:#00c8ff;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:11px 28px;cursor:pointer}
18
+ </style>
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ const emit = defineEmits<{ close: [] }>()
3
+ </script>
4
+ <template>
5
+ <div class="p-shell">
6
+ <div class="p-icon">🗺️</div>
7
+ <h2 class="p-title">Manage Map</h2>
8
+ <p class="p-body">Advanced map management tools are coming soon — including layer controls, object bulk editing, terrain sculpting, and Our World map publishing.</p>
9
+ <button class="p-btn" @click="emit('close')">OK</button>
10
+ </div>
11
+ </template>
12
+ <style scoped>
13
+ .p-shell{display:flex;flex-direction:column;align-items:center;gap:16px;padding:32px 20px;text-align:center}.p-icon{font-size:44px}.p-title{font-family:'Orbitron',sans-serif;font-size:18px;color:#fff;margin:0}.p-body{font-size:14px;color:#a8bfd8;line-height:1.6;margin:0;max-width:360px}.p-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 28px;cursor:pointer;transition:opacity .2s}.p-btn:hover{opacity:.85}
14
+ </style>
@@ -0,0 +1,38 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ interface Location { id: string; name: string; type: string; x: number; y: number; description: string }
4
+ const selected = ref<Location | null>(null)
5
+ const locations = ref<Location[]>([
6
+ { id: '1', name: 'OASIS Hub Alpha', type: 'Hub', x: 20, y: 30, description: 'Central hub for OASIS operations and avatar registration.' },
7
+ { id: '2', name: 'Neon City', type: 'City', x: 55, y: 20, description: 'A sprawling cyberpunk metropolis in the OASIS.' },
8
+ { id: '3', name: 'Enchanted Forest', type: 'Nature', x: 75, y: 60, description: 'Ancient woodland teeming with rare seeds and creatures.' },
9
+ { id: '4', name: 'Battle Grounds', type: 'Quest Zone', x: 35, y: 70, description: 'Arena for quests, challenges, and PvP competitions.' },
10
+ { id: '5', name: 'Crystal Spire', type: 'Hub', x: 85, y: 35, description: 'Trading post and NFT marketplace in the sky.' },
11
+ ])
12
+ const types = [{ icon: '🏙️', label: 'City' }, { icon: '🌲', label: 'Nature' }, { icon: '⚔️', label: 'Quest Zone' }, { icon: '🏛️', label: 'Hub' }]
13
+ const icons: Record<string, string> = { Hub: '🏛️', City: '🏙️', Nature: '🌲', 'Quest Zone': '⚔️' }
14
+ function locIcon(type: string) { return icons[type] ?? '📍' }
15
+ </script>
16
+ <template>
17
+ <div class="map-shell">
18
+ <div class="map-header"><h2 class="map-title">🗺️ OASIS Map</h2><p class="map-sub">Explore the OASIS Omniverse.</p></div>
19
+ <div class="map-viewport">
20
+ <div class="map-grid-bg"></div>
21
+ <div v-for="loc in locations" :key="loc.id" class="map-pin" :class="{ 'map-pin--selected': selected?.id === loc.id }" :style="{ left: loc.x + '%', top: loc.y + '%' }" @click="selected = loc" :title="loc.name">
22
+ <div class="map-pin-dot">{{ locIcon(loc.type) }}</div>
23
+ </div>
24
+ </div>
25
+ <div v-if="selected" class="map-detail">
26
+ <div class="map-detail-name">{{ selected.name }}</div>
27
+ <div class="map-detail-type">{{ selected.type }}</div>
28
+ <div class="map-detail-desc">{{ selected.description }}</div>
29
+ <button class="map-btn" @click="selected = null">Close</button>
30
+ </div>
31
+ <div class="map-legend">
32
+ <div v-for="t in types" :key="t.label" class="map-legend-item"><span>{{ t.icon }}</span><span>{{ t.label }}</span></div>
33
+ </div>
34
+ </div>
35
+ </template>
36
+ <style scoped>
37
+ .map-shell{display:flex;flex-direction:column;gap:16px}.map-header{text-align:center}.map-title{font-family:'Orbitron',sans-serif;font-size:20px;color:#fff;margin:0 0 6px}.map-sub{font-size:13px;color:#7a9bbf;margin:0}.map-viewport{position:relative;height:300px;background:#030d1a;border:1px solid rgba(0,200,255,.2);border-radius:12px;overflow:hidden}.map-grid-bg{position:absolute;inset:0;background-image:linear-gradient(rgba(0,200,255,.05) 1px,transparent 1px),linear-gradient(90deg,rgba(0,200,255,.05) 1px,transparent 1px);background-size:40px 40px}.map-pin{position:absolute;transform:translate(-50%,-50%);cursor:pointer;transition:transform .2s}.map-pin:hover{transform:translate(-50%,-50%) scale(1.2)}.map-pin--selected .map-pin-dot{outline:2px solid #00c8ff;outline-offset:3px;border-radius:50%}.map-pin-dot{font-size:22px}.map-detail{background:rgba(255,255,255,.04);border:1px solid rgba(0,200,255,.2);border-radius:10px;padding:14px 16px;display:flex;align-items:center;gap:12px}.map-detail-name{font-family:'Orbitron',sans-serif;font-size:13px;color:#fff;flex:0 0 auto}.map-detail-type{font-size:11px;color:#5ba8ff;text-transform:uppercase;letter-spacing:.06em;flex:0 0 auto}.map-detail-desc{font-size:12px;color:#7a9bbf;flex:1}.map-btn{background:transparent;border:1px solid rgba(0,200,255,.3);border-radius:7px;color:#00c8ff;font-family:'Orbitron',sans-serif;font-size:11px;font-weight:700;padding:6px 14px;cursor:pointer}.map-legend{display:flex;gap:16px;flex-wrap:wrap}.map-legend-item{display:flex;align-items:center;gap:6px;font-size:12px;color:#7a9bbf}
38
+ </style>
@@ -0,0 +1,25 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ const emit = defineEmits<{ close: []; submit: [{ from: string; to: string; mode: string }] }>()
4
+ const form = ref({ from: '', to: '', mode: 'Walking' })
5
+ function handleSubmit() { emit('submit', { ...form.value }) }
6
+ </script>
7
+ <template>
8
+ <div class="p-shell">
9
+ <h2 class="p-title">📍 Plot Route on Map</h2>
10
+ <form class="p-form" @submit.prevent="handleSubmit">
11
+ <div class="p-row"><label class="p-label">From (coordinates or place)</label><input class="p-input" v-model="form.from" placeholder="Start location" /></div>
12
+ <div class="p-row"><label class="p-label">To (coordinates or place)</label><input class="p-input" v-model="form.to" placeholder="End location" /></div>
13
+ <div class="p-row">
14
+ <label class="p-label">Travel Mode</label>
15
+ <select class="p-input" v-model="form.mode">
16
+ <option>Walking</option><option>Driving</option><option>Flying</option><option>HolON Path</option>
17
+ </select>
18
+ </div>
19
+ <div class="p-actions"><button class="p-btn-cancel" type="button" @click="emit('close')">Cancel</button><button class="p-btn" type="submit">Plot Route</button></div>
20
+ </form>
21
+ </div>
22
+ </template>
23
+ <style scoped>
24
+ .p-shell{display:flex;flex-direction:column;gap:20px;padding:24px 20px}.p-title{font-family:'Orbitron',sans-serif;font-size:18px;color:#fff;margin:0}.p-form{display:flex;flex-direction:column;gap:14px}.p-row{display:flex;flex-direction:column;gap:6px}.p-label{font-size:12px;color:#7a9bbf;font-weight:600;letter-spacing:.05em}.p-input{background:rgba(255,255,255,.06);border:1px solid rgba(0,200,255,.2);border-radius:8px;color:#fff;font-size:14px;padding:10px 12px;width:100%;box-sizing:border-box;outline:none;transition:border-color .2s}.p-input:focus{border-color:rgba(0,200,255,.5)}.p-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:4px}.p-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:10px 24px;cursor:pointer;transition:opacity .2s}.p-btn:hover{opacity:.85}.p-btn-cancel{background:transparent;border:1px solid rgba(0,200,255,.3);border-radius:8px;color:#00c8ff;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:10px 24px;cursor:pointer}
25
+ </style>
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ const emit = defineEmits<{ close: []; submit: [{ query: string; type: string }] }>()
4
+ const form = ref({ query: '', type: 'All' })
5
+ function handleSubmit() { emit('submit', { ...form.value }) }
6
+ </script>
7
+ <template>
8
+ <div class="p-shell">
9
+ <h2 class="p-title">🔍 Search Map</h2>
10
+ <form class="p-form" @submit.prevent="handleSubmit">
11
+ <div class="p-row"><label class="p-label">Search Term</label><input class="p-input" v-model="form.query" placeholder="Search locations, objects, quests..." /></div>
12
+ <div class="p-row">
13
+ <label class="p-label">Type</label>
14
+ <select class="p-input" v-model="form.type">
15
+ <option>All</option><option>Location</option><option>Quest</option><option>OAPP</option><option>HolON</option><option>3D Object</option>
16
+ </select>
17
+ </div>
18
+ <div class="p-actions"><button class="p-btn-cancel" type="button" @click="emit('close')">Cancel</button><button class="p-btn" type="submit">Search</button></div>
19
+ </form>
20
+ </div>
21
+ </template>
22
+ <style scoped>
23
+ .p-shell{display:flex;flex-direction:column;gap:20px;padding:24px 20px}.p-title{font-family:'Orbitron',sans-serif;font-size:18px;color:#fff;margin:0}.p-form{display:flex;flex-direction:column;gap:14px}.p-row{display:flex;flex-direction:column;gap:6px}.p-label{font-size:12px;color:#7a9bbf;font-weight:600;letter-spacing:.05em}.p-input{background:rgba(255,255,255,.06);border:1px solid rgba(0,200,255,.2);border-radius:8px;color:#fff;font-size:14px;padding:10px 12px;width:100%;box-sizing:border-box;outline:none;transition:border-color .2s}.p-input:focus{border-color:rgba(0,200,255,.5)}.p-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:4px}.p-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:10px 24px;cursor:pointer;transition:opacity .2s}.p-btn:hover{opacity:.85}.p-btn-cancel{background:transparent;border:1px solid rgba(0,200,255,.3);border-radius:8px;color:#00c8ff;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:10px 24px;cursor:pointer}
24
+ </style>
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ const emit = defineEmits<{ close: [] }>()
3
+ </script>
4
+ <template>
5
+ <div class="p-shell">
6
+ <div class="p-icon">🌐</div>
7
+ <h2 class="p-title">View Global 3D Map</h2>
8
+ <p class="p-body">The global 3D map of Our World is coming soon — a fully immersive view of the entire OASIS planet including all player-built objects, quests, and HolONs.</p>
9
+ <button class="p-btn" @click="emit('close')">OK</button>
10
+ </div>
11
+ </template>
12
+ <style scoped>
13
+ .p-shell{display:flex;flex-direction:column;align-items:center;gap:16px;padding:32px 20px;text-align:center}.p-icon{font-size:44px}.p-title{font-family:'Orbitron',sans-serif;font-size:18px;color:#fff;margin:0}.p-body{font-size:14px;color:#a8bfd8;line-height:1.6;margin:0;max-width:360px}.p-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 28px;cursor:pointer;transition:opacity .2s}.p-btn:hover{opacity:.85}
14
+ </style>
@@ -0,0 +1,27 @@
1
+ <script setup lang="ts">
2
+ const emit = defineEmits<{ close: [] }>()
3
+ const halons = [
4
+ { name: 'London HolON', lat: '51.5074', lng: '-0.1278', members: 4200 },
5
+ { name: 'New York HolON', lat: '40.7128', lng: '-74.0060', members: 8100 },
6
+ { name: 'Tokyo HolON', lat: '35.6762', lng: '139.6503', members: 6300 },
7
+ ]
8
+ </script>
9
+ <template>
10
+ <div class="p-shell">
11
+ <h2 class="p-title">🔮 HolONs on Map</h2>
12
+ <div class="p-list">
13
+ <div v-for="h in halons" :key="h.name" class="p-item">
14
+ <span class="p-item-icon">🔮</span>
15
+ <div class="p-item-info">
16
+ <span class="p-item-name">{{ h.name }}</span>
17
+ <span class="p-item-desc">{{ h.lat }}, {{ h.lng }} · {{ h.members.toLocaleString() }} members</span>
18
+ </div>
19
+ <button class="p-view-btn">View</button>
20
+ </div>
21
+ </div>
22
+ <button class="p-btn" @click="emit('close')">Close</button>
23
+ </div>
24
+ </template>
25
+ <style scoped>
26
+ .p-shell{display:flex;flex-direction:column;gap:18px;padding:24px 20px}.p-title{font-family:'Orbitron',sans-serif;font-size:18px;color:#fff;margin:0}.p-list{display:flex;flex-direction:column;gap:10px}.p-item{display:flex;align-items:center;gap:14px;background:rgba(255,255,255,.04);border:1px solid rgba(0,200,255,.15);border-radius:10px;padding:14px}.p-item-icon{font-size:24px;flex-shrink:0}.p-item-info{display:flex;flex-direction:column;gap:3px;flex:1}.p-item-name{font-family:'Orbitron',sans-serif;font-size:13px;color:#fff;font-weight:700}.p-item-desc{font-size:12px;color:#7a9bbf}.p-view-btn{background:rgba(0,200,255,.12);border:1px solid rgba(0,200,255,.3);border-radius:6px;color:#00c8ff;font-family:'Orbitron',sans-serif;font-size:10px;font-weight:700;letter-spacing:.06em;padding:6px 14px;cursor:pointer}.p-btn{align-self:flex-end;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:10px 24px;cursor:pointer;transition:opacity .2s}.p-btn:hover{opacity:.85}
27
+ </style>
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ const emit = defineEmits<{ close: [] }>()
3
+ </script>
4
+ <template>
5
+ <div class="p-shell">
6
+ <div class="p-icon">📱</div>
7
+ <h2 class="p-title">View OAPPs on Map</h2>
8
+ <p class="p-body">See all OAPPs (OASIS Applications) pinned to real-world and virtual locations in Our World. This feature is coming soon.</p>
9
+ <button class="p-btn" @click="emit('close')">OK</button>
10
+ </div>
11
+ </template>
12
+ <style scoped>
13
+ .p-shell{display:flex;flex-direction:column;align-items:center;gap:16px;padding:32px 20px;text-align:center}.p-icon{font-size:44px}.p-title{font-family:'Orbitron',sans-serif;font-size:18px;color:#fff;margin:0}.p-body{font-size:14px;color:#a8bfd8;line-height:1.6;margin:0;max-width:360px}.p-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 28px;cursor:pointer;transition:opacity .2s}.p-btn:hover{opacity:.85}
14
+ </style>
@@ -0,0 +1,20 @@
1
+ <script setup lang="ts">
2
+ defineProps<{ questName?: string; lat?: string; lng?: string; description?: string }>()
3
+ const emit = defineEmits<{ close: [] }>()
4
+ </script>
5
+ <template>
6
+ <div class="p-shell">
7
+ <div class="p-icon">🗺️</div>
8
+ <h2 class="p-title">{{ questName ?? 'Quest Location' }}</h2>
9
+ <div class="p-coords" v-if="lat || lng">
10
+ <span class="p-coord-label">Coordinates</span>
11
+ <span class="p-coord-value">{{ lat ?? '0.0' }}, {{ lng ?? '0.0' }}</span>
12
+ </div>
13
+ <p class="p-body" v-if="description">{{ description }}</p>
14
+ <p class="p-body" v-else>Quest map integration is coming soon — you will be able to see quest locations, waypoints, and objectives overlaid on the Our World map.</p>
15
+ <button class="p-btn" @click="emit('close')">Close</button>
16
+ </div>
17
+ </template>
18
+ <style scoped>
19
+ .p-shell{display:flex;flex-direction:column;align-items:center;gap:16px;padding:32px 20px;text-align:center}.p-icon{font-size:44px}.p-title{font-family:'Orbitron',sans-serif;font-size:18px;color:#fff;margin:0}.p-coords{background:rgba(0,200,255,.06);border:1px solid rgba(0,200,255,.2);border-radius:8px;padding:10px 16px;display:flex;flex-direction:column;gap:4px}.p-coord-label{font-size:11px;color:#7a9bbf;font-weight:600;letter-spacing:.08em;text-transform:uppercase}.p-coord-value{font-family:'Orbitron',sans-serif;font-size:14px;color:#00c8ff}.p-body{font-size:14px;color:#a8bfd8;line-height:1.6;margin:0;max-width:360px}.p-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 28px;cursor:pointer;transition:opacity .2s}.p-btn:hover{opacity:.85}
20
+ </style>
@@ -0,0 +1,72 @@
1
+ <script setup lang="ts">
2
+ import { ref, computed } from 'vue';
3
+
4
+ interface Action { label: string; onClick: () => void; }
5
+ type MessageType = 'info' | 'success' | 'warning' | 'error';
6
+
7
+ const props = withDefaults(defineProps<{
8
+ title?: string;
9
+ message?: string;
10
+ icon?: string;
11
+ type?: MessageType;
12
+ badge?: string;
13
+ actions?: Action[];
14
+ }>(), {
15
+ title: 'Notice',
16
+ message: '',
17
+ icon: 'ℹ️',
18
+ type: 'info',
19
+ badge: '',
20
+ actions: () => [],
21
+ });
22
+
23
+ const emit = defineEmits<{ dismissed: [] }>();
24
+
25
+ const TYPE_COLORS: Record<MessageType, { border: string; bg: string }> = {
26
+ info: { border: 'rgba(0,200,255,.25)', bg: 'rgba(0,200,255,.05)' },
27
+ success: { border: 'rgba(72,220,130,.25)', bg: 'rgba(72,220,130,.05)' },
28
+ warning: { border: 'rgba(255,180,60,.25)', bg: 'rgba(255,180,60,.05)' },
29
+ error: { border: 'rgba(255,80,80,.25)', bg: 'rgba(255,80,80,.05)' },
30
+ };
31
+
32
+ const visible = ref(true);
33
+ const colors = computed(() => TYPE_COLORS[props.type] ?? TYPE_COLORS.info);
34
+
35
+ function dismiss() { visible.value = false; emit('dismissed'); }
36
+ </script>
37
+
38
+ <template>
39
+ <div v-if="visible" class="mm-shell" :style="{ border: `1px solid ${colors.border}`, background: colors.bg }">
40
+ <div class="mm-header">
41
+ <span class="mm-icon">{{ icon }}</span>
42
+ <span class="mm-title">{{ title }}</span>
43
+ <span v-if="badge" class="mm-badge">{{ badge }}</span>
44
+ <button class="mm-close" @click="dismiss" aria-label="Dismiss">✕</button>
45
+ </div>
46
+ <div class="mm-body">
47
+ <p v-if="message" class="mm-msg">{{ message }}</p>
48
+ <div v-if="actions.length > 0" class="mm-actions">
49
+ <button
50
+ v-for="(a, i) in actions"
51
+ :key="i"
52
+ :class="i === 0 ? 'mm-btn' : 'mm-btn-ghost'"
53
+ @click="a.onClick()"
54
+ >{{ a.label }}</button>
55
+ </div>
56
+ </div>
57
+ </div>
58
+ </template>
59
+
60
+ <style scoped>
61
+ .mm-shell { font-family: 'Rajdhani', sans-serif; border-radius: 12px; overflow: hidden; }
62
+ .mm-header { padding: 14px 18px; background: rgba(0,200,255,.07); border-bottom: 1px solid rgba(0,200,255,.12); display: flex; align-items: center; gap: 12px; }
63
+ .mm-icon { font-size: 20px; }
64
+ .mm-title { font-family: 'Orbitron', sans-serif; font-size: 15px; font-weight: 700; color: #fff; flex: 1; }
65
+ .mm-badge { display: inline-block; background: rgba(0,200,255,.12); border: 1px solid rgba(0,200,255,.3); color: #00c8ff; border-radius: 999px; font-size: 11px; font-weight: 700; letter-spacing: .08em; padding: 3px 12px; text-transform: uppercase; }
66
+ .mm-close { background: none; border: none; color: #7a9bbf; font-size: 18px; cursor: pointer; line-height: 1; }
67
+ .mm-body { padding: 18px; display: flex; flex-direction: column; gap: 12px; }
68
+ .mm-msg { font-size: 14px; color: #a8bfd8; line-height: 1.65; text-align: center; margin: 0; }
69
+ .mm-actions { display: flex; gap: 10px; justify-content: center; margin-top: 4px; }
70
+ .mm-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: 9px 22px; cursor: pointer; }
71
+ .mm-btn-ghost { background: transparent; border: 1px solid rgba(0,200,255,.3); border-radius: 8px; color: #00c8ff; font-family: 'Orbitron', sans-serif; font-size: 12px; font-weight: 700; letter-spacing: .08em; padding: 9px 22px; cursor: pointer; }
72
+ </style>
@@ -0,0 +1,50 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ interface Contact { name: string; lastMessage: string; date: string; active: boolean }
4
+ interface Msg { from: string; date: string; message: string }
5
+ const contacts: Contact[] = [
6
+ { name: 'Alice', lastMessage: 'See you in Our World!', date: 'Today', active: true },
7
+ { name: 'Bob', lastMessage: 'Quest complete!', date: 'Yesterday', active: false },
8
+ ]
9
+ const messages: Msg[] = [
10
+ { from: 'Alice', date: '10:00 am', message: 'Hey! Are you joining the quest later?' },
11
+ { from: 'me', date: '10:02 am', message: 'Yes! Just finishing up some karma votes.' },
12
+ { from: 'Alice', date: '10:05 am', message: 'Great, see you in Our World!' },
13
+ ]
14
+ const draft = ref('')
15
+ const emit = defineEmits<{ close: [] }>()
16
+ </script>
17
+ <template>
18
+ <div class="msg-shell">
19
+ <div class="msg-sidebar">
20
+ <div class="msg-sidebar-title">Messages</div>
21
+ <div v-for="c in contacts" :key="c.name" class="msg-contact" :class="{ 'msg-contact--active': c.active }">
22
+ <div class="msg-contact-avatar">{{ c.name[0] }}</div>
23
+ <div class="msg-contact-info">
24
+ <span class="msg-contact-name">{{ c.name }}</span>
25
+ <span class="msg-contact-last">{{ c.lastMessage }}</span>
26
+ </div>
27
+ <span class="msg-contact-date">{{ c.date }}</span>
28
+ </div>
29
+ </div>
30
+ <div class="msg-main">
31
+ <div class="msg-header">
32
+ <span class="msg-header-name">Alice</span>
33
+ <button class="msg-close-btn" @click="emit('close')">✕</button>
34
+ </div>
35
+ <div class="msg-feed">
36
+ <div v-for="(m, i) in messages" :key="i" class="msg-bubble" :class="m.from === 'me' ? 'msg-bubble--me' : 'msg-bubble--them'">
37
+ <span class="msg-text">{{ m.message }}</span>
38
+ <span class="msg-date">{{ m.date }}</span>
39
+ </div>
40
+ </div>
41
+ <form class="msg-compose" @submit.prevent="draft = ''">
42
+ <input class="msg-input" v-model="draft" placeholder="Type a message..." />
43
+ <button class="msg-send-btn" type="submit">Send</button>
44
+ </form>
45
+ </div>
46
+ </div>
47
+ </template>
48
+ <style scoped>
49
+ .msg-shell{display:flex;height:420px;overflow:hidden;border-radius:12px}.msg-sidebar{width:200px;flex-shrink:0;border-right:1px solid rgba(0,200,255,.15);display:flex;flex-direction:column;overflow-y:auto}.msg-sidebar-title{font-family:'Orbitron',sans-serif;font-size:13px;color:#00c8ff;padding:16px 14px 10px;font-weight:700;letter-spacing:.06em}.msg-contact{display:flex;align-items:center;gap:10px;padding:10px 14px;cursor:pointer;transition:background .2s}.msg-contact:hover{background:rgba(0,200,255,.05)}.msg-contact--active{background:rgba(0,200,255,.08)}.msg-contact-avatar{width:34px;height:34px;border-radius:50%;background:linear-gradient(135deg,#00c8ff,#0080ff);display:flex;align-items:center;justify-content:center;font-family:'Orbitron',sans-serif;font-size:13px;color:#fff;font-weight:700;flex-shrink:0}.msg-contact-info{flex:1;overflow:hidden;display:flex;flex-direction:column;gap:2px}.msg-contact-name{font-size:13px;color:#fff;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.msg-contact-last{font-size:11px;color:#7a9bbf;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.msg-contact-date{font-size:10px;color:#5a7a9a;flex-shrink:0}.msg-main{flex:1;display:flex;flex-direction:column;overflow:hidden}.msg-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid rgba(0,200,255,.12)}.msg-header-name{font-family:'Orbitron',sans-serif;font-size:14px;color:#fff;font-weight:700}.msg-close-btn{background:none;border:none;color:#7a9bbf;font-size:16px;cursor:pointer;padding:4px 8px}.msg-feed{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:10px}.msg-bubble{display:flex;flex-direction:column;gap:3px;max-width:75%}.msg-bubble--me{align-self:flex-end;align-items:flex-end}.msg-bubble--them{align-self:flex-start;align-items:flex-start}.msg-text{background:rgba(0,200,255,.12);border:1px solid rgba(0,200,255,.2);border-radius:10px;color:#fff;font-size:13px;padding:8px 12px;line-height:1.5}.msg-bubble--me .msg-text{background:rgba(0,128,255,.2);border-color:rgba(0,128,255,.3)}.msg-date{font-size:10px;color:#5a7a9a}.msg-compose{display:flex;gap:8px;padding:12px 16px;border-top:1px solid rgba(0,200,255,.12)}.msg-input{flex:1;background:rgba(255,255,255,.06);border:1px solid rgba(0,200,255,.2);border-radius:8px;color:#fff;font-size:13px;padding:9px 12px;outline:none;transition:border-color .2s}.msg-input:focus{border-color:rgba(0,200,255,.5)}.msg-send-btn{background:linear-gradient(135deg,#00c8ff,#0080ff);border:none;border-radius:8px;color:#fff;font-family:'Orbitron',sans-serif;font-size:11px;font-weight:700;letter-spacing:.06em;padding:9px 18px;cursor:pointer;transition:opacity .2s}.msg-send-btn:hover{opacity:.85}
50
+ </style>
@@ -0,0 +1,44 @@
1
+ <script setup lang="ts">
2
+ import { ref, computed } from 'vue'
3
+ interface Message { id: string; from: string; preview: string; time: string; read: boolean; body: string }
4
+ const searchQuery = ref(''), reply = ref(''), selected = ref<Message | null>(null)
5
+ const messages = ref<Message[]>([
6
+ { id: '1', from: 'OASIS Team', preview: 'Welcome to the OASIS network!', time: 'Just now', read: false, body: 'Welcome to the OASIS Omniverse! Your avatar is now connected to the network. Explore NFTs, karma, quests and more.' },
7
+ { id: '2', from: 'System', preview: 'Your karma level has increased.', time: '2h ago', read: true, body: 'Congratulations! Your karma level has increased. Keep contributing to the community to unlock new features and NFTs.' },
8
+ ])
9
+ const filtered = computed(() => {
10
+ const q = searchQuery.value.toLowerCase()
11
+ return messages.value.filter(m => m.from.toLowerCase().includes(q) || m.preview.toLowerCase().includes(q))
12
+ })
13
+ function open(m: Message) { m.read = true; selected.value = { ...m }; reply.value = '' }
14
+ function sendReply() { if (!reply.value.trim()) return; reply.value = '' }
15
+ </script>
16
+ <template>
17
+ <div class="msg-shell">
18
+ <div class="msg-sidebar">
19
+ <div class="msg-search-wrap"><input class="msg-search" type="text" v-model="searchQuery" placeholder="Search messages…" /></div>
20
+ <div class="msg-list">
21
+ <div v-for="m in filtered" :key="m.id" class="msg-item" :class="{ 'msg-item--active': selected?.id === m.id, 'msg-item--unread': !m.read }" @click="open(m)">
22
+ <div class="msg-from">{{ m.from }}</div>
23
+ <div class="msg-preview">{{ m.preview }}</div>
24
+ <div class="msg-time">{{ m.time }}</div>
25
+ </div>
26
+ <div v-if="filtered.length === 0" class="msg-empty">No messages found.</div>
27
+ </div>
28
+ </div>
29
+ <div class="msg-main">
30
+ <template v-if="selected">
31
+ <div class="msg-detail-header"><div class="msg-detail-from">{{ selected.from }}</div><div class="msg-detail-time">{{ selected.time }}</div></div>
32
+ <div class="msg-body">{{ selected.body }}</div>
33
+ <div class="msg-reply-wrap">
34
+ <textarea class="msg-reply-input" v-model="reply" placeholder="Write a reply…" rows="3"></textarea>
35
+ <button class="oasis-btn" :disabled="!reply.trim()" @click="sendReply">Send</button>
36
+ </div>
37
+ </template>
38
+ <div v-else class="msg-placeholder">📬 Select a message to read it</div>
39
+ </div>
40
+ </div>
41
+ </template>
42
+ <style scoped>
43
+ .msg-shell{display:grid;grid-template-columns:280px 1fr;height:480px;border:1px solid rgba(0,200,255,.15);border-radius:12px;overflow:hidden}.msg-sidebar{border-right:1px solid rgba(0,200,255,.1);display:flex;flex-direction:column}.msg-search-wrap{padding:12px;border-bottom:1px solid rgba(0,200,255,.1)}.msg-search{width:100%;background:rgba(255,255,255,.05);border:1px solid rgba(0,200,255,.2);border-radius:8px;padding:8px 12px;color:#fff;font-size:13px;outline:none;box-sizing:border-box}.msg-list{flex:1;overflow-y:auto}.msg-item{padding:12px 14px;border-bottom:1px solid rgba(0,200,255,.07);cursor:pointer;transition:background .15s}.msg-item:hover{background:rgba(0,200,255,.06)}.msg-item--active{background:rgba(0,200,255,.1);border-left:3px solid #00c8ff}.msg-item--unread .msg-from{font-weight:700}.msg-from{font-size:13px;color:#e0f0ff;margin-bottom:3px}.msg-preview{font-size:12px;color:#7a9bbf;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.msg-time{font-size:11px;color:#4a6a88;margin-top:4px}.msg-empty{padding:24px;text-align:center;color:#4a6a88;font-size:13px}.msg-main{display:flex;flex-direction:column;background:rgba(0,0,0,.2)}.msg-placeholder{display:flex;align-items:center;justify-content:center;flex:1;color:#4a6a88;font-size:14px}.msg-detail-header{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;border-bottom:1px solid rgba(0,200,255,.1)}.msg-detail-from{font-family:'Orbitron',sans-serif;font-size:14px;color:#fff}.msg-detail-time{font-size:12px;color:#4a6a88}.msg-body{flex:1;padding:20px;font-size:14px;color:#a8bfd8;line-height:1.7;overflow-y:auto}.msg-reply-wrap{padding:16px;border-top:1px solid rgba(0,200,255,.1);display:flex;flex-direction:column;gap:10px}.msg-reply-input{width:100%;background:rgba(255,255,255,.05);border:1px solid rgba(0,200,255,.2);border-radius:8px;padding:10px 14px;color:#fff;font-size:13px;outline:none;resize:none;box-sizing:border-box;font-family:inherit}.oasis-btn{align-self:flex-end;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:9px 24px;cursor:pointer;transition:opacity .2s}.oasis-btn:disabled{opacity:.4;cursor:not-allowed}
44
+ </style>
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ const emit = defineEmits<{ close: [] }>()
3
+ </script>
4
+ <template>
5
+ <div class="p-shell">
6
+ <div class="p-icon">🎯</div>
7
+ <h2 class="p-title">Manage Mission</h2>
8
+ <p class="p-body">Mission management tools are coming soon — create, edit, and track your OASIS missions with full multi-provider support.</p>
9
+ <button class="p-btn" @click="emit('close')">OK</button>
10
+ </div>
11
+ </template>
12
+ <style scoped>
13
+ .p-shell{display:flex;flex-direction:column;align-items:center;gap:16px;padding:32px 20px;text-align:center}.p-icon{font-size:44px}.p-title{font-family:'Orbitron',sans-serif;font-size:18px;color:#fff;margin:0}.p-body{font-size:14px;color:#a8bfd8;line-height:1.6;margin:0;max-width:360px}.p-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 28px;cursor:pointer;transition:opacity .2s}.p-btn:hover{opacity:.85}
14
+ </style>
@@ -0,0 +1,32 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ interface Mission { id: string; title: string; description: string; reward: number; status: 'available' | 'active' | 'complete' }
4
+ const missions = ref<Mission[]>([
5
+ { id: '1', title: 'First Contact', description: 'Log into OASIS for the first time and explore the hub.', reward: 100, status: 'complete' },
6
+ { id: '2', title: 'Karma Cultivator', description: 'Earn 500 karma through positive actions in the OASIS.', reward: 250, status: 'active' },
7
+ { id: '3', title: 'NFT Hunter', description: 'Acquire your first rare NFT from the marketplace.', reward: 400, status: 'available' },
8
+ { id: '4', title: 'Seed Planter', description: 'Plant 3 seeds and nurture them to full growth.', reward: 150, status: 'available' },
9
+ ])
10
+ function statusLabel(s: string) { return s === 'available' ? 'Available' : s === 'active' ? 'In Progress' : 'Complete' }
11
+ function accept(m: Mission) { m.status = 'active' }
12
+ function complete(m: Mission) { m.status = 'complete' }
13
+ </script>
14
+ <template>
15
+ <div class="mis-shell">
16
+ <div class="mis-header"><h2 class="mis-title">🎯 Missions</h2><p class="mis-sub">Complete missions to earn karma and unlock rewards.</p></div>
17
+ <div class="mis-list">
18
+ <div v-for="m in missions" :key="m.id" class="mis-card" :class="`mis-card--${m.status}`">
19
+ <div class="mis-left"><div class="mis-title-text">{{ m.title }}</div><div class="mis-desc">{{ m.description }}</div></div>
20
+ <div class="mis-right">
21
+ <div class="mis-reward">+{{ m.reward }} karma</div>
22
+ <div class="mis-status-badge" :class="`mis-status-badge--${m.status}`">{{ statusLabel(m.status) }}</div>
23
+ <button v-if="m.status === 'available'" class="mis-btn" @click="accept(m)">Accept</button>
24
+ <button v-if="m.status === 'active'" class="mis-btn mis-btn--complete" @click="complete(m)">Complete</button>
25
+ </div>
26
+ </div>
27
+ </div>
28
+ </div>
29
+ </template>
30
+ <style scoped>
31
+ .mis-shell{display:flex;flex-direction:column;gap:18px}.mis-header{text-align:center}.mis-title{font-family:'Orbitron',sans-serif;font-size:20px;color:#fff;margin:0 0 6px}.mis-sub{font-size:13px;color:#7a9bbf;margin:0}.mis-list{display:flex;flex-direction:column;gap:12px}.mis-card{display:flex;align-items:center;gap:16px;background:rgba(255,255,255,.04);border:1px solid rgba(0,200,255,.12);border-radius:12px;padding:16px}.mis-card--active{border-color:rgba(0,200,255,.35);background:rgba(0,200,255,.05)}.mis-card--complete{border-color:rgba(72,220,130,.25);background:rgba(72,220,130,.04);opacity:.7}.mis-left{flex:1}.mis-title-text{font-family:'Orbitron',sans-serif;font-size:13px;color:#fff;margin-bottom:4px}.mis-desc{font-size:12px;color:#7a9bbf;line-height:1.5}.mis-right{display:flex;flex-direction:column;align-items:flex-end;gap:8px;flex-shrink:0}.mis-reward{font-size:12px;color:#48dc82;font-weight:600;white-space:nowrap}.mis-status-badge{font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;border-radius:999px;padding:3px 10px;border:1px solid currentColor}.mis-status-badge--available{color:#7a9bbf;border-color:rgba(122,155,191,.3)}.mis-status-badge--active{color:#00c8ff;border-color:rgba(0,200,255,.35)}.mis-status-badge--complete{color:#48dc82;border-color:rgba(72,220,130,.3)}.mis-btn{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:7px 16px;cursor:pointer;white-space:nowrap}.mis-btn--complete{background:linear-gradient(135deg,#48dc82,#00aa55)}
32
+ </style>
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ const emit = defineEmits<{ close: []; submit: [{ query: string; status: string }] }>()
4
+ const form = ref({ query: '', status: 'All' })
5
+ function handleSubmit() { emit('submit', { ...form.value }) }
6
+ </script>
7
+ <template>
8
+ <div class="p-shell">
9
+ <h2 class="p-title">🔍 Search Mission</h2>
10
+ <form class="p-form" @submit.prevent="handleSubmit">
11
+ <div class="p-row"><label class="p-label">Mission Name</label><input class="p-input" v-model="form.query" placeholder="Search missions..." /></div>
12
+ <div class="p-row">
13
+ <label class="p-label">Status</label>
14
+ <select class="p-input" v-model="form.status">
15
+ <option>All</option><option>Active</option><option>Completed</option><option>Failed</option><option>Pending</option>
16
+ </select>
17
+ </div>
18
+ <div class="p-actions"><button class="p-btn-cancel" type="button" @click="emit('close')">Cancel</button><button class="p-btn" type="submit">Search</button></div>
19
+ </form>
20
+ </div>
21
+ </template>
22
+ <style scoped>
23
+ .p-shell{display:flex;flex-direction:column;gap:20px;padding:24px 20px}.p-title{font-family:'Orbitron',sans-serif;font-size:18px;color:#fff;margin:0}.p-form{display:flex;flex-direction:column;gap:14px}.p-row{display:flex;flex-direction:column;gap:6px}.p-label{font-size:12px;color:#7a9bbf;font-weight:600;letter-spacing:.05em}.p-input{background:rgba(255,255,255,.06);border:1px solid rgba(0,200,255,.2);border-radius:8px;color:#fff;font-size:14px;padding:10px 12px;width:100%;box-sizing:border-box;outline:none;transition:border-color .2s}.p-input:focus{border-color:rgba(0,200,255,.5)}.p-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:4px}.p-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:10px 24px;cursor:pointer;transition:opacity .2s}.p-btn:hover{opacity:.85}.p-btn-cancel{background:transparent;border:1px solid rgba(0,200,255,.3);border-radius:8px;color:#00c8ff;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:10px 24px;cursor:pointer}
24
+ </style>
@@ -0,0 +1,21 @@
1
+ <script setup lang="ts">
2
+ defineProps<{ name?: string; description?: string; status?: string; reward?: string; progress?: number }>()
3
+ const emit = defineEmits<{ close: [] }>()
4
+ </script>
5
+ <template>
6
+ <div class="p-shell">
7
+ <div class="p-icon">🎯</div>
8
+ <h2 class="p-title">{{ name ?? 'Mission Details' }}</h2>
9
+ <div class="p-status-badge" :class="`p-status--${(status ?? 'active').toLowerCase()}`">{{ status ?? 'Active' }}</div>
10
+ <p class="p-body">{{ description ?? 'Complete objectives to advance this mission and earn rewards in the OASIS.' }}</p>
11
+ <div class="p-reward" v-if="reward"><span class="p-reward-label">Reward</span><span class="p-reward-value">{{ reward }}</span></div>
12
+ <div class="p-progress-wrap" v-if="progress !== undefined">
13
+ <div class="p-progress-bar"><div class="p-progress-fill" :style="{ width: progress + '%' }"></div></div>
14
+ <span class="p-pct">{{ progress }}% complete</span>
15
+ </div>
16
+ <button class="p-btn" @click="emit('close')">Close</button>
17
+ </div>
18
+ </template>
19
+ <style scoped>
20
+ .p-shell{display:flex;flex-direction:column;align-items:center;gap:16px;padding:32px 20px;text-align:center}.p-icon{font-size:48px}.p-title{font-family:'Orbitron',sans-serif;font-size:18px;color:#fff;margin:0}.p-status-badge{font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;border-radius:999px;padding:4px 12px;border:1px solid currentColor}.p-status--active{color:#00e676}.p-status--completed{color:#ffb43c}.p-status--failed{color:#ff4444}.p-status--pending{color:#7a9bbf}.p-body{font-size:14px;color:#a8bfd8;line-height:1.6;margin:0;max-width:360px}.p-reward{background:rgba(255,180,60,.06);border:1px solid rgba(255,180,60,.2);border-radius:8px;padding:10px 16px;display:flex;gap:10px;align-items:center}.p-reward-label{font-size:11px;color:#7a9bbf;font-weight:600;letter-spacing:.08em;text-transform:uppercase}.p-reward-value{font-family:'Orbitron',sans-serif;font-size:14px;color:#ffb43c;font-weight:700}.p-progress-wrap{width:100%;max-width:300px;display:flex;flex-direction:column;gap:6px;align-items:center}.p-progress-bar{width:100%;height:8px;background:rgba(255,255,255,.1);border-radius:999px;overflow:hidden}.p-progress-fill{height:100%;background:linear-gradient(90deg,#00c8ff,#0080ff);border-radius:999px}.p-pct{font-size:12px;color:#7a9bbf}.p-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 28px;cursor:pointer;transition:opacity .2s}.p-btn:hover{opacity:.85}
21
+ </style>