chore: supabase CLI setup, migrations, type regeneration - Install supabase CLI as dev dependency - Fix migration 023: use gen_random_uuid() instead of uuid_generate_v4() - Push migrations 023 + 024 to remote Supabase - Regenerate TypeScript types from live DB schema - Remove all (supabase as any) workaround casts across 6 files - Add convenience type aliases to generated types file - Align EventMember/EventRole/EventDepartment interfaces with DB nullability - Add npm scripts: db:push, db:types, db:migrate - svelte-check: 0 errors, vitest: 112/112 passed
This commit is contained in:
165
package-lock.json
generated
165
package-lock.json
generated
@@ -35,6 +35,7 @@
|
|||||||
"@types/twemoji": "^13.1.1",
|
"@types/twemoji": "^13.1.1",
|
||||||
"@vitest/browser-playwright": "^4.0.18",
|
"@vitest/browser-playwright": "^4.0.18",
|
||||||
"playwright": "^1.58.0",
|
"playwright": "^1.58.0",
|
||||||
|
"supabase": "^2.76.1",
|
||||||
"svelte": "^5.48.2",
|
"svelte": "^5.48.2",
|
||||||
"svelte-check": "^4.3.5",
|
"svelte-check": "^4.3.5",
|
||||||
"tailwindcss": "^4.1.18",
|
"tailwindcss": "^4.1.18",
|
||||||
@@ -558,6 +559,19 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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==",
|
||||||
|
"dev": true,
|
||||||
|
"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.13",
|
"version": "0.3.13",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
|
||||||
@@ -2513,6 +2527,23 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/bin-links": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bin-links/-/bin-links-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-X4CiKlcV2GjnCMwnKAfbVWpHa++65th9TuzAEYtZoATiOE2DQKhSp4CJlyLoTqdhBKlXjpXjCTYPNNFS33Fi6w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"cmd-shim": "^8.0.0",
|
||||||
|
"npm-normalize-package-bin": "^5.0.0",
|
||||||
|
"proc-log": "^6.0.0",
|
||||||
|
"read-cmd-shim": "^6.0.0",
|
||||||
|
"write-file-atomic": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^20.17.0 || >=22.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||||
@@ -2563,6 +2594,16 @@
|
|||||||
"url": "https://paulmillr.com/funding/"
|
"url": "https://paulmillr.com/funding/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BlueOak-1.0.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/clsx": {
|
"node_modules/clsx": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||||
@@ -2572,6 +2613,16 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cmd-shim": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-Jk/BK6NCapZ58BKUxlSI+ouKRbjH1NLZCgJkYoab+vEHUY3f6OzpNBN9u7HFSv9J6TRDGs4PLOHezoKGaFRSCA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": "^20.17.0 || >=22.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/color-convert": {
|
"node_modules/color-convert": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||||
@@ -3194,6 +3245,16 @@
|
|||||||
"node": ">=20.0.0"
|
"node": ">=20.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/imurmurhash": {
|
||||||
|
"version": "0.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
||||||
|
"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8.19"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-core-module": {
|
"node_modules/is-core-module": {
|
||||||
"version": "2.16.1",
|
"version": "2.16.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
|
||||||
@@ -3791,6 +3852,19 @@
|
|||||||
"node": ">=16 || 14 >=14.17"
|
"node": ">=16 || 14 >=14.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/minizlib": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"minipass": "^7.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mri": {
|
"node_modules/mri": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
|
||||||
@@ -3874,6 +3948,16 @@
|
|||||||
"url": "https://opencollective.com/node-fetch"
|
"url": "https://opencollective.com/node-fetch"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/npm-normalize-package-bin": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": "^20.17.0 || >=22.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/obug": {
|
"node_modules/obug": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz",
|
||||||
@@ -4082,6 +4166,16 @@
|
|||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/proc-log": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": "^20.17.0 || >=22.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/prosemirror-changeset": {
|
"node_modules/prosemirror-changeset": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.3.1.tgz",
|
||||||
@@ -4289,6 +4383,16 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/read-cmd-shim": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-1zM5HuOfagXCBWMN83fuFI/x+T/UhZ7k+KIzhrHXcQoeX5+7gmaDYjELQHmmzIodumBHeByBJT4QYS7ufAgs7A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": "^20.17.0 || >=22.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/readdirp": {
|
"node_modules/readdirp": {
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
||||||
@@ -4627,6 +4731,26 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/supabase": {
|
||||||
|
"version": "2.76.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/supabase/-/supabase-2.76.1.tgz",
|
||||||
|
"integrity": "sha512-wWN7trvmcFfI/T4Jr1t4eKSD3JUCMsisssDAoywwMP7HlF4lVrAxQyROah3uBRV05RuEFhO74mFlYr4+koGb0Q==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"bin-links": "^6.0.0",
|
||||||
|
"https-proxy-agent": "^7.0.2",
|
||||||
|
"node-fetch": "^3.3.2",
|
||||||
|
"tar": "7.5.7"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"supabase": "bin/supabase"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"npm": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/supports-preserve-symlinks-flag": {
|
"node_modules/supports-preserve-symlinks-flag": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
||||||
@@ -4722,6 +4846,23 @@
|
|||||||
"url": "https://opencollective.com/webpack"
|
"url": "https://opencollective.com/webpack"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tar": {
|
||||||
|
"version": "7.5.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz",
|
||||||
|
"integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BlueOak-1.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@isaacs/fs-minipass": "^4.0.0",
|
||||||
|
"chownr": "^3.0.0",
|
||||||
|
"minipass": "^7.1.2",
|
||||||
|
"minizlib": "^3.1.0",
|
||||||
|
"yallist": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tinybench": {
|
"node_modules/tinybench": {
|
||||||
"version": "2.9.0",
|
"version": "2.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
|
||||||
@@ -5237,6 +5378,20 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/write-file-atomic": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-YnlPC6JqnZl6aO4uRc+dx5PHguiR9S6WeoLtpxNT9wIG+BDya7ZNE1q7KOjVgaA73hKhKLpVPgJ5QA9THQ5BRg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"imurmurhash": "^0.1.4",
|
||||||
|
"signal-exit": "^4.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^20.17.0 || >=22.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ws": {
|
"node_modules/ws": {
|
||||||
"version": "8.19.0",
|
"version": "8.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
|
||||||
@@ -5258,6 +5413,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BlueOak-1.0.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/zimmerframe": {
|
"node_modules/zimmerframe": {
|
||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz",
|
||||||
|
|||||||
@@ -11,7 +11,10 @@
|
|||||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||||
"test:unit": "vitest",
|
"test:unit": "vitest",
|
||||||
"test": "npm run test:unit -- --run"
|
"test": "npm run test:unit -- --run",
|
||||||
|
"db:push": "npx supabase db push",
|
||||||
|
"db:types": "npx supabase gen types --lang=typescript --project-id zlworzrghsrokdkuckez --schema public > src/lib/supabase/types.ts",
|
||||||
|
"db:migrate": "npm run db:push && npm run db:types"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@inlang/paraglide-js": "^2.10.0",
|
"@inlang/paraglide-js": "^2.10.0",
|
||||||
@@ -26,6 +29,7 @@
|
|||||||
"@types/twemoji": "^13.1.1",
|
"@types/twemoji": "^13.1.1",
|
||||||
"@vitest/browser-playwright": "^4.0.18",
|
"@vitest/browser-playwright": "^4.0.18",
|
||||||
"playwright": "^1.58.0",
|
"playwright": "^1.58.0",
|
||||||
|
"supabase": "^2.76.1",
|
||||||
"svelte": "^5.48.2",
|
"svelte": "^5.48.2",
|
||||||
"svelte-check": "^4.3.5",
|
"svelte-check": "^4.3.5",
|
||||||
"tailwindcss": "^4.1.18",
|
"tailwindcss": "^4.1.18",
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ export interface EventMember {
|
|||||||
id: string;
|
id: string;
|
||||||
event_id: string;
|
event_id: string;
|
||||||
user_id: string;
|
user_id: string;
|
||||||
role: 'lead' | 'manager' | 'member';
|
role: string;
|
||||||
role_id: string | null;
|
role_id: string | null;
|
||||||
notes: string | null;
|
notes: string | null;
|
||||||
assigned_at: string;
|
assigned_at: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EventRole {
|
export interface EventRole {
|
||||||
@@ -39,7 +39,7 @@ export interface EventRole {
|
|||||||
color: string;
|
color: string;
|
||||||
sort_order: number;
|
sort_order: number;
|
||||||
is_default: boolean;
|
is_default: boolean;
|
||||||
created_at: string;
|
created_at: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EventDepartment {
|
export interface EventDepartment {
|
||||||
@@ -49,14 +49,14 @@ export interface EventDepartment {
|
|||||||
color: string;
|
color: string;
|
||||||
description: string | null;
|
description: string | null;
|
||||||
sort_order: number;
|
sort_order: number;
|
||||||
created_at: string;
|
created_at: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EventMemberDepartment {
|
export interface EventMemberDepartment {
|
||||||
id: string;
|
id: string;
|
||||||
event_member_id: string;
|
event_member_id: string;
|
||||||
department_id: string;
|
department_id: string;
|
||||||
assigned_at: string;
|
assigned_at: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EventMemberWithDetails extends EventMember {
|
export interface EventMemberWithDetails extends EventMember {
|
||||||
@@ -262,41 +262,41 @@ export async function fetchEventMembers(
|
|||||||
|
|
||||||
// Fetch profiles separately (same pattern as org_members)
|
// Fetch profiles separately (same pattern as org_members)
|
||||||
const userIds = members.map((m: any) => m.user_id);
|
const userIds = members.map((m: any) => m.user_id);
|
||||||
const { data: profiles } = await (supabase as any)
|
const { data: profiles } = await supabase
|
||||||
.from('profiles')
|
.from('profiles')
|
||||||
.select('id, email, full_name, avatar_url, phone, discord_handle, shirt_size, hoodie_size')
|
.select('id, email, full_name, avatar_url, phone, discord_handle, shirt_size, hoodie_size')
|
||||||
.in('id', userIds);
|
.in('id', userIds);
|
||||||
|
|
||||||
const profileMap = Object.fromEntries((profiles ?? []).map((p: any) => [p.id, p]));
|
const profileMap = Object.fromEntries((profiles ?? []).map(p => [p.id, p]));
|
||||||
|
|
||||||
// Fetch roles for this event
|
// Fetch roles for this event
|
||||||
const { data: roles } = await (supabase as any)
|
const { data: roles } = await supabase
|
||||||
.from('event_roles')
|
.from('event_roles')
|
||||||
.select('*')
|
.select('*')
|
||||||
.eq('event_id', eventId);
|
.eq('event_id', eventId);
|
||||||
const roleMap = Object.fromEntries((roles ?? []).map((r: any) => [r.id, r]));
|
const roleMap = Object.fromEntries((roles ?? []).map(r => [r.id, r]));
|
||||||
|
|
||||||
// Fetch member-department assignments
|
// Fetch member-department assignments
|
||||||
const memberIds = members.map((m: any) => m.id);
|
const memberIds = members.map((m: any) => m.id);
|
||||||
const { data: memberDepts } = await (supabase as any)
|
const { data: memberDepts } = await supabase
|
||||||
.from('event_member_departments')
|
.from('event_member_departments')
|
||||||
.select('*')
|
.select('*')
|
||||||
.in('event_member_id', memberIds);
|
.in('event_member_id', memberIds);
|
||||||
|
|
||||||
// Fetch departments for this event
|
// Fetch departments for this event
|
||||||
const { data: departments } = await (supabase as any)
|
const { data: departments } = await supabase
|
||||||
.from('event_departments')
|
.from('event_departments')
|
||||||
.select('*')
|
.select('*')
|
||||||
.eq('event_id', eventId);
|
.eq('event_id', eventId);
|
||||||
const deptMap = Object.fromEntries((departments ?? []).map((d: any) => [d.id, d]));
|
const deptMap = Object.fromEntries((departments ?? []).map(d => [d.id, d]));
|
||||||
|
|
||||||
// Build member-to-departments map
|
// Build member-to-departments map
|
||||||
const memberDeptMap: Record<string, EventDepartment[]> = {};
|
const memberDeptMap: Record<string, EventDepartment[]> = {};
|
||||||
for (const md of (memberDepts ?? [])) {
|
for (const md of (memberDepts ?? [])) {
|
||||||
const dept = deptMap[(md as any).department_id];
|
const dept = deptMap[md.department_id];
|
||||||
if (dept) {
|
if (dept) {
|
||||||
if (!memberDeptMap[(md as any).event_member_id]) memberDeptMap[(md as any).event_member_id] = [];
|
if (!memberDeptMap[md.event_member_id]) memberDeptMap[md.event_member_id] = [];
|
||||||
memberDeptMap[(md as any).event_member_id].push(dept as unknown as EventDepartment);
|
memberDeptMap[md.event_member_id].push(dept as unknown as EventDepartment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,7 +314,7 @@ export async function addEventMember(
|
|||||||
userId: string,
|
userId: string,
|
||||||
params: { role?: 'lead' | 'manager' | 'member'; role_id?: string; notes?: string } = {}
|
params: { role?: 'lead' | 'manager' | 'member'; role_id?: string; notes?: string } = {}
|
||||||
): Promise<EventMember> {
|
): Promise<EventMember> {
|
||||||
const { data, error } = await (supabase as any)
|
const { data, error } = await supabase
|
||||||
.from('event_members')
|
.from('event_members')
|
||||||
.upsert({
|
.upsert({
|
||||||
event_id: eventId,
|
event_id: eventId,
|
||||||
@@ -358,7 +358,7 @@ export async function fetchEventRoles(
|
|||||||
supabase: SupabaseClient<Database>,
|
supabase: SupabaseClient<Database>,
|
||||||
eventId: string
|
eventId: string
|
||||||
): Promise<EventRole[]> {
|
): Promise<EventRole[]> {
|
||||||
const { data, error } = await (supabase as any)
|
const { data, error } = await supabase
|
||||||
.from('event_roles')
|
.from('event_roles')
|
||||||
.select('*')
|
.select('*')
|
||||||
.eq('event_id', eventId)
|
.eq('event_id', eventId)
|
||||||
@@ -376,7 +376,7 @@ export async function createEventRole(
|
|||||||
eventId: string,
|
eventId: string,
|
||||||
params: { name: string; color?: string; sort_order?: number }
|
params: { name: string; color?: string; sort_order?: number }
|
||||||
): Promise<EventRole> {
|
): Promise<EventRole> {
|
||||||
const { data, error } = await (supabase as any)
|
const { data, error } = await supabase
|
||||||
.from('event_roles')
|
.from('event_roles')
|
||||||
.insert({
|
.insert({
|
||||||
event_id: eventId,
|
event_id: eventId,
|
||||||
@@ -399,7 +399,7 @@ export async function updateEventRole(
|
|||||||
roleId: string,
|
roleId: string,
|
||||||
params: Partial<Pick<EventRole, 'name' | 'color' | 'sort_order' | 'is_default'>>
|
params: Partial<Pick<EventRole, 'name' | 'color' | 'sort_order' | 'is_default'>>
|
||||||
): Promise<EventRole> {
|
): Promise<EventRole> {
|
||||||
const { data, error } = await (supabase as any)
|
const { data, error } = await supabase
|
||||||
.from('event_roles')
|
.from('event_roles')
|
||||||
.update(params)
|
.update(params)
|
||||||
.eq('id', roleId)
|
.eq('id', roleId)
|
||||||
@@ -417,7 +417,7 @@ export async function deleteEventRole(
|
|||||||
supabase: SupabaseClient<Database>,
|
supabase: SupabaseClient<Database>,
|
||||||
roleId: string
|
roleId: string
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const { error } = await (supabase as any)
|
const { error } = await supabase
|
||||||
.from('event_roles')
|
.from('event_roles')
|
||||||
.delete()
|
.delete()
|
||||||
.eq('id', roleId);
|
.eq('id', roleId);
|
||||||
@@ -436,7 +436,7 @@ export async function fetchEventDepartments(
|
|||||||
supabase: SupabaseClient<Database>,
|
supabase: SupabaseClient<Database>,
|
||||||
eventId: string
|
eventId: string
|
||||||
): Promise<EventDepartment[]> {
|
): Promise<EventDepartment[]> {
|
||||||
const { data, error } = await (supabase as any)
|
const { data, error } = await supabase
|
||||||
.from('event_departments')
|
.from('event_departments')
|
||||||
.select('*')
|
.select('*')
|
||||||
.eq('event_id', eventId)
|
.eq('event_id', eventId)
|
||||||
@@ -454,7 +454,7 @@ export async function createEventDepartment(
|
|||||||
eventId: string,
|
eventId: string,
|
||||||
params: { name: string; color?: string; description?: string; sort_order?: number }
|
params: { name: string; color?: string; description?: string; sort_order?: number }
|
||||||
): Promise<EventDepartment> {
|
): Promise<EventDepartment> {
|
||||||
const { data, error } = await (supabase as any)
|
const { data, error } = await supabase
|
||||||
.from('event_departments')
|
.from('event_departments')
|
||||||
.insert({
|
.insert({
|
||||||
event_id: eventId,
|
event_id: eventId,
|
||||||
@@ -478,7 +478,7 @@ export async function updateEventDepartment(
|
|||||||
deptId: string,
|
deptId: string,
|
||||||
params: Partial<Pick<EventDepartment, 'name' | 'color' | 'description' | 'sort_order'>>
|
params: Partial<Pick<EventDepartment, 'name' | 'color' | 'description' | 'sort_order'>>
|
||||||
): Promise<EventDepartment> {
|
): Promise<EventDepartment> {
|
||||||
const { data, error } = await (supabase as any)
|
const { data, error } = await supabase
|
||||||
.from('event_departments')
|
.from('event_departments')
|
||||||
.update(params)
|
.update(params)
|
||||||
.eq('id', deptId)
|
.eq('id', deptId)
|
||||||
@@ -496,7 +496,7 @@ export async function deleteEventDepartment(
|
|||||||
supabase: SupabaseClient<Database>,
|
supabase: SupabaseClient<Database>,
|
||||||
deptId: string
|
deptId: string
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const { error } = await (supabase as any)
|
const { error } = await supabase
|
||||||
.from('event_departments')
|
.from('event_departments')
|
||||||
.delete()
|
.delete()
|
||||||
.eq('id', deptId);
|
.eq('id', deptId);
|
||||||
@@ -516,7 +516,7 @@ export async function assignMemberDepartment(
|
|||||||
eventMemberId: string,
|
eventMemberId: string,
|
||||||
departmentId: string
|
departmentId: string
|
||||||
): Promise<EventMemberDepartment> {
|
): Promise<EventMemberDepartment> {
|
||||||
const { data, error } = await (supabase as any)
|
const { data, error } = await supabase
|
||||||
.from('event_member_departments')
|
.from('event_member_departments')
|
||||||
.upsert(
|
.upsert(
|
||||||
{ event_member_id: eventMemberId, department_id: departmentId },
|
{ event_member_id: eventMemberId, department_id: departmentId },
|
||||||
@@ -537,7 +537,7 @@ export async function unassignMemberDepartment(
|
|||||||
eventMemberId: string,
|
eventMemberId: string,
|
||||||
departmentId: string
|
departmentId: string
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const { error } = await (supabase as any)
|
const { error } = await supabase
|
||||||
.from('event_member_departments')
|
.from('event_member_departments')
|
||||||
.delete()
|
.delete()
|
||||||
.eq('event_member_id', eventMemberId)
|
.eq('event_member_id', eventMemberId)
|
||||||
|
|||||||
@@ -360,26 +360,106 @@ export type Database = {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
event_departments: {
|
||||||
|
Row: {
|
||||||
|
color: string
|
||||||
|
created_at: string | null
|
||||||
|
description: string | null
|
||||||
|
event_id: string
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
sort_order: number
|
||||||
|
}
|
||||||
|
Insert: {
|
||||||
|
color?: string
|
||||||
|
created_at?: string | null
|
||||||
|
description?: string | null
|
||||||
|
event_id: string
|
||||||
|
id?: string
|
||||||
|
name: string
|
||||||
|
sort_order?: number
|
||||||
|
}
|
||||||
|
Update: {
|
||||||
|
color?: string
|
||||||
|
created_at?: string | null
|
||||||
|
description?: string | null
|
||||||
|
event_id?: string
|
||||||
|
id?: string
|
||||||
|
name?: string
|
||||||
|
sort_order?: number
|
||||||
|
}
|
||||||
|
Relationships: [
|
||||||
|
{
|
||||||
|
foreignKeyName: "event_departments_event_id_fkey"
|
||||||
|
columns: ["event_id"]
|
||||||
|
isOneToOne: false
|
||||||
|
referencedRelation: "events"
|
||||||
|
referencedColumns: ["id"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
event_member_departments: {
|
||||||
|
Row: {
|
||||||
|
assigned_at: string | null
|
||||||
|
department_id: string
|
||||||
|
event_member_id: string
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
Insert: {
|
||||||
|
assigned_at?: string | null
|
||||||
|
department_id: string
|
||||||
|
event_member_id: string
|
||||||
|
id?: string
|
||||||
|
}
|
||||||
|
Update: {
|
||||||
|
assigned_at?: string | null
|
||||||
|
department_id?: string
|
||||||
|
event_member_id?: string
|
||||||
|
id?: string
|
||||||
|
}
|
||||||
|
Relationships: [
|
||||||
|
{
|
||||||
|
foreignKeyName: "event_member_departments_department_id_fkey"
|
||||||
|
columns: ["department_id"]
|
||||||
|
isOneToOne: false
|
||||||
|
referencedRelation: "event_departments"
|
||||||
|
referencedColumns: ["id"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
foreignKeyName: "event_member_departments_event_member_id_fkey"
|
||||||
|
columns: ["event_member_id"]
|
||||||
|
isOneToOne: false
|
||||||
|
referencedRelation: "event_members"
|
||||||
|
referencedColumns: ["id"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
event_members: {
|
event_members: {
|
||||||
Row: {
|
Row: {
|
||||||
assigned_at: string | null
|
assigned_at: string | null
|
||||||
event_id: string
|
event_id: string
|
||||||
id: string
|
id: string
|
||||||
|
notes: string | null
|
||||||
role: string
|
role: string
|
||||||
|
role_id: string | null
|
||||||
user_id: string
|
user_id: string
|
||||||
}
|
}
|
||||||
Insert: {
|
Insert: {
|
||||||
assigned_at?: string | null
|
assigned_at?: string | null
|
||||||
event_id: string
|
event_id: string
|
||||||
id?: string
|
id?: string
|
||||||
|
notes?: string | null
|
||||||
role?: string
|
role?: string
|
||||||
|
role_id?: string | null
|
||||||
user_id: string
|
user_id: string
|
||||||
}
|
}
|
||||||
Update: {
|
Update: {
|
||||||
assigned_at?: string | null
|
assigned_at?: string | null
|
||||||
event_id?: string
|
event_id?: string
|
||||||
id?: string
|
id?: string
|
||||||
|
notes?: string | null
|
||||||
role?: string
|
role?: string
|
||||||
|
role_id?: string | null
|
||||||
user_id?: string
|
user_id?: string
|
||||||
}
|
}
|
||||||
Relationships: [
|
Relationships: [
|
||||||
@@ -390,6 +470,51 @@ export type Database = {
|
|||||||
referencedRelation: "events"
|
referencedRelation: "events"
|
||||||
referencedColumns: ["id"]
|
referencedColumns: ["id"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
foreignKeyName: "event_members_role_id_fkey"
|
||||||
|
columns: ["role_id"]
|
||||||
|
isOneToOne: false
|
||||||
|
referencedRelation: "event_roles"
|
||||||
|
referencedColumns: ["id"]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
event_roles: {
|
||||||
|
Row: {
|
||||||
|
color: string
|
||||||
|
created_at: string | null
|
||||||
|
event_id: string
|
||||||
|
id: string
|
||||||
|
is_default: boolean
|
||||||
|
name: string
|
||||||
|
sort_order: number
|
||||||
|
}
|
||||||
|
Insert: {
|
||||||
|
color?: string
|
||||||
|
created_at?: string | null
|
||||||
|
event_id: string
|
||||||
|
id?: string
|
||||||
|
is_default?: boolean
|
||||||
|
name: string
|
||||||
|
sort_order?: number
|
||||||
|
}
|
||||||
|
Update: {
|
||||||
|
color?: string
|
||||||
|
created_at?: string | null
|
||||||
|
event_id?: string
|
||||||
|
id?: string
|
||||||
|
is_default?: boolean
|
||||||
|
name?: string
|
||||||
|
sort_order?: number
|
||||||
|
}
|
||||||
|
Relationships: [
|
||||||
|
{
|
||||||
|
foreignKeyName: "event_roles_event_id_fkey"
|
||||||
|
columns: ["event_id"]
|
||||||
|
isOneToOne: false
|
||||||
|
referencedRelation: "events"
|
||||||
|
referencedColumns: ["id"]
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
events: {
|
events: {
|
||||||
@@ -982,25 +1107,37 @@ export type Database = {
|
|||||||
Row: {
|
Row: {
|
||||||
avatar_url: string | null
|
avatar_url: string | null
|
||||||
created_at: string | null
|
created_at: string | null
|
||||||
|
discord_handle: string | null
|
||||||
email: string
|
email: string
|
||||||
full_name: string | null
|
full_name: string | null
|
||||||
|
hoodie_size: string | null
|
||||||
id: string
|
id: string
|
||||||
|
phone: string | null
|
||||||
|
shirt_size: string | null
|
||||||
updated_at: string | null
|
updated_at: string | null
|
||||||
}
|
}
|
||||||
Insert: {
|
Insert: {
|
||||||
avatar_url?: string | null
|
avatar_url?: string | null
|
||||||
created_at?: string | null
|
created_at?: string | null
|
||||||
|
discord_handle?: string | null
|
||||||
email: string
|
email: string
|
||||||
full_name?: string | null
|
full_name?: string | null
|
||||||
|
hoodie_size?: string | null
|
||||||
id: string
|
id: string
|
||||||
|
phone?: string | null
|
||||||
|
shirt_size?: string | null
|
||||||
updated_at?: string | null
|
updated_at?: string | null
|
||||||
}
|
}
|
||||||
Update: {
|
Update: {
|
||||||
avatar_url?: string | null
|
avatar_url?: string | null
|
||||||
created_at?: string | null
|
created_at?: string | null
|
||||||
|
discord_handle?: string | null
|
||||||
email?: string
|
email?: string
|
||||||
full_name?: string | null
|
full_name?: string | null
|
||||||
|
hoodie_size?: string | null
|
||||||
id?: string
|
id?: string
|
||||||
|
phone?: string | null
|
||||||
|
shirt_size?: string | null
|
||||||
updated_at?: string | null
|
updated_at?: string | null
|
||||||
}
|
}
|
||||||
Relationships: []
|
Relationships: []
|
||||||
@@ -1296,29 +1433,15 @@ export const Constants = {
|
|||||||
},
|
},
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
// ── Convenience type aliases ─────────────────────────────────────────
|
// ============================================================
|
||||||
export type MemberRole = 'owner' | 'admin' | 'editor' | 'viewer';
|
// Convenience type aliases (used across the codebase)
|
||||||
type PublicTables = Database['public']['Tables']
|
// ============================================================
|
||||||
|
export type Profile = Tables<'profiles'>
|
||||||
export type Organization = PublicTables['organizations']['Row']
|
export type Organization = Tables<'organizations'>
|
||||||
export type OrgMember = PublicTables['org_members']['Row']
|
export type Document = Tables<'documents'>
|
||||||
export type OrgRole = PublicTables['org_roles']['Row']
|
export type KanbanBoard = Tables<'kanban_boards'>
|
||||||
export type OrgInvite = PublicTables['org_invites']['Row']
|
export type KanbanColumn = Tables<'kanban_columns'>
|
||||||
export type Profile = PublicTables['profiles']['Row']
|
export type KanbanCard = Tables<'kanban_cards'>
|
||||||
export type Document = PublicTables['documents']['Row']
|
export type CalendarEvent = Tables<'calendar_events'>
|
||||||
export type DocumentLock = PublicTables['document_locks']['Row']
|
export type OrgRole = Tables<'org_roles'>
|
||||||
export type CalendarEvent = PublicTables['calendar_events']['Row']
|
export type MemberRole = string
|
||||||
export type KanbanBoard = PublicTables['kanban_boards']['Row']
|
|
||||||
export type KanbanColumn = PublicTables['kanban_columns']['Row']
|
|
||||||
export type KanbanCard = PublicTables['kanban_cards']['Row']
|
|
||||||
export type KanbanComment = PublicTables['kanban_comments']['Row']
|
|
||||||
export type KanbanLabel = PublicTables['kanban_labels']['Row']
|
|
||||||
export type KanbanChecklistItem = PublicTables['kanban_checklist_items']['Row']
|
|
||||||
export type Tag = PublicTables['tags']['Row']
|
|
||||||
export type Team = PublicTables['teams']['Row']
|
|
||||||
export type OrgGoogleCalendar = PublicTables['org_google_calendars']['Row']
|
|
||||||
export type ActivityLog = PublicTables['activity_log']['Row']
|
|
||||||
export type UserPreferences = PublicTables['user_preferences']['Row']
|
|
||||||
export type MatrixCredentials = PublicTables['matrix_credentials']['Row']
|
|
||||||
export type EventRow = PublicTables['events']['Row']
|
|
||||||
export type EventMemberRow = PublicTables['event_members']['Row']
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export const load: LayoutServerLoad = async ({ params, locals }) => {
|
|||||||
.eq('org_id', org.id)
|
.eq('org_id', org.id)
|
||||||
.order('created_at', { ascending: false })
|
.order('created_at', { ascending: false })
|
||||||
.limit(10),
|
.limit(10),
|
||||||
(locals.supabase as any)
|
locals.supabase
|
||||||
.from('profiles')
|
.from('profiles')
|
||||||
.select('id, email, full_name, avatar_url, phone, discord_handle, shirt_size, hoodie_size')
|
.select('id, email, full_name, avatar_url, phone, discord_handle, shirt_size, hoodie_size')
|
||||||
.eq('id', user.id)
|
.eq('id', user.id)
|
||||||
@@ -111,13 +111,13 @@ export const load: LayoutServerLoad = async ({ params, locals }) => {
|
|||||||
let memberProfilesMap: Record<string, { id: string; email: string; full_name: string | null; avatar_url: string | null; phone: string | null; discord_handle: string | null; shirt_size: string | null; hoodie_size: string | null }> = {};
|
let memberProfilesMap: Record<string, { id: string; email: string; full_name: string | null; avatar_url: string | null; phone: string | null; discord_handle: string | null; shirt_size: string | null; hoodie_size: string | null }> = {};
|
||||||
|
|
||||||
if (memberUserIds.length > 0) {
|
if (memberUserIds.length > 0) {
|
||||||
const { data: memberProfiles } = await (locals.supabase as any)
|
const { data: memberProfiles } = await locals.supabase
|
||||||
.from('profiles')
|
.from('profiles')
|
||||||
.select('id, email, full_name, avatar_url, phone, discord_handle, shirt_size, hoodie_size')
|
.select('id, email, full_name, avatar_url, phone, discord_handle, shirt_size, hoodie_size')
|
||||||
.in('id', memberUserIds);
|
.in('id', memberUserIds);
|
||||||
|
|
||||||
if (memberProfiles) {
|
if (memberProfiles) {
|
||||||
memberProfilesMap = Object.fromEntries(memberProfiles.map((p: any) => [p.id, p]));
|
memberProfilesMap = Object.fromEntries(memberProfiles.map(p => [p.id, p]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -175,7 +175,7 @@
|
|||||||
|
|
||||||
async function saveProfile() {
|
async function saveProfile() {
|
||||||
isSaving = true;
|
isSaving = true;
|
||||||
const { error } = await (supabase as any)
|
const { error } = await supabase
|
||||||
.from("profiles")
|
.from("profiles")
|
||||||
.update({
|
.update({
|
||||||
full_name: fullName || null,
|
full_name: fullName || null,
|
||||||
|
|||||||
@@ -72,7 +72,7 @@
|
|||||||
if (!newEventName.trim()) return;
|
if (!newEventName.trim()) return;
|
||||||
creating = true;
|
creating = true;
|
||||||
try {
|
try {
|
||||||
const { data: created, error } = await (supabase as any)
|
const { data: created, error } = await supabase
|
||||||
.from("events")
|
.from("events")
|
||||||
.insert({
|
.insert({
|
||||||
org_id: data.org.id,
|
org_id: data.org.id,
|
||||||
|
|||||||
@@ -151,7 +151,7 @@
|
|||||||
async function handleSave() {
|
async function handleSave() {
|
||||||
saving = true;
|
saving = true;
|
||||||
try {
|
try {
|
||||||
const { error } = await (supabase as any)
|
const { error } = await supabase
|
||||||
.from("events")
|
.from("events")
|
||||||
.update({
|
.update({
|
||||||
name: editName.trim(),
|
name: editName.trim(),
|
||||||
@@ -183,7 +183,7 @@
|
|||||||
async function handleDelete() {
|
async function handleDelete() {
|
||||||
deleting = true;
|
deleting = true;
|
||||||
try {
|
try {
|
||||||
const { error } = await (supabase as any)
|
const { error } = await supabase
|
||||||
.from("events")
|
.from("events")
|
||||||
.delete()
|
.delete()
|
||||||
.eq("id", data.event.id);
|
.eq("id", data.event.id);
|
||||||
|
|||||||
@@ -141,7 +141,7 @@
|
|||||||
if (!selectedUserId) return;
|
if (!selectedUserId) return;
|
||||||
adding = true;
|
adding = true;
|
||||||
try {
|
try {
|
||||||
const { data: inserted, error } = await (supabase as any)
|
const { data: inserted, error } = await supabase
|
||||||
.from("event_members")
|
.from("event_members")
|
||||||
.upsert(
|
.upsert(
|
||||||
{
|
{
|
||||||
@@ -159,7 +159,7 @@
|
|||||||
|
|
||||||
// Assign departments
|
// Assign departments
|
||||||
for (const deptId of selectedDeptIds) {
|
for (const deptId of selectedDeptIds) {
|
||||||
await (supabase as any)
|
await supabase
|
||||||
.from("event_member_departments")
|
.from("event_member_departments")
|
||||||
.upsert(
|
.upsert(
|
||||||
{ event_member_id: inserted.id, department_id: deptId },
|
{ event_member_id: inserted.id, department_id: deptId },
|
||||||
@@ -209,7 +209,7 @@
|
|||||||
updatingMember = true;
|
updatingMember = true;
|
||||||
try {
|
try {
|
||||||
// Update member record
|
// Update member record
|
||||||
const { error } = await (supabase as any)
|
const { error } = await supabase
|
||||||
.from("event_members")
|
.from("event_members")
|
||||||
.update({
|
.update({
|
||||||
role_id: editRoleId || null,
|
role_id: editRoleId || null,
|
||||||
@@ -224,14 +224,14 @@
|
|||||||
const toAdd = editDeptIds.filter((id) => !oldDeptIds.includes(id));
|
const toAdd = editDeptIds.filter((id) => !oldDeptIds.includes(id));
|
||||||
|
|
||||||
for (const deptId of toRemove) {
|
for (const deptId of toRemove) {
|
||||||
await (supabase as any)
|
await supabase
|
||||||
.from("event_member_departments")
|
.from("event_member_departments")
|
||||||
.delete()
|
.delete()
|
||||||
.eq("event_member_id", editingMember.id)
|
.eq("event_member_id", editingMember.id)
|
||||||
.eq("department_id", deptId);
|
.eq("department_id", deptId);
|
||||||
}
|
}
|
||||||
for (const deptId of toAdd) {
|
for (const deptId of toAdd) {
|
||||||
await (supabase as any)
|
await supabase
|
||||||
.from("event_member_departments")
|
.from("event_member_departments")
|
||||||
.upsert(
|
.upsert(
|
||||||
{ event_member_id: editingMember.id, department_id: deptId },
|
{ event_member_id: editingMember.id, department_id: deptId },
|
||||||
@@ -268,7 +268,7 @@
|
|||||||
if (!memberToRemove) return;
|
if (!memberToRemove) return;
|
||||||
removing = true;
|
removing = true;
|
||||||
try {
|
try {
|
||||||
const { error } = await (supabase as any)
|
const { error } = await supabase
|
||||||
.from("event_members")
|
.from("event_members")
|
||||||
.delete()
|
.delete()
|
||||||
.eq("id", memberToRemove.id);
|
.eq("id", memberToRemove.id);
|
||||||
@@ -298,7 +298,7 @@
|
|||||||
savingDept = true;
|
savingDept = true;
|
||||||
try {
|
try {
|
||||||
if (editingDept) {
|
if (editingDept) {
|
||||||
const { data: updated, error } = await (supabase as any)
|
const { data: updated, error } = await supabase
|
||||||
.from("event_departments")
|
.from("event_departments")
|
||||||
.update({ name: deptName.trim(), color: deptColor })
|
.update({ name: deptName.trim(), color: deptColor })
|
||||||
.eq("id", editingDept.id)
|
.eq("id", editingDept.id)
|
||||||
@@ -310,7 +310,7 @@
|
|||||||
);
|
);
|
||||||
toasts.success(m.team_dept_updated());
|
toasts.success(m.team_dept_updated());
|
||||||
} else {
|
} else {
|
||||||
const { data: created, error } = await (supabase as any)
|
const { data: created, error } = await supabase
|
||||||
.from("event_departments")
|
.from("event_departments")
|
||||||
.insert({
|
.insert({
|
||||||
event_id: data.event.id,
|
event_id: data.event.id,
|
||||||
@@ -334,7 +334,7 @@
|
|||||||
|
|
||||||
async function handleDeleteDept(dept: EventDepartment) {
|
async function handleDeleteDept(dept: EventDepartment) {
|
||||||
try {
|
try {
|
||||||
const { error } = await (supabase as any)
|
const { error } = await supabase
|
||||||
.from("event_departments")
|
.from("event_departments")
|
||||||
.delete()
|
.delete()
|
||||||
.eq("id", dept.id);
|
.eq("id", dept.id);
|
||||||
@@ -364,7 +364,7 @@
|
|||||||
savingRole = true;
|
savingRole = true;
|
||||||
try {
|
try {
|
||||||
if (editingRole) {
|
if (editingRole) {
|
||||||
const { data: updated, error } = await (supabase as any)
|
const { data: updated, error } = await supabase
|
||||||
.from("event_roles")
|
.from("event_roles")
|
||||||
.update({ name: roleName.trim(), color: roleColor })
|
.update({ name: roleName.trim(), color: roleColor })
|
||||||
.eq("id", editingRole.id)
|
.eq("id", editingRole.id)
|
||||||
@@ -376,7 +376,7 @@
|
|||||||
);
|
);
|
||||||
toasts.success(m.team_role_updated());
|
toasts.success(m.team_role_updated());
|
||||||
} else {
|
} else {
|
||||||
const { data: created, error } = await (supabase as any)
|
const { data: created, error } = await supabase
|
||||||
.from("event_roles")
|
.from("event_roles")
|
||||||
.insert({
|
.insert({
|
||||||
event_id: data.event.id,
|
event_id: data.event.id,
|
||||||
@@ -400,7 +400,7 @@
|
|||||||
|
|
||||||
async function handleDeleteRole(role: EventRole) {
|
async function handleDeleteRole(role: EventRole) {
|
||||||
try {
|
try {
|
||||||
const { error } = await (supabase as any)
|
const { error } = await supabase
|
||||||
.from("event_roles")
|
.from("event_roles")
|
||||||
.delete()
|
.delete()
|
||||||
.eq("id", role.id);
|
.eq("id", role.id);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
-- 1. Event Roles: customizable per-event position types
|
-- 1. Event Roles: customizable per-event position types
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
CREATE TABLE event_roles (
|
CREATE TABLE event_roles (
|
||||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
event_id UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE,
|
event_id UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
color TEXT NOT NULL DEFAULT '#6366f1',
|
color TEXT NOT NULL DEFAULT '#6366f1',
|
||||||
@@ -21,7 +21,7 @@ CREATE INDEX idx_event_roles_event ON event_roles(event_id);
|
|||||||
-- 2. Event Departments: teams/areas within an event
|
-- 2. Event Departments: teams/areas within an event
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
CREATE TABLE event_departments (
|
CREATE TABLE event_departments (
|
||||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
event_id UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE,
|
event_id UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
color TEXT NOT NULL DEFAULT '#00A3E0',
|
color TEXT NOT NULL DEFAULT '#00A3E0',
|
||||||
@@ -44,7 +44,7 @@ ALTER TABLE event_members
|
|||||||
-- 4. Member-Department assignments (many-to-many)
|
-- 4. Member-Department assignments (many-to-many)
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
CREATE TABLE event_member_departments (
|
CREATE TABLE event_member_departments (
|
||||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
event_member_id UUID NOT NULL REFERENCES event_members(id) ON DELETE CASCADE,
|
event_member_id UUID NOT NULL REFERENCES event_members(id) ON DELETE CASCADE,
|
||||||
department_id UUID NOT NULL REFERENCES event_departments(id) ON DELETE CASCADE,
|
department_id UUID NOT NULL REFERENCES event_departments(id) ON DELETE CASCADE,
|
||||||
assigned_at TIMESTAMPTZ DEFAULT now(),
|
assigned_at TIMESTAMPTZ DEFAULT now(),
|
||||||
|
|||||||
Reference in New Issue
Block a user