feat: import Pinia & complete link to MetaMask

This commit is contained in:
snsd0805 2023-06-08 04:30:38 +08:00
parent af7091837d
commit 7c4c1760bc
Signed by: snsd0805
GPG Key ID: 569349933C77A854
11 changed files with 238 additions and 44 deletions

View File

@ -8,9 +8,11 @@
"preview": "vite preview"
},
"dependencies": {
"@metamask/detect-provider": "^2.0.0",
"pinia": "^2.0.36",
"vue": "^3.3.2",
"vue-router": "^4.2.0"
"vue-router": "^4.2.0",
"web3": "^1.8.2"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.2.3",

View File

@ -77,7 +77,7 @@ hr {
}
.blog-posts {
min-height: 100vh;
min-height: 80vh;
background: #191b1f;
padding-top: 4rem;
padding-bottom: 10rem;

View File

@ -6,7 +6,7 @@ export default {
</script>
<template>
<section class="hero">
<section class="hero is-large">
<footer class="footer">
<div class="content has-text-centered">
<p>

View File

@ -0,0 +1,15 @@
<script>
export default {
name: 'PageTitle',
props: [
'title', 'subtitle'
]
}
</script>
<template>
<div class="block">
<h1 class="title is-1">{{ title }}</h1>
<h1 class="subtitle is-6">{{ subtitle }}</h1>
</div>
</template>

View File

@ -0,0 +1,35 @@
<script>
export default {
name: 'SuccessModal',
props: ['active', 'successMsg', 'link', 'btnName'],
computed: {
modalStatus () {
if (this.active) {
return 'modal is-active'
} else {
return 'modal'
}
}
}
}
</script>
<template>
<div :class="modalStatus">
<div class="modal-background"></div>
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">Success</p>
<button class="delete" aria-label="close" @click="$emit('closeModal')"></button>
</header>
<section class="modal-card-body">
<!-- Content ... -->
<p>{{ successMsg }}</p>
</section>
<footer class="modal-card-foot">
<RouterLink :to="link" class="button is-success" @click="$emit('closeModal')">{{ btnName }}</RouterLink>
<button class="button" @click="$emit('closeModal')">Cancel</button>
</footer>
</div>
</div>
</template>

View File

@ -0,0 +1,34 @@
<script>
export default {
name: 'WarningModal',
props: ['active', 'errorMsg'],
computed: {
modalStatus () {
if (this.active) {
return 'modal is-active'
} else {
return 'modal'
}
}
}
}
</script>
<template>
<div :class="modalStatus">
<div class="modal-background"></div>
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">Warning</p>
<button class="delete" aria-label="close" @click="$emit('closeModal')"></button>
</header>
<section class="modal-card-body">
<!-- Content ... -->
<p>{{ errorMsg }}</p>
</section>
<footer class="modal-card-foot">
<button class="button is-danger" @click="$emit('closeModal')">OK</button>
</footer>
</div>
</div>
</template>

View File

@ -1,5 +1,7 @@
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import SignupView from '../views/SignupView.vue'
import LinkSBTView from '../views/LinkSBTView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
@ -8,6 +10,16 @@ const router = createRouter({
path: '/',
name: 'home',
component: HomeView
},
{
path: '/signup',
name: 'signup',
component: SignupView
},
{
path: '/signup/linksbt',
name: 'linksbt',
component: LinkSBTView
}
]
})

10
src/stores/Client.js Normal file
View File

@ -0,0 +1,10 @@
import { defineStore } from 'pinia'
export const useClientStore = defineStore('Client', {
state () {
return {
address: '',
linked: false
}
}
})

10
src/views/LinkSBTView.vue Normal file
View File

@ -0,0 +1,10 @@
<script>
export default {
name: 'PageFooter'
}
</script>
<template>
SBT
</template>

76
src/views/SignupView.vue Normal file
View File

@ -0,0 +1,76 @@
<script>
import PageTitle from '../components/PageTitle.vue'
import detectEthereumProvider from '@metamask/detect-provider'
import WarningModal from '../components/WarningModal.vue'
import SuccessModal from '../components/SuccessModal.vue'
import { useClientStore } from '../stores/Client.js'
export default {
components: { PageTitle, WarningModal, SuccessModal },
data () {
return {
warningModalStatus: false,
successModalStatus: false,
msg: '',
client: useClientStore()
}
},
methods: {
async detect () {
const provider = await detectEthereumProvider()
if (provider) {
const chainId = await window.ethereum.request({ method: 'eth_chainId' })
if (chainId == 0xaa36a7) {
const account = await window.ethereum.request({ method: 'eth_requestAccounts' })
this.client.address = account[0]
this.client.linked = true
this.msg = 'Success: 已經成功連接 MetaMask繼續完成 Soulbound Token 設定'
this.successModalStatus = true
} else {
this.msg = 'ERROR: 你連接的不是 Sepolia 測試網路,目前只接受 Sepolia address'
this.warningModalStatus = true
}
} else {
this.msg = 'ERROR: no Metamask'
this.warningModalStatus = true
}
}
}
}
</script>
<template>
<section class="blog-posts">
<div class="container">
<div class="block">
<PageTitle title="Sign Up" subtitle="連接 MetaMask 錢包並使用 Soulbound Token (SBT) 進行身份驗證"></PageTitle>
</div>
<div class="block">
<div class="box">
<div class="content">
<h5 class="title is-5">流程說明</h5>
<ol>
<li>連接 MetaMask 個人錢包</li>
<li>Mint 新的或連接已有的 Soulbound Token(SBT) 以紀錄個人信用並作為身份驗證憑證</li>
<li>申請信用評分並設定信用額度</li>
<li>進行消費</li>
</ol>
</div>
</div>
</div>
<div class="block">
<div class="columns">
<div class="column is-2 is-offset-4">
<button @click="detect" class="button is-primary is-fullwidth is-medium is-outlined">Link to MetaMask</button>
</div>
<div class="column is-2">
<RouterLink to="/" class="button is-danger is-fullwidth is-medium is-outlined">Cancel</RouterLink>
</div>
</div>
</div>
</div>
</section>
<WarningModal :active="warningModalStatus" :errorMsg="msg" @closeModal="warningModalStatus=false"></WarningModal>
<SuccessModal :active="successModalStatus" :successMsg="msg" @closeModal="successModalStatus=false" link="/signup/linksbt" btnName="繼續"></SuccessModal>
</template>