Archived
mongo -> supabase
This commit is contained in:
Generated
+405
-3
@@ -9,6 +9,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@supabase/supabase-js": "^2.49.4",
|
||||||
"@vercel/analytics": "^1.5.0",
|
"@vercel/analytics": "^1.5.0",
|
||||||
"@vercel/speed-insights": "^1.2.0",
|
"@vercel/speed-insights": "^1.2.0",
|
||||||
"autoprefixer": "^10.4.17",
|
"autoprefixer": "^10.4.17",
|
||||||
@@ -21,6 +22,7 @@
|
|||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"remark": "^15.0.1",
|
"remark": "^15.0.1",
|
||||||
"remark-html": "^16.0.1",
|
"remark-html": "^16.0.1",
|
||||||
|
"supabase": "^2.22.12",
|
||||||
"tailwindcss": "^3.4.1"
|
"tailwindcss": "^3.4.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -584,6 +586,18 @@
|
|||||||
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
|
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@isaacs/fs-minipass": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"minipass": "^7.0.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@jridgewell/gen-mapping": {
|
"node_modules/@jridgewell/gen-mapping": {
|
||||||
"version": "0.3.8",
|
"version": "0.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
|
||||||
@@ -867,6 +881,102 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@supabase/auth-js": {
|
||||||
|
"version": "2.69.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.69.1.tgz",
|
||||||
|
"integrity": "sha512-FILtt5WjCNzmReeRLq5wRs3iShwmnWgBvxHfqapC/VoljJl+W8hDAyFmf1NVw3zH+ZjZ05AKxiKxVeb0HNWRMQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@supabase/node-fetch": "^2.6.14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@supabase/functions-js": {
|
||||||
|
"version": "2.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.4.4.tgz",
|
||||||
|
"integrity": "sha512-WL2p6r4AXNGwop7iwvul2BvOtuJ1YQy8EbOd0dhG1oN1q8el/BIRSFCFnWAMM/vJJlHWLi4ad22sKbKr9mvjoA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@supabase/node-fetch": "^2.6.14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@supabase/node-fetch": {
|
||||||
|
"version": "2.6.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz",
|
||||||
|
"integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"whatwg-url": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "4.x || >=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@supabase/node-fetch/node_modules/tr46": {
|
||||||
|
"version": "0.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||||
|
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@supabase/node-fetch/node_modules/webidl-conversions": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
|
||||||
|
"license": "BSD-2-Clause"
|
||||||
|
},
|
||||||
|
"node_modules/@supabase/node-fetch/node_modules/whatwg-url": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tr46": "~0.0.3",
|
||||||
|
"webidl-conversions": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@supabase/postgrest-js": {
|
||||||
|
"version": "1.19.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.19.4.tgz",
|
||||||
|
"integrity": "sha512-O4soKqKtZIW3olqmbXXbKugUtByD2jPa8kL2m2c1oozAO11uCcGrRhkZL0kVxjBLrXHE0mdSkFsMj7jDSfyNpw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@supabase/node-fetch": "^2.6.14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@supabase/realtime-js": {
|
||||||
|
"version": "2.11.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.11.2.tgz",
|
||||||
|
"integrity": "sha512-u/XeuL2Y0QEhXSoIPZZwR6wMXgB+RQbJzG9VErA3VghVt7uRfSVsjeqd7m5GhX3JR6dM/WRmLbVR8URpDWG4+w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@supabase/node-fetch": "^2.6.14",
|
||||||
|
"@types/phoenix": "^1.5.4",
|
||||||
|
"@types/ws": "^8.5.10",
|
||||||
|
"ws": "^8.18.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@supabase/storage-js": {
|
||||||
|
"version": "2.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.7.1.tgz",
|
||||||
|
"integrity": "sha512-asYHcyDR1fKqrMpytAS1zjyEfvxuOIp1CIXX7ji4lHHcJKqyk+sLl/Vxgm4sN6u8zvuUtae9e4kDxQP2qrwWBA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@supabase/node-fetch": "^2.6.14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@supabase/supabase-js": {
|
||||||
|
"version": "2.49.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.49.4.tgz",
|
||||||
|
"integrity": "sha512-jUF0uRUmS8BKt37t01qaZ88H9yV1mbGYnqLeuFWLcdV+x1P4fl0yP9DGtaEhFPZcwSom7u16GkLEH9QJZOqOkw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@supabase/auth-js": "2.69.1",
|
||||||
|
"@supabase/functions-js": "2.4.4",
|
||||||
|
"@supabase/node-fetch": "2.6.15",
|
||||||
|
"@supabase/postgrest-js": "1.19.4",
|
||||||
|
"@supabase/realtime-js": "2.11.2",
|
||||||
|
"@supabase/storage-js": "2.7.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@swc/counter": {
|
"node_modules/@swc/counter": {
|
||||||
"version": "0.1.3",
|
"version": "0.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
|
||||||
@@ -967,12 +1077,17 @@
|
|||||||
"version": "20.17.24",
|
"version": "20.17.24",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.24.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.24.tgz",
|
||||||
"integrity": "sha512-d7fGCyB96w9BnWQrOsJtpyiSaBcAYYr75bnK6ZRjDbql2cGLj/3GsL5OYmLPNq76l7Gf2q4Rv9J2o6h5CrD9sA==",
|
"integrity": "sha512-d7fGCyB96w9BnWQrOsJtpyiSaBcAYYr75bnK6ZRjDbql2cGLj/3GsL5OYmLPNq76l7Gf2q4Rv9J2o6h5CrD9sA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~6.19.2"
|
"undici-types": "~6.19.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/phoenix": {
|
||||||
|
"version": "1.6.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.6.tgz",
|
||||||
|
"integrity": "sha512-PIzZZlEppgrpoT2QgbnDU+MMzuR6BbCjllj0bM70lWoejMeNJAxCchxnv7J3XFkI8MpygtRpzXrIlmWUBclP5A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/prop-types": {
|
"node_modules/@types/prop-types": {
|
||||||
"version": "15.7.14",
|
"version": "15.7.14",
|
||||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz",
|
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz",
|
||||||
@@ -1022,6 +1137,15 @@
|
|||||||
"@types/webidl-conversions": "*"
|
"@types/webidl-conversions": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/ws": {
|
||||||
|
"version": "8.18.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
|
||||||
|
"integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.26.1",
|
"version": "8.26.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.1.tgz",
|
||||||
@@ -1500,6 +1624,15 @@
|
|||||||
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/agent-base": {
|
||||||
|
"version": "7.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
|
||||||
|
"integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ajv": {
|
"node_modules/ajv": {
|
||||||
"version": "6.12.6",
|
"version": "6.12.6",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||||
@@ -1847,6 +1980,22 @@
|
|||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/bin-links": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bin-links/-/bin-links-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-sdleLVfCjBtgO5cNjA2HVRvWBJAHs4zwenaCPMNJAJU0yNxpzj80IpjOIimkpkr+mhlA+how5poQtt53PygbHA==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"cmd-shim": "^7.0.0",
|
||||||
|
"npm-normalize-package-bin": "^4.0.0",
|
||||||
|
"proc-log": "^5.0.0",
|
||||||
|
"read-cmd-shim": "^5.0.0",
|
||||||
|
"write-file-atomic": "^6.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || >=20.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/binary-extensions": {
|
"node_modules/binary-extensions": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
||||||
@@ -2116,12 +2265,30 @@
|
|||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/chownr": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
|
||||||
|
"license": "BlueOak-1.0.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/client-only": {
|
"node_modules/client-only": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
||||||
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
|
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/cmd-shim": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-rtpaCbr164TPPh+zFdkWpCyZuKkjpAzODfaZCf/SVJZzJN+4bHQb/LP3Jzq5/+84um3XXY8r548XiWKSborwVw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || >=20.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/color": {
|
"node_modules/color": {
|
||||||
"version": "4.2.3",
|
"version": "4.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
|
||||||
@@ -2231,6 +2398,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.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
|
||||||
@@ -3191,6 +3367,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",
|
||||||
@@ -3287,6 +3486,18 @@
|
|||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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/fraction.js": {
|
"node_modules/fraction.js": {
|
||||||
"version": "4.3.7",
|
"version": "4.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
|
||||||
@@ -3733,6 +3944,19 @@
|
|||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/https-proxy-agent": {
|
||||||
|
"version": "7.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
|
||||||
|
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"agent-base": "^7.1.2",
|
||||||
|
"debug": "4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ignore": {
|
"node_modules/ignore": {
|
||||||
"version": "5.3.2",
|
"version": "5.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||||
@@ -3764,7 +3988,6 @@
|
|||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
||||||
"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
|
"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.19"
|
"node": ">=0.8.19"
|
||||||
@@ -5115,6 +5338,33 @@
|
|||||||
"node": ">=16 || 14 >=14.17"
|
"node": ">=16 || 14 >=14.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/minizlib": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"minipass": "^7.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mkdirp": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"mkdirp": "dist/cjs/src/bin.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mongodb": {
|
"node_modules/mongodb": {
|
||||||
"version": "6.15.0",
|
"version": "6.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.15.0.tgz",
|
||||||
@@ -5294,6 +5544,44 @@
|
|||||||
"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==",
|
||||||
|
"deprecated": "Use your platform's native DOMException instead",
|
||||||
|
"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-releases": {
|
"node_modules/node-releases": {
|
||||||
"version": "2.0.19",
|
"version": "2.0.19",
|
||||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
|
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
|
||||||
@@ -5318,6 +5606,15 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/npm-normalize-package-bin": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || >=20.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/object-assign": {
|
"node_modules/object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
@@ -5790,6 +6087,15 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/proc-log": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || >=20.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/prop-types": {
|
"node_modules/prop-types": {
|
||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
@@ -5882,6 +6188,15 @@
|
|||||||
"pify": "^2.3.0"
|
"pify": "^2.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/read-cmd-shim": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-SEbJV7tohp3DAAILbEMPXavBjAnMN0tVnh4+9G8ihV4Pq3HYF9h8QNez9zkJ1ILkv9G2BjdzwctznGZXgu/HGw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || >=20.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/readdirp": {
|
"node_modules/readdirp": {
|
||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
@@ -6778,6 +7093,25 @@
|
|||||||
"node": ">=16 || 14 >=14.17"
|
"node": ">=16 || 14 >=14.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/supabase": {
|
||||||
|
"version": "2.22.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/supabase/-/supabase-2.22.12.tgz",
|
||||||
|
"integrity": "sha512-PWQT+uzwAXcamM/FK60CaWRjVwsX2SGW5vF7edbiTQC6vsNvTBnSIvd1yiXsIpq32uzQFu+iOrayxaTQytNiTw==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"bin-links": "^5.0.0",
|
||||||
|
"https-proxy-agent": "^7.0.2",
|
||||||
|
"node-fetch": "^3.3.2",
|
||||||
|
"tar": "7.4.3"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"supabase": "bin/supabase"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"npm": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/supports-color": {
|
"node_modules/supports-color": {
|
||||||
"version": "7.2.0",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||||
@@ -6840,6 +7174,23 @@
|
|||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tar": {
|
||||||
|
"version": "7.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz",
|
||||||
|
"integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@isaacs/fs-minipass": "^4.0.0",
|
||||||
|
"chownr": "^3.0.0",
|
||||||
|
"minipass": "^7.1.2",
|
||||||
|
"minizlib": "^3.0.1",
|
||||||
|
"mkdirp": "^3.0.1",
|
||||||
|
"yallist": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/text-table": {
|
"node_modules/text-table": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||||
@@ -7136,7 +7487,6 @@
|
|||||||
"version": "6.19.8",
|
"version": "6.19.8",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
||||||
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/unified": {
|
"node_modules/unified": {
|
||||||
@@ -7300,6 +7650,15 @@
|
|||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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/webidl-conversions": {
|
"node_modules/webidl-conversions": {
|
||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
||||||
@@ -7537,6 +7896,49 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/write-file-atomic": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-GmqrO8WJ1NuzJ2DrziEI2o57jKAVIQNf8a18W3nCYU3H7PNWqCCVTeH6/NQE93CIllIgQS98rrmVkYgTX9fFJQ==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"imurmurhash": "^0.1.4",
|
||||||
|
"signal-exit": "^4.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || >=20.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ws": {
|
||||||
|
"version": "8.18.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz",
|
||||||
|
"integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"utf-8-validate": ">=5.0.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"bufferutil": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"utf-8-validate": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yallist": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
|
||||||
|
"license": "BlueOak-1.0.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/yaml": {
|
"node_modules/yaml": {
|
||||||
"version": "2.7.0",
|
"version": "2.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz",
|
||||||
|
|||||||
+2
-1
@@ -19,18 +19,19 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@supabase/supabase-js": "^2.49.4",
|
||||||
"@vercel/analytics": "^1.5.0",
|
"@vercel/analytics": "^1.5.0",
|
||||||
"@vercel/speed-insights": "^1.2.0",
|
"@vercel/speed-insights": "^1.2.0",
|
||||||
"autoprefixer": "^10.4.17",
|
"autoprefixer": "^10.4.17",
|
||||||
"date-fns": "^3.3.1",
|
"date-fns": "^3.3.1",
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
"mongodb": "^6.15.0",
|
|
||||||
"next": "^15.2.4",
|
"next": "^15.2.4",
|
||||||
"postcss": "^8.4.33",
|
"postcss": "^8.4.33",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"remark": "^15.0.1",
|
"remark": "^15.0.1",
|
||||||
"remark-html": "^16.0.1",
|
"remark-html": "^16.0.1",
|
||||||
|
"supabase": "^2.22.12",
|
||||||
"tailwindcss": "^3.4.1"
|
"tailwindcss": "^3.4.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { supabase } from '@/utils/supabase';
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
|
|
||||||
interface CommentFormProps {
|
interface CommentFormProps {
|
||||||
@@ -5,9 +6,10 @@ interface CommentFormProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Comment {
|
interface Comment {
|
||||||
|
id: number; // Supabase tables typically have an ID
|
||||||
name: string;
|
name: string;
|
||||||
comment: string;
|
comment: string;
|
||||||
createdAt: string;
|
created_at: string; // Use the Supabase column name
|
||||||
}
|
}
|
||||||
|
|
||||||
const CommentSection: React.FC<CommentFormProps> = ({ postId }) => {
|
const CommentSection: React.FC<CommentFormProps> = ({ postId }) => {
|
||||||
@@ -18,24 +20,48 @@ const CommentSection: React.FC<CommentFormProps> = ({ postId }) => {
|
|||||||
const [isSubmitted, setIsSubmitted] = useState(false);
|
const [isSubmitted, setIsSubmitted] = useState(false);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [comments, setComments] = useState<Comment[]>([]);
|
const [comments, setComments] = useState<Comment[]>([]);
|
||||||
|
const [isLoadingComments, setIsLoadingComments] = useState(true); // Add loading state
|
||||||
|
|
||||||
|
// Fetch comments when the component mounts or postId changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchComments = async () => {
|
const fetchComments = async () => {
|
||||||
try {
|
setIsLoadingComments(true); // Set loading to true
|
||||||
const response = await fetch(`/api/comments?postId=${postId}`);
|
const { data, error } = await supabase
|
||||||
if (response.ok) {
|
.from('comments') // Replace 'comments' with your Supabase table name
|
||||||
const data = await response.json();
|
.select('id, name, comment, created_at') // Select specific columns
|
||||||
setComments(data);
|
.eq('post_id', postId) // Filter by post_id
|
||||||
} else {
|
.order('created_at', { ascending: false }); // Order by creation date
|
||||||
console.error('Failed to fetch comments');
|
|
||||||
}
|
if (error) {
|
||||||
} catch (err) {
|
console.error('Error fetching comments:', error);
|
||||||
console.error('Error fetching comments:', err);
|
setError('Failed to load comments.'); // Display error to user
|
||||||
|
setComments([]); // Clear comments on error
|
||||||
|
} else {
|
||||||
|
setComments(data || []); // Set comments (handle case where data is null)
|
||||||
|
setError(null); // Clear any previous errors
|
||||||
}
|
}
|
||||||
|
setIsLoadingComments(false); // Set loading to false
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchComments();
|
fetchComments();
|
||||||
}, [postId]);
|
|
||||||
|
// Optional: Set up real-time subscriptions for new comments
|
||||||
|
// Be mindful of performance and resource usage with real-time subscriptions
|
||||||
|
// This is a basic example; you might need more sophisticated handling
|
||||||
|
const subscription = supabase
|
||||||
|
.channel(`comments:post_id=eq.${postId}`)
|
||||||
|
.on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'comments', filter: `post_id=eq.${postId}` }, (payload) => {
|
||||||
|
// Add the new comment to the beginning of the list
|
||||||
|
setComments((currentComments) => [payload.new as Comment, ...currentComments]);
|
||||||
|
})
|
||||||
|
.subscribe();
|
||||||
|
|
||||||
|
// Cleanup the subscription when the component unmounts or postId changes
|
||||||
|
return () => {
|
||||||
|
supabase.removeChannel(subscription);
|
||||||
|
};
|
||||||
|
|
||||||
|
}, [postId]); // Dependency array includes postId
|
||||||
|
|
||||||
const handleSubmit = async (e: React.FormEvent) => {
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -49,33 +75,42 @@ const CommentSection: React.FC<CommentFormProps> = ({ postId }) => {
|
|||||||
setError(null);
|
setError(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/comments', {
|
const { data, error } = await supabase
|
||||||
method: 'POST',
|
.from('comments') // Replace 'comments' with your Supabase table name
|
||||||
headers: { 'Content-Type': 'application/json' },
|
.insert([
|
||||||
body: JSON.stringify({ name, email, comment, postId }),
|
{
|
||||||
});
|
name,
|
||||||
|
email, // Storing email is dependent on your privacy policy and RLS
|
||||||
|
comment,
|
||||||
|
post_id: postId, // Assuming your Supabase column is named 'post_id'
|
||||||
|
// created_at will likely be automatically set by Supabase with a default value
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.select('id, name, comment, created_at'); // Select the inserted data
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error('Error inserting comment:', error);
|
||||||
|
setError(error.message || 'Something went wrong. Please try again later.');
|
||||||
|
} else {
|
||||||
|
// Assuming real-time subscription is active,
|
||||||
|
// the new comment will be added to the comments state automatically.
|
||||||
|
// If not using real-time, you would manually add the new comment here:
|
||||||
|
// if (data && data.length > 0) {
|
||||||
|
// setComments((currentComments) => [data[0], ...currentComments]);
|
||||||
|
// }
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
setName('');
|
setName('');
|
||||||
setEmail('');
|
setEmail('');
|
||||||
setComment('');
|
setComment('');
|
||||||
setIsSubmitted(true);
|
setIsSubmitted(true);
|
||||||
setIsSubmitting(false);
|
// No need to re-fetch all comments if using real-time subscriptions
|
||||||
|
|
||||||
// Fetch updated comments
|
|
||||||
const updatedComments = await fetch(`/api/comments?postId=${postId}`).then((res) =>
|
|
||||||
res.json()
|
|
||||||
);
|
|
||||||
setComments(updatedComments);
|
|
||||||
|
|
||||||
setTimeout(() => setIsSubmitted(false), 5000);
|
setTimeout(() => setIsSubmitted(false), 5000);
|
||||||
} else {
|
|
||||||
const data = await response.json();
|
|
||||||
setError(data.message || 'Something went wrong. Please try again later.');
|
|
||||||
setIsSubmitting(false);
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
console.error('Unexpected error during submission:', err);
|
||||||
setError('Something went wrong. Please try again later.');
|
setError('Something went wrong. Please try again later.');
|
||||||
|
} finally {
|
||||||
setIsSubmitting(false);
|
setIsSubmitting(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -152,30 +187,31 @@ const CommentSection: React.FC<CommentFormProps> = ({ postId }) => {
|
|||||||
></textarea>
|
></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* <div className="flex items-center">
|
{/* The save info checkbox logic can remain as it interacts with localStorage */}
|
||||||
<input
|
{/* <div className="flex items-center">
|
||||||
type="checkbox"
|
<input
|
||||||
id="save-info"
|
type="checkbox"
|
||||||
className="h-4 w-4 text-accent border-primary-300 rounded focus:ring-accent"
|
id="save-info"
|
||||||
checked={typeof window !== 'undefined' && localStorage.getItem('saveInfo') === 'true'}
|
className="h-4 w-4 text-accent border-primary-300 rounded focus:ring-accent"
|
||||||
onChange={(e) => {
|
checked={typeof window !== 'undefined' && localStorage.getItem('saveInfo') === 'true'}
|
||||||
if (typeof window !== 'undefined') {
|
onChange={(e) => {
|
||||||
const saveInfo = e.target.checked;
|
if (typeof window !== 'undefined') {
|
||||||
localStorage.setItem('saveInfo', saveInfo.toString());
|
const saveInfo = e.target.checked;
|
||||||
if (saveInfo) {
|
localStorage.setItem('saveInfo', saveInfo.toString());
|
||||||
localStorage.setItem('name', name);
|
if (saveInfo) {
|
||||||
localStorage.setItem('email', email);
|
localStorage.setItem('name', name);
|
||||||
} else {
|
localStorage.setItem('email', email);
|
||||||
localStorage.removeItem('name');
|
} else {
|
||||||
localStorage.removeItem('email');
|
localStorage.removeItem('name');
|
||||||
}
|
localStorage.removeItem('email');
|
||||||
}
|
}
|
||||||
}}
|
}
|
||||||
/>
|
}}
|
||||||
<label htmlFor="save-info" className="ml-2 block text-sm text-primary-600">
|
/>
|
||||||
Save my name and email for the next time I comment
|
<label htmlFor="save-info" className="ml-2 block text-sm text-primary-600">
|
||||||
</label>
|
Save my name and email for the next time I comment
|
||||||
</div> */}
|
</label>
|
||||||
|
</div> */}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
@@ -189,24 +225,37 @@ const CommentSection: React.FC<CommentFormProps> = ({ postId }) => {
|
|||||||
<div className="mt-12">
|
<div className="mt-12">
|
||||||
<h3 className="text-xl font-bold mb-6">Comments ({comments.length})</h3>
|
<h3 className="text-xl font-bold mb-6">Comments ({comments.length})</h3>
|
||||||
|
|
||||||
<div className="space-y-6">
|
{isLoadingComments ? (
|
||||||
{comments.map((comment) => (
|
<p>Loading comments...</p>
|
||||||
<div
|
) : comments.length === 0 ? (
|
||||||
key={comment.createdAt}
|
<p>No comments yet. Be the first to leave one!</p>
|
||||||
className="bg-white p-6 rounded-md shadow-sm border border-primary-200"
|
) : (
|
||||||
>
|
<div className="space-y-6">
|
||||||
<div className="flex justify-between items-start mb-4">
|
{comments.map((comment) => (
|
||||||
<div>
|
<div
|
||||||
<h4 className="font-bold">{comment.name}</h4>
|
// Use a more stable key than createdAt if possible, like comment.id from Supabase
|
||||||
<p className="text-sm text-primary-500">
|
key={comment.id || comment.created_at}
|
||||||
{new Date(comment.createdAt).toLocaleDateString()}
|
className="bg-white p-6 rounded-md shadow-sm border border-primary-200"
|
||||||
</p>
|
>
|
||||||
|
<div className="flex justify-between items-start mb-4">
|
||||||
|
<div>
|
||||||
|
<h4 className="font-bold">{comment.name}</h4>
|
||||||
|
<p className="text-sm text-primary-500">
|
||||||
|
{new Date(comment.created_at).toLocaleDateString('en-US', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
day: 'numeric',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit',
|
||||||
|
})}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<p className="text-primary-700">{comment.comment}</p>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-primary-700">{comment.comment}</p>
|
))}
|
||||||
</div>
|
</div>
|
||||||
))}
|
)}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
+2
-1
@@ -3,4 +3,5 @@ import type { AppProps } from 'next/app';
|
|||||||
|
|
||||||
export default function App({ Component, pageProps }: AppProps) {
|
export default function App({ Component, pageProps }: AppProps) {
|
||||||
return <Component {...pageProps} />;
|
return <Component {...pageProps} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+51
-38
@@ -1,55 +1,68 @@
|
|||||||
import { NextApiRequest, NextApiResponse } from 'next';
|
import { supabase } from '@/utils/supabase';
|
||||||
import { MongoClient } from 'mongodb';
|
import { NextRequest, NextResponse } from 'next/server'; // Use next/server for Edge runtime
|
||||||
|
|
||||||
export const runtime = 'edge';
|
export const runtime = 'edge';
|
||||||
const uri = process.env.MONGODB_URI || 'your-mongodb-uri';
|
|
||||||
const dbName = 'confessions-of-grace';
|
|
||||||
|
|
||||||
const client = new MongoClient(uri);
|
export default async function POST(req: NextRequest) {
|
||||||
|
try {
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
const { name, email, comment, postId } = await req.json();
|
||||||
if (req.method === 'POST') {
|
|
||||||
const { name, email, comment, postId } = req.body;
|
|
||||||
|
|
||||||
if (!name || !email || !comment || !postId) {
|
if (!name || !email || !comment || !postId) {
|
||||||
return res.status(400).json({ message: 'All fields are required' });
|
return NextResponse.json({ message: 'All fields are required' }, { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
// Insert data into the 'comments' table
|
||||||
if (!client.db(dbName)) await client.connect();
|
const { data, error } = await supabase
|
||||||
const db = client.db(dbName);
|
.from('comments') // Replace 'comments' with your Supabase table name
|
||||||
const collection = db.collection('comments');
|
.insert([
|
||||||
|
{
|
||||||
|
name,
|
||||||
|
email,
|
||||||
|
comment,
|
||||||
|
post_id: postId,
|
||||||
|
created_at: new Date().toISOString(), // Supabase often uses ISO strings for timestamps
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
await collection.insertOne({ name, email, comment, postId, createdAt: new Date() });
|
if (error) {
|
||||||
|
console.error('Error inserting comment:', error);
|
||||||
res.status(201).json({ message: 'Comment submitted successfully' });
|
return NextResponse.json({ message: 'Error submitting comment', error }, { status: 500 });
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ message: 'Internal server error' });
|
|
||||||
}
|
}
|
||||||
} else if (req.method === 'GET') {
|
|
||||||
const { postId } = req.query;
|
return NextResponse.json({ message: 'Comment submitted successfully', data }, { status: 201 });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Internal server error during POST:', error);
|
||||||
|
// Catching and returning a 500 for unexpected errors
|
||||||
|
return NextResponse.json({ message: 'Internal server error' }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET(req: NextRequest) {
|
||||||
|
try {
|
||||||
|
// Get query parameters from the URL
|
||||||
|
const { searchParams } = new URL(req.url);
|
||||||
|
const postId = searchParams.get('postId');
|
||||||
|
|
||||||
if (!postId) {
|
if (!postId) {
|
||||||
return res.status(400).json({ message: 'Post ID is required' });
|
return NextResponse.json({ message: 'Post ID is required' }, { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
// Fetch comments for a specific postId, ordered by creation date descending
|
||||||
if (!client.db(dbName)) await client.connect();
|
const { data: comments, error } = await supabase
|
||||||
const db = client.db(dbName);
|
.from('comments') // Replace 'comments' with your Supabase table name
|
||||||
const collection = db.collection('comments');
|
.select('*')
|
||||||
|
.eq('post_id', postId) // Assuming your Supabase column for post ID is 'post_id'
|
||||||
|
.order('created_at', { ascending: false }); // Assuming your timestamp column is 'created_at'
|
||||||
|
|
||||||
const comments = await collection
|
if (error) {
|
||||||
.find({ postId })
|
console.error('Error fetching comments:', error);
|
||||||
.sort({ createdAt: -1 })
|
return NextResponse.json({ message: 'Error fetching comments', error }, { status: 500 });
|
||||||
.toArray();
|
|
||||||
|
|
||||||
res.status(200).json(comments);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ message: 'Internal server error' });
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
res.status(405).json({ message: 'Method not allowed' });
|
return NextResponse.json(comments, { status: 200 });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Internal server error during GET:', error);
|
||||||
|
// Catching and returning a 500 for unexpected errors
|
||||||
|
return NextResponse.json({ message: 'Internal server error' }, { status: 500 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+49
-45
@@ -1,57 +1,61 @@
|
|||||||
import { MongoClient } from 'mongodb';
|
import { supabase } from '@/utils/supabase';
|
||||||
import { NextApiRequest, NextApiResponse } from 'next';
|
import { NextRequest, NextResponse } from 'next/server'; // Use next/server for Edge runtime
|
||||||
|
|
||||||
export const runtime = 'edge';
|
export const runtime = 'edge';
|
||||||
const MONGODB_URI = process.env.MONGODB_URI as string; // Add this in your .env.local file
|
|
||||||
// Create a MongoClient instance
|
|
||||||
let cachedClient: MongoClient | null = null;
|
|
||||||
|
|
||||||
async function connectToDatabase() {
|
export default async function POST(req: NextRequest) {
|
||||||
if (!cachedClient) {
|
// Only allow POST requests - this is handled by exporting the POST function
|
||||||
cachedClient = new MongoClient(MONGODB_URI);
|
|
||||||
await cachedClient.connect();
|
|
||||||
}
|
|
||||||
return cachedClient.db(MONGODB_URI);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
const { email } = await req.json(); // Get body from Edge request
|
||||||
// Only allow POST requests
|
|
||||||
if (req.method !== 'POST') {
|
// Check if email was provided
|
||||||
res.setHeader('Allow', ['POST']);
|
if (!email) {
|
||||||
return res.status(405).json({ message: `Method ${req.method} Not Allowed` });
|
return NextResponse.json({ message: 'Email is required.' }, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate email format
|
||||||
|
const emailRegex = /\S+@\S+\.\S+/;
|
||||||
|
if (!emailRegex.test(email)) {
|
||||||
|
return NextResponse.json({ message: 'Invalid email address.' }, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check if the email already exists in the 'subscriptions' table
|
||||||
|
const { data: existingEmails, error: selectError } = await supabase
|
||||||
|
.from('subscriptions') // Replace 'subscriptions' with your Supabase table name
|
||||||
|
.select('email')
|
||||||
|
.eq('email', email);
|
||||||
|
|
||||||
|
if (selectError) {
|
||||||
|
console.error('Error checking existing email:', selectError);
|
||||||
|
return NextResponse.json({ message: 'An unexpected error occurred while checking email.' }, { status: 500 });
|
||||||
}
|
}
|
||||||
|
|
||||||
const { email } = req.body;
|
if (existingEmails && existingEmails.length > 0) {
|
||||||
|
return NextResponse.json({ message: 'Email is already subscribed.' }, { status: 400 });
|
||||||
// Check if email was provided
|
|
||||||
if (!email) {
|
|
||||||
return res.status(400).json({ message: 'Email is required.' });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate email format
|
// Save email to the 'subscriptions' table
|
||||||
const emailRegex = /\S+@\S+\.\S+/;
|
const { data: insertedData, error: insertError } = await supabase
|
||||||
if (!emailRegex.test(email)) {
|
.from('subscriptions') // Replace 'subscriptions' with your Supabase table name
|
||||||
return res.status(400).json({ message: 'Invalid email address.' });
|
.insert([
|
||||||
|
{
|
||||||
|
email,
|
||||||
|
created_at: new Date().toISOString(),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (insertError) {
|
||||||
|
console.error('Failed to save subscription:', insertError);
|
||||||
|
return NextResponse.json({ message: 'An unexpected error occurred while saving subscription.' }, { status: 500 });
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
// Respond with success
|
||||||
// Connect to the database
|
return NextResponse.json({ message: 'Successfully subscribed!' }, { status: 200 });
|
||||||
const db = await connectToDatabase();
|
|
||||||
|
|
||||||
// Check if the email already exists
|
} catch (error) {
|
||||||
const existingEmail = await db.collection('subscriptions').findOne({ email });
|
// Log unexpected errors
|
||||||
if (existingEmail) {
|
console.error('An unexpected server error occurred:', error);
|
||||||
return res.status(400).json({ message: 'Email is already subscribed.' });
|
return NextResponse.json({ message: 'An unexpected error occurred.' }, { status: 500 });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save email to the database
|
|
||||||
await db.collection('subscriptions').insertOne({ email, subscribedAt: new Date() });
|
|
||||||
|
|
||||||
// Respond with success
|
|
||||||
return res.status(200).json({ message: 'Successfully subscribed!' });
|
|
||||||
} catch (error) {
|
|
||||||
// Log the error and respond with a server error status
|
|
||||||
console.error('Failed to save subscription:', error);
|
|
||||||
return res.status(500).json({ message: 'An unexpected error occurred.' });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { createClient } from "@supabase/supabase-js";
|
||||||
|
|
||||||
|
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!;
|
||||||
|
const supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!;
|
||||||
|
|
||||||
|
export const supabase = createClient(supabaseUrl, supabaseKey);
|
||||||
Reference in New Issue
Block a user