feat: shop's nav block

This commit is contained in:
snsd0805 2023-06-11 17:18:11 +08:00
parent ebe58b6d08
commit 26bc81aa56
Signed by: snsd0805
GPG Key ID: 569349933C77A854
10 changed files with 232 additions and 13 deletions

View File

@ -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()

View File

@ -2,14 +2,14 @@
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',
pay: 'panel-block', pay: 'panel-block',
credit: 'panel-block', credit: 'panel-block',

View File

@ -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('/')
} }
} }

View 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>

View File

@ -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
},
] ]
}) })

View File

@ -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">

View File

@ -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>

View File

@ -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>

View File

@ -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
View 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>