diff --git a/apps/site/app/[username]/page.tsx b/apps/site/app/[username]/page.tsx
index 58a3c3a7b..5591d5fa4 100644
--- a/apps/site/app/[username]/page.tsx
+++ b/apps/site/app/[username]/page.tsx
@@ -1,6 +1,6 @@
-import { Button, Flex, Grid, Stack, Typography } from '@/design-system'
+import { Flex, Grid, Stack, Typography } from '@/design-system'
import { getChannelsItemsWithUser } from '@/gql'
-import { getDataForUsername } from '@/lib'
+import { getDataForUsername, getItemsWithUserId } from '@/lib'
import { ChannelCard } from '@/server'
import { pluralize, sortChannels } from '@/utils'
import { ChannelDialog, NewChannelTrigger, UserSettings } from '@/client'
@@ -11,6 +11,7 @@ export default async function Profile({
params: { username: string }
}) {
const userData = await getDataForUsername({ username: params.username })
+
let channels
let items
@@ -23,6 +24,8 @@ export default async function Profile({
items = itemsResp
}
+ const { itemsWithUserId } = await getItemsWithUserId(userData.id)
+
// @ts-ignore
const sortedChannels = channels?.items ? sortChannels(channels.items) : []
@@ -35,7 +38,7 @@ export default async function Profile({
{pluralize(sortedChannels.length as number, 'channel', 'channels')},{' '}
- {pluralize(items?.items?.length as number, 'item', 'items')}
+ {pluralize(itemsWithUserId as number, 'item', 'items')}
diff --git a/apps/site/config/pgPool.ts b/apps/site/config/pgPool.ts
new file mode 100644
index 000000000..a1fc994be
--- /dev/null
+++ b/apps/site/config/pgPool.ts
@@ -0,0 +1,9 @@
+'server-only'
+
+import pg from 'pg'
+
+const { Pool } = pg
+
+export const pgPool = new Pool({
+ connectionString: process.env.DATABASE_URL,
+})
diff --git a/apps/site/lib/actions/getItemsWithUserId.ts b/apps/site/lib/actions/getItemsWithUserId.ts
new file mode 100644
index 000000000..04b173fd0
--- /dev/null
+++ b/apps/site/lib/actions/getItemsWithUserId.ts
@@ -0,0 +1,16 @@
+'use server'
+
+import { pgPool } from '@/config/pgPool'
+
+export async function getItemsWithUserId(createdById: number) {
+ try {
+ await pgPool.connect()
+ const query =
+ 'SELECT COUNT(*) FROM "public"."Item" WHERE "createdById" = $1;'
+ const res = await pgPool.query(query, [createdById])
+ return { itemsWithUserId: res.rows[0].count }
+ } catch (err) {
+ console.error(err)
+ return { itemsWithUserId: 0 } // Ensure a return on error
+ }
+}
diff --git a/apps/site/lib/actions/index.ts b/apps/site/lib/actions/index.ts
index 3284a9efb..a474919aa 100644
--- a/apps/site/lib/actions/index.ts
+++ b/apps/site/lib/actions/index.ts
@@ -1 +1,2 @@
+export * from './getItemsWithUserId'
export * from './revalidationHelper'
diff --git a/apps/site/package.json b/apps/site/package.json
index 721608580..0852b1d1b 100644
--- a/apps/site/package.json
+++ b/apps/site/package.json
@@ -45,6 +45,7 @@
"nextjs-toploader": "^1.6.11",
"p-queue": "^8.0.1",
"p-retry": "^6.2.0",
+ "pg": "^8.11.5",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-dropzone": "^14.2.3",
@@ -71,6 +72,7 @@
"@graphql-codegen/typescript-graphql-request": "^5.0.0",
"@graphql-codegen/typescript-operations": "^4.0.1",
"@types/node": "^20.5.6",
+ "@types/pg": "^8.11.6",
"@types/react": "18.2.21",
"@types/react-dom": "18.2.7",
"autoprefixer": "10.4.15",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2762ea711..711734e7c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -178,6 +178,9 @@ importers:
p-retry:
specifier: ^6.2.0
version: 6.2.0
+ pg:
+ specifier: ^8.11.5
+ version: 8.11.5
react:
specifier: 18.2.0
version: 18.2.0
@@ -251,6 +254,9 @@ importers:
'@types/node':
specifier: ^20.5.6
version: 20.5.6
+ '@types/pg':
+ specifier: ^8.11.6
+ version: 8.11.6
'@types/react':
specifier: 18.2.21
version: 18.2.21
@@ -5085,7 +5091,6 @@ packages:
resolution: {integrity: sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==}
dependencies:
undici-types: 5.26.5
- dev: false
/@types/node@20.5.6:
resolution: {integrity: sha512-Gi5wRGPbbyOTX+4Y2iULQ27oUPrefaB0PxGQJnfyWN3kvEDGM3mIB5M/gQLmitZf7A9FmLeaqxD3L1CXpm3VKQ==}
@@ -5105,6 +5110,14 @@ packages:
'@types/node': 20.11.19
dev: false
+ /@types/pg@8.11.6:
+ resolution: {integrity: sha512-/2WmmBXHLsfRqzfHW7BNZ8SbYzE8OSk7i3WjFYvfgRHj7S1xj+16Je5fUKv3lVdVzk/zn9TXOqf+avFCFIE0yQ==}
+ dependencies:
+ '@types/node': 20.11.19
+ pg-protocol: 1.6.1
+ pg-types: 4.0.2
+ dev: true
+
/@types/prop-types@15.7.10:
resolution: {integrity: sha512-mxSnDQxPqsZxmeShFH+uwQ4kO4gcJcGahjjMFeLbKE95IAZiiZyiEepGZjtXJ7hN/yfu0bu9xN2ajcU0JcxX6A==}
@@ -11299,6 +11312,10 @@ packages:
http-https: 1.0.0
dev: false
+ /obuf@1.1.2:
+ resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==}
+ dev: true
+
/ofetch@1.3.3:
resolution: {integrity: sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg==}
dependencies:
@@ -11678,10 +11695,18 @@ packages:
resolution: {integrity: sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==}
dev: false
+ /pg-connection-string@2.6.4:
+ resolution: {integrity: sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==}
+ dev: false
+
/pg-int8@1.0.1:
resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
engines: {node: '>=4.0.0'}
- dev: false
+
+ /pg-numeric@1.0.2:
+ resolution: {integrity: sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==}
+ engines: {node: '>=4'}
+ dev: true
/pg-pool@3.6.1(pg@8.11.3):
resolution: {integrity: sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==}
@@ -11691,10 +11716,21 @@ packages:
pg: 8.11.3
dev: false
+ /pg-pool@3.6.2(pg@8.11.5):
+ resolution: {integrity: sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==}
+ peerDependencies:
+ pg: '>=8.0'
+ dependencies:
+ pg: 8.11.5
+ dev: false
+
/pg-protocol@1.6.0:
resolution: {integrity: sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==}
dev: false
+ /pg-protocol@1.6.1:
+ resolution: {integrity: sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==}
+
/pg-types@2.2.0:
resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
engines: {node: '>=4'}
@@ -11706,6 +11742,19 @@ packages:
postgres-interval: 1.2.0
dev: false
+ /pg-types@4.0.2:
+ resolution: {integrity: sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==}
+ engines: {node: '>=10'}
+ dependencies:
+ pg-int8: 1.0.1
+ pg-numeric: 1.0.2
+ postgres-array: 3.0.2
+ postgres-bytea: 3.0.0
+ postgres-date: 2.1.0
+ postgres-interval: 3.0.0
+ postgres-range: 1.1.4
+ dev: true
+
/pg@8.11.3:
resolution: {integrity: sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==}
engines: {node: '>= 8.0.0'}
@@ -11726,6 +11775,24 @@ packages:
pg-cloudflare: 1.1.1
dev: false
+ /pg@8.11.5:
+ resolution: {integrity: sha512-jqgNHSKL5cbDjFlHyYsCXmQDrfIX/3RsNwYqpd4N0Kt8niLuNoRNH+aazv6cOd43gPh9Y4DjQCtb+X0MH0Hvnw==}
+ engines: {node: '>= 8.0.0'}
+ peerDependencies:
+ pg-native: '>=3.0.1'
+ peerDependenciesMeta:
+ pg-native:
+ optional: true
+ dependencies:
+ pg-connection-string: 2.6.4
+ pg-pool: 3.6.2(pg@8.11.5)
+ pg-protocol: 1.6.1
+ pg-types: 2.2.0
+ pgpass: 1.0.5
+ optionalDependencies:
+ pg-cloudflare: 1.1.1
+ dev: false
+
/pgpass@1.0.5:
resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==}
dependencies:
@@ -11945,16 +12012,33 @@ packages:
engines: {node: '>=4'}
dev: false
+ /postgres-array@3.0.2:
+ resolution: {integrity: sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==}
+ engines: {node: '>=12'}
+ dev: true
+
/postgres-bytea@1.0.0:
resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==}
engines: {node: '>=0.10.0'}
dev: false
+ /postgres-bytea@3.0.0:
+ resolution: {integrity: sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==}
+ engines: {node: '>= 6'}
+ dependencies:
+ obuf: 1.1.2
+ dev: true
+
/postgres-date@1.0.7:
resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
engines: {node: '>=0.10.0'}
dev: false
+ /postgres-date@2.1.0:
+ resolution: {integrity: sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==}
+ engines: {node: '>=12'}
+ dev: true
+
/postgres-interval@1.2.0:
resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
engines: {node: '>=0.10.0'}
@@ -11962,6 +12046,15 @@ packages:
xtend: 4.0.2
dev: false
+ /postgres-interval@3.0.0:
+ resolution: {integrity: sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /postgres-range@1.1.4:
+ resolution: {integrity: sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==}
+ dev: true
+
/preact@10.19.2:
resolution: {integrity: sha512-UA9DX/OJwv6YwP9Vn7Ti/vF80XL+YA5H2l7BpCtUr3ya8LWHFzpiO5R+N7dN16ujpIxhekRFuOOF82bXX7K/lg==}
dev: false