initial drafting of nostr global search fro products

This commit is contained in:
Tiago Vasconcelos 2023-03-10 16:14:23 +00:00
parent b10531763e
commit 469aabc10a
4 changed files with 128 additions and 10 deletions

View file

@ -1,4 +1,42 @@
<div> <div>
<div v-if="searchNostr" class="row q-col-gutter-md">
<div class="col-12 col-md-7 q-gutter-y-md">
<q-card>
<q-card-section>
<div class="row items-center no-wrap q-mb-md">
<div class="col">
<h5 class="text-subtitle1 q-my-none">Search Globally</h5>
<p>Search for products on Nostr</p>
</div>
</div>
</q-card-section>
<q-card-section>
<q-input
class="q-ml-md"
standout
square
dense
outlined
clearable
v-model.trim="search"
label="Search products"
hint="Enter search terms separated by spaces"
>
<template v-slot:after>
<q-btn
dense
flat
icon="search"
label="Search"
@click="searchProducts"
@keydown.enter="searchProducts"
/>
</template>
</q-input>
</q-card-section>
</q-card>
</div>
</div>
<q-toolbar> <q-toolbar>
<q-breadcrumbs> <q-breadcrumbs>
<q-breadcrumbs-el label="Market" icon="home"></q-breadcrumbs-el> <q-breadcrumbs-el label="Market" icon="home"></q-breadcrumbs-el>

View file

@ -4,13 +4,47 @@ async function customerMarket(path) {
name: 'customer-market', name: 'customer-market',
template, template,
props: ['products', 'change-page'], props: [
'products',
'change-page',
'search-nostr',
'relays',
'update-products',
'update-stalls'
],
data: function () { data: function () {
return {} return {
search: null
}
}, },
methods: { methods: {
changePageM(page, opts) { changePageM(page, opts) {
this.$emit('change-page', page, opts) this.$emit('change-page', page, opts)
},
async searchProducts() {
this.$q.loading.show()
let searchTags = this.search.split(' ')
const pool = new NostrTools.SimplePool()
let relays = Array.from(this.relays)
let merchants = new Set()
let productEvents = await pool.list(relays, [
{
kinds: [30018],
'#t': searchTags,
search: this.search, // NIP50, not very well supported
limit: 100
}
])
productEvents.map(e => merchants.add(e.pubkey))
let stallEvents = await pool.list(relays, [
{
kinds: [30017],
authors: Array.from(merchants)
}
])
await this.$emit('update-data', [...stallEvents, ...productEvents])
this.$q.loading.hide()
} }
}, },
created() {} created() {}

View file

@ -10,7 +10,8 @@ const market = async () => {
'wss://nostr.zebedee.cloud' 'wss://nostr.zebedee.cloud'
] ]
const eventToObj = event => { const eventToObj = event => {
event.content = JSON.parse(event.content) console.log(event.content)
event.content = JSON.parse(event.content) || null
return { return {
...event, ...event,
...Object.values(event.tags).reduce((acc, tag) => { ...Object.values(event.tags).reduce((acc, tag) => {
@ -41,6 +42,7 @@ const market = async () => {
key: null key: null
} }
}, },
searchNostr: false,
drawer: false, drawer: false,
pubkeys: new Set(), pubkeys: new Set(),
relays: new Set(), relays: new Set(),
@ -62,13 +64,15 @@ const market = async () => {
if (this.activeStall) { if (this.activeStall) {
products = products.filter(p => p.stall_id == this.activeStall) products = products.filter(p => p.stall_id == this.activeStall)
} }
if (!this.searchText || this.searchText.length < 2) return products
const searchText = this.searchText.toLowerCase() const searchText = this.searchText.toLowerCase()
if (!searchText || searchText.length < 2) return products
return products.filter(p => { return products.filter(p => {
return ( return (
p.name.toLowerCase().includes(searchText) || p.name.toLowerCase().includes(searchText) ||
p.description.toLowerCase().includes(searchText) || (p.description &&
p.categories.toLowerCase().includes(searchText) p.description.toLowerCase().includes(searchText)) ||
(p.categories &&
p.categories.toString().toLowerCase().includes(searchText))
) )
}) })
}, },
@ -191,6 +195,36 @@ const market = async () => {
this.accountDialog.data.watchOnly = true this.accountDialog.data.watchOnly = true
return return
}, },
async updateData(events) {
let products = new Map()
let stalls = new Map()
this.stalls.forEach(s => stalls.set(s.id, s))
this.products.forEach(p => products.set(p.id, p))
events.map(eventToObj).map(e => {
if (e.kind == 30018) {
//it's a product `d` is the prod. id
products.set(e.d, {...e.content, id: e.d[0], categories: e.t})
} else if (e.kind == 30017) {
// it's a stall `d` is the stall id
stalls.set(e.d, {...e.content, id: e.d[0], pubkey: e.pubkey})
return
}
})
this.stalls = await Array.from(stalls.values())
this.products = Array.from(products.values()).map(obj => {
let stall = this.stalls.find(s => s.id == obj.stall_id)
obj.stallName = stall.name
obj.images = [obj.image]
if (obj.currency != 'sat') {
obj.formatedPrice = this.getAmountFormated(obj.price, obj.currency)
}
return obj
})
},
async initNostr() { async initNostr() {
this.$q.loading.show() this.$q.loading.show()
const pool = new NostrTools.SimplePool() const pool = new NostrTools.SimplePool()
@ -205,8 +239,8 @@ const market = async () => {
authors: Array.from(this.pubkeys) authors: Array.from(this.pubkeys)
} }
]) ])
.then(events => { .then(async events => {
console.log(events) // ;[stalls, products] = await this.updateData(events)
this.events = events || [] this.events = events || []
this.events.map(eventToObj).map(e => { this.events.map(eventToObj).map(e => {
if (e.kind == 0) { if (e.kind == 0) {

View file

@ -148,15 +148,24 @@
{{ activePage }} {{ activePage }}
</q-toolbar-title> </q-toolbar-title>
{%endraw%} {%endraw%}
<q-space></q-space>
<q-btn
v-if="!activeStall"
color="primary"
label="Search"
icon="travel_explore"
@click="searchNostr = !searchNostr"
><q-tooltip>Search for products on Nostr</q-tooltip></q-btn
>
<q-input <q-input
class="float-left q-ml-md" class="q-ml-md"
standout standout
square square
dense dense
outlined outlined
clearable clearable
v-model.trim="searchText" v-model.trim="searchText"
label="Search for products" label="Filter products"
> >
<template v-slot:append> <template v-slot:append>
<q-icon v-if="!searchText" name="search" /> <q-icon v-if="!searchText" name="search" />
@ -176,8 +185,11 @@
></customer-stall> ></customer-stall>
<customer-market <customer-market
v-else v-else
:search-nostr="searchNostr"
:relays="relays"
:products="filterProducts" :products="filterProducts"
@change-page="navigateTo" @change-page="navigateTo"
@update-data="updateData"
></customer-market> ></customer-market>
</q-page-container> </q-page-container>
<!-- ACCOUNT DIALOG --> <!-- ACCOUNT DIALOG -->