feat: import Pinia & complete link to MetaMask
This commit is contained in:
parent
af7091837d
commit
7c4c1760bc
@ -8,9 +8,11 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@metamask/detect-provider": "^2.0.0",
|
||||||
"pinia": "^2.0.36",
|
"pinia": "^2.0.36",
|
||||||
"vue": "^3.3.2",
|
"vue": "^3.3.2",
|
||||||
"vue-router": "^4.2.0"
|
"vue-router": "^4.2.0",
|
||||||
|
"web3": "^1.8.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^4.2.3",
|
"@vitejs/plugin-vue": "^4.2.3",
|
||||||
|
|||||||
@ -77,7 +77,7 @@ hr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.blog-posts {
|
.blog-posts {
|
||||||
min-height: 100vh;
|
min-height: 80vh;
|
||||||
background: #191b1f;
|
background: #191b1f;
|
||||||
padding-top: 4rem;
|
padding-top: 4rem;
|
||||||
padding-bottom: 10rem;
|
padding-bottom: 10rem;
|
||||||
|
|||||||
@ -6,13 +6,13 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="hero">
|
<section class="hero is-large">
|
||||||
<footer class="footer">
|
<footer class="footer">
|
||||||
<div class="content has-text-centered">
|
<div class="content has-text-centered">
|
||||||
<p>
|
<p>
|
||||||
<strong>暨大區塊鏈銀行</strong> by <a href="https://www.csie.ncnu.edu.tw/home">NCNU CSIE</a>.
|
<strong>暨大區塊鏈銀行</strong> by <a href="https://www.csie.ncnu.edu.tw/home">NCNU CSIE</a>.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -6,40 +6,40 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="hero is-large">
|
<section class="hero is-large">
|
||||||
<div class="hero-head">
|
<div class="hero-head">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<nav class="navbar" role="navigation" aria-label="main navigation">
|
<nav class="navbar" role="navigation" aria-label="main navigation">
|
||||||
<div class="navbar-brand">
|
<div class="navbar-brand">
|
||||||
<a class="navbar-item" href="https://bulma.io">
|
<a class="navbar-item" href="https://bulma.io">
|
||||||
<img src="@/assets/NCNU_Bank.png" width="112" height="28">
|
<img src="@/assets/NCNU_Bank.png" width="112" height="28">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false"
|
<a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false"
|
||||||
data-target="navbarBasicExample">
|
data-target="navbarBasicExample">
|
||||||
<span aria-hidden="true"></span>
|
<span aria-hidden="true"></span>
|
||||||
<span aria-hidden="true"></span>
|
<span aria-hidden="true"></span>
|
||||||
<span aria-hidden="true"></span>
|
<span aria-hidden="true"></span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="navbarBasicExample" class="navbar-menu">
|
<div id="navbarBasicExample" class="navbar-menu">
|
||||||
<div class="navbar-start">
|
<div class="navbar-start">
|
||||||
<RouterLink to="/" class="navbar-item">Home</RouterLink>
|
<RouterLink to="/" class="navbar-item">Home</RouterLink>
|
||||||
<RouterLink to="/document" class="navbar-item">Documentation</RouterLink>
|
<RouterLink to="/document" class="navbar-item">Documentation</RouterLink>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="navbar-end">
|
|
||||||
<div class="navbar-item">
|
|
||||||
<div class="buttons">
|
|
||||||
<RouterLink to="/signup" class="button is-primary is-outlined">Sign up</RouterLink>
|
|
||||||
<RouterLink to="/login" class="button is-info is-outlined">Log in</RouterLink>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</section>
|
<div class="navbar-end">
|
||||||
|
<div class="navbar-item">
|
||||||
|
<div class="buttons">
|
||||||
|
<RouterLink to="/signup" class="button is-primary is-outlined">Sign up</RouterLink>
|
||||||
|
<RouterLink to="/login" class="button is-info is-outlined">Log in</RouterLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
15
src/components/PageTitle.vue
Normal file
15
src/components/PageTitle.vue
Normal 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>
|
||||||
35
src/components/SuccessModal.vue
Normal file
35
src/components/SuccessModal.vue
Normal 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>
|
||||||
34
src/components/WarningModal.vue
Normal file
34
src/components/WarningModal.vue
Normal 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>
|
||||||
@ -1,5 +1,7 @@
|
|||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
import HomeView from '../views/HomeView.vue'
|
import HomeView from '../views/HomeView.vue'
|
||||||
|
import SignupView from '../views/SignupView.vue'
|
||||||
|
import LinkSBTView from '../views/LinkSBTView.vue'
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
@ -8,6 +10,16 @@ const router = createRouter({
|
|||||||
path: '/',
|
path: '/',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
component: HomeView
|
component: HomeView
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/signup',
|
||||||
|
name: 'signup',
|
||||||
|
component: SignupView
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/signup/linksbt',
|
||||||
|
name: 'linksbt',
|
||||||
|
component: LinkSBTView
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|||||||
10
src/stores/Client.js
Normal file
10
src/stores/Client.js
Normal 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
10
src/views/LinkSBTView.vue
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'PageFooter'
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
SBT
|
||||||
|
</template>
|
||||||
76
src/views/SignupView.vue
Normal file
76
src/views/SignupView.vue
Normal 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>
|
||||||
Loading…
Reference in New Issue
Block a user