@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.
- package/package.json +37 -0
- package/src/components/Avatar/AvatarWallet.vue +29 -0
- package/src/components/Avatar/EditAvatar.vue +21 -0
- package/src/components/Avatar/SearchAvatar.vue +24 -0
- package/src/components/Avatar/ViewAvatar.vue +19 -0
- package/src/components/AvatarConnect/AvatarConnect.vue +64 -0
- package/src/components/AvatarProfile/AvatarProfile.vue +123 -0
- package/src/components/ComingSoon/ComingSoon.vue +14 -0
- package/src/components/Confirmation/Confirmation.vue +18 -0
- package/src/components/Contact/Contact.vue +40 -0
- package/src/components/DataScreen/AddData.vue +26 -0
- package/src/components/DataScreen/CrossChainManagement.vue +14 -0
- package/src/components/DataScreen/LoadData.vue +24 -0
- package/src/components/DataScreen/ManageData.vue +14 -0
- package/src/components/DataScreen/OffChainManagement.vue +14 -0
- package/src/components/DataScreen/SearchData.vue +24 -0
- package/src/components/Eggs/Eggs.vue +40 -0
- package/src/components/Eggs/ManageEggs.vue +14 -0
- package/src/components/Eggs/SearchEggs.vue +24 -0
- package/src/components/Eggs/ViewEggs.vue +20 -0
- package/src/components/ForgotPassword/ForgotPassword.vue +71 -0
- package/src/components/Game/Game.vue +29 -0
- package/src/components/Game/SearchProfiles.vue +24 -0
- package/src/components/Game/ViewAchievements.vue +25 -0
- package/src/components/Game/ViewLeagues.vue +25 -0
- package/src/components/Game/ViewTournaments.vue +27 -0
- package/src/components/HyperDrive/HyperDrive.vue +46 -0
- package/src/components/Karma/SearchKarma.vue +24 -0
- package/src/components/Karma/ViewAvatarKarma.vue +20 -0
- package/src/components/Karma/ViewKarma.vue +30 -0
- package/src/components/Karma/VoteKarma.vue +26 -0
- package/src/components/KarmaPanel/KarmaPanel.vue +71 -0
- package/src/components/KarmaToast/KarmaToast.vue +29 -0
- package/src/components/Login/Login.vue +90 -0
- package/src/components/Map/Add2dObjectMap.vue +23 -0
- package/src/components/Map/Add3dObjectMap.vue +24 -0
- package/src/components/Map/AddQuestToMap.vue +22 -0
- package/src/components/Map/DownloadOurWorld.vue +18 -0
- package/src/components/Map/ManageMap.vue +14 -0
- package/src/components/Map/Map.vue +38 -0
- package/src/components/Map/PlotRouteOnMap.vue +25 -0
- package/src/components/Map/SearchMap.vue +24 -0
- package/src/components/Map/ViewGlobal3dMap.vue +14 -0
- package/src/components/Map/ViewHalonsOnMap.vue +27 -0
- package/src/components/Map/ViewOappOnMap.vue +14 -0
- package/src/components/Map/ViewQuestOnMap.vue +20 -0
- package/src/components/MenuMessage/MenuMessage.vue +72 -0
- package/src/components/Message/Message.vue +50 -0
- package/src/components/Messaging/Messaging.vue +44 -0
- package/src/components/Mission/ManageMission.vue +14 -0
- package/src/components/Mission/Mission.vue +32 -0
- package/src/components/Mission/SearchMission.vue +24 -0
- package/src/components/Mission/ViewMission.vue +21 -0
- package/src/components/NFT/ContactPopup.vue +36 -0
- package/src/components/NFT/ManageOasisNft.vue +14 -0
- package/src/components/NFT/NFT.vue +36 -0
- package/src/components/NFT/PurchaseOasisNft.vue +21 -0
- package/src/components/NFT/PurchaseOasisVirtualLandNft.vue +23 -0
- package/src/components/NFT/SearchOasisNft.vue +30 -0
- package/src/components/NFT/Solana.vue +27 -0
- package/src/components/NFT/ViewOasisNft.vue +20 -0
- package/src/components/NavBar/NavBar.vue +71 -0
- package/src/components/OApp/CreateOAPP.vue +31 -0
- package/src/components/OApp/DeployOAPP.vue +23 -0
- package/src/components/OApp/DownloadOurWorld.vue +18 -0
- package/src/components/OApp/EditOAPP.vue +21 -0
- package/src/components/OApp/InstallOAPP.vue +23 -0
- package/src/components/OApp/LaunchOAPP.vue +19 -0
- package/src/components/OApp/ManageOAPP.vue +14 -0
- package/src/components/OApp/OApp.vue +40 -0
- package/src/components/OApp/SearchOAPP.vue +30 -0
- package/src/components/ONET/ONET.vue +40 -0
- package/src/components/ONODE/ONODE.vue +42 -0
- package/src/components/OasisModal/OasisModal.vue +36 -0
- package/src/components/Provider/ActivityPub.vue +14 -0
- package/src/components/Provider/CompareProviderSpeeds.vue +32 -0
- package/src/components/Provider/Eosio.vue +14 -0
- package/src/components/Provider/Ethereum.vue +14 -0
- package/src/components/Provider/Holochain.vue +14 -0
- package/src/components/Provider/Ipfs.vue +14 -0
- package/src/components/Provider/ManageAutoFailOver.vue +14 -0
- package/src/components/Provider/ManageAutoReplicaton.vue +14 -0
- package/src/components/Provider/ManageLoadBalancing.vue +14 -0
- package/src/components/Provider/ManageProviders.vue +27 -0
- package/src/components/Provider/MongoDb.vue +14 -0
- package/src/components/Provider/Neo4j.vue +14 -0
- package/src/components/Provider/SearchProviders.vue +24 -0
- package/src/components/Provider/Seeds.vue +14 -0
- package/src/components/Provider/Solid.vue +14 -0
- package/src/components/Provider/SqlLite.vue +14 -0
- package/src/components/Provider/ThreeFold.vue +14 -0
- package/src/components/Provider/ViewProviderStats.vue +27 -0
- package/src/components/Provider/ViewProviders.vue +30 -0
- package/src/components/ProviderDropdown/ProviderDropdown.vue +34 -0
- package/src/components/Providers/Providers.vue +30 -0
- package/src/components/Quest/ManageQuest.vue +14 -0
- package/src/components/Quest/Quest.vue +35 -0
- package/src/components/Quest/SearchQuest.vue +30 -0
- package/src/components/Quest/ViewQuest.vue +23 -0
- package/src/components/ResetPassword/ResetPassword.vue +39 -0
- package/src/components/SearchAvatars/SearchAvatars.vue +42 -0
- package/src/components/Seeds/AcceptInvite.vue +26 -0
- package/src/components/Seeds/DonateSeeds.vue +34 -0
- package/src/components/Seeds/ManageSeeds.vue +14 -0
- package/src/components/Seeds/PayWithSeeds.vue +34 -0
- package/src/components/Seeds/RewardSeeds.vue +20 -0
- package/src/components/Seeds/SearchSeeds.vue +18 -0
- package/src/components/Seeds/Seeds.vue +37 -0
- package/src/components/Seeds/SendInvite.vue +34 -0
- package/src/components/Seeds/ViewOrganizations.vue +27 -0
- package/src/components/Seeds/ViewSeeds.vue +34 -0
- package/src/components/Settings/Settings.vue +52 -0
- package/src/components/Signup/Signup.vue +121 -0
- package/src/components/StarField/StarField.vue +55 -0
- package/src/components/VerifyEmail/VerifyEmail.vue +21 -0
- package/src/components/Wallet/Wallet.vue +41 -0
- package/src/index.ts +143 -0
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@oasisomniverse/vue",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "OASIS Omniverse Vue 3 UI components",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"oasis",
|
|
7
|
+
"omniverse",
|
|
8
|
+
"vue",
|
|
9
|
+
"vue3",
|
|
10
|
+
"components"
|
|
11
|
+
],
|
|
12
|
+
"author": "NextGenSoftware",
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/NextGenSoftwareUK/OASIS-Vue-UI-Component-Library.git"
|
|
17
|
+
},
|
|
18
|
+
"main": "src/index.ts",
|
|
19
|
+
"module": "src/index.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": "./src/index.ts",
|
|
22
|
+
"./components/*": "./src/components/*.vue"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"src"
|
|
26
|
+
],
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"vue": "\u003e=3.0.0",
|
|
29
|
+
"@oasisomniverse/web4-api": "\u003e=2.0.0"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
|
|
33
|
+
},
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
interface WalletRow { date: string; note: string; fromAvatar: string; fromWallet: string; token: string; amount: string; balance: string; provider: string; type: string }
|
|
3
|
+
const emit = defineEmits<{ close: [] }>()
|
|
4
|
+
const rows: WalletRow[] = [
|
|
5
|
+
{ date: '2024-01-01', note: 'Initial deposit', fromAvatar: 'System', fromWallet: 'Genesis', token: 'KARMA', amount: '+500', balance: '500', provider: 'Holochain', type: 'Credit' },
|
|
6
|
+
{ date: '2024-01-15', note: 'Quest reward', fromAvatar: 'QuestMaster', fromWallet: '0xabc...', token: 'SEEDS', amount: '+100', balance: '600', provider: 'Ethereum', type: 'Credit' },
|
|
7
|
+
]
|
|
8
|
+
</script>
|
|
9
|
+
<template>
|
|
10
|
+
<div class="p-shell">
|
|
11
|
+
<h2 class="p-title">💳 Avatar Wallet</h2>
|
|
12
|
+
<div class="p-table-wrap">
|
|
13
|
+
<table class="p-table">
|
|
14
|
+
<thead>
|
|
15
|
+
<tr><th>Date</th><th>Note</th><th>From Avatar</th><th>From Wallet</th><th>Token</th><th>Amount</th><th>Balance</th><th>Provider</th><th>Type</th></tr>
|
|
16
|
+
</thead>
|
|
17
|
+
<tbody>
|
|
18
|
+
<tr v-for="(r, i) in rows" :key="i">
|
|
19
|
+
<td>{{ r.date }}</td><td>{{ r.note }}</td><td>{{ r.fromAvatar }}</td><td>{{ r.fromWallet }}</td><td>{{ r.token }}</td><td>{{ r.amount }}</td><td>{{ r.balance }}</td><td>{{ r.provider }}</td><td>{{ r.type }}</td>
|
|
20
|
+
</tr>
|
|
21
|
+
</tbody>
|
|
22
|
+
</table>
|
|
23
|
+
</div>
|
|
24
|
+
<button class="p-btn" @click="emit('close')">Close</button>
|
|
25
|
+
</div>
|
|
26
|
+
</template>
|
|
27
|
+
<style scoped>
|
|
28
|
+
.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-table-wrap{overflow-x:auto;border-radius:10px;border:1px solid rgba(0,200,255,.15)}.p-table{width:100%;border-collapse:collapse;font-size:13px}.p-table th{background:rgba(0,200,255,.08);color:#00c8ff;font-family:'Orbitron',sans-serif;font-size:11px;font-weight:700;letter-spacing:.06em;padding:10px 12px;text-align:left;white-space:nowrap}.p-table td{color:#c8dff0;padding:9px 12px;border-top:1px solid rgba(255,255,255,.05)}.p-table tr:hover td{background:rgba(0,200,255,.04)}.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}
|
|
29
|
+
</style>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
const emit = defineEmits<{ close: []; submit: [{ username: string; bio: string; avatar2d: string; avatar3d: string }] }>()
|
|
4
|
+
const form = ref({ username: '', bio: '', avatar2d: '', avatar3d: '' })
|
|
5
|
+
function handleSubmit() { emit('submit', { ...form.value }) }
|
|
6
|
+
</script>
|
|
7
|
+
<template>
|
|
8
|
+
<div class="p-shell">
|
|
9
|
+
<h2 class="p-title">✏️ Edit Avatar</h2>
|
|
10
|
+
<form class="p-form" @submit.prevent="handleSubmit">
|
|
11
|
+
<div class="p-row"><label class="p-label">Username</label><input class="p-input" v-model="form.username" placeholder="Your username" /></div>
|
|
12
|
+
<div class="p-row"><label class="p-label">Bio</label><textarea class="p-textarea" v-model="form.bio" placeholder="Tell the OASIS about yourself..."></textarea></div>
|
|
13
|
+
<div class="p-row"><label class="p-label">2D Avatar URL</label><input class="p-input" v-model="form.avatar2d" placeholder="https://..." /></div>
|
|
14
|
+
<div class="p-row"><label class="p-label">3D Avatar URL</label><input class="p-input" v-model="form.avatar3d" placeholder="https://..." /></div>
|
|
15
|
+
<div class="p-actions"><button class="p-btn-cancel" type="button" @click="emit('close')">Cancel</button><button class="p-btn" type="submit">Save</button></div>
|
|
16
|
+
</form>
|
|
17
|
+
</div>
|
|
18
|
+
</template>
|
|
19
|
+
<style scoped>
|
|
20
|
+
.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,.p-textarea{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,.p-textarea:focus{border-color:rgba(0,200,255,.5)}.p-textarea{min-height:80px;resize:vertical}.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}
|
|
21
|
+
</style>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
const emit = defineEmits<{ close: []; submit: [{ query: string; provider: string }] }>()
|
|
4
|
+
const form = ref({ query: '', provider: 'All' })
|
|
5
|
+
function handleSubmit() { emit('submit', { ...form.value }) }
|
|
6
|
+
</script>
|
|
7
|
+
<template>
|
|
8
|
+
<div class="p-shell">
|
|
9
|
+
<h2 class="p-title">🔍 Search Avatar</h2>
|
|
10
|
+
<form class="p-form" @submit.prevent="handleSubmit">
|
|
11
|
+
<div class="p-row"><label class="p-label">Username / ID</label><input class="p-input" v-model="form.query" placeholder="Search by username or avatar ID" /></div>
|
|
12
|
+
<div class="p-row">
|
|
13
|
+
<label class="p-label">Provider</label>
|
|
14
|
+
<select class="p-input" v-model="form.provider">
|
|
15
|
+
<option>All</option><option>Holochain</option><option>Ethereum</option><option>Solana</option><option>IPFS</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,19 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
defineProps<{ username?: string; level?: number; karma?: number; provider?: string }>()
|
|
3
|
+
const emit = defineEmits<{ close: [] }>()
|
|
4
|
+
</script>
|
|
5
|
+
<template>
|
|
6
|
+
<div class="p-shell">
|
|
7
|
+
<div class="p-avatar-icon">👤</div>
|
|
8
|
+
<h2 class="p-title">{{ username ?? 'Avatar Profile' }}</h2>
|
|
9
|
+
<div class="p-stats">
|
|
10
|
+
<div class="p-stat"><span class="p-stat-label">Level</span><span class="p-stat-value">{{ level ?? 1 }}</span></div>
|
|
11
|
+
<div class="p-stat"><span class="p-stat-label">Karma</span><span class="p-stat-value">{{ karma ?? 0 }}</span></div>
|
|
12
|
+
<div class="p-stat"><span class="p-stat-label">Provider</span><span class="p-stat-value">{{ provider ?? 'Holochain' }}</span></div>
|
|
13
|
+
</div>
|
|
14
|
+
<button class="p-btn" @click="emit('close')">Close</button>
|
|
15
|
+
</div>
|
|
16
|
+
</template>
|
|
17
|
+
<style scoped>
|
|
18
|
+
.p-shell{display:flex;flex-direction:column;align-items:center;gap:18px;padding:32px 20px;text-align:center}.p-avatar-icon{font-size:60px}.p-title{font-family:'Orbitron',sans-serif;font-size:20px;color:#fff;margin:0}.p-stats{display:flex;gap:24px}.p-stat{display:flex;flex-direction:column;gap:4px;align-items:center;background:rgba(0,200,255,.06);border:1px solid rgba(0,200,255,.15);border-radius:10px;padding:12px 18px}.p-stat-label{font-size:11px;color:#7a9bbf;font-weight:600;letter-spacing:.08em;text-transform:uppercase}.p-stat-value{font-family:'Orbitron',sans-serif;font-size:16px;color:#00c8ff;font-weight:700}.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}
|
|
19
|
+
</style>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<div v-if="session" class="avatar-badge">
|
|
4
|
+
<span class="avatar-icon">⬡</span>
|
|
5
|
+
<span class="avatar-name">{{ session.username }}</span>
|
|
6
|
+
<span class="karma-pill">{{ session.karma.toLocaleString() }} ✦</span>
|
|
7
|
+
<button class="logout-btn" @click="logout">✕</button>
|
|
8
|
+
</div>
|
|
9
|
+
<button v-else class="connect-btn" @click="open = true">⬡ CONNECT AVATAR</button>
|
|
10
|
+
|
|
11
|
+
<OasisModal :open="open" accent-color="rgba(0,232,124,.25)" @close="open = false">
|
|
12
|
+
<div class="modal-icon">⬡</div>
|
|
13
|
+
<h2 class="modal-title">Connect Your Avatar</h2>
|
|
14
|
+
<p class="modal-sub">Sign in to your OASIS avatar to earn karma across Noah's Ark ARN.</p>
|
|
15
|
+
<input v-model="username" class="oasis-input" placeholder="Avatar username" />
|
|
16
|
+
<input v-model="password" class="oasis-input" type="password" placeholder="Password" />
|
|
17
|
+
<p v-if="error" class="error-msg">{{ error }}</p>
|
|
18
|
+
<button class="btn-primary" :disabled="loading" @click="doLogin">
|
|
19
|
+
{{ loading ? 'Connecting…' : 'Connect Avatar' }}
|
|
20
|
+
</button>
|
|
21
|
+
</OasisModal>
|
|
22
|
+
</div>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script setup lang="ts">
|
|
26
|
+
import { ref } from 'vue'
|
|
27
|
+
import { useOasis } from '../../../composables/useOasis'
|
|
28
|
+
import OasisModal from '../OasisModal/OasisModal.vue'
|
|
29
|
+
|
|
30
|
+
const { session, login, logout } = useOasis()
|
|
31
|
+
const open = ref(false)
|
|
32
|
+
const loading = ref(false)
|
|
33
|
+
const error = ref('')
|
|
34
|
+
const username = ref('')
|
|
35
|
+
const password = ref('')
|
|
36
|
+
|
|
37
|
+
async function doLogin() {
|
|
38
|
+
if (!username.value || !password.value) { error.value = 'Please fill in both fields.'; return }
|
|
39
|
+
loading.value = true; error.value = ''
|
|
40
|
+
try {
|
|
41
|
+
await login(username.value, password.value)
|
|
42
|
+
open.value = false; username.value = ''; password.value = ''
|
|
43
|
+
} catch {
|
|
44
|
+
error.value = 'Login failed. Please check your credentials.'
|
|
45
|
+
} finally { loading.value = false }
|
|
46
|
+
}
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<style scoped>
|
|
50
|
+
.connect-btn { background: none; border: 1px solid rgba(0,232,124,.4); border-radius: 999px; padding: 8px 18px; color: #00e87c; font-family: 'Share Tech Mono', monospace; font-size: 11px; letter-spacing: .1em; cursor: pointer; transition: background .2s; }
|
|
51
|
+
.connect-btn:hover { background: rgba(0,232,124,.08); }
|
|
52
|
+
.avatar-badge { display: flex; align-items: center; gap: 8px; }
|
|
53
|
+
.avatar-icon { color: #00e87c; font-size: 16px; }
|
|
54
|
+
.avatar-name { font-family: 'Share Tech Mono', monospace; font-size: 12px; color: #fff; letter-spacing: .06em; }
|
|
55
|
+
.karma-pill { background: rgba(0,232,124,.12); border: 1px solid rgba(0,232,124,.3); border-radius: 999px; padding: 2px 10px; font-family: 'Share Tech Mono', monospace; font-size: 11px; color: #00e87c; }
|
|
56
|
+
.logout-btn { background: none; border: none; color: #a8bfd8; cursor: pointer; font-size: 14px; }
|
|
57
|
+
.modal-icon { font-size: 40px; text-align: center; color: #00e87c; margin-bottom: 16px; }
|
|
58
|
+
.modal-title { font-family: 'Orbitron', sans-serif; font-size: 20px; font-weight: 700; color: #fff; text-align: center; margin: 0 0 8px; }
|
|
59
|
+
.modal-sub { font-size: 14px; color: #a8bfd8; text-align: center; line-height: 1.6; margin: 0 0 24px; }
|
|
60
|
+
.oasis-input { width: 100%; background: rgba(255,255,255,.05); border: 1px solid rgba(0,232,124,.2); border-radius: 8px; padding: 11px 14px; color: #fff; font-size: 14px; outline: none; box-sizing: border-box; margin-bottom: 12px; display: block; font-family: inherit; }
|
|
61
|
+
.btn-primary { width: 100%; padding: 14px; background: linear-gradient(135deg, #00e87c, #059669); border: none; border-radius: 10px; color: #fff; font-family: 'Orbitron', sans-serif; font-size: 13px; font-weight: 700; letter-spacing: .08em; cursor: pointer; margin-top: 4px; }
|
|
62
|
+
.btn-primary:disabled { opacity: .5; cursor: not-allowed; }
|
|
63
|
+
.error-msg { color: #f87171; font-size: 13px; text-align: center; margin-bottom: 8px; }
|
|
64
|
+
</style>
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref, computed } from 'vue'
|
|
3
|
+
import { useOasis } from '../../../composables/useOasis'
|
|
4
|
+
|
|
5
|
+
const { session } = useOasis()
|
|
6
|
+
|
|
7
|
+
const fields = ref({ title: '', firstName: '', lastName: '', username: session.value?.username ?? '', email: '', address: '' })
|
|
8
|
+
const dirty = ref(false)
|
|
9
|
+
const saving = ref(false)
|
|
10
|
+
const status = ref('')
|
|
11
|
+
const statusError = ref(false)
|
|
12
|
+
|
|
13
|
+
function markDirty() { dirty.value = true }
|
|
14
|
+
|
|
15
|
+
async function save() {
|
|
16
|
+
saving.value = true
|
|
17
|
+
status.value = ''
|
|
18
|
+
try {
|
|
19
|
+
await new Promise(r => setTimeout(r, 600))
|
|
20
|
+
dirty.value = false
|
|
21
|
+
statusError.value = false
|
|
22
|
+
status.value = 'Changes saved.'
|
|
23
|
+
setTimeout(() => { status.value = '' }, 3000)
|
|
24
|
+
} catch (e: any) {
|
|
25
|
+
statusError.value = true
|
|
26
|
+
status.value = e?.message ?? 'Save failed.'
|
|
27
|
+
} finally {
|
|
28
|
+
saving.value = false
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function discard() {
|
|
33
|
+
fields.value = { title: '', firstName: '', lastName: '', username: session.value?.username ?? '', email: '', address: '' }
|
|
34
|
+
dirty.value = false
|
|
35
|
+
status.value = ''
|
|
36
|
+
}
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<template>
|
|
40
|
+
<div class="avp-shell">
|
|
41
|
+
<div v-if="!session" class="avp-empty">Please <strong>Beam In</strong> to view your avatar.</div>
|
|
42
|
+
|
|
43
|
+
<div v-else class="avp-layout">
|
|
44
|
+
<aside class="avp-summary">
|
|
45
|
+
<div class="avp-avatar-img"><span class="avp-avatar-icon">👤</span></div>
|
|
46
|
+
<div class="avp-name">{{ session?.username }}</div>
|
|
47
|
+
<div class="avp-stats">
|
|
48
|
+
<div class="avp-stat">
|
|
49
|
+
<span class="avp-stat-icon">⚡</span>
|
|
50
|
+
<div>
|
|
51
|
+
<div class="avp-stat-value">{{ session?.karma ?? '—' }}</div>
|
|
52
|
+
<div class="avp-stat-label">Karma</div>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</aside>
|
|
57
|
+
|
|
58
|
+
<div class="avp-fields">
|
|
59
|
+
<div class="avp-section-label">PROFILE</div>
|
|
60
|
+
<div class="avp-field-row">
|
|
61
|
+
<label class="avp-label" for="avp-title">Title</label>
|
|
62
|
+
<input class="avp-input" id="avp-title" type="text" v-model="fields.title" placeholder="Dr, Mr, Ms…" @input="markDirty" />
|
|
63
|
+
</div>
|
|
64
|
+
<div class="avp-field-row">
|
|
65
|
+
<label class="avp-label" for="avp-first">First Name</label>
|
|
66
|
+
<input class="avp-input" id="avp-first" type="text" v-model="fields.firstName" placeholder="First name" @input="markDirty" />
|
|
67
|
+
</div>
|
|
68
|
+
<div class="avp-field-row">
|
|
69
|
+
<label class="avp-label" for="avp-last">Last Name</label>
|
|
70
|
+
<input class="avp-input" id="avp-last" type="text" v-model="fields.lastName" placeholder="Last name" @input="markDirty" />
|
|
71
|
+
</div>
|
|
72
|
+
<div class="avp-field-row">
|
|
73
|
+
<label class="avp-label" for="avp-username">Username</label>
|
|
74
|
+
<input class="avp-input" id="avp-username" type="text" v-model="fields.username" placeholder="Username" @input="markDirty" />
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<div class="avp-section-label" style="margin-top:18px">CONTACT</div>
|
|
78
|
+
<div class="avp-field-row">
|
|
79
|
+
<label class="avp-label" for="avp-email">Email</label>
|
|
80
|
+
<input class="avp-input" id="avp-email" type="email" v-model="fields.email" placeholder="name@example.com" @input="markDirty" />
|
|
81
|
+
</div>
|
|
82
|
+
<div class="avp-field-row">
|
|
83
|
+
<label class="avp-label" for="avp-address">Address</label>
|
|
84
|
+
<input class="avp-input" id="avp-address" type="text" v-model="fields.address" placeholder="Optional" @input="markDirty" />
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<div v-if="status" class="avp-status" :class="{ 'avp-status--error': statusError }">{{ status }}</div>
|
|
88
|
+
|
|
89
|
+
<div v-if="dirty" class="avp-actions">
|
|
90
|
+
<button class="avp-btn" @click="save" :disabled="saving">{{ saving ? 'Saving…' : 'Save Changes' }}</button>
|
|
91
|
+
<button class="avp-btn avp-btn--ghost" @click="discard">Discard</button>
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
</template>
|
|
97
|
+
|
|
98
|
+
<style scoped>
|
|
99
|
+
.avp-shell { color:#fff; }
|
|
100
|
+
.avp-empty { text-align:center; padding:40px; color:#7a9bbf; font-size:14px; }
|
|
101
|
+
.avp-layout { display:grid; grid-template-columns:180px 1fr; gap:28px; }
|
|
102
|
+
.avp-summary { display:flex; flex-direction:column; align-items:center; gap:14px; }
|
|
103
|
+
.avp-avatar-img { width:88px; height:88px; border-radius:50%; background:rgba(0,200,255,.1); border:2px solid rgba(0,200,255,.3); display:flex; align-items:center; justify-content:center; }
|
|
104
|
+
.avp-avatar-icon { font-size:40px; }
|
|
105
|
+
.avp-name { font-family:'Orbitron',sans-serif; font-size:13px; color:#fff; text-align:center; word-break:break-all; }
|
|
106
|
+
.avp-stats { display:flex; flex-direction:column; gap:8px; width:100%; }
|
|
107
|
+
.avp-stat { display:flex; align-items:center; gap:8px; background:rgba(0,200,255,.06); border-radius:8px; padding:8px 10px; }
|
|
108
|
+
.avp-stat-icon { font-size:16px; }
|
|
109
|
+
.avp-stat-value { font-family:'Orbitron',sans-serif; font-size:14px; color:#00c8ff; }
|
|
110
|
+
.avp-stat-label { font-size:11px; color:#7a9bbf; text-transform:uppercase; letter-spacing:.06em; }
|
|
111
|
+
.avp-fields { display:flex; flex-direction:column; gap:12px; }
|
|
112
|
+
.avp-section-label { font-size:10px; font-weight:700; letter-spacing:.12em; color:#7a9bbf; text-transform:uppercase; margin-bottom:4px; }
|
|
113
|
+
.avp-field-row { display:grid; grid-template-columns:90px 1fr; align-items:center; gap:12px; }
|
|
114
|
+
.avp-label { font-size:12px; color:#7a9bbf; text-align:right; }
|
|
115
|
+
.avp-input { width:100%; background:rgba(255,255,255,.05); border:1px solid rgba(0,200,255,.2); border-radius:6px; padding:8px 12px; color:#fff; font-size:13px; outline:none; box-sizing:border-box; transition:border-color .2s; }
|
|
116
|
+
.avp-input:focus { border-color:rgba(0,200,255,.5); }
|
|
117
|
+
.avp-status { margin-top:4px; font-size:13px; color:#48dc82; }
|
|
118
|
+
.avp-status--error { color:#ff6b6b; }
|
|
119
|
+
.avp-actions { display:flex; gap:10px; margin-top:4px; }
|
|
120
|
+
.avp-btn { background:linear-gradient(135deg,#00c8ff,#0080ff); border:none; border-radius:6px; color:#fff; font-family:'Orbitron',sans-serif; font-size:11px; font-weight:700; letter-spacing:.08em; padding:9px 16px; cursor:pointer; transition:opacity .2s; }
|
|
121
|
+
.avp-btn:disabled { opacity:.5; cursor:not-allowed; }
|
|
122
|
+
.avp-btn--ghost { background:transparent; border:1px solid rgba(0,200,255,.3); color:#00c8ff; }
|
|
123
|
+
</style>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
defineProps<{ title?: string; message?: string }>()
|
|
3
|
+
</script>
|
|
4
|
+
<template>
|
|
5
|
+
<div class="cs-shell">
|
|
6
|
+
<div class="cs-icon">🚀</div>
|
|
7
|
+
<h2 class="cs-title">{{ title ?? 'Feature Coming Soon' }}</h2>
|
|
8
|
+
<p class="cs-body">{{ message ?? 'This feature is currently under development and will be available soon.' }}</p>
|
|
9
|
+
<div class="cs-badge">Coming Soon</div>
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
12
|
+
<style scoped>
|
|
13
|
+
.cs-shell{display:flex;flex-direction:column;align-items:center;gap:16px;padding:40px 20px;text-align:center}.cs-icon{font-size:48px}.cs-title{font-family:'Orbitron',sans-serif;font-size:20px;color:#fff;margin:0}.cs-body{font-size:14px;color:#7a9bbf;line-height:1.6;margin:0;max-width:360px}.cs-badge{background:rgba(255,180,60,.12);border:1px solid rgba(255,180,60,.28);color:#ffb43c;border-radius:999px;font-size:11px;font-weight:700;letter-spacing:.1em;padding:5px 14px;text-transform:uppercase}
|
|
14
|
+
</style>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
defineProps<{ title?: string; message?: string; icon?: string; confirmLabel?: string; cancelLabel?: string }>()
|
|
3
|
+
const emit = defineEmits<{ confirm: []; cancel: [] }>()
|
|
4
|
+
</script>
|
|
5
|
+
<template>
|
|
6
|
+
<div class="conf-shell">
|
|
7
|
+
<div class="conf-icon">{{ icon ?? '⚠️' }}</div>
|
|
8
|
+
<h2 class="conf-title">{{ title ?? 'Are you sure?' }}</h2>
|
|
9
|
+
<p class="conf-body">{{ message ?? 'This action cannot be undone.' }}</p>
|
|
10
|
+
<div class="conf-actions">
|
|
11
|
+
<button class="conf-btn conf-btn--confirm" @click="emit('confirm')">{{ confirmLabel ?? 'Confirm' }}</button>
|
|
12
|
+
<button class="conf-btn conf-btn--cancel" @click="emit('cancel')">{{ cancelLabel ?? 'Cancel' }}</button>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
</template>
|
|
16
|
+
<style scoped>
|
|
17
|
+
.conf-shell{display:flex;flex-direction:column;align-items:center;gap:18px;padding:20px;text-align:center}.conf-icon{font-size:44px}.conf-title{font-family:'Orbitron',sans-serif;font-size:18px;color:#fff;margin:0}.conf-body{font-size:14px;color:#a8bfd8;line-height:1.6;margin:0;max-width:360px}.conf-actions{display:flex;gap:12px;margin-top:4px}.conf-btn{border:none;border-radius:8px;font-family:'Orbitron',sans-serif;font-size:12px;font-weight:700;letter-spacing:.08em;padding:11px 24px;cursor:pointer;transition:opacity .2s}.conf-btn--confirm{background:linear-gradient(135deg,#ff4444,#cc0000);color:#fff}.conf-btn--cancel{background:transparent;border:1px solid rgba(0,200,255,.3);color:#00c8ff}
|
|
18
|
+
</style>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
const firstName = ref(''), lastName = ref(''), email = ref(''), subject = ref(''), message = ref('')
|
|
4
|
+
const loading = ref(false), error = ref(''), sent = ref(false)
|
|
5
|
+
async function submit() {
|
|
6
|
+
if (!email.value || !message.value) { error.value = 'Please fill in your email and message.'; return }
|
|
7
|
+
loading.value = true; error.value = ''
|
|
8
|
+
try {
|
|
9
|
+
await fetch('https://formsubmit.co/ajax/davidellams@hotmail.com', {
|
|
10
|
+
method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
|
11
|
+
body: JSON.stringify({ firstName: firstName.value, lastName: lastName.value, email: email.value, subject: subject.value, message: message.value })
|
|
12
|
+
})
|
|
13
|
+
sent.value = true
|
|
14
|
+
} catch (e: any) { error.value = e?.message ?? 'Send failed. Please try again.' }
|
|
15
|
+
finally { loading.value = false }
|
|
16
|
+
}
|
|
17
|
+
</script>
|
|
18
|
+
<template>
|
|
19
|
+
<div class="ct-shell">
|
|
20
|
+
<div class="ct-header">
|
|
21
|
+
<h2 class="ct-title">Contact Us</h2>
|
|
22
|
+
<p class="ct-sub">Get in touch with the OASIS team.</p>
|
|
23
|
+
</div>
|
|
24
|
+
<div v-if="sent" class="oasis-auth-success">✅ Message sent! We'll be in touch soon.</div>
|
|
25
|
+
<template v-else>
|
|
26
|
+
<div v-if="error" class="oasis-auth-error">{{ error }}</div>
|
|
27
|
+
<div class="oasis-grid-2">
|
|
28
|
+
<div class="oasis-field"><label class="oasis-label">First Name</label><input class="oasis-input" type="text" v-model="firstName" placeholder="John" /></div>
|
|
29
|
+
<div class="oasis-field"><label class="oasis-label">Last Name</label><input class="oasis-input" type="text" v-model="lastName" placeholder="Doe" /></div>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="oasis-field"><label class="oasis-label">Email</label><input class="oasis-input" type="email" v-model="email" placeholder="name@example.com" /></div>
|
|
32
|
+
<div class="oasis-field"><label class="oasis-label">Subject</label><input class="oasis-input" type="text" v-model="subject" placeholder="How can we help?" /></div>
|
|
33
|
+
<div class="oasis-field"><label class="oasis-label">Message</label><textarea class="oasis-input oasis-textarea" v-model="message" placeholder="Your message…" rows="4"></textarea></div>
|
|
34
|
+
<button class="oasis-btn" :disabled="loading" @click="submit">{{ loading ? 'Sending…' : 'Send Message' }}</button>
|
|
35
|
+
</template>
|
|
36
|
+
</div>
|
|
37
|
+
</template>
|
|
38
|
+
<style scoped>
|
|
39
|
+
.ct-shell{display:flex;flex-direction:column;gap:18px}.ct-header{text-align:center}.ct-title{font-family:'Orbitron',sans-serif;font-size:20px;color:#fff;margin:0 0 6px}.ct-sub{font-size:13px;color:#7a9bbf;margin:0}.oasis-auth-error{background:rgba(255,80,80,.12);border:1px solid rgba(255,80,80,.3);color:#ff6b6b;border-radius:8px;padding:10px 14px;font-size:13px}.oasis-auth-success{background:rgba(72,220,130,.12);border:1px solid rgba(72,220,130,.3);color:#48dc82;border-radius:8px;padding:10px 14px;font-size:13px}.oasis-grid-2{display:grid;grid-template-columns:1fr 1fr;gap:14px}.oasis-field{display:flex;flex-direction:column;gap:6px}.oasis-label{font-size:12px;font-weight:600;letter-spacing:.06em;color:#7a9bbf;text-transform:uppercase}.oasis-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:14px;outline:none;box-sizing:border-box;transition:border-color .2s;font-family:inherit}.oasis-input:focus{border-color:rgba(0,200,255,.5)}.oasis-textarea{resize:vertical;min-height:100px}.oasis-btn{background:linear-gradient(135deg,#00c8ff,#0080ff);border:none;border-radius:8px;color:#fff;font-family:'Orbitron',sans-serif;font-size:13px;font-weight:700;letter-spacing:.08em;padding:12px;cursor:pointer;transition:opacity .2s}.oasis-btn:disabled{opacity:.5;cursor:not-allowed}
|
|
40
|
+
</style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
const emit = defineEmits<{ close: []; submit: [{ provider: string; json: string; file: File | null }] }>()
|
|
4
|
+
const form = ref({ provider: 'Holochain', json: '', file: null as File | null })
|
|
5
|
+
function onFile(e: Event) { form.value.file = (e.target as HTMLInputElement).files?.[0] ?? null }
|
|
6
|
+
function handleSubmit() { emit('submit', { ...form.value }) }
|
|
7
|
+
</script>
|
|
8
|
+
<template>
|
|
9
|
+
<div class="p-shell">
|
|
10
|
+
<h2 class="p-title">📤 Add Data</h2>
|
|
11
|
+
<form class="p-form" @submit.prevent="handleSubmit">
|
|
12
|
+
<div class="p-row">
|
|
13
|
+
<label class="p-label">Provider</label>
|
|
14
|
+
<select class="p-input" v-model="form.provider">
|
|
15
|
+
<option>Holochain</option><option>Ethereum</option><option>IPFS</option><option>MongoDB</option><option>Neo4j</option><option>SQLite</option>
|
|
16
|
+
</select>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="p-row"><label class="p-label">JSON</label><textarea class="p-textarea" v-model="form.json" placeholder='{"key": "value"}'></textarea></div>
|
|
19
|
+
<div class="p-row"><label class="p-label">File</label><input class="p-input" type="file" @change="onFile" /></div>
|
|
20
|
+
<div class="p-actions"><button class="p-btn-cancel" type="button" @click="emit('close')">Cancel</button><button class="p-btn" type="submit">Save</button></div>
|
|
21
|
+
</form>
|
|
22
|
+
</div>
|
|
23
|
+
</template>
|
|
24
|
+
<style scoped>
|
|
25
|
+
.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-textarea{background:rgba(255,255,255,.06);border:1px solid rgba(0,200,255,.2);border-radius:8px;color:#fff;font-size:13px;font-family:monospace;padding:10px 12px;width:100%;box-sizing:border-box;outline:none;min-height:100px;resize:vertical;transition:border-color .2s}.p-textarea: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}
|
|
26
|
+
</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">Cross-Chain Management</h2>
|
|
8
|
+
<p class="p-body">Cross-chain data management is coming soon to the OASIS — enabling seamless data replication across multiple blockchains and distributed storage providers.</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,24 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
const emit = defineEmits<{ close: []; submit: [{ provider: string; id: string }] }>()
|
|
4
|
+
const form = ref({ provider: 'Holochain', id: '' })
|
|
5
|
+
function handleSubmit() { emit('submit', { ...form.value }) }
|
|
6
|
+
</script>
|
|
7
|
+
<template>
|
|
8
|
+
<div class="p-shell">
|
|
9
|
+
<h2 class="p-title">📥 Load Data</h2>
|
|
10
|
+
<form class="p-form" @submit.prevent="handleSubmit">
|
|
11
|
+
<div class="p-row">
|
|
12
|
+
<label class="p-label">Provider</label>
|
|
13
|
+
<select class="p-input" v-model="form.provider">
|
|
14
|
+
<option>Holochain</option><option>Ethereum</option><option>IPFS</option><option>MongoDB</option><option>Neo4j</option><option>SQLite</option>
|
|
15
|
+
</select>
|
|
16
|
+
</div>
|
|
17
|
+
<div class="p-row"><label class="p-label">Data ID / Key</label><input class="p-input" v-model="form.id" placeholder="Enter data ID or key" /></div>
|
|
18
|
+
<div class="p-actions"><button class="p-btn-cancel" type="button" @click="emit('close')">Cancel</button><button class="p-btn" type="submit">Load</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">Manage Data</h2>
|
|
8
|
+
<p class="p-body">Data management tools are coming soon. You can currently access this functionality via the OASIS API from the Developer menu.</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,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">Off-Chain Management</h2>
|
|
8
|
+
<p class="p-body">Off-chain data management is coming soon to the OASIS — enabling storage across IPFS, MongoDB, and other off-chain providers.</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,24 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
const emit = defineEmits<{ close: []; submit: [{ query: string; provider: string }] }>()
|
|
4
|
+
const form = ref({ query: '', provider: 'All' })
|
|
5
|
+
function handleSubmit() { emit('submit', { ...form.value }) }
|
|
6
|
+
</script>
|
|
7
|
+
<template>
|
|
8
|
+
<div class="p-shell">
|
|
9
|
+
<h2 class="p-title">🔍 Search Data</h2>
|
|
10
|
+
<form class="p-form" @submit.prevent="handleSubmit">
|
|
11
|
+
<div class="p-row"><label class="p-label">Search Query</label><input class="p-input" v-model="form.query" placeholder="Enter search terms..." /></div>
|
|
12
|
+
<div class="p-row">
|
|
13
|
+
<label class="p-label">Provider</label>
|
|
14
|
+
<select class="p-input" v-model="form.provider">
|
|
15
|
+
<option>All</option><option>Holochain</option><option>Ethereum</option><option>IPFS</option><option>MongoDB</option><option>Neo4j</option><option>SQLite</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,40 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
interface Egg { id: string; name: string; rarity: string; hatchProgress: number; hatched: boolean; reward: string }
|
|
4
|
+
const eggs = ref<Egg[]>([
|
|
5
|
+
{ id: '1', name: 'Cosmic Egg', rarity: 'Legendary', hatchProgress: 75, hatched: false, reward: '+500 Karma Companion' },
|
|
6
|
+
{ id: '2', name: 'Forest Egg', rarity: 'Common', hatchProgress: 100, hatched: true, reward: 'Woodland Sprite' },
|
|
7
|
+
{ id: '3', name: 'Astral Egg', rarity: 'Epic', hatchProgress: 30, hatched: false, reward: '+200 Karma Companion' },
|
|
8
|
+
{ id: '4', name: 'Ocean Egg', rarity: 'Rare', hatchProgress: 55, hatched: false, reward: 'Sea Guardian' },
|
|
9
|
+
])
|
|
10
|
+
function incubate(e: Egg) {
|
|
11
|
+
const next = Math.min(100, e.hatchProgress + 25)
|
|
12
|
+
e.hatchProgress = next; e.hatched = next >= 100
|
|
13
|
+
}
|
|
14
|
+
</script>
|
|
15
|
+
<template>
|
|
16
|
+
<div class="eggs-shell">
|
|
17
|
+
<div class="eggs-header">
|
|
18
|
+
<h2 class="eggs-title">🥚 Eggs</h2>
|
|
19
|
+
<p class="eggs-sub">Hatch eggs to discover rare OASIS companions and rewards.</p>
|
|
20
|
+
</div>
|
|
21
|
+
<div class="eggs-grid">
|
|
22
|
+
<div v-for="e in eggs" :key="e.id" class="egg-card" :class="{ 'egg-card--hatched': e.hatched }">
|
|
23
|
+
<div class="egg-rarity" :class="`egg-rarity--${e.rarity.toLowerCase()}`">{{ e.rarity }}</div>
|
|
24
|
+
<div class="egg-icon">{{ e.hatched ? '🐣' : '🥚' }}</div>
|
|
25
|
+
<div class="egg-name">{{ e.name }}</div>
|
|
26
|
+
<template v-if="!e.hatched">
|
|
27
|
+
<div class="egg-progress-wrap">
|
|
28
|
+
<div class="egg-progress-bar"><div class="egg-progress-fill" :style="{ width: e.hatchProgress + '%' }"></div></div>
|
|
29
|
+
<div class="egg-pct">{{ e.hatchProgress }}%</div>
|
|
30
|
+
</div>
|
|
31
|
+
<button class="egg-btn" @click="incubate(e)">Incubate</button>
|
|
32
|
+
</template>
|
|
33
|
+
<div v-else class="egg-reward">✨ {{ e.reward }}</div>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
</template>
|
|
38
|
+
<style scoped>
|
|
39
|
+
.eggs-shell{display:flex;flex-direction:column;gap:20px}.eggs-header{text-align:center}.eggs-title{font-family:'Orbitron',sans-serif;font-size:20px;color:#fff;margin:0 0 6px}.eggs-sub{font-size:13px;color:#7a9bbf;margin:0}.eggs-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:16px}.egg-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}.egg-card:hover{border-color:rgba(0,200,255,.35)}.egg-card--hatched{border-color:rgba(255,180,60,.3);background:rgba(255,180,60,.04)}.egg-rarity{font-size:10px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;border-radius:999px;padding:3px 10px;border:1px solid currentColor}.egg-rarity--common{color:#7a9bbf;border-color:rgba(122,155,191,.3)}.egg-rarity--rare{color:#5ba8ff;border-color:rgba(91,168,255,.3)}.egg-rarity--epic{color:#b87fff;border-color:rgba(184,127,255,.3)}.egg-rarity--legendary{color:#ffb43c;border-color:rgba(255,180,60,.3)}.egg-icon{font-size:40px}.egg-name{font-family:'Orbitron',sans-serif;font-size:12px;color:#fff;text-align:center}.egg-progress-wrap{width:100%;display:flex;flex-direction:column;gap:4px;align-items:center}.egg-progress-bar{width:100%;height:6px;background:rgba(255,255,255,.1);border-radius:999px;overflow:hidden}.egg-progress-fill{height:100%;background:linear-gradient(90deg,#00c8ff,#0080ff);border-radius:999px;transition:width .4s}.egg-pct{font-size:11px;color:#7a9bbf}.egg-btn{width:100%;background:linear-gradient(135deg,#ffb43c,#ff8c00);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}.egg-btn:hover{opacity:.85}.egg-reward{font-size:12px;color:#ffb43c;font-weight:600;text-align:center}
|
|
40
|
+
</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 Eggs</h2>
|
|
8
|
+
<p class="p-body">Advanced egg management is coming soon. Hatch, trade and evolve your OASIS eggs to discover rare companions and unlock rewards.</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>
|