mirror of
https://github.com/AustinKelsay/plebdevs.git
synced 2025-06-06 01:02:04 +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,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@getalby/bitcoin-connect-react": "^3.5.3",
|
"@getalby/bitcoin-connect-react": "^3.5.3",
|
||||||
|
"@nostr-dev-kit/ndk": "^2.10.0",
|
||||||
"@prisma/client": "^5.17.0",
|
"@prisma/client": "^5.17.0",
|
||||||
"@tanstack/react-query": "^5.51.21",
|
"@tanstack/react-query": "^5.51.21",
|
||||||
"@uiw/react-markdown-preview": "^5.1.2",
|
"@uiw/react-markdown-preview": "^5.1.2",
|
||||||
@ -987,6 +988,15 @@
|
|||||||
"url": "https://paulmillr.com/funding/"
|
"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": {
|
"node_modules/@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
@ -1025,6 +1035,53 @@
|
|||||||
"node": ">= 8"
|
"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": {
|
"node_modules/@panva/hkdf": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.2.1.tgz",
|
||||||
@ -3588,6 +3645,19 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true
|
"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": {
|
"node_modules/busboy": {
|
||||||
"version": "1.6.0",
|
"version": "1.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
|
||||||
@ -3922,6 +3992,19 @@
|
|||||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/damerau-levenshtein": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
||||||
@ -3929,6 +4012,15 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause"
|
"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": {
|
"node_modules/data-view-buffer": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz",
|
"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"
|
"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": {
|
"node_modules/escalade": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
|
||||||
@ -4825,6 +4957,21 @@
|
|||||||
"url": "https://opencollective.com/eslint"
|
"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": {
|
"node_modules/espree": {
|
||||||
"version": "9.6.1",
|
"version": "9.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
|
||||||
@ -4897,6 +5044,16 @@
|
|||||||
"node": ">=0.10.0"
|
"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": {
|
"node_modules/eventemitter3": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
|
||||||
@ -4913,6 +5070,15 @@
|
|||||||
"node": ">=0.8.x"
|
"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": {
|
"node_modules/extend": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||||
@ -4984,6 +5150,29 @@
|
|||||||
"reusify": "^1.0.4"
|
"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": {
|
"node_modules/file-entry-cache": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
|
||||||
@ -5126,6 +5315,18 @@
|
|||||||
"node": ">= 6"
|
"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": {
|
"node_modules/fs.realpath": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
@ -6711,6 +6912,12 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"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": {
|
"node_modules/is-weakmap": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
|
"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"
|
"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": {
|
"node_modules/next/node_modules/postcss": {
|
||||||
"version": "8.4.31",
|
"version": "8.4.31",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
|
||||||
@ -8283,6 +8496,54 @@
|
|||||||
"node": "^10 || ^12 || >=14"
|
"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": {
|
"node_modules/node-releases": {
|
||||||
"version": "2.0.17",
|
"version": "2.0.17",
|
||||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.17.tgz",
|
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.17.tgz",
|
||||||
@ -10884,12 +11145,30 @@
|
|||||||
"json5": "lib/cli.js"
|
"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": {
|
"node_modules/tslib": {
|
||||||
"version": "2.6.3",
|
"version": "2.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
|
||||||
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
|
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
|
||||||
"license": "0BSD"
|
"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": {
|
"node_modules/type-check": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||||
@ -10993,6 +11272,15 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"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": {
|
"node_modules/typescript": {
|
||||||
"version": "5.5.3",
|
"version": "5.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz",
|
||||||
@ -11008,6 +11296,12 @@
|
|||||||
"node": ">=14.17"
|
"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": {
|
"node_modules/unbox-primitive": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
|
"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"
|
"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": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
@ -11355,6 +11671,15 @@
|
|||||||
"url": "https://github.com/sponsors/wooorm"
|
"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": {
|
"node_modules/webpack": {
|
||||||
"version": "5.93.0",
|
"version": "5.93.0",
|
||||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz",
|
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz",
|
||||||
@ -11456,6 +11781,47 @@
|
|||||||
"url": "https://opencollective.com/webpack"
|
"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": {
|
"node_modules/which": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||||
@ -11673,6 +12039,15 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"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": {
|
"node_modules/yallist": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@getalby/bitcoin-connect-react": "^3.5.3",
|
"@getalby/bitcoin-connect-react": "^3.5.3",
|
||||||
|
"@nostr-dev-kit/ndk": "^2.10.0",
|
||||||
"@prisma/client": "^5.17.0",
|
"@prisma/client": "^5.17.0",
|
||||||
"@tanstack/react-query": "^5.51.21",
|
"@tanstack/react-query": "^5.51.21",
|
||||||
"@uiw/react-markdown-preview": "^5.1.2",
|
"@uiw/react-markdown-preview": "^5.1.2",
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import React, { useState, useEffect, use } from 'react';
|
import React, { useState, useEffect, use } from 'react';
|
||||||
import { Carousel } from 'primereact/carousel';
|
import { Carousel } from 'primereact/carousel';
|
||||||
import { parseCourseEvent } from '@/utils/nostr';
|
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 CourseTemplate from '@/components/content/carousels/templates/CourseTemplate';
|
||||||
import TemplateSkeleton from '@/components/content/carousels/skeletons/TemplateSkeleton';
|
import TemplateSkeleton from '@/components/content/carousels/skeletons/TemplateSkeleton';
|
||||||
// import { useNostrQueries } from '@/hooks/useNostrQueries';
|
|
||||||
import { useCoursesQuery } from '@/hooks/nostrQueries/useCoursesQuery';
|
import { useCoursesQuery } from '@/hooks/nostrQueries/useCoursesQuery';
|
||||||
|
|
||||||
const responsiveOptions = [
|
const responsiveOptions = [
|
||||||
@ -27,35 +26,28 @@ const responsiveOptions = [
|
|||||||
|
|
||||||
export default function CoursesCarousel() {
|
export default function CoursesCarousel() {
|
||||||
const [processedCourses, setProcessedCourses] = useState([]);
|
const [processedCourses, setProcessedCourses] = useState([]);
|
||||||
const { fetchZapsForEvents } = useNostr();
|
const { courses, coursesLoading, coursesError, refetchCourses } = useCoursesQuery()
|
||||||
// const { courses, coursesError, zapsForEvents, refetchZapsForEvents } = useNostrQueries()
|
const { zaps, zapsLoading, zapsError, refetchZaps } = useZapsQuery({ events: courses })
|
||||||
const { courses, coursesError, refetchCourses } = useCoursesQuery()
|
|
||||||
|
useEffect(() => {
|
||||||
|
refetchZaps(courses)
|
||||||
|
}, [courses, refetchZaps]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetch = async () => {
|
const fetch = async () => {
|
||||||
try {
|
try {
|
||||||
if (courses && courses.length > 0) {
|
if (courses && courses.length > 0 && zaps) {
|
||||||
console.log('courses:', courses);
|
|
||||||
// First process the courses to be ready for display
|
|
||||||
const processedCourses = courses.map(course => parseCourseEvent(course));
|
const processedCourses = courses.map(course => parseCourseEvent(course));
|
||||||
|
|
||||||
// Fetch zaps for all processed courses at once
|
let coursesWithZaps = processedCourses.map(course => {
|
||||||
const allZaps = await fetchZapsForEvents(processedCourses);
|
let collectedZaps = []
|
||||||
console.log('allZaps:', allZaps);
|
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}`)) {
|
||||||
// Process zaps to associate them with their respective courses
|
collectedZaps.push(zap)
|
||||||
const coursesWithZaps = processedCourses.map(course => {
|
}
|
||||||
const relevantZaps = allZaps.filter(zap => {
|
})
|
||||||
const eTagMatches = zap.tags.find(tag => tag[0] === 'e' && tag[1] === course.id);
|
return { ...course, zaps: collectedZaps }
|
||||||
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
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
setProcessedCourses(coursesWithZaps);
|
setProcessedCourses(coursesWithZaps);
|
||||||
} else {
|
} else {
|
||||||
@ -66,12 +58,16 @@ export default function CoursesCarousel() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
fetch();
|
fetch();
|
||||||
}, [courses]);
|
}, [courses, zaps]);
|
||||||
|
|
||||||
if (coursesError) {
|
if (coursesError) {
|
||||||
return <div>Error: {coursesError.message}</div>
|
return <div>Error: {coursesError.message}</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (coursesLoading) {
|
||||||
|
return <div>Loading...</div>
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h2 className="ml-[6%] mt-4">Courses</h2>
|
<h2 className="ml-[6%] mt-4">Courses</h2>
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Carousel } from 'primereact/carousel';
|
import { Carousel } from 'primereact/carousel';
|
||||||
import { useNostr } from '@/hooks/useNostr';
|
|
||||||
import { parseEvent } from '@/utils/nostr';
|
import { parseEvent } from '@/utils/nostr';
|
||||||
import ResourceTemplate from '@/components/content/carousels/templates/ResourceTemplate';
|
import ResourceTemplate from '@/components/content/carousels/templates/ResourceTemplate';
|
||||||
import TemplateSkeleton from '@/components/content/carousels/skeletons/TemplateSkeleton';
|
import TemplateSkeleton from '@/components/content/carousels/skeletons/TemplateSkeleton';
|
||||||
import { useNostrQueries } from '@/hooks/useNostrQueries';
|
import { useResourcesQuery } from '@/hooks/nostrQueries/useResourcesQuery';
|
||||||
import { useResourcesQuery } from '@/hooks/useResourcesQuery';
|
import { useZapsQuery } from '@/hooks/nostrQueries/useZapsQuery';
|
||||||
|
|
||||||
const responsiveOptions = [
|
const responsiveOptions = [
|
||||||
{
|
{
|
||||||
@ -27,36 +26,32 @@ const responsiveOptions = [
|
|||||||
|
|
||||||
export default function ResourcesCarousel() {
|
export default function ResourcesCarousel() {
|
||||||
const [processedResources, setProcessedResources] = useState([]);
|
const [processedResources, setProcessedResources] = useState([]);
|
||||||
const { fetchZapsForEvents } = useNostr();
|
const { resources, resourcesLoading, resourcesError, refetchResources } = useResourcesQuery()
|
||||||
// const { resources, resourcesError, refetchResources } = useNostrQueries()
|
const { zaps, zapsLoading, zapsError, refetchZaps } = useZapsQuery({ events: resources })
|
||||||
const { resources, resourcesError, refetchResources } = useResourcesQuery()
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (resources && resources.length > 0) {
|
||||||
|
refetchZaps(resources)
|
||||||
|
}
|
||||||
|
}, [resources, refetchZaps]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetch = async () => {
|
const fetch = async () => {
|
||||||
try {
|
try {
|
||||||
if (resources && resources.length > 0) {
|
if (resources && resources.length > 0 && zaps) {
|
||||||
const processedResources = resources.map(resource => parseEvent(resource));
|
const processedResources = resources.map(resource => parseEvent(resource));
|
||||||
|
|
||||||
console.log('processedResources:', processedResources);
|
let resourcesWithZaps = processedResources.map(resource => {
|
||||||
|
let collectedZaps = []
|
||||||
const allZaps = await fetchZapsForEvents(processedResources);
|
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}`)) {
|
||||||
const resourcesWithZaps = processedResources.map(resource => {
|
collectedZaps.push(zap)
|
||||||
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');
|
return { ...resource, zaps: collectedZaps }
|
||||||
const aTagMatches = aTag && resource.d === aTag[1].split(':').pop();
|
})
|
||||||
return eTagMatches || aTagMatches;
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
...resource,
|
|
||||||
zaps: relevantZaps
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
setProcessedResources(resourcesWithZaps);
|
setProcessedResources(resourcesWithZaps);
|
||||||
} else {
|
|
||||||
refetchResources();
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching resources:', error);
|
console.error('Error fetching resources:', error);
|
||||||
@ -65,10 +60,13 @@ export default function ResourcesCarousel() {
|
|||||||
fetch();
|
fetch();
|
||||||
}, [resources]);
|
}, [resources]);
|
||||||
|
|
||||||
|
if (resourcesLoading) {
|
||||||
|
return <div>Loading...</div>
|
||||||
|
}
|
||||||
|
|
||||||
if (resourcesError) {
|
if (resourcesError) {
|
||||||
return <div>Error: {resourcesError.message}</div>
|
return <div>Error: {resourcesError.message}</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Carousel } from 'primereact/carousel';
|
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 { parseEvent } from '@/utils/nostr';
|
||||||
import WorkshopTemplate from '@/components/content/carousels/templates/WorkshopTemplate';
|
import WorkshopTemplate from '@/components/content/carousels/templates/WorkshopTemplate';
|
||||||
import TemplateSkeleton from '@/components/content/carousels/skeletons/TemplateSkeleton';
|
import TemplateSkeleton from '@/components/content/carousels/skeletons/TemplateSkeleton';
|
||||||
// import { useNostrQueries } from '@/hooks/useNostrQueries';
|
|
||||||
import { useWorkshopsQuery } from '@/hooks/nostrQueries/useWorkshopsQuery';
|
import { useWorkshopsQuery } from '@/hooks/nostrQueries/useWorkshopsQuery';
|
||||||
|
import { useZapsQuery } from '@/hooks/nostrQueries/useZapsQuery';
|
||||||
|
|
||||||
const responsiveOptions = [
|
const responsiveOptions = [
|
||||||
{
|
{
|
||||||
@ -29,32 +26,29 @@ const responsiveOptions = [
|
|||||||
|
|
||||||
export default function WorkshopsCarousel() {
|
export default function WorkshopsCarousel() {
|
||||||
const [processedWorkshops, setProcessedWorkshops] = useState([])
|
const [processedWorkshops, setProcessedWorkshops] = useState([])
|
||||||
|
const { workshops, workshopsLoading, workshopsError, refetchWorkshops } = useWorkshopsQuery()
|
||||||
|
const { zaps, zapsLoading, zapsError, refetchZaps } = useZapsQuery({ events: workshops })
|
||||||
|
|
||||||
// const { workshops, workshopsError } = useNostrQueries()
|
useEffect(() => {
|
||||||
const { workshops, workshopsError, refetchWorkshops } = useWorkshopsQuery()
|
refetchZaps(workshops)
|
||||||
const { fetchZapsForEvents } = useNostr()
|
}, [workshops, refetchZaps]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetch = async () => {
|
const fetch = async () => {
|
||||||
try {
|
try {
|
||||||
console.debug('workshops', workshops);
|
console.debug('workshops', workshops);
|
||||||
if (workshops && workshops.length > 0) {
|
if (workshops && workshops.length > 0 && zaps) {
|
||||||
const processedWorkshops = workshops.map(workshop => parseEvent(workshop));
|
const processedWorkshops = workshops.map(workshop => parseEvent(workshop));
|
||||||
|
|
||||||
const allZaps = await fetchZapsForEvents(processedWorkshops);
|
let workshopsWithZaps = processedWorkshops.map(workshop => {
|
||||||
|
let collectedZaps = []
|
||||||
const workshopsWithZaps = processedWorkshops.map(workshop => {
|
zaps.forEach(zap => {
|
||||||
const relevantZaps = allZaps.filter(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}`)) {
|
||||||
const eTagMatches = zap.tags.find(tag => tag[0] === 'e' && tag[1] === workshop.id);
|
collectedZaps.push(zap)
|
||||||
const aTag = zap.tags.find(tag => tag[0] === 'a');
|
}
|
||||||
const aTagMatches = aTag && workshop.d === aTag[1].split(':').pop();
|
})
|
||||||
return eTagMatches || aTagMatches;
|
return { ...workshop, zaps: collectedZaps }
|
||||||
});
|
})
|
||||||
return {
|
|
||||||
...workshop,
|
|
||||||
zaps: relevantZaps
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
setProcessedWorkshops(workshopsWithZaps);
|
setProcessedWorkshops(workshopsWithZaps);
|
||||||
} else {
|
} else {
|
||||||
@ -65,11 +59,10 @@ export default function WorkshopsCarousel() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
fetch();
|
fetch();
|
||||||
}, [workshops]);
|
}, [workshops, zaps]);
|
||||||
|
|
||||||
if (workshopsError) {
|
if (workshopsLoading) return <div>Loading...</div>;
|
||||||
return <div>Error: {workshopsError.message}</div>
|
if (workshopsError) return <div>Error: {workshopsError}</div>;
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -3,20 +3,20 @@ import Image from "next/image";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { formatTimestampToHowLongAgo } from "@/utils/time";
|
import { formatTimestampToHowLongAgo } from "@/utils/time";
|
||||||
import { useImageProxy } from "@/hooks/useImageProxy";
|
import { useImageProxy } from "@/hooks/useImageProxy";
|
||||||
import { useNostr } from "@/hooks/useNostr";
|
|
||||||
import { getSatAmountFromInvoice } from "@/utils/lightning";
|
import { getSatAmountFromInvoice } from "@/utils/lightning";
|
||||||
import ZapDisplay from "@/components/zaps/ZapDisplay";
|
import ZapDisplay from "@/components/zaps/ZapDisplay";
|
||||||
|
|
||||||
const CourseTemplate = ({course}) => {
|
const CourseTemplate = ({ course }) => {
|
||||||
const [zapAmount, setZapAmount] = useState(null);
|
const [zapAmount, setZapAmount] = useState(0);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { returnImageProxy } = useImageProxy();
|
const { returnImageProxy } = useImageProxy();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!course || !course.zaps) return;
|
if (!course?.zaps || !course?.zaps.length > 0) return;
|
||||||
|
|
||||||
let total = 0;
|
let total = 0;
|
||||||
course.zaps.forEach((zap) => {
|
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 bolt11Tag = zap.tags.find(tag => tag[0] === "bolt11");
|
||||||
const invoice = bolt11Tag ? bolt11Tag[1] : null;
|
const invoice = bolt11Tag ? bolt11Tag[1] : null;
|
||||||
if (invoice) {
|
if (invoice) {
|
||||||
|
@ -3,39 +3,41 @@ import Image from "next/image";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { formatTimestampToHowLongAgo } from "@/utils/time";
|
import { formatTimestampToHowLongAgo } from "@/utils/time";
|
||||||
import { useImageProxy } from "@/hooks/useImageProxy";
|
import { useImageProxy } from "@/hooks/useImageProxy";
|
||||||
import { useNostr } from "@/hooks/useNostr";
|
import { useZapsQuery } from "@/hooks/nostrQueries/useZapsQuery";
|
||||||
import { getSatAmountFromInvoice } from "@/utils/lightning";
|
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 router = useRouter();
|
||||||
const { returnImageProxy } = useImageProxy();
|
const { returnImageProxy } = useImageProxy();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!resource || !resource.zaps) return;
|
if (!resource?.zaps || !resource?.zaps.length > 0) return;
|
||||||
|
|
||||||
let total = 0;
|
let total = 0;
|
||||||
resource.zaps.forEach((zap) => {
|
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 bolt11Tag = zap.tags.find(tag => tag[0] === "bolt11");
|
||||||
const invoice = bolt11Tag ? bolt11Tag[1] : null;
|
const invoice = bolt11Tag ? bolt11Tag[1] : null;
|
||||||
if (invoice) {
|
if (invoice) {
|
||||||
const amount = getSatAmountFromInvoice(invoice);
|
const amount = getSatAmountFromInvoice(invoice);
|
||||||
total += amount;
|
total += amount;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
setZapAmount(total);
|
setZapAmount(total);
|
||||||
}, [resource]);
|
}, [resource]);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="flex flex-col items-center mx-auto px-4 mt-8 rounded-md"
|
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 */}
|
{/* 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
|
<div
|
||||||
onClick={() => router.push(`/details/${resource.id}`)}
|
onClick={() => router.push(`/details/${resource.id}`)}
|
||||||
className="relative w-full h-0 hover:opacity-80 transition-opacity duration-300 cursor-pointer"
|
className="relative w-full h-0 hover:opacity-80 transition-opacity duration-300 cursor-pointer"
|
||||||
style={{ paddingBottom: "56.25%"}}
|
style={{ paddingBottom: "56.25%" }}
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
alt="resource thumbnail"
|
alt="resource thumbnail"
|
||||||
@ -55,9 +57,7 @@ const ResourceTemplate = ({resource}) => {
|
|||||||
<p className="text-xs text-gray-400">
|
<p className="text-xs text-gray-400">
|
||||||
{formatTimestampToHowLongAgo(resource.published_at)}
|
{formatTimestampToHowLongAgo(resource.published_at)}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-xs cursor-pointer">
|
<ZapDisplay zapAmount={zapAmount} event={resource} />
|
||||||
<i className="pi pi-bolt text-yellow-300"></i> {zapAmount}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,28 +3,36 @@ import Image from "next/image";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { formatTimestampToHowLongAgo } from "@/utils/time";
|
import { formatTimestampToHowLongAgo } from "@/utils/time";
|
||||||
import { useImageProxy } from "@/hooks/useImageProxy";
|
import { useImageProxy } from "@/hooks/useImageProxy";
|
||||||
import { useNostr } from "@/hooks/useNostr";
|
import { useZapsQuery } from "@/hooks/nostrQueries/useZapsQuery";
|
||||||
import { getSatAmountFromInvoice } from "@/utils/lightning";
|
import { getSatAmountFromInvoice } from "@/utils/lightning";
|
||||||
|
import ZapDisplay from "@/components/zaps/ZapDisplay";
|
||||||
|
|
||||||
const WorkshopTemplate = ({workshop}) => {
|
const WorkshopTemplate = ({workshop}) => {
|
||||||
const [zapAmount, setZapAmount] = useState(null);
|
const [zapAmount, setZapAmount] = useState(0);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { returnImageProxy } = useImageProxy();
|
const { returnImageProxy } = useImageProxy();
|
||||||
|
const { zaps, zapsLoading, zapsError, refetchZaps } = useZapsQuery({event: workshop});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!workshop || !workshop.zaps) return;
|
if (!zaps || !zaps.length > 0) return;
|
||||||
|
|
||||||
let total = 0;
|
let total = 0;
|
||||||
workshop.zaps.forEach((zap) => {
|
zaps.forEach((zap) => {
|
||||||
const bolt11Tag = zap.tags.find(tag => tag[0] === "bolt11");
|
// If the zap matches the event or the parameterized event, then add the zap to the total
|
||||||
const invoice = bolt11Tag ? bolt11Tag[1] : null;
|
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) {
|
if (invoice) {
|
||||||
const amount = getSatAmountFromInvoice(invoice);
|
const amount = getSatAmountFromInvoice(invoice);
|
||||||
total += amount;
|
total += amount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
setZapAmount(total);
|
setZapAmount(total);
|
||||||
}, [workshop]);
|
}, [zaps, workshop]);
|
||||||
|
|
||||||
|
if (zapsLoading) return <div>Loading...</div>;
|
||||||
|
if (zapsError) return <div>Error: {zapsError}</div>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -53,9 +61,7 @@ const WorkshopTemplate = ({workshop}) => {
|
|||||||
<p className="text-xs text-gray-400">
|
<p className="text-xs text-gray-400">
|
||||||
{formatTimestampToHowLongAgo(workshop.published_at)}
|
{formatTimestampToHowLongAgo(workshop.published_at)}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-xs cursor-pointer">
|
<ZapDisplay zapAmount={zapAmount} event={workshop} />
|
||||||
<i className="pi pi-bolt text-yellow-300"></i> {zapAmount}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</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 { useState, useEffect } from 'react';
|
||||||
import { useNostr } from '@/hooks/useNostr';
|
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import { useNDKContext } from '@/context/NDKContext';
|
||||||
|
|
||||||
const AUTHOR_PUBKEY = process.env.NEXT_PUBLIC_AUTHOR_PUBKEY
|
const AUTHOR_PUBKEY = process.env.NEXT_PUBLIC_AUTHOR_PUBKEY
|
||||||
|
|
||||||
export function useCoursesQuery() {
|
export function useCoursesQuery() {
|
||||||
const [isClient, setIsClient] = useState(false);
|
const [isClient, setIsClient] = useState(false);
|
||||||
const { subscribe } = useNostr();
|
const ndk = useNDKContext();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsClient(true);
|
setIsClient(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const fetchCourses = async () => {
|
const fetchCoursesFromNDK = async () => {
|
||||||
const filter = [{ kinds: [30004], authors: [AUTHOR_PUBKEY] }];
|
try {
|
||||||
// Do we need required tags for courses? community instead?
|
console.log('Fetching courses from NDK');
|
||||||
// const hasRequiredTags = (tags) => {
|
await ndk.connect();
|
||||||
// const hasPlebDevs = tags.some(([tag, value]) => tag === "t" && value === "plebdevs");
|
|
||||||
// const hasCourse = tags.some(([tag, value]) => tag === "t" && value === "course");
|
const filter = { kinds: [30004], authors: [AUTHOR_PUBKEY] };
|
||||||
// return hasPlebDevs && hasCourse;
|
const events = await ndk.fetchEvents(filter);
|
||||||
// };
|
|
||||||
|
if (events && events.size > 0) {
|
||||||
return new Promise((resolve, reject) => {
|
const eventsArray = Array.from(events);
|
||||||
let courses = [];
|
console.log('eventsArray', eventsArray)
|
||||||
const subscription = subscribe(
|
// const resources = eventsArray.filter(event => hasRequiredTags(event.tags));
|
||||||
filter,
|
// return resources;
|
||||||
{
|
return eventsArray;
|
||||||
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);
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
);
|
return [];
|
||||||
|
} catch (error) {
|
||||||
setTimeout(() => {
|
console.error('Error fetching workshops from NDK:', error);
|
||||||
subscription?.close();
|
return [];
|
||||||
resolve(courses);
|
}
|
||||||
}, 2000);
|
};
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const { data: courses, isLoading: coursesLoading, error: coursesError, refetch: refetchCourses } = useQuery({
|
const { data: courses, isLoading: coursesLoading, error: coursesError, refetch: refetchCourses } = useQuery({
|
||||||
queryKey: ['courses', isClient],
|
queryKey: ['courses', isClient],
|
||||||
queryFn: fetchCourses,
|
queryFn: fetchCoursesFromNDK,
|
||||||
staleTime: 1000 * 60 * 10, // 10 minutes
|
staleTime: 1000 * 60 * 30, // 30 minutes
|
||||||
cacheTime: 1000 * 60 * 60, // 1 hour
|
cacheTime: 1000 * 60 * 60, // 1 hour
|
||||||
enabled: isClient,
|
enabled: isClient,
|
||||||
})
|
})
|
||||||
|
@ -1,58 +1,48 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { useNostr } from '@/hooks/useNostr';
|
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import { useNDKContext } from '@/context/NDKContext';
|
||||||
|
|
||||||
const AUTHOR_PUBKEY = process.env.NEXT_PUBLIC_AUTHOR_PUBKEY
|
const AUTHOR_PUBKEY = process.env.NEXT_PUBLIC_AUTHOR_PUBKEY
|
||||||
|
|
||||||
export function useResourcesQuery() {
|
export function useResourcesQuery() {
|
||||||
const [isClient, setIsClient] = useState(false);
|
const [isClient, setIsClient] = useState(false);
|
||||||
const { subscribe } = useNostr();
|
const ndk = useNDKContext();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsClient(true);
|
setIsClient(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const fetchResources = async () => {
|
const hasRequiredTags = (tags) => {
|
||||||
console.log('fetching resources');
|
const hasPlebDevs = tags.some(([tag, value]) => tag === "t" && value === "plebdevs");
|
||||||
const filter = [{ kinds: [30023, 30402], authors: [AUTHOR_PUBKEY] }];
|
const hasWorkshop = tags.some(([tag, value]) => tag === "t" && value === "resource");
|
||||||
const hasRequiredTags = (tags) => {
|
return hasPlebDevs && hasWorkshop;
|
||||||
const hasPlebDevs = tags.some(([tag, value]) => tag === "t" && value === "plebdevs");
|
};
|
||||||
const hasResource = tags.some(([tag, value]) => tag === "t" && value === "resource");
|
|
||||||
return hasPlebDevs && hasResource;
|
|
||||||
};
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
const fetchResourcesFromNDK = async () => {
|
||||||
let resources = [];
|
try {
|
||||||
const subscription = subscribe(
|
console.log('Fetching workshops from NDK');
|
||||||
filter,
|
await ndk.connect();
|
||||||
{
|
|
||||||
onevent: (event) => {
|
|
||||||
if (hasRequiredTags(event.tags)) {
|
|
||||||
resources.push(event);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onerror: (error) => {
|
|
||||||
console.error('Error fetching resources:', error);
|
|
||||||
reject(error);
|
|
||||||
},
|
|
||||||
onclose: () => {
|
|
||||||
resolve(resources);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set a timeout to resolve the promise after collecting events
|
const filter = { kinds: [30023, 30402], authors: [AUTHOR_PUBKEY] };
|
||||||
setTimeout(() => {
|
const events = await ndk.fetchEvents(filter);
|
||||||
subscription?.close();
|
|
||||||
resolve(resources);
|
if (events && events.size > 0) {
|
||||||
}, 2000); // Adjust the timeout value as needed
|
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({
|
const { data: resources, isLoading: resourcesLoading, error: resourcesError, refetch: refetchResources } = useQuery({
|
||||||
queryKey: ['resources', isClient],
|
queryKey: ['resources', isClient],
|
||||||
queryFn: fetchResources,
|
queryFn: fetchResourcesFromNDK,
|
||||||
staleTime: 1000 * 60 * 10, // 10 minutes
|
staleTime: 1000 * 60 * 30, // 30 minutes
|
||||||
cacheTime: 1000 * 60 * 60, // 1 hour
|
cacheTime: 1000 * 60 * 60, // 1 hour
|
||||||
enabled: isClient,
|
enabled: isClient,
|
||||||
})
|
})
|
||||||
|
@ -1,58 +1,48 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { useNostr } from '@/hooks/useNostr';
|
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import { useNDKContext } from '@/context/NDKContext';
|
||||||
|
|
||||||
const AUTHOR_PUBKEY = process.env.NEXT_PUBLIC_AUTHOR_PUBKEY
|
const AUTHOR_PUBKEY = process.env.NEXT_PUBLIC_AUTHOR_PUBKEY
|
||||||
|
|
||||||
export function useWorkshopsQuery() {
|
export function useWorkshopsQuery() {
|
||||||
const [isClient, setIsClient] = useState(false);
|
const [isClient, setIsClient] = useState(false);
|
||||||
const { subscribe } = useNostr();
|
const ndk = useNDKContext();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsClient(true);
|
setIsClient(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const fetchWorkshops = async () => {
|
const hasRequiredTags = (tags) => {
|
||||||
console.log('fetching workshops');
|
const hasPlebDevs = tags.some(([tag, value]) => tag === "t" && value === "plebdevs");
|
||||||
const filter = [{ kinds: [30023, 30402], authors: [AUTHOR_PUBKEY] }];
|
const hasWorkshop = tags.some(([tag, value]) => tag === "t" && value === "workshop");
|
||||||
const hasRequiredTags = (tags) => {
|
return hasPlebDevs && hasWorkshop;
|
||||||
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) => {
|
const fetchWorkshopsFromNDK = async () => {
|
||||||
let resources = [];
|
try {
|
||||||
const subscription = subscribe(
|
console.log('Fetching workshops from NDK');
|
||||||
filter,
|
await ndk.connect();
|
||||||
{
|
|
||||||
onevent: (event) => {
|
const filter = { kinds: [30023, 30402], authors: [AUTHOR_PUBKEY] };
|
||||||
if (hasRequiredTags(event.tags)) {
|
const events = await ndk.fetchEvents(filter);
|
||||||
resources.push(event);
|
|
||||||
}
|
if (events && events.size > 0) {
|
||||||
},
|
const eventsArray = Array.from(events);
|
||||||
onerror: (error) => {
|
console.log('eventsArray', eventsArray)
|
||||||
console.error('Error fetching resources:', error);
|
const resources = eventsArray.filter(event => hasRequiredTags(event.tags));
|
||||||
reject(error);
|
return resources;
|
||||||
},
|
|
||||||
onclose: () => {
|
|
||||||
resolve(resources);
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
);
|
return [];
|
||||||
|
} catch (error) {
|
||||||
// Set a timeout to resolve the promise after collecting events
|
console.error('Error fetching workshops from NDK:', error);
|
||||||
setTimeout(() => {
|
return [];
|
||||||
subscription?.close();
|
}
|
||||||
resolve(resources);
|
};
|
||||||
}, 2000); // Adjust the timeout value as needed
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const { data: workshops, isLoading: workshopsLoading, error: workshopsError, refetch: refetchWorkshops } = useQuery({
|
const { data: workshops, isLoading: workshopsLoading, error: workshopsError, refetch: refetchWorkshops } = useQuery({
|
||||||
queryKey: ['workshops', isClient],
|
queryKey: ['workshops', isClient],
|
||||||
queryFn: fetchWorkshops,
|
queryFn: fetchWorkshopsFromNDK,
|
||||||
staleTime: 1000 * 60 * 10, // 10 minutes
|
staleTime: 1000 * 60 * 30, // 30 minutes
|
||||||
cacheTime: 1000 * 60 * 60, // 1 hour
|
cacheTime: 1000 * 60 * 60, // 1 hour
|
||||||
enabled: isClient,
|
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 "@uiw/react-markdown-preview/markdown.css";
|
||||||
import Sidebar from '@/components/sidebar/Sidebar';
|
import Sidebar from '@/components/sidebar/Sidebar';
|
||||||
import { NostrProvider } from '@/context/NostrContext';
|
import { NostrProvider } from '@/context/NostrContext';
|
||||||
|
import { NDKProvider } from '@/context/NDKContext';
|
||||||
import {
|
import {
|
||||||
QueryClient,
|
QueryClient,
|
||||||
QueryClientProvider,
|
QueryClientProvider,
|
||||||
@ -22,22 +23,24 @@ export default function MyApp({
|
|||||||
return (
|
return (
|
||||||
<PrimeReactProvider>
|
<PrimeReactProvider>
|
||||||
<NostrProvider>
|
<NostrProvider>
|
||||||
<QueryClientProvider client={queryClient}>
|
<NDKProvider>
|
||||||
<ToastProvider>
|
<QueryClientProvider client={queryClient}>
|
||||||
<Layout>
|
<ToastProvider>
|
||||||
<div className="flex flex-col min-h-screen">
|
<Layout>
|
||||||
<Navbar />
|
<div className="flex flex-col min-h-screen">
|
||||||
{/* <div className='flex'> */}
|
<Navbar />
|
||||||
{/* <Sidebar /> */}
|
{/* <div className='flex'> */}
|
||||||
{/* <div className='max-w-[100vw] pl-[15vw]'> */}
|
{/* <Sidebar /> */}
|
||||||
<div className='max-w-[100vw]'>
|
{/* <div className='max-w-[100vw] pl-[15vw]'> */}
|
||||||
<Component {...pageProps} />
|
<div className='max-w-[100vw]'>
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</div>
|
||||||
|
{/* </div> */}
|
||||||
</div>
|
</div>
|
||||||
{/* </div> */}
|
</Layout>
|
||||||
</div>
|
</ToastProvider>
|
||||||
</Layout>
|
</QueryClientProvider>
|
||||||
</ToastProvider>
|
</NDKProvider>
|
||||||
</QueryClientProvider>
|
|
||||||
</NostrProvider>
|
</NostrProvider>
|
||||||
</PrimeReactProvider>
|
</PrimeReactProvider>
|
||||||
);
|
);
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
import React, { useEffect, useCallback } from 'react';
|
import React from 'react';
|
||||||
import CoursesCarousel from '@/components/content/carousels/CoursesCarousel';
|
import CoursesCarousel from '@/components/content/carousels/CoursesCarousel';
|
||||||
import WorkshopsCarousel from '@/components/content/carousels/WorkshopsCarousel';
|
import WorkshopsCarousel from '@/components/content/carousels/WorkshopsCarousel';
|
||||||
import HeroBanner from '@/components/banner/HeroBanner';
|
import HeroBanner from '@/components/banner/HeroBanner';
|
||||||
import ResourcesCarousel from '@/components/content/carousels/ResourcesCarousel';
|
import ResourcesCarousel from '@/components/content/carousels/ResourcesCarousel';
|
||||||
import { useLocalStorageWithEffect } from '@/hooks/useLocalStorage';
|
|
||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
|
|
||||||
@ -20,8 +18,8 @@ export default function Home() {
|
|||||||
<main>
|
<main>
|
||||||
<HeroBanner />
|
<HeroBanner />
|
||||||
<CoursesCarousel />
|
<CoursesCarousel />
|
||||||
<WorkshopsCarousel />
|
{/* <WorkshopsCarousel />
|
||||||
<ResourcesCarousel />
|
<ResourcesCarousel /> */}
|
||||||
</main>
|
</main>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user