feat: shop's nav block
This commit is contained in:
parent
ebe58b6d08
commit
26bc81aa56
@ -94,6 +94,18 @@ def get_order(id):
|
|||||||
|
|
||||||
return jsonify(ans)
|
return jsonify(ans)
|
||||||
|
|
||||||
|
@app.route('/shop/check', methods=['POST'])
|
||||||
|
def shop_check():
|
||||||
|
address = request.get_json()['address']
|
||||||
|
db = sqlite3.connect(DATABASE)
|
||||||
|
cursor = db.cursor()
|
||||||
|
cursor.execute("SELECT COUNT(*) FROM `shops` WHERE `address`=?", (address, ))
|
||||||
|
result = cursor.fetchone()[0]
|
||||||
|
print(result, type(result))
|
||||||
|
if result != 0:
|
||||||
|
return jsonify({'status': True})
|
||||||
|
else:
|
||||||
|
return jsonify({'status': False})
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
initDB()
|
initDB()
|
||||||
|
|||||||
@ -2,12 +2,12 @@
|
|||||||
export default {
|
export default {
|
||||||
name: 'ClientNav',
|
name: 'ClientNav',
|
||||||
props: ['path'],
|
props: ['path'],
|
||||||
mounted () {
|
mounted() {
|
||||||
console.log(this.path)
|
if (this.path in this.navCSS) {
|
||||||
this.navCSS[this.path] += ' is-active'
|
this.navCSS[this.path] += ' is-active'
|
||||||
console.log(this.navCSS)
|
}
|
||||||
},
|
},
|
||||||
data () {
|
data() {
|
||||||
return {
|
return {
|
||||||
navCSS: {
|
navCSS: {
|
||||||
main: 'panel-block',
|
main: 'panel-block',
|
||||||
|
|||||||
@ -44,6 +44,15 @@ export default {
|
|||||||
this.web3.eth.defaultAccount = clientAddr
|
this.web3.eth.defaultAccount = clientAddr
|
||||||
var returnNumber = await token.methods.getSBTNumber(clientAddr).call({from: clientAddr})
|
var returnNumber = await token.methods.getSBTNumber(clientAddr).call({from: clientAddr})
|
||||||
if (returnNumber != 0){
|
if (returnNumber != 0){
|
||||||
|
var result = await fetch(import.meta.env.VITE_BACKEND_PREFIX+"/shop/check", {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({'address': clientAddr})
|
||||||
|
})
|
||||||
|
var result = await result.json()
|
||||||
|
this.$cookies.set('isShop', result.status)
|
||||||
this.$cookies.set('address', clientAddr)
|
this.$cookies.set('address', clientAddr)
|
||||||
this.$cookies.set('linked', true)
|
this.$cookies.set('linked', true)
|
||||||
this.$cookies.set('SBTNumber', returnNumber)
|
this.$cookies.set('SBTNumber', returnNumber)
|
||||||
@ -71,6 +80,7 @@ export default {
|
|||||||
this.$cookies.remove('linked')
|
this.$cookies.remove('linked')
|
||||||
this.$cookies.remove('address')
|
this.$cookies.remove('address')
|
||||||
this.$cookies.remove('SBTNumber')
|
this.$cookies.remove('SBTNumber')
|
||||||
|
this.$cookies.remove('shop')
|
||||||
this.$router.push('/')
|
this.$router.push('/')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
62
src/components/ShopNav.vue
Normal file
62
src/components/ShopNav.vue
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'ShopNav',
|
||||||
|
props: ['path'],
|
||||||
|
mounted() {
|
||||||
|
if (this.path in this.navCSS) {
|
||||||
|
this.navCSS[this.path] += ' is-active'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
navCSS: {
|
||||||
|
shoppay: 'panel-block',
|
||||||
|
shoplog: 'panel-block',
|
||||||
|
shopproducts: 'panel-block',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<nav class="panel">
|
||||||
|
<p class="panel-heading">
|
||||||
|
店家選項
|
||||||
|
</p>
|
||||||
|
<RouterLink to="/shop/pay" :class="this.navCSS['shoppay']">
|
||||||
|
<span class="panel-icon">
|
||||||
|
<i class="fas fa-book" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
<template v-if="this.path == 'shoppay'">
|
||||||
|
<strong>店家結帳</strong>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<p>店家結帳</p>
|
||||||
|
</template>
|
||||||
|
</RouterLink>
|
||||||
|
<RouterLink to="/shop/log" :class="this.navCSS['shoplog']">
|
||||||
|
<span class="panel-icon">
|
||||||
|
<i class="fas fa-book" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
<template v-if="this.path == 'shoplog'">
|
||||||
|
<strong>店家收款紀錄</strong>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<p>店家收款紀錄</p>
|
||||||
|
</template>
|
||||||
|
</RouterLink>
|
||||||
|
<RouterLink to="/shop/products" :class="this.navCSS['shopproducts']">
|
||||||
|
<span class="panel-icon">
|
||||||
|
<i class="fas fa-book" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
<template v-if="this.path == 'shopproducts'">
|
||||||
|
<strong>店家商品管理</strong>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<p>店家商品管理</p>
|
||||||
|
</template>
|
||||||
|
</RouterLink>
|
||||||
|
</nav>
|
||||||
|
</template>
|
||||||
@ -8,6 +8,7 @@ import ClientInfoView from '../views/ClientInfoView.vue'
|
|||||||
import ClientCreditView from '../views/ClientCreditView.vue'
|
import ClientCreditView from '../views/ClientCreditView.vue'
|
||||||
import ClientPayView from '../views/ClientPayView.vue'
|
import ClientPayView from '../views/ClientPayView.vue'
|
||||||
import PaymentView from '../views/PaymentView.vue'
|
import PaymentView from '../views/PaymentView.vue'
|
||||||
|
import ShopPayView from '../views/ShopPayView.vue'
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
@ -57,6 +58,11 @@ const router = createRouter({
|
|||||||
name: 'clientpayment',
|
name: 'clientpayment',
|
||||||
component: PaymentView
|
component: PaymentView
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/shop/pay',
|
||||||
|
name: 'shoppay',
|
||||||
|
component: ShopPayView
|
||||||
|
},
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import WarningModal from '../components/WarningModal.vue'
|
|||||||
import SuccessModal from '../components/SuccessModal.vue'
|
import SuccessModal from '../components/SuccessModal.vue'
|
||||||
import { useClientStore } from '../stores/Client.js'
|
import { useClientStore } from '../stores/Client.js'
|
||||||
import ClientNav from '../components/ClientNav.vue'
|
import ClientNav from '../components/ClientNav.vue'
|
||||||
|
import ShopNav from '../components/ShopNav.vue'
|
||||||
|
|
||||||
// To use Html5QrcodeScanner (more info below)
|
// To use Html5QrcodeScanner (more info below)
|
||||||
import { Html5QrcodeScanner } from "html5-qrcode";
|
import { Html5QrcodeScanner } from "html5-qrcode";
|
||||||
@ -17,7 +18,7 @@ import { Html5Qrcode } from "html5-qrcode";
|
|||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { PageTitle, WarningModal, SuccessModal, ClientNav },
|
components: { PageTitle, WarningModal, SuccessModal, ClientNav, ShopNav },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
SBTAddress: import.meta.env.VITE_SBT_ADDR,
|
SBTAddress: import.meta.env.VITE_SBT_ADDR,
|
||||||
@ -94,6 +95,10 @@ export default {
|
|||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column is-2">
|
<div class="column is-2">
|
||||||
<ClientNav path="credit"></ClientNav>
|
<ClientNav path="credit"></ClientNav>
|
||||||
|
<template v-if="this.$cookies.get('isShop') == 'true'">
|
||||||
|
<ShopNav path="credit"></ShopNav>
|
||||||
|
</template>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import WarningModal from '../components/WarningModal.vue'
|
|||||||
import SuccessModal from '../components/SuccessModal.vue'
|
import SuccessModal from '../components/SuccessModal.vue'
|
||||||
import { useClientStore } from '../stores/Client.js'
|
import { useClientStore } from '../stores/Client.js'
|
||||||
import ClientNav from '../components/ClientNav.vue'
|
import ClientNav from '../components/ClientNav.vue'
|
||||||
|
import ShopNav from '../components/ShopNav.vue'
|
||||||
|
|
||||||
// To use Html5QrcodeScanner (more info below)
|
// To use Html5QrcodeScanner (more info below)
|
||||||
import { Html5QrcodeScanner } from "html5-qrcode";
|
import { Html5QrcodeScanner } from "html5-qrcode";
|
||||||
@ -17,7 +18,7 @@ import { Html5Qrcode } from "html5-qrcode";
|
|||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { PageTitle, WarningModal, SuccessModal, ClientNav },
|
components: { PageTitle, WarningModal, SuccessModal, ClientNav, ShopNav },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
SBTAddress: import.meta.env.VITE_SBT_ADDR,
|
SBTAddress: import.meta.env.VITE_SBT_ADDR,
|
||||||
@ -82,6 +83,10 @@ export default {
|
|||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column is-2">
|
<div class="column is-2">
|
||||||
<ClientNav path="info"></ClientNav>
|
<ClientNav path="info"></ClientNav>
|
||||||
|
<template v-if="this.$cookies.get('isShop') == 'true'">
|
||||||
|
<ShopNav path="info"></ShopNav>
|
||||||
|
</template>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@ -98,7 +103,7 @@ export default {
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>目前信用額度:</th>
|
<th>目前信用額度:</th>
|
||||||
<td>{{ this.credit }} ETH (尚可使用 {{ this.credit-this.arrear }} ETH)</td>
|
<td>{{ this.credit }} ETH (尚可使用 {{ this.credit - this.arrear }} ETH)</td>
|
||||||
<!-- <td>{{ this.clientAddr.slice(0, 8)+"..."+this.clientAddr.slice(33, 42) }}</td> -->
|
<!-- <td>{{ this.clientAddr.slice(0, 8)+"..."+this.clientAddr.slice(33, 42) }}</td> -->
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -116,7 +121,8 @@ export default {
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Soulbound Token NFT 證書:</th>
|
<th>Soulbound Token NFT 證書:</th>
|
||||||
<td>{{ picName }}<div class="block is-fullwidth" v-html="pic"></div></td>
|
<td>{{ picName }}<div class="block is-fullwidth" v-html="pic"></div>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@ -30,7 +30,8 @@ export default {
|
|||||||
token: null,
|
token: null,
|
||||||
isWaiting: false,
|
isWaiting: false,
|
||||||
log: [],
|
log: [],
|
||||||
scanner: null
|
scanner: null,
|
||||||
|
isShop: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
@ -40,6 +41,7 @@ export default {
|
|||||||
this.web3 = new Web3(window.ethereum)
|
this.web3 = new Web3(window.ethereum)
|
||||||
this.clientAddr = this.$cookies.get('address')
|
this.clientAddr = this.$cookies.get('address')
|
||||||
this.web3.eth.defaultAccount = this.clientAddr
|
this.web3.eth.defaultAccount = this.clientAddr
|
||||||
|
this.isShop = (this.$cookies.get('isShop') == 'true')
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onScanSuccess(decodedText, decodedResult) {
|
onScanSuccess(decodedText, decodedResult) {
|
||||||
@ -47,7 +49,7 @@ export default {
|
|||||||
console.log(`Code matched = ${decodedText}`, decodedResult);
|
console.log(`Code matched = ${decodedText}`, decodedResult);
|
||||||
this.scanner.clear()
|
this.scanner.clear()
|
||||||
},
|
},
|
||||||
scan () {
|
scan() {
|
||||||
this.scanner = new Html5QrcodeScanner(
|
this.scanner = new Html5QrcodeScanner(
|
||||||
"reader",
|
"reader",
|
||||||
{ fps: 10, qrbox: { width: 250, height: 250 } },
|
{ fps: 10, qrbox: { width: 250, height: 250 } },
|
||||||
@ -96,6 +98,29 @@ export default {
|
|||||||
<!-- <p class="subtitle">Top tile</p> -->
|
<!-- <p class="subtitle">Top tile</p> -->
|
||||||
</article>
|
</article>
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
|
|
||||||
|
<template v-if="this.isShop">
|
||||||
|
<RouterLink to="/shop/pay" class="tile is-child notification is-info">
|
||||||
|
<article>
|
||||||
|
<p class="title"><i class="fas fa-history"></i> 店家結帳</p>
|
||||||
|
<!-- <p class="subtitle">Top tile</p> -->
|
||||||
|
</article>
|
||||||
|
</RouterLink>
|
||||||
|
<RouterLink to="/shop/log" class="tile is-child notification is-info">
|
||||||
|
<article>
|
||||||
|
<p class="title"><i class="fas fa-history"></i> 店家收款紀錄</p>
|
||||||
|
<!-- <p class="subtitle">Top tile</p> -->
|
||||||
|
</article>
|
||||||
|
</RouterLink>
|
||||||
|
<RouterLink to="/shop/products" class="tile is-child notification is-info">
|
||||||
|
<article>
|
||||||
|
<p class="title"><i class="fas fa-history"></i> 店家商品管理</p>
|
||||||
|
<!-- <p class="subtitle">Top tile</p> -->
|
||||||
|
</article>
|
||||||
|
</RouterLink>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -6,13 +6,14 @@ import PageTitle from '../components/PageTitle.vue'
|
|||||||
import WarningModal from '../components/WarningModal.vue'
|
import WarningModal from '../components/WarningModal.vue'
|
||||||
import SuccessModal from '../components/SuccessModal.vue'
|
import SuccessModal from '../components/SuccessModal.vue'
|
||||||
import ClientNav from '../components/ClientNav.vue'
|
import ClientNav from '../components/ClientNav.vue'
|
||||||
|
import ShopNav from '../components/ShopNav.vue'
|
||||||
|
|
||||||
// To use Html5QrcodeScanner (more info below)
|
// To use Html5QrcodeScanner (more info below)
|
||||||
import { Html5QrcodeScanner } from "html5-qrcode";
|
import { Html5QrcodeScanner } from "html5-qrcode";
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { PageTitle, WarningModal, SuccessModal, ClientNav },
|
components: { PageTitle, WarningModal, SuccessModal, ClientNav, ShopNav },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
SBTAddress: import.meta.env.VITE_SBT_ADDR,
|
SBTAddress: import.meta.env.VITE_SBT_ADDR,
|
||||||
@ -71,6 +72,10 @@ export default {
|
|||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column is-2">
|
<div class="column is-2">
|
||||||
<ClientNav path="pay"></ClientNav>
|
<ClientNav path="pay"></ClientNav>
|
||||||
|
<template v-if="this.$cookies.get('isShop') == 'true'">
|
||||||
|
<ShopNav path="pay"></ShopNav>
|
||||||
|
</template>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|||||||
88
src/views/ShopPayView.vue
Normal file
88
src/views/ShopPayView.vue
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
<script>
|
||||||
|
import Web3 from 'web3';
|
||||||
|
import SBT from '@/assets/SBT.json'
|
||||||
|
import Bank from '@/assets/Bank.json'
|
||||||
|
import PageTitle from '../components/PageTitle.vue'
|
||||||
|
import WarningModal from '../components/WarningModal.vue'
|
||||||
|
import SuccessModal from '../components/SuccessModal.vue'
|
||||||
|
import ClientNav from '../components/ClientNav.vue'
|
||||||
|
import ShopNav from '../components/ShopNav.vue'
|
||||||
|
|
||||||
|
// To use Html5QrcodeScanner (more info below)
|
||||||
|
import { Html5QrcodeScanner } from "html5-qrcode";
|
||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { PageTitle, WarningModal, SuccessModal, ClientNav, ShopNav },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
SBTAddress: import.meta.env.VITE_SBT_ADDR,
|
||||||
|
BankAddress: import.meta.env.VITE_BANK_ADDR,
|
||||||
|
clientAddr: '',
|
||||||
|
web3: null,
|
||||||
|
token: null,
|
||||||
|
bank: null,
|
||||||
|
picName: '',
|
||||||
|
pic: '',
|
||||||
|
credit: '',
|
||||||
|
arrear: '',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async mounted() {
|
||||||
|
// if (!this.$cookies.isKey('linked')) {
|
||||||
|
// this.$router.push('/')
|
||||||
|
// }
|
||||||
|
this.web3 = new Web3(window.ethereum)
|
||||||
|
this.clientAddr = this.$cookies.get('address')
|
||||||
|
this.web3.eth.defaultAccount = this.clientAddr
|
||||||
|
this.token = new this.web3.eth.Contract(SBT, this.SBTAddress)
|
||||||
|
this.bank = new this.web3.eth.Contract(Bank, this.BankAddress)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onScanSuccess(decodedText, decodedResult) {
|
||||||
|
// handle the scanned code as you like, for example:
|
||||||
|
console.log(`Code matched = ${decodedText}`, decodedResult);
|
||||||
|
var last_id = decodedText.split('/').pop()
|
||||||
|
this.scanner.clear()
|
||||||
|
this.$router.push('/client/pay/'+last_id)
|
||||||
|
},
|
||||||
|
scan() {
|
||||||
|
this.scanner = new Html5QrcodeScanner(
|
||||||
|
"reader",
|
||||||
|
{ fps: 10, qrbox: { width: 250, height: 250 } },
|
||||||
|
/* verbose= */ false);
|
||||||
|
this.scanner.render(this.onScanSuccess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<section class="blog-posts">
|
||||||
|
<div class="container">
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column is-2">
|
||||||
|
<ClientNav path="shoppay"></ClientNav>
|
||||||
|
<ShopNav path="shoppay"></ShopNav>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<div class="container">
|
||||||
|
<div class="block">
|
||||||
|
<PageTitle title="店家收款" subtitle="掃描商品條碼以加入收款單"></PageTitle>
|
||||||
|
</div>
|
||||||
|
<div class="block">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="block">
|
||||||
|
<button class="button is-success is-outlined is-large" @click="scan">Pay</button>
|
||||||
|
<div id="reader" width="300px"></div>
|
||||||
|
</div>
|
||||||
|
</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