mirror of
https://github.com/AustinKelsay/plebdevs.git
synced 2025-06-04 08:12:02 +00:00
Implemented ndk with tanstack query for courses resources and workshops, and zaps is mostly working
This commit is contained in:
parent
9a1694dc74
commit
4b0476c509
375
package-lock.json
generated
375
package-lock.json
generated
@ -10,6 +10,7 @@
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@getalby/bitcoin-connect-react": "^3.5.3",
|
||||
"@nostr-dev-kit/ndk": "^2.10.0",
|
||||
"@prisma/client": "^5.17.0",
|
||||
"@tanstack/react-query": "^5.51.21",
|
||||
"@uiw/react-markdown-preview": "^5.1.2",
|
||||
@ -987,6 +988,15 @@
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@noble/secp256k1": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-2.1.0.tgz",
|
||||
"integrity": "sha512-XLEQQNdablO0XZOIniFQimiXsZDNwaYgL96dZwC54Q30imSbAOFf3NKtepc+cXyuZf5Q1HCgbqgZ2UFFuHVcEw==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
@ -1025,6 +1035,53 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@nostr-dev-kit/ndk": {
|
||||
"version": "2.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@nostr-dev-kit/ndk/-/ndk-2.10.0.tgz",
|
||||
"integrity": "sha512-TqCAAo6ylORraAXrzRkCGFN2xTMiFbdER8Y8CtUT0HwOpFG/Wn+PBNeDeDmqkl/6LaPdeyXmVwCWj2KcUjIwYA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/curves": "^1.4.0",
|
||||
"@noble/hashes": "^1.3.1",
|
||||
"@noble/secp256k1": "^2.0.0",
|
||||
"@scure/base": "^1.1.1",
|
||||
"debug": "^4.3.4",
|
||||
"light-bolt11-decoder": "^3.0.0",
|
||||
"node-fetch": "^3.3.1",
|
||||
"nostr-tools": "^2.7.1",
|
||||
"tseep": "^1.1.1",
|
||||
"typescript-lru-cache": "^2.0.0",
|
||||
"utf8-buffer": "^1.0.0",
|
||||
"websocket-polyfill": "^0.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@nostr-dev-kit/ndk/node_modules/@noble/curves": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz",
|
||||
"integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/hashes": "1.4.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@nostr-dev-kit/ndk/node_modules/@noble/hashes": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz",
|
||||
"integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@panva/hkdf": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.2.1.tgz",
|
||||
@ -3588,6 +3645,19 @@
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/bufferutil": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz",
|
||||
"integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"node-gyp-build": "^4.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.14.2"
|
||||
}
|
||||
},
|
||||
"node_modules/busboy": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
|
||||
@ -3922,6 +3992,19 @@
|
||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/d": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz",
|
||||
"integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"es5-ext": "^0.10.64",
|
||||
"type": "^2.7.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/damerau-levenshtein": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
||||
@ -3929,6 +4012,15 @@
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/data-uri-to-buffer": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
|
||||
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/data-view-buffer": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz",
|
||||
@ -4431,6 +4523,46 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/es5-ext": {
|
||||
"version": "0.10.64",
|
||||
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz",
|
||||
"integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==",
|
||||
"hasInstallScript": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"es6-iterator": "^2.0.3",
|
||||
"es6-symbol": "^3.1.3",
|
||||
"esniff": "^2.0.1",
|
||||
"next-tick": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/es6-iterator": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
|
||||
"integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"d": "1",
|
||||
"es5-ext": "^0.10.35",
|
||||
"es6-symbol": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/es6-symbol": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz",
|
||||
"integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"d": "^1.0.2",
|
||||
"ext": "^1.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
|
||||
@ -4825,6 +4957,21 @@
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/esniff": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz",
|
||||
"integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"d": "^1.0.1",
|
||||
"es5-ext": "^0.10.62",
|
||||
"event-emitter": "^0.3.5",
|
||||
"type": "^2.7.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/espree": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
|
||||
@ -4897,6 +5044,16 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/event-emitter": {
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
|
||||
"integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"d": "1",
|
||||
"es5-ext": "~0.10.14"
|
||||
}
|
||||
},
|
||||
"node_modules/eventemitter3": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
|
||||
@ -4913,6 +5070,15 @@
|
||||
"node": ">=0.8.x"
|
||||
}
|
||||
},
|
||||
"node_modules/ext": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
|
||||
"integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"type": "^2.7.2"
|
||||
}
|
||||
},
|
||||
"node_modules/extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
@ -4984,6 +5150,29 @@
|
||||
"reusify": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/fetch-blob": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
||||
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/jimmywarting"
|
||||
},
|
||||
{
|
||||
"type": "paypal",
|
||||
"url": "https://paypal.me/jimmywarting"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"node-domexception": "^1.0.0",
|
||||
"web-streams-polyfill": "^3.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20 || >= 14.13"
|
||||
}
|
||||
},
|
||||
"node_modules/file-entry-cache": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
|
||||
@ -5126,6 +5315,18 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/formdata-polyfill": {
|
||||
"version": "4.0.10",
|
||||
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
||||
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fetch-blob": "^3.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
@ -6711,6 +6912,12 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/is-weakmap": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
|
||||
@ -8255,6 +8462,12 @@
|
||||
"babel-plugin-transform-remove-imports": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/next-tick": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
|
||||
"integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/next/node_modules/postcss": {
|
||||
"version": "8.4.31",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
|
||||
@ -8283,6 +8496,54 @@
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/node-domexception": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/jimmywarting"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://paypal.me/jimmywarting"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
|
||||
"integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"data-uri-to-buffer": "^4.0.0",
|
||||
"fetch-blob": "^3.1.4",
|
||||
"formdata-polyfill": "^4.0.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/node-fetch"
|
||||
}
|
||||
},
|
||||
"node_modules/node-gyp-build": {
|
||||
"version": "4.8.1",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz",
|
||||
"integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"node-gyp-build": "bin.js",
|
||||
"node-gyp-build-optional": "optional.js",
|
||||
"node-gyp-build-test": "build-test.js"
|
||||
}
|
||||
},
|
||||
"node_modules/node-releases": {
|
||||
"version": "2.0.17",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.17.tgz",
|
||||
@ -10884,12 +11145,30 @@
|
||||
"json5": "lib/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/tseep": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/tseep/-/tseep-1.2.2.tgz",
|
||||
"integrity": "sha512-GgPFuNx+08UaYBYmJQmuI86ykYa2PUUtfXAYb4MLRHGunSCp8k9N+dbsR4PK1yk4/zV9q4e4PrNg8ymXqGYaYA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.6.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
|
||||
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/tstl": {
|
||||
"version": "2.5.16",
|
||||
"resolved": "https://registry.npmjs.org/tstl/-/tstl-2.5.16.tgz",
|
||||
"integrity": "sha512-+O2ybLVLKcBwKm4HymCEwZIT0PpwS3gCYnxfSDEjJEKADvIFruaQjd3m7CAKNU1c7N3X3WjVz87re7TA2A5FUw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/type": {
|
||||
"version": "2.7.3",
|
||||
"resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz",
|
||||
"integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
@ -10993,6 +11272,15 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/typedarray-to-buffer": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
|
||||
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-typedarray": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.5.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz",
|
||||
@ -11008,6 +11296,12 @@
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript-lru-cache": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/typescript-lru-cache/-/typescript-lru-cache-2.0.0.tgz",
|
||||
"integrity": "sha512-Jp57Qyy8wXeMkdNuZiglE6v2Cypg13eDA1chHwDG6kq51X7gk4K7P7HaDdzZKCxkegXkVHNcPD0n5aW6OZH3aA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/unbox-primitive": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
|
||||
@ -11201,6 +11495,28 @@
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/utf-8-validate": {
|
||||
"version": "5.0.10",
|
||||
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz",
|
||||
"integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"node-gyp-build": "^4.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.14.2"
|
||||
}
|
||||
},
|
||||
"node_modules/utf8-buffer": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/utf8-buffer/-/utf8-buffer-1.0.0.tgz",
|
||||
"integrity": "sha512-ueuhzvWnp5JU5CiGSY4WdKbiN/PO2AZ/lpeLiz2l38qwdLy/cW40XobgyuIWucNyum0B33bVB0owjFCeGBSLqg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
@ -11355,6 +11671,15 @@
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/web-streams-polyfill": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
|
||||
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack": {
|
||||
"version": "5.93.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz",
|
||||
@ -11456,6 +11781,47 @@
|
||||
"url": "https://opencollective.com/webpack"
|
||||
}
|
||||
},
|
||||
"node_modules/websocket": {
|
||||
"version": "1.0.35",
|
||||
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.35.tgz",
|
||||
"integrity": "sha512-/REy6amwPZl44DDzvRCkaI1q1bIiQB0mEFQLUrhz3z2EK91cp3n72rAjUlrTP0zV22HJIUOVHQGPxhFRjxjt+Q==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"debug": "^2.2.0",
|
||||
"es5-ext": "^0.10.63",
|
||||
"typedarray-to-buffer": "^3.1.5",
|
||||
"utf-8-validate": "^5.0.2",
|
||||
"yaeti": "^0.0.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/websocket-polyfill": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/websocket-polyfill/-/websocket-polyfill-0.0.3.tgz",
|
||||
"integrity": "sha512-pF3kR8Uaoau78MpUmFfzbIRxXj9PeQrCuPepGE6JIsfsJ/o/iXr07Q2iQNzKSSblQJ0FiGWlS64N4pVSm+O3Dg==",
|
||||
"dependencies": {
|
||||
"tstl": "^2.0.7",
|
||||
"websocket": "^1.0.28"
|
||||
}
|
||||
},
|
||||
"node_modules/websocket/node_modules/debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/websocket/node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
@ -11673,6 +12039,15 @@
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/yaeti": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz",
|
||||
"integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.32"
|
||||
}
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
|
@ -11,6 +11,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@getalby/bitcoin-connect-react": "^3.5.3",
|
||||
"@nostr-dev-kit/ndk": "^2.10.0",
|
||||
"@prisma/client": "^5.17.0",
|
||||
"@tanstack/react-query": "^5.51.21",
|
||||
"@uiw/react-markdown-preview": "^5.1.2",
|
||||
|
@ -1,10 +1,9 @@
|
||||
import React, { useState, useEffect, use } from 'react';
|
||||
import { Carousel } from 'primereact/carousel';
|
||||
import { parseCourseEvent } from '@/utils/nostr';
|
||||
import { useNostr } from '@/hooks/useNostr';
|
||||
import { useZapsQuery } from '@/hooks/nostrQueries/useZapsQuery';
|
||||
import CourseTemplate from '@/components/content/carousels/templates/CourseTemplate';
|
||||
import TemplateSkeleton from '@/components/content/carousels/skeletons/TemplateSkeleton';
|
||||
// import { useNostrQueries } from '@/hooks/useNostrQueries';
|
||||
import { useCoursesQuery } from '@/hooks/nostrQueries/useCoursesQuery';
|
||||
|
||||
const responsiveOptions = [
|
||||
@ -27,35 +26,28 @@ const responsiveOptions = [
|
||||
|
||||
export default function CoursesCarousel() {
|
||||
const [processedCourses, setProcessedCourses] = useState([]);
|
||||
const { fetchZapsForEvents } = useNostr();
|
||||
// const { courses, coursesError, zapsForEvents, refetchZapsForEvents } = useNostrQueries()
|
||||
const { courses, coursesError, refetchCourses } = useCoursesQuery()
|
||||
const { courses, coursesLoading, coursesError, refetchCourses } = useCoursesQuery()
|
||||
const { zaps, zapsLoading, zapsError, refetchZaps } = useZapsQuery({ events: courses })
|
||||
|
||||
useEffect(() => {
|
||||
refetchZaps(courses)
|
||||
}, [courses, refetchZaps]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetch = async () => {
|
||||
try {
|
||||
if (courses && courses.length > 0) {
|
||||
console.log('courses:', courses);
|
||||
// First process the courses to be ready for display
|
||||
if (courses && courses.length > 0 && zaps) {
|
||||
const processedCourses = courses.map(course => parseCourseEvent(course));
|
||||
|
||||
// Fetch zaps for all processed courses at once
|
||||
const allZaps = await fetchZapsForEvents(processedCourses);
|
||||
console.log('allZaps:', allZaps);
|
||||
|
||||
// Process zaps to associate them with their respective courses
|
||||
const coursesWithZaps = processedCourses.map(course => {
|
||||
const relevantZaps = allZaps.filter(zap => {
|
||||
const eTagMatches = zap.tags.find(tag => tag[0] === 'e' && tag[1] === course.id);
|
||||
const aTag = zap.tags.find(tag => tag[0] === 'a');
|
||||
const aTagMatches = aTag && course.d === aTag[1].split(':').pop();
|
||||
return eTagMatches || aTagMatches;
|
||||
});
|
||||
return {
|
||||
...course,
|
||||
zaps: relevantZaps
|
||||
};
|
||||
});
|
||||
let coursesWithZaps = processedCourses.map(course => {
|
||||
let collectedZaps = []
|
||||
zaps.forEach(zap => {
|
||||
if (zap.tags.find(tag => tag[0] === "e" && tag[1] === course.id) || zap.tags.find(tag => tag[0] === "a" && tag[1] === `${course.kind}:${course.id}:${course.d}`)) {
|
||||
collectedZaps.push(zap)
|
||||
}
|
||||
})
|
||||
return { ...course, zaps: collectedZaps }
|
||||
})
|
||||
|
||||
setProcessedCourses(coursesWithZaps);
|
||||
} else {
|
||||
@ -66,12 +58,16 @@ export default function CoursesCarousel() {
|
||||
}
|
||||
};
|
||||
fetch();
|
||||
}, [courses]);
|
||||
}, [courses, zaps]);
|
||||
|
||||
if (coursesError) {
|
||||
return <div>Error: {coursesError.message}</div>
|
||||
}
|
||||
|
||||
if (coursesLoading) {
|
||||
return <div>Loading...</div>
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<h2 className="ml-[6%] mt-4">Courses</h2>
|
||||
|
@ -1,11 +1,10 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Carousel } from 'primereact/carousel';
|
||||
import { useNostr } from '@/hooks/useNostr';
|
||||
import { parseEvent } from '@/utils/nostr';
|
||||
import ResourceTemplate from '@/components/content/carousels/templates/ResourceTemplate';
|
||||
import TemplateSkeleton from '@/components/content/carousels/skeletons/TemplateSkeleton';
|
||||
import { useNostrQueries } from '@/hooks/useNostrQueries';
|
||||
import { useResourcesQuery } from '@/hooks/useResourcesQuery';
|
||||
import { useResourcesQuery } from '@/hooks/nostrQueries/useResourcesQuery';
|
||||
import { useZapsQuery } from '@/hooks/nostrQueries/useZapsQuery';
|
||||
|
||||
const responsiveOptions = [
|
||||
{
|
||||
@ -27,36 +26,32 @@ const responsiveOptions = [
|
||||
|
||||
export default function ResourcesCarousel() {
|
||||
const [processedResources, setProcessedResources] = useState([]);
|
||||
const { fetchZapsForEvents } = useNostr();
|
||||
// const { resources, resourcesError, refetchResources } = useNostrQueries()
|
||||
const { resources, resourcesError, refetchResources } = useResourcesQuery()
|
||||
const { resources, resourcesLoading, resourcesError, refetchResources } = useResourcesQuery()
|
||||
const { zaps, zapsLoading, zapsError, refetchZaps } = useZapsQuery({ events: resources })
|
||||
|
||||
useEffect(() => {
|
||||
if (resources && resources.length > 0) {
|
||||
refetchZaps(resources)
|
||||
}
|
||||
}, [resources, refetchZaps]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetch = async () => {
|
||||
try {
|
||||
if (resources && resources.length > 0) {
|
||||
if (resources && resources.length > 0 && zaps) {
|
||||
const processedResources = resources.map(resource => parseEvent(resource));
|
||||
|
||||
console.log('processedResources:', processedResources);
|
||||
|
||||
const allZaps = await fetchZapsForEvents(processedResources);
|
||||
|
||||
const resourcesWithZaps = processedResources.map(resource => {
|
||||
const relevantZaps = allZaps.filter(zap => {
|
||||
const eTagMatches = zap.tags.find(tag => tag[0] === 'e' && tag[1] === resource.id);
|
||||
const aTag = zap.tags.find(tag => tag[0] === 'a');
|
||||
const aTagMatches = aTag && resource.d === aTag[1].split(':').pop();
|
||||
return eTagMatches || aTagMatches;
|
||||
});
|
||||
return {
|
||||
...resource,
|
||||
zaps: relevantZaps
|
||||
};
|
||||
});
|
||||
|
||||
let resourcesWithZaps = processedResources.map(resource => {
|
||||
let collectedZaps = []
|
||||
zaps.forEach(zap => {
|
||||
if (zap.tags.find(tag => tag[0] === "e" && tag[1] === resource.id) || zap.tags.find(tag => tag[0] === "a" && tag[1] === `${resource.kind}:${resource.id}:${resource.d}`)) {
|
||||
collectedZaps.push(zap)
|
||||
}
|
||||
})
|
||||
return { ...resource, zaps: collectedZaps }
|
||||
})
|
||||
|
||||
setProcessedResources(resourcesWithZaps);
|
||||
} else {
|
||||
refetchResources();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching resources:', error);
|
||||
@ -65,10 +60,13 @@ export default function ResourcesCarousel() {
|
||||
fetch();
|
||||
}, [resources]);
|
||||
|
||||
if (resourcesLoading) {
|
||||
return <div>Loading...</div>
|
||||
}
|
||||
|
||||
if (resourcesError) {
|
||||
return <div>Error: {resourcesError.message}</div>
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -1,13 +1,10 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Carousel } from 'primereact/carousel';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useImageProxy } from '@/hooks/useImageProxy';
|
||||
import { useNostr } from '@/hooks/useNostr';
|
||||
import { parseEvent } from '@/utils/nostr';
|
||||
import WorkshopTemplate from '@/components/content/carousels/templates/WorkshopTemplate';
|
||||
import TemplateSkeleton from '@/components/content/carousels/skeletons/TemplateSkeleton';
|
||||
// import { useNostrQueries } from '@/hooks/useNostrQueries';
|
||||
import { useWorkshopsQuery } from '@/hooks/nostrQueries/useWorkshopsQuery';
|
||||
import { useZapsQuery } from '@/hooks/nostrQueries/useZapsQuery';
|
||||
|
||||
const responsiveOptions = [
|
||||
{
|
||||
@ -29,32 +26,29 @@ const responsiveOptions = [
|
||||
|
||||
export default function WorkshopsCarousel() {
|
||||
const [processedWorkshops, setProcessedWorkshops] = useState([])
|
||||
const { workshops, workshopsLoading, workshopsError, refetchWorkshops } = useWorkshopsQuery()
|
||||
const { zaps, zapsLoading, zapsError, refetchZaps } = useZapsQuery({ events: workshops })
|
||||
|
||||
// const { workshops, workshopsError } = useNostrQueries()
|
||||
const { workshops, workshopsError, refetchWorkshops } = useWorkshopsQuery()
|
||||
const { fetchZapsForEvents } = useNostr()
|
||||
useEffect(() => {
|
||||
refetchZaps(workshops)
|
||||
}, [workshops, refetchZaps]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetch = async () => {
|
||||
try {
|
||||
console.debug('workshops', workshops);
|
||||
if (workshops && workshops.length > 0) {
|
||||
if (workshops && workshops.length > 0 && zaps) {
|
||||
const processedWorkshops = workshops.map(workshop => parseEvent(workshop));
|
||||
|
||||
const allZaps = await fetchZapsForEvents(processedWorkshops);
|
||||
|
||||
const workshopsWithZaps = processedWorkshops.map(workshop => {
|
||||
const relevantZaps = allZaps.filter(zap => {
|
||||
const eTagMatches = zap.tags.find(tag => tag[0] === 'e' && tag[1] === workshop.id);
|
||||
const aTag = zap.tags.find(tag => tag[0] === 'a');
|
||||
const aTagMatches = aTag && workshop.d === aTag[1].split(':').pop();
|
||||
return eTagMatches || aTagMatches;
|
||||
});
|
||||
return {
|
||||
...workshop,
|
||||
zaps: relevantZaps
|
||||
};
|
||||
});
|
||||
|
||||
let workshopsWithZaps = processedWorkshops.map(workshop => {
|
||||
let collectedZaps = []
|
||||
zaps.forEach(zap => {
|
||||
if (zap.tags.find(tag => tag[0] === "e" && tag[1] === workshop.id) || zap.tags.find(tag => tag[0] === "a" && tag[1] === `${workshop.kind}:${workshop.id}:${workshop.d}`)) {
|
||||
collectedZaps.push(zap)
|
||||
}
|
||||
})
|
||||
return { ...workshop, zaps: collectedZaps }
|
||||
})
|
||||
|
||||
setProcessedWorkshops(workshopsWithZaps);
|
||||
} else {
|
||||
@ -65,11 +59,10 @@ export default function WorkshopsCarousel() {
|
||||
}
|
||||
};
|
||||
fetch();
|
||||
}, [workshops]);
|
||||
}, [workshops, zaps]);
|
||||
|
||||
if (workshopsError) {
|
||||
return <div>Error: {workshopsError.message}</div>
|
||||
}
|
||||
if (workshopsLoading) return <div>Loading...</div>;
|
||||
if (workshopsError) return <div>Error: {workshopsError}</div>;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -3,20 +3,20 @@ import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import { formatTimestampToHowLongAgo } from "@/utils/time";
|
||||
import { useImageProxy } from "@/hooks/useImageProxy";
|
||||
import { useNostr } from "@/hooks/useNostr";
|
||||
import { getSatAmountFromInvoice } from "@/utils/lightning";
|
||||
import ZapDisplay from "@/components/zaps/ZapDisplay";
|
||||
|
||||
const CourseTemplate = ({course}) => {
|
||||
const [zapAmount, setZapAmount] = useState(null);
|
||||
const CourseTemplate = ({ course }) => {
|
||||
const [zapAmount, setZapAmount] = useState(0);
|
||||
const router = useRouter();
|
||||
const { returnImageProxy } = useImageProxy();
|
||||
|
||||
useEffect(() => {
|
||||
if (!course || !course.zaps) return;
|
||||
if (!course?.zaps || !course?.zaps.length > 0) return;
|
||||
|
||||
let total = 0;
|
||||
course.zaps.forEach((zap) => {
|
||||
// If the zap matches the event or the parameterized event, then add the zap to the total
|
||||
const bolt11Tag = zap.tags.find(tag => tag[0] === "bolt11");
|
||||
const invoice = bolt11Tag ? bolt11Tag[1] : null;
|
||||
if (invoice) {
|
||||
|
@ -3,39 +3,41 @@ import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import { formatTimestampToHowLongAgo } from "@/utils/time";
|
||||
import { useImageProxy } from "@/hooks/useImageProxy";
|
||||
import { useNostr } from "@/hooks/useNostr";
|
||||
import { useZapsQuery } from "@/hooks/nostrQueries/useZapsQuery";
|
||||
import { getSatAmountFromInvoice } from "@/utils/lightning";
|
||||
import ZapDisplay from "@/components/zaps/ZapDisplay";
|
||||
|
||||
const ResourceTemplate = ({ resource }) => {
|
||||
const [zapAmount, setZapAmount] = useState(0);
|
||||
|
||||
const ResourceTemplate = ({resource}) => {
|
||||
const [zapAmount, setZapAmount] = useState(null);
|
||||
const router = useRouter();
|
||||
const { returnImageProxy } = useImageProxy();
|
||||
|
||||
useEffect(() => {
|
||||
if (!resource || !resource.zaps) return;
|
||||
|
||||
if (!resource?.zaps || !resource?.zaps.length > 0) return;
|
||||
|
||||
let total = 0;
|
||||
resource.zaps.forEach((zap) => {
|
||||
// If the zap matches the event or the parameterized event, then add the zap to the total
|
||||
const bolt11Tag = zap.tags.find(tag => tag[0] === "bolt11");
|
||||
const invoice = bolt11Tag ? bolt11Tag[1] : null;
|
||||
if (invoice) {
|
||||
const amount = getSatAmountFromInvoice(invoice);
|
||||
total += amount;
|
||||
const amount = getSatAmountFromInvoice(invoice);
|
||||
total += amount;
|
||||
}
|
||||
});
|
||||
setZapAmount(total);
|
||||
}, [resource]);
|
||||
|
||||
}, [resource]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="flex flex-col items-center mx-auto px-4 mt-8 rounded-md"
|
||||
>
|
||||
{/* Wrap the image in a div with a relative class with a padding-bottom of 56.25% representing the aspect ratio of 16:9 */}
|
||||
<div
|
||||
{/* Wrap the image in a div with a relative class with a padding-bottom of 56.25% representing the aspect ratio of 16:9 */}
|
||||
<div
|
||||
onClick={() => router.push(`/details/${resource.id}`)}
|
||||
className="relative w-full h-0 hover:opacity-80 transition-opacity duration-300 cursor-pointer"
|
||||
style={{ paddingBottom: "56.25%"}}
|
||||
style={{ paddingBottom: "56.25%" }}
|
||||
>
|
||||
<Image
|
||||
alt="resource thumbnail"
|
||||
@ -55,9 +57,7 @@ const ResourceTemplate = ({resource}) => {
|
||||
<p className="text-xs text-gray-400">
|
||||
{formatTimestampToHowLongAgo(resource.published_at)}
|
||||
</p>
|
||||
<p className="text-xs cursor-pointer">
|
||||
<i className="pi pi-bolt text-yellow-300"></i> {zapAmount}
|
||||
</p>
|
||||
<ZapDisplay zapAmount={zapAmount} event={resource} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3,28 +3,36 @@ import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import { formatTimestampToHowLongAgo } from "@/utils/time";
|
||||
import { useImageProxy } from "@/hooks/useImageProxy";
|
||||
import { useNostr } from "@/hooks/useNostr";
|
||||
import { useZapsQuery } from "@/hooks/nostrQueries/useZapsQuery";
|
||||
import { getSatAmountFromInvoice } from "@/utils/lightning";
|
||||
import ZapDisplay from "@/components/zaps/ZapDisplay";
|
||||
|
||||
const WorkshopTemplate = ({workshop}) => {
|
||||
const [zapAmount, setZapAmount] = useState(null);
|
||||
const [zapAmount, setZapAmount] = useState(0);
|
||||
const router = useRouter();
|
||||
const { returnImageProxy } = useImageProxy();
|
||||
const { zaps, zapsLoading, zapsError, refetchZaps } = useZapsQuery({event: workshop});
|
||||
|
||||
useEffect(() => {
|
||||
if (!workshop || !workshop.zaps) return;
|
||||
if (!zaps || !zaps.length > 0) return;
|
||||
|
||||
let total = 0;
|
||||
workshop.zaps.forEach((zap) => {
|
||||
const bolt11Tag = zap.tags.find(tag => tag[0] === "bolt11");
|
||||
const invoice = bolt11Tag ? bolt11Tag[1] : null;
|
||||
zaps.forEach((zap) => {
|
||||
// If the zap matches the event or the parameterized event, then add the zap to the total
|
||||
if (zap.tags.find(tag => tag[0] === "e" && tag[1] === workshop.id) || zap.tags.find(tag => tag[0] === "a" && tag[1] === `${workshop.kind}:${workshop.id}:${workshop.d}`)) {
|
||||
const bolt11Tag = zap.tags.find(tag => tag[0] === "bolt11");
|
||||
const invoice = bolt11Tag ? bolt11Tag[1] : null;
|
||||
if (invoice) {
|
||||
const amount = getSatAmountFromInvoice(invoice);
|
||||
total += amount;
|
||||
}
|
||||
}
|
||||
});
|
||||
setZapAmount(total);
|
||||
}, [workshop]);
|
||||
}, [zaps, workshop]);
|
||||
|
||||
if (zapsLoading) return <div>Loading...</div>;
|
||||
if (zapsError) return <div>Error: {zapsError}</div>;
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -53,9 +61,7 @@ const WorkshopTemplate = ({workshop}) => {
|
||||
<p className="text-xs text-gray-400">
|
||||
{formatTimestampToHowLongAgo(workshop.published_at)}
|
||||
</p>
|
||||
<p className="text-xs cursor-pointer">
|
||||
<i className="pi pi-bolt text-yellow-300"></i> {zapAmount}
|
||||
</p>
|
||||
<ZapDisplay zapAmount={zapAmount} event={workshop} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
41
src/context/NDKContext.js
Normal file
41
src/context/NDKContext.js
Normal file
@ -0,0 +1,41 @@
|
||||
import React, { createContext, useContext, useEffect, useState } from 'react';
|
||||
import NDK from "@nostr-dev-kit/ndk";
|
||||
|
||||
const NDKContext = createContext(null);
|
||||
|
||||
// Define the public key of the author whose events we want to fetch.
|
||||
const AUTHOR_PUBKEY = process.env.NEXT_PUBLIC_AUTHOR_PUBKEY;
|
||||
|
||||
// Ensure AUTHOR_PUBKEY is defined
|
||||
if (!AUTHOR_PUBKEY) {
|
||||
throw new Error("NEXT_PUBLIC_AUTHOR_PUBKEY is not defined in the environment variables");
|
||||
}
|
||||
|
||||
const relayUrls = [
|
||||
"wss://nos.lol/",
|
||||
"wss://relay.damus.io/",
|
||||
"wss://relay.snort.social/",
|
||||
"wss://relay.nostr.band/",
|
||||
"wss://nostr.mutinywallet.com/",
|
||||
"wss://relay.mutinywallet.com/",
|
||||
"wss://relay.primal.net/"
|
||||
];
|
||||
|
||||
export const NDKProvider = ({ children }) => {
|
||||
const [ndk, setNdk] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
const instance = new NDK({ explicitRelayUrls: relayUrls });
|
||||
setNdk(instance);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<NDKContext.Provider value={ndk}>
|
||||
{children}
|
||||
</NDKContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useNDKContext = () => {
|
||||
return useContext(NDKContext);
|
||||
};
|
@ -1,58 +1,43 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useNostr } from '@/hooks/useNostr';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useNDKContext } from '@/context/NDKContext';
|
||||
|
||||
const AUTHOR_PUBKEY = process.env.NEXT_PUBLIC_AUTHOR_PUBKEY
|
||||
|
||||
export function useCoursesQuery() {
|
||||
const [isClient, setIsClient] = useState(false);
|
||||
const { subscribe } = useNostr();
|
||||
const ndk = useNDKContext();
|
||||
|
||||
useEffect(() => {
|
||||
setIsClient(true);
|
||||
}, []);
|
||||
|
||||
const fetchCourses = async () => {
|
||||
const filter = [{ kinds: [30004], authors: [AUTHOR_PUBKEY] }];
|
||||
// Do we need required tags for courses? community instead?
|
||||
// const hasRequiredTags = (tags) => {
|
||||
// const hasPlebDevs = tags.some(([tag, value]) => tag === "t" && value === "plebdevs");
|
||||
// const hasCourse = tags.some(([tag, value]) => tag === "t" && value === "course");
|
||||
// return hasPlebDevs && hasCourse;
|
||||
// };
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let courses = [];
|
||||
const subscription = subscribe(
|
||||
filter,
|
||||
{
|
||||
onevent: (event) => {
|
||||
// if (hasRequiredTags(event.tags)) {
|
||||
// courses.push(event);
|
||||
// }
|
||||
courses.push(event);
|
||||
},
|
||||
onerror: (error) => {
|
||||
console.error('Error fetching courses:', error);
|
||||
reject(error);
|
||||
},
|
||||
onclose: () => {
|
||||
resolve(courses);
|
||||
},
|
||||
const fetchCoursesFromNDK = async () => {
|
||||
try {
|
||||
console.log('Fetching courses from NDK');
|
||||
await ndk.connect();
|
||||
|
||||
const filter = { kinds: [30004], authors: [AUTHOR_PUBKEY] };
|
||||
const events = await ndk.fetchEvents(filter);
|
||||
|
||||
if (events && events.size > 0) {
|
||||
const eventsArray = Array.from(events);
|
||||
console.log('eventsArray', eventsArray)
|
||||
// const resources = eventsArray.filter(event => hasRequiredTags(event.tags));
|
||||
// return resources;
|
||||
return eventsArray;
|
||||
}
|
||||
);
|
||||
|
||||
setTimeout(() => {
|
||||
subscription?.close();
|
||||
resolve(courses);
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
return [];
|
||||
} catch (error) {
|
||||
console.error('Error fetching workshops from NDK:', error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const { data: courses, isLoading: coursesLoading, error: coursesError, refetch: refetchCourses } = useQuery({
|
||||
queryKey: ['courses', isClient],
|
||||
queryFn: fetchCourses,
|
||||
staleTime: 1000 * 60 * 10, // 10 minutes
|
||||
queryFn: fetchCoursesFromNDK,
|
||||
staleTime: 1000 * 60 * 30, // 30 minutes
|
||||
cacheTime: 1000 * 60 * 60, // 1 hour
|
||||
enabled: isClient,
|
||||
})
|
||||
|
@ -1,58 +1,48 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useNostr } from '@/hooks/useNostr';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useNDKContext } from '@/context/NDKContext';
|
||||
|
||||
const AUTHOR_PUBKEY = process.env.NEXT_PUBLIC_AUTHOR_PUBKEY
|
||||
|
||||
export function useResourcesQuery() {
|
||||
const [isClient, setIsClient] = useState(false);
|
||||
const { subscribe } = useNostr();
|
||||
const ndk = useNDKContext();
|
||||
|
||||
useEffect(() => {
|
||||
setIsClient(true);
|
||||
}, []);
|
||||
|
||||
const fetchResources = async () => {
|
||||
console.log('fetching resources');
|
||||
const filter = [{ kinds: [30023, 30402], authors: [AUTHOR_PUBKEY] }];
|
||||
const hasRequiredTags = (tags) => {
|
||||
const hasPlebDevs = tags.some(([tag, value]) => tag === "t" && value === "plebdevs");
|
||||
const hasResource = tags.some(([tag, value]) => tag === "t" && value === "resource");
|
||||
return hasPlebDevs && hasResource;
|
||||
};
|
||||
const hasRequiredTags = (tags) => {
|
||||
const hasPlebDevs = tags.some(([tag, value]) => tag === "t" && value === "plebdevs");
|
||||
const hasWorkshop = tags.some(([tag, value]) => tag === "t" && value === "resource");
|
||||
return hasPlebDevs && hasWorkshop;
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let resources = [];
|
||||
const subscription = subscribe(
|
||||
filter,
|
||||
{
|
||||
onevent: (event) => {
|
||||
if (hasRequiredTags(event.tags)) {
|
||||
resources.push(event);
|
||||
}
|
||||
},
|
||||
onerror: (error) => {
|
||||
console.error('Error fetching resources:', error);
|
||||
reject(error);
|
||||
},
|
||||
onclose: () => {
|
||||
resolve(resources);
|
||||
},
|
||||
}
|
||||
);
|
||||
const fetchResourcesFromNDK = async () => {
|
||||
try {
|
||||
console.log('Fetching workshops from NDK');
|
||||
await ndk.connect();
|
||||
|
||||
// Set a timeout to resolve the promise after collecting events
|
||||
setTimeout(() => {
|
||||
subscription?.close();
|
||||
resolve(resources);
|
||||
}, 2000); // Adjust the timeout value as needed
|
||||
});
|
||||
const filter = { kinds: [30023, 30402], authors: [AUTHOR_PUBKEY] };
|
||||
const events = await ndk.fetchEvents(filter);
|
||||
|
||||
if (events && events.size > 0) {
|
||||
const eventsArray = Array.from(events);
|
||||
console.log('eventsArray', eventsArray)
|
||||
const resources = eventsArray.filter(event => hasRequiredTags(event.tags));
|
||||
return resources;
|
||||
}
|
||||
return [];
|
||||
} catch (error) {
|
||||
console.error('Error fetching workshops from NDK:', error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const { data: resources, isLoading: resourcesLoading, error: resourcesError, refetch: refetchResources } = useQuery({
|
||||
queryKey: ['resources', isClient],
|
||||
queryFn: fetchResources,
|
||||
staleTime: 1000 * 60 * 10, // 10 minutes
|
||||
queryFn: fetchResourcesFromNDK,
|
||||
staleTime: 1000 * 60 * 30, // 30 minutes
|
||||
cacheTime: 1000 * 60 * 60, // 1 hour
|
||||
enabled: isClient,
|
||||
})
|
||||
|
@ -1,58 +1,48 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useNostr } from '@/hooks/useNostr';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useNDKContext } from '@/context/NDKContext';
|
||||
|
||||
const AUTHOR_PUBKEY = process.env.NEXT_PUBLIC_AUTHOR_PUBKEY
|
||||
|
||||
export function useWorkshopsQuery() {
|
||||
const [isClient, setIsClient] = useState(false);
|
||||
const { subscribe } = useNostr();
|
||||
const ndk = useNDKContext();
|
||||
|
||||
useEffect(() => {
|
||||
setIsClient(true);
|
||||
}, []);
|
||||
|
||||
const fetchWorkshops = async () => {
|
||||
console.log('fetching workshops');
|
||||
const filter = [{ kinds: [30023, 30402], authors: [AUTHOR_PUBKEY] }];
|
||||
const hasRequiredTags = (tags) => {
|
||||
const hasPlebDevs = tags.some(([tag, value]) => tag === "t" && value === "plebdevs");
|
||||
const hasWorkshop = tags.some(([tag, value]) => tag === "t" && value === "workshop");
|
||||
return hasPlebDevs && hasWorkshop;
|
||||
};
|
||||
const hasRequiredTags = (tags) => {
|
||||
const hasPlebDevs = tags.some(([tag, value]) => tag === "t" && value === "plebdevs");
|
||||
const hasWorkshop = tags.some(([tag, value]) => tag === "t" && value === "workshop");
|
||||
return hasPlebDevs && hasWorkshop;
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let resources = [];
|
||||
const subscription = subscribe(
|
||||
filter,
|
||||
{
|
||||
onevent: (event) => {
|
||||
if (hasRequiredTags(event.tags)) {
|
||||
resources.push(event);
|
||||
}
|
||||
},
|
||||
onerror: (error) => {
|
||||
console.error('Error fetching resources:', error);
|
||||
reject(error);
|
||||
},
|
||||
onclose: () => {
|
||||
resolve(resources);
|
||||
},
|
||||
const fetchWorkshopsFromNDK = async () => {
|
||||
try {
|
||||
console.log('Fetching workshops from NDK');
|
||||
await ndk.connect();
|
||||
|
||||
const filter = { kinds: [30023, 30402], authors: [AUTHOR_PUBKEY] };
|
||||
const events = await ndk.fetchEvents(filter);
|
||||
|
||||
if (events && events.size > 0) {
|
||||
const eventsArray = Array.from(events);
|
||||
console.log('eventsArray', eventsArray)
|
||||
const resources = eventsArray.filter(event => hasRequiredTags(event.tags));
|
||||
return resources;
|
||||
}
|
||||
);
|
||||
|
||||
// Set a timeout to resolve the promise after collecting events
|
||||
setTimeout(() => {
|
||||
subscription?.close();
|
||||
resolve(resources);
|
||||
}, 2000); // Adjust the timeout value as needed
|
||||
});
|
||||
}
|
||||
return [];
|
||||
} catch (error) {
|
||||
console.error('Error fetching workshops from NDK:', error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const { data: workshops, isLoading: workshopsLoading, error: workshopsError, refetch: refetchWorkshops } = useQuery({
|
||||
queryKey: ['workshops', isClient],
|
||||
queryFn: fetchWorkshops,
|
||||
staleTime: 1000 * 60 * 10, // 10 minutes
|
||||
queryFn: fetchWorkshopsFromNDK,
|
||||
staleTime: 1000 * 60 * 30, // 30 minutes
|
||||
cacheTime: 1000 * 60 * 60, // 1 hour
|
||||
enabled: isClient,
|
||||
})
|
||||
|
47
src/hooks/nostrQueries/useZapsQuery.js
Normal file
47
src/hooks/nostrQueries/useZapsQuery.js
Normal file
@ -0,0 +1,47 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useNDKContext } from '@/context/NDKContext';
|
||||
|
||||
export function useZapsQuery({ events }) {
|
||||
const [isClient, setIsClient] = useState(false);
|
||||
const ndk = useNDKContext();
|
||||
|
||||
useEffect(() => {
|
||||
setIsClient(true);
|
||||
}, []);
|
||||
|
||||
const fetchZapsFromNDK = async (events) => {
|
||||
try {
|
||||
await ndk.connect();
|
||||
|
||||
let zaps = [];
|
||||
|
||||
for (const event of events) {
|
||||
const uniqueEvents = new Set();
|
||||
const filters = [{ kinds: [9735], "#e": [event.id] }, { kinds: [9735], "#a": [`${event.kind}:${event.id}:${event.d}`] }];
|
||||
|
||||
for (const filter of filters) {
|
||||
const zapEvents = await ndk.fetchEvents(filter);
|
||||
zapEvents.forEach(zap => uniqueEvents.add(zap));
|
||||
}
|
||||
|
||||
zaps = [...zaps, ...Array.from(uniqueEvents)];
|
||||
}
|
||||
console.log('Zaps fetched:', zaps);
|
||||
return zaps;
|
||||
} catch (error) {
|
||||
console.error('Error fetching zaps from NDK:', error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const { data: zaps, isLoading: zapsLoading, error: zapsError, refetch: refetchZaps } = useQuery({
|
||||
queryKey: ['zaps', isClient],
|
||||
queryFn: () => fetchZapsFromNDK(events),
|
||||
staleTime: 1000 * 60 * 3, // 3 minutes
|
||||
cacheTime: 1000 * 60 * 60, // 1 hour
|
||||
enabled: isClient,
|
||||
})
|
||||
|
||||
return { zaps, zapsLoading, zapsError, refetchZaps }
|
||||
}
|
@ -9,6 +9,7 @@ import "@uiw/react-md-editor/markdown-editor.css";
|
||||
import "@uiw/react-markdown-preview/markdown.css";
|
||||
import Sidebar from '@/components/sidebar/Sidebar';
|
||||
import { NostrProvider } from '@/context/NostrContext';
|
||||
import { NDKProvider } from '@/context/NDKContext';
|
||||
import {
|
||||
QueryClient,
|
||||
QueryClientProvider,
|
||||
@ -22,22 +23,24 @@ export default function MyApp({
|
||||
return (
|
||||
<PrimeReactProvider>
|
||||
<NostrProvider>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<ToastProvider>
|
||||
<Layout>
|
||||
<div className="flex flex-col min-h-screen">
|
||||
<Navbar />
|
||||
{/* <div className='flex'> */}
|
||||
{/* <Sidebar /> */}
|
||||
{/* <div className='max-w-[100vw] pl-[15vw]'> */}
|
||||
<div className='max-w-[100vw]'>
|
||||
<Component {...pageProps} />
|
||||
<NDKProvider>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<ToastProvider>
|
||||
<Layout>
|
||||
<div className="flex flex-col min-h-screen">
|
||||
<Navbar />
|
||||
{/* <div className='flex'> */}
|
||||
{/* <Sidebar /> */}
|
||||
{/* <div className='max-w-[100vw] pl-[15vw]'> */}
|
||||
<div className='max-w-[100vw]'>
|
||||
<Component {...pageProps} />
|
||||
</div>
|
||||
{/* </div> */}
|
||||
</div>
|
||||
{/* </div> */}
|
||||
</div>
|
||||
</Layout>
|
||||
</ToastProvider>
|
||||
</QueryClientProvider>
|
||||
</Layout>
|
||||
</ToastProvider>
|
||||
</QueryClientProvider>
|
||||
</NDKProvider>
|
||||
</NostrProvider>
|
||||
</PrimeReactProvider>
|
||||
);
|
||||
|
@ -1,11 +1,9 @@
|
||||
import Head from 'next/head';
|
||||
import React, { useEffect, useCallback } from 'react';
|
||||
import React from 'react';
|
||||
import CoursesCarousel from '@/components/content/carousels/CoursesCarousel';
|
||||
import WorkshopsCarousel from '@/components/content/carousels/WorkshopsCarousel';
|
||||
import HeroBanner from '@/components/banner/HeroBanner';
|
||||
import ResourcesCarousel from '@/components/content/carousels/ResourcesCarousel';
|
||||
import { useLocalStorageWithEffect } from '@/hooks/useLocalStorage';
|
||||
import axios from 'axios';
|
||||
|
||||
export default function Home() {
|
||||
|
||||
@ -20,8 +18,8 @@ export default function Home() {
|
||||
<main>
|
||||
<HeroBanner />
|
||||
<CoursesCarousel />
|
||||
<WorkshopsCarousel />
|
||||
<ResourcesCarousel />
|
||||
{/* <WorkshopsCarousel />
|
||||
<ResourcesCarousel /> */}
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user