Fixes
This commit is contained in:
parent
8f41c04ca1
commit
cbe002f4c4
640
package-lock.json
generated
640
package-lock.json
generated
@ -10,6 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sveltejs/adapter-node": "^5.2.9",
|
"@sveltejs/adapter-node": "^5.2.9",
|
||||||
"@tailwindcss/forms": "^0.5.9",
|
"@tailwindcss/forms": "^0.5.9",
|
||||||
|
"@tailwindcss/vite": "^4.1.10",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"bcrypt": "^5.1.1",
|
"bcrypt": "^5.1.1",
|
||||||
"desm": "^1.3.1",
|
"desm": "^1.3.1",
|
||||||
@ -40,7 +41,7 @@
|
|||||||
"prettier-plugin-tailwindcss": "^0.6.9",
|
"prettier-plugin-tailwindcss": "^0.6.9",
|
||||||
"svelte": "^5.0.0",
|
"svelte": "^5.0.0",
|
||||||
"svelte-check": "^4.0.0",
|
"svelte-check": "^4.0.0",
|
||||||
"tailwindcss": "^3.4.9",
|
"tailwindcss": "^3.4.17",
|
||||||
"typescript": "^5.0.0",
|
"typescript": "^5.0.0",
|
||||||
"typescript-eslint": "^8.0.0",
|
"typescript-eslint": "^8.0.0",
|
||||||
"vite": "^6.0.0"
|
"vite": "^6.0.0"
|
||||||
@ -763,6 +764,27 @@
|
|||||||
"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/@isaacs/fs-minipass/node_modules/minipass": {
|
||||||
|
"version": "7.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||||
|
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16 || 14 >=14.17"
|
||||||
|
}
|
||||||
|
},
|
||||||
"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",
|
||||||
@ -1329,6 +1351,360 @@
|
|||||||
"tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1"
|
"tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tailwindcss/node": {
|
||||||
|
"version": "4.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.10.tgz",
|
||||||
|
"integrity": "sha512-2ACf1znY5fpRBwRhMgj9ZXvb2XZW8qs+oTfotJ2C5xR0/WNL7UHZ7zXl6s+rUqedL1mNi+0O+WQr5awGowS3PQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@ampproject/remapping": "^2.3.0",
|
||||||
|
"enhanced-resolve": "^5.18.1",
|
||||||
|
"jiti": "^2.4.2",
|
||||||
|
"lightningcss": "1.30.1",
|
||||||
|
"magic-string": "^0.30.17",
|
||||||
|
"source-map-js": "^1.2.1",
|
||||||
|
"tailwindcss": "4.1.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/node/node_modules/jiti": {
|
||||||
|
"version": "2.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
|
||||||
|
"integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"jiti": "lib/jiti-cli.mjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/node/node_modules/tailwindcss": {
|
||||||
|
"version": "4.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.10.tgz",
|
||||||
|
"integrity": "sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide": {
|
||||||
|
"version": "4.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.10.tgz",
|
||||||
|
"integrity": "sha512-v0C43s7Pjw+B9w21htrQwuFObSkio2aV/qPx/mhrRldbqxbWJK6KizM+q7BF1/1CmuLqZqX3CeYF7s7P9fbA8Q==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"detect-libc": "^2.0.4",
|
||||||
|
"tar": "^7.4.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@tailwindcss/oxide-android-arm64": "4.1.10",
|
||||||
|
"@tailwindcss/oxide-darwin-arm64": "4.1.10",
|
||||||
|
"@tailwindcss/oxide-darwin-x64": "4.1.10",
|
||||||
|
"@tailwindcss/oxide-freebsd-x64": "4.1.10",
|
||||||
|
"@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.10",
|
||||||
|
"@tailwindcss/oxide-linux-arm64-gnu": "4.1.10",
|
||||||
|
"@tailwindcss/oxide-linux-arm64-musl": "4.1.10",
|
||||||
|
"@tailwindcss/oxide-linux-x64-gnu": "4.1.10",
|
||||||
|
"@tailwindcss/oxide-linux-x64-musl": "4.1.10",
|
||||||
|
"@tailwindcss/oxide-wasm32-wasi": "4.1.10",
|
||||||
|
"@tailwindcss/oxide-win32-arm64-msvc": "4.1.10",
|
||||||
|
"@tailwindcss/oxide-win32-x64-msvc": "4.1.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-android-arm64": {
|
||||||
|
"version": "4.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.10.tgz",
|
||||||
|
"integrity": "sha512-VGLazCoRQ7rtsCzThaI1UyDu/XRYVyH4/EWiaSX6tFglE+xZB5cvtC5Omt0OQ+FfiIVP98su16jDVHDEIuH4iQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-darwin-arm64": {
|
||||||
|
"version": "4.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.10.tgz",
|
||||||
|
"integrity": "sha512-ZIFqvR1irX2yNjWJzKCqTCcHZbgkSkSkZKbRM3BPzhDL/18idA8uWCoopYA2CSDdSGFlDAxYdU2yBHwAwx8euQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-darwin-x64": {
|
||||||
|
"version": "4.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.10.tgz",
|
||||||
|
"integrity": "sha512-eCA4zbIhWUFDXoamNztmS0MjXHSEJYlvATzWnRiTqJkcUteSjO94PoRHJy1Xbwp9bptjeIxxBHh+zBWFhttbrQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-freebsd-x64": {
|
||||||
|
"version": "4.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.10.tgz",
|
||||||
|
"integrity": "sha512-8/392Xu12R0cc93DpiJvNpJ4wYVSiciUlkiOHOSOQNH3adq9Gi/dtySK7dVQjXIOzlpSHjeCL89RUUI8/GTI6g==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"freebsd"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
|
||||||
|
"version": "4.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.10.tgz",
|
||||||
|
"integrity": "sha512-t9rhmLT6EqeuPT+MXhWhlRYIMSfh5LZ6kBrC4FS6/+M1yXwfCtp24UumgCWOAJVyjQwG+lYva6wWZxrfvB+NhQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
|
||||||
|
"version": "4.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.10.tgz",
|
||||||
|
"integrity": "sha512-3oWrlNlxLRxXejQ8zImzrVLuZ/9Z2SeKoLhtCu0hpo38hTO2iL86eFOu4sVR8cZc6n3z7eRXXqtHJECa6mFOvA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-linux-arm64-musl": {
|
||||||
|
"version": "4.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.10.tgz",
|
||||||
|
"integrity": "sha512-saScU0cmWvg/Ez4gUmQWr9pvY9Kssxt+Xenfx1LG7LmqjcrvBnw4r9VjkFcqmbBb7GCBwYNcZi9X3/oMda9sqQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-linux-x64-gnu": {
|
||||||
|
"version": "4.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.10.tgz",
|
||||||
|
"integrity": "sha512-/G3ao/ybV9YEEgAXeEg28dyH6gs1QG8tvdN9c2MNZdUXYBaIY/Gx0N6RlJzfLy/7Nkdok4kaxKPHKJUlAaoTdA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-linux-x64-musl": {
|
||||||
|
"version": "4.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.10.tgz",
|
||||||
|
"integrity": "sha512-LNr7X8fTiKGRtQGOerSayc2pWJp/9ptRYAa4G+U+cjw9kJZvkopav1AQc5HHD+U364f71tZv6XamaHKgrIoVzA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi": {
|
||||||
|
"version": "4.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.10.tgz",
|
||||||
|
"integrity": "sha512-d6ekQpopFQJAcIK2i7ZzWOYGZ+A6NzzvQ3ozBvWFdeyqfOZdYHU66g5yr+/HC4ipP1ZgWsqa80+ISNILk+ae/Q==",
|
||||||
|
"bundleDependencies": [
|
||||||
|
"@napi-rs/wasm-runtime",
|
||||||
|
"@emnapi/core",
|
||||||
|
"@emnapi/runtime",
|
||||||
|
"@tybys/wasm-util",
|
||||||
|
"@emnapi/wasi-threads",
|
||||||
|
"tslib"
|
||||||
|
],
|
||||||
|
"cpu": [
|
||||||
|
"wasm32"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/core": "^1.4.3",
|
||||||
|
"@emnapi/runtime": "^1.4.3",
|
||||||
|
"@emnapi/wasi-threads": "^1.0.2",
|
||||||
|
"@napi-rs/wasm-runtime": "^0.2.10",
|
||||||
|
"@tybys/wasm-util": "^0.9.0",
|
||||||
|
"tslib": "^2.8.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
||||||
|
"version": "4.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.10.tgz",
|
||||||
|
"integrity": "sha512-i1Iwg9gRbwNVOCYmnigWCCgow8nDWSFmeTUU5nbNx3rqbe4p0kRbEqLwLJbYZKmSSp23g4N6rCDmm7OuPBXhDA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-win32-x64-msvc": {
|
||||||
|
"version": "4.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.10.tgz",
|
||||||
|
"integrity": "sha512-sGiJTjcBSfGq2DVRtaSljq5ZgZS2SDHSIfhOylkBvHVjwOsodBhnb3HdmiKkVuUGKD0I7G63abMOVaskj1KpOA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide/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/@tailwindcss/oxide/node_modules/minipass": {
|
||||||
|
"version": "7.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||||
|
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16 || 14 >=14.17"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide/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/@tailwindcss/oxide/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/@tailwindcss/oxide/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/@tailwindcss/oxide/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/@tailwindcss/vite": {
|
||||||
|
"version": "4.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.10.tgz",
|
||||||
|
"integrity": "sha512-QWnD5HDY2IADv+vYR82lOhqOlS1jSCUUAmfem52cXAhRTKxpDh3ARX8TTXJTCCO7Rv7cD2Nlekabv02bwP3a2A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@tailwindcss/node": "4.1.10",
|
||||||
|
"@tailwindcss/oxide": "4.1.10",
|
||||||
|
"tailwindcss": "4.1.10"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vite": "^5.2.0 || ^6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/vite/node_modules/tailwindcss": {
|
||||||
|
"version": "4.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.10.tgz",
|
||||||
|
"integrity": "sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/bcrypt": {
|
"node_modules/@types/bcrypt": {
|
||||||
"version": "5.0.2",
|
"version": "5.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz",
|
||||||
@ -2449,9 +2825,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/detect-libc": {
|
"node_modules/detect-libc": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
|
||||||
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
|
"integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
@ -2543,6 +2919,19 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/enhanced-resolve": {
|
||||||
|
"version": "5.18.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz",
|
||||||
|
"integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"graceful-fs": "^4.2.4",
|
||||||
|
"tapable": "^2.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.13.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/es-define-property": {
|
"node_modules/es-define-property": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||||
@ -3385,6 +3774,12 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/graceful-fs": {
|
||||||
|
"version": "4.2.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||||
|
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/graphemer": {
|
"node_modules/graphemer": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
||||||
@ -3783,6 +4178,234 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lightningcss": {
|
||||||
|
"version": "1.30.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
|
||||||
|
"integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==",
|
||||||
|
"license": "MPL-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"detect-libc": "^2.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"lightningcss-darwin-arm64": "1.30.1",
|
||||||
|
"lightningcss-darwin-x64": "1.30.1",
|
||||||
|
"lightningcss-freebsd-x64": "1.30.1",
|
||||||
|
"lightningcss-linux-arm-gnueabihf": "1.30.1",
|
||||||
|
"lightningcss-linux-arm64-gnu": "1.30.1",
|
||||||
|
"lightningcss-linux-arm64-musl": "1.30.1",
|
||||||
|
"lightningcss-linux-x64-gnu": "1.30.1",
|
||||||
|
"lightningcss-linux-x64-musl": "1.30.1",
|
||||||
|
"lightningcss-win32-arm64-msvc": "1.30.1",
|
||||||
|
"lightningcss-win32-x64-msvc": "1.30.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lightningcss-darwin-arm64": {
|
||||||
|
"version": "1.30.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz",
|
||||||
|
"integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MPL-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lightningcss-darwin-x64": {
|
||||||
|
"version": "1.30.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz",
|
||||||
|
"integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MPL-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lightningcss-freebsd-x64": {
|
||||||
|
"version": "1.30.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz",
|
||||||
|
"integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MPL-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"freebsd"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lightningcss-linux-arm-gnueabihf": {
|
||||||
|
"version": "1.30.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz",
|
||||||
|
"integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"license": "MPL-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lightningcss-linux-arm64-gnu": {
|
||||||
|
"version": "1.30.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz",
|
||||||
|
"integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MPL-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lightningcss-linux-arm64-musl": {
|
||||||
|
"version": "1.30.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz",
|
||||||
|
"integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MPL-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lightningcss-linux-x64-gnu": {
|
||||||
|
"version": "1.30.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz",
|
||||||
|
"integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MPL-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lightningcss-linux-x64-musl": {
|
||||||
|
"version": "1.30.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz",
|
||||||
|
"integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MPL-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lightningcss-win32-arm64-msvc": {
|
||||||
|
"version": "1.30.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz",
|
||||||
|
"integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "MPL-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lightningcss-win32-x64-msvc": {
|
||||||
|
"version": "1.30.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz",
|
||||||
|
"integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "MPL-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lilconfig": {
|
"node_modules/lilconfig": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
|
||||||
@ -5823,6 +6446,15 @@
|
|||||||
"node": ">=8.10.0"
|
"node": ">=8.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tapable": {
|
||||||
|
"version": "2.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz",
|
||||||
|
"integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tar": {
|
"node_modules/tar": {
|
||||||
"version": "6.2.1",
|
"version": "6.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
"prettier-plugin-tailwindcss": "^0.6.9",
|
"prettier-plugin-tailwindcss": "^0.6.9",
|
||||||
"svelte": "^5.0.0",
|
"svelte": "^5.0.0",
|
||||||
"svelte-check": "^4.0.0",
|
"svelte-check": "^4.0.0",
|
||||||
"tailwindcss": "^3.4.9",
|
"tailwindcss": "^3.4.17",
|
||||||
"typescript": "^5.0.0",
|
"typescript": "^5.0.0",
|
||||||
"typescript-eslint": "^8.0.0",
|
"typescript-eslint": "^8.0.0",
|
||||||
"vite": "^6.0.0"
|
"vite": "^6.0.0"
|
||||||
@ -39,6 +39,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sveltejs/adapter-node": "^5.2.9",
|
"@sveltejs/adapter-node": "^5.2.9",
|
||||||
"@tailwindcss/forms": "^0.5.9",
|
"@tailwindcss/forms": "^0.5.9",
|
||||||
|
"@tailwindcss/vite": "^4.1.10",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"bcrypt": "^5.1.1",
|
"bcrypt": "^5.1.1",
|
||||||
"desm": "^1.3.1",
|
"desm": "^1.3.1",
|
||||||
|
|||||||
@ -20,12 +20,12 @@
|
|||||||
[data-theme='dark'] {
|
[data-theme='dark'] {
|
||||||
--text-color: #f4f4f4;
|
--text-color: #f4f4f4;
|
||||||
--bg-color: #0c0c0c;
|
--bg-color: #0c0c0c;
|
||||||
--hover-bg-color: #1a1c1c;
|
--hover-bg-color: #1c1e1e;
|
||||||
--separator-line-color: #1a2029;
|
--separator-line-color: #2e343d;
|
||||||
--low-emphasis-text-color: #999999;
|
--low-emphasis-text-color: #999999;
|
||||||
--primary-color: #1F96F3;
|
--primary-color: #1F96F3;
|
||||||
--dull-primary-color: #1569ab;
|
--dull-primary-color: #1569ab;
|
||||||
--elevated-bg-color: #151516;
|
--elevated-bg-color: #1a1a1b;
|
||||||
--bg-accent-color: #202020;
|
--bg-accent-color: #202020;
|
||||||
--danger-color: #ff1d1f;
|
--danger-color: #ff1d1f;
|
||||||
--hyperlink-color: #3b82f6;
|
--hyperlink-color: #3b82f6;
|
||||||
|
|||||||
@ -40,31 +40,30 @@ export async function updateUser(user: User): Promise<number> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Construct the SQL query
|
// Construct the SQL query
|
||||||
const response = await sql`UPDATE users
|
const response = await sql`
|
||||||
SET username = ${user.username},
|
UPDATE users
|
||||||
${
|
SET username = ${user.username},
|
||||||
user.perms !== undefined
|
${
|
||||||
? sql`perms
|
user.perms !== undefined
|
||||||
=
|
? sql`perms = ${user.perms},`
|
||||||
${user.perms},`
|
: sql``
|
||||||
: sql``
|
}
|
||||||
}
|
${
|
||||||
${
|
user.active !== undefined
|
||||||
user.active !== undefined
|
? sql`active = ${user.active},`
|
||||||
? sql`active
|
: sql``
|
||||||
=
|
}
|
||||||
${user.active},`
|
${
|
||||||
: sql``
|
password_hash !== null
|
||||||
} ${
|
? sql`password_hash = ${password_hash},`
|
||||||
password_hash !== null
|
: sql``
|
||||||
? sql`password_hash
|
}
|
||||||
=
|
email = ${user.email},
|
||||||
${password_hash},`
|
phone = ${user.phone},
|
||||||
: sql``
|
full_name = ${user.fullName},
|
||||||
}
|
company_code = ${user.companyCode}
|
||||||
email = ${user.email}, phone = ${user.phone}, full_name = ${user.fullName}, company_code = ${user.companyCode}
|
WHERE id = ${user.id}
|
||||||
WHERE id = ${user.id}
|
RETURNING id;`;
|
||||||
RETURNING id;`;
|
|
||||||
|
|
||||||
await saveAvatar(user);
|
await saveAvatar(user);
|
||||||
|
|
||||||
@ -220,7 +219,8 @@ export async function getUserWithCompanyAndApplications(
|
|||||||
application_data AS (SELECT id,
|
application_data AS (SELECT id,
|
||||||
posting_id AS "postingId",
|
posting_id AS "postingId",
|
||||||
(SELECT title FROM postings WHERE id = posting_id) AS "postingTitle",
|
(SELECT title FROM postings WHERE id = posting_id) AS "postingTitle",
|
||||||
created_at AT TIME ZONE 'UTC' AS "createdAt"
|
created_at AT TIME ZONE 'UTC' AS "createdAt",
|
||||||
|
candidate_statement AS "candidateStatement"
|
||||||
FROM applications
|
FROM applications
|
||||||
WHERE "user_id" = ${id})
|
WHERE "user_id" = ${id})
|
||||||
SELECT (SELECT row_to_json(company_data)
|
SELECT (SELECT row_to_json(company_data)
|
||||||
@ -236,7 +236,7 @@ export async function getUserWithCompanyAndApplications(
|
|||||||
if (!data) {
|
if (!data) {
|
||||||
error(404, 'User not found');
|
error(404, 'User not found');
|
||||||
}
|
}
|
||||||
let user = data[0].user;
|
const user = data[0].user;
|
||||||
if (data[0].company) {
|
if (data[0].company) {
|
||||||
user.company = data[0].company;
|
user.company = data[0].company;
|
||||||
}
|
}
|
||||||
@ -246,7 +246,7 @@ export async function getUserWithCompanyAndApplications(
|
|||||||
if (user.company) {
|
if (user.company) {
|
||||||
user.company.createdAt = new Date(user.company.createdAt);
|
user.company.createdAt = new Date(user.company.createdAt);
|
||||||
}
|
}
|
||||||
let applications = data[0].applications;
|
const applications = data[0].applications;
|
||||||
if (applications) {
|
if (applications) {
|
||||||
applications.forEach((application: { createdAt: string | number | Date }) => {
|
applications.forEach((application: { createdAt: string | number | Date }) => {
|
||||||
application.createdAt = new Date(application.createdAt);
|
application.createdAt = new Date(application.createdAt);
|
||||||
@ -509,8 +509,8 @@ export async function getCompanyEmployers(
|
|||||||
if (data[0].users) {
|
if (data[0].users) {
|
||||||
data[0].users.forEach(
|
data[0].users.forEach(
|
||||||
(user: {
|
(user: {
|
||||||
company: { id: any };
|
company: { id: unknown };
|
||||||
companyId: any;
|
companyId: unknown;
|
||||||
createdAt: string | number | Date;
|
createdAt: string | number | Date;
|
||||||
lastSignIn: string | number | Date;
|
lastSignIn: string | number | Date;
|
||||||
}) => {
|
}) => {
|
||||||
@ -576,8 +576,8 @@ export async function getCompanyEmployersAndRequests(
|
|||||||
if (data[0].employers) {
|
if (data[0].employers) {
|
||||||
data[0].employers.forEach(
|
data[0].employers.forEach(
|
||||||
(user: {
|
(user: {
|
||||||
company: { id: any };
|
company: { id: unknown };
|
||||||
companyId: any;
|
companyId: unknown;
|
||||||
createdAt: string | number | Date;
|
createdAt: string | number | Date;
|
||||||
lastSignIn: string | number | Date;
|
lastSignIn: string | number | Date;
|
||||||
}) => {
|
}) => {
|
||||||
@ -593,8 +593,8 @@ export async function getCompanyEmployersAndRequests(
|
|||||||
if (data[0].requests) {
|
if (data[0].requests) {
|
||||||
data[0].requests.forEach(
|
data[0].requests.forEach(
|
||||||
(user: {
|
(user: {
|
||||||
company: { id: any };
|
company: { id: unknown };
|
||||||
companyId: any;
|
companyId: unknown;
|
||||||
createdAt: string | number | Date;
|
createdAt: string | number | Date;
|
||||||
lastSignIn: string | number | Date;
|
lastSignIn: string | number | Date;
|
||||||
}) => {
|
}) => {
|
||||||
@ -751,7 +751,7 @@ export async function getPostingWithCompanyUser(id: number): Promise<Posting> {
|
|||||||
if (!data) {
|
if (!data) {
|
||||||
error(404, 'Posting not found');
|
error(404, 'Posting not found');
|
||||||
}
|
}
|
||||||
let posting = <Posting>data[0].posting;
|
const posting = <Posting>data[0].posting;
|
||||||
posting.company = <Company>data[0].company;
|
posting.company = <Company>data[0].company;
|
||||||
posting.employer = <User>data[0].user;
|
posting.employer = <User>data[0].user;
|
||||||
|
|
||||||
@ -765,16 +765,107 @@ export async function getPostingWithCompanyUser(id: number): Promise<Posting> {
|
|||||||
return posting;
|
return posting;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createApplication(application: Application): Promise<number> {
|
|
||||||
const response = await sql`
|
export async function getEditApplicationPageData(applicationId: number): Promise<{ posting: Posting; application: Application }> {
|
||||||
INSERT INTO applications (posting_id, user_id, candidate_statement, created_at)
|
const data = await sql`
|
||||||
VALUES (${application.postingId}, ${application.userId}, ${application.candidateStatement}, NOW()) RETURNING id;
|
WITH application_data AS (
|
||||||
|
SELECT id AS application_id,
|
||||||
|
candidate_statement,
|
||||||
|
posting_id
|
||||||
|
FROM applications
|
||||||
|
WHERE id = ${applicationId}
|
||||||
|
),
|
||||||
|
company_data AS (
|
||||||
|
SELECT id,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
website,
|
||||||
|
created_at AS "createdAt"
|
||||||
|
FROM companies
|
||||||
|
WHERE id = (
|
||||||
|
SELECT company_id
|
||||||
|
FROM postings
|
||||||
|
WHERE id = (SELECT posting_id FROM application_data)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
user_data AS (
|
||||||
|
SELECT username,
|
||||||
|
email,
|
||||||
|
phone,
|
||||||
|
full_name AS "fullName"
|
||||||
|
FROM users
|
||||||
|
WHERE company_id = (
|
||||||
|
SELECT company_id
|
||||||
|
FROM postings
|
||||||
|
WHERE id = (SELECT posting_id FROM application_data)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
posting_data AS (
|
||||||
|
SELECT id,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
employer_id AS "employerId",
|
||||||
|
address,
|
||||||
|
employment_type AS "employmentType",
|
||||||
|
wage,
|
||||||
|
link,
|
||||||
|
tag_ids AS "tagIds",
|
||||||
|
created_at AT TIME ZONE 'UTC' AS "createdAt",
|
||||||
|
updated_at AT TIME ZONE 'UTC' AS "updatedAt",
|
||||||
|
flyer_link AS "flyerLink"
|
||||||
|
FROM postings
|
||||||
|
WHERE id = (SELECT posting_id FROM application_data)
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
(SELECT row_to_json(company_data) FROM company_data) AS company,
|
||||||
|
(SELECT row_to_json(user_data) FROM user_data) AS user,
|
||||||
|
(SELECT row_to_json(posting_data) FROM posting_data) AS posting,
|
||||||
|
(SELECT row_to_json(application_data) FROM application_data) AS application;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
sendEmployerNotificationEmail(application.postingId).catch((err) => {
|
if (!data || !data[0]?.posting) {
|
||||||
console.error('Failed to send employer notification email: ', err);
|
error(404, 'Posting not found');
|
||||||
});
|
}
|
||||||
return response[0].id;
|
|
||||||
|
const posting = <Posting>data[0].posting;
|
||||||
|
posting.company = <Company>data[0].company;
|
||||||
|
posting.employer = <User>data[0].user;
|
||||||
|
|
||||||
|
if (posting.createdAt) {
|
||||||
|
posting.createdAt = new Date(posting.createdAt);
|
||||||
|
}
|
||||||
|
if (posting.updatedAt) {
|
||||||
|
posting.updatedAt = new Date(posting.updatedAt);
|
||||||
|
}
|
||||||
|
|
||||||
|
const application = <Application>{
|
||||||
|
id: data[0].application.application_id,
|
||||||
|
candidateStatement: data[0].application.candidate_statement
|
||||||
|
};
|
||||||
|
|
||||||
|
return { posting, application };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createApplication(application: Application): Promise<number> {
|
||||||
|
try {
|
||||||
|
|
||||||
|
const response = await sql`
|
||||||
|
INSERT INTO applications (posting_id, user_id, candidate_statement, created_at)
|
||||||
|
VALUES (${application.postingId}, ${application.userId}, ${application.candidateStatement}, NOW()) RETURNING id;
|
||||||
|
`;
|
||||||
|
sendEmployerNotificationEmail(application.postingId).catch((err) => {
|
||||||
|
console.error('Failed to send employer notification email: ', err);
|
||||||
|
});
|
||||||
|
return response[0].id;
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
if (err instanceof Error && err.message.includes('duplicate key value')) {
|
||||||
|
error(400, 'You have already applied for this job');
|
||||||
|
} else {
|
||||||
|
error(500, 'Internal server error while creating application');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteApplication(id: number): Promise<void> {
|
export async function deleteApplication(id: number): Promise<void> {
|
||||||
@ -789,7 +880,6 @@ export async function deleteApplicationWithUser(
|
|||||||
applicationId: number,
|
applicationId: number,
|
||||||
userId: number
|
userId: number
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
console.log(applicationId, userId);
|
|
||||||
await sql`
|
await sql`
|
||||||
DELETE
|
DELETE
|
||||||
FROM applications
|
FROM applications
|
||||||
@ -798,6 +888,14 @@ export async function deleteApplicationWithUser(
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function editApplication(application: Application): Promise<void> {
|
||||||
|
await sql`
|
||||||
|
UPDATE applications
|
||||||
|
SET candidate_statement = ${application.candidateStatement}
|
||||||
|
WHERE id = ${application.id};
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
export async function getApplications(postingId: number): Promise<Application[]> {
|
export async function getApplications(postingId: number): Promise<Application[]> {
|
||||||
const data = await sql`
|
const data = await sql`
|
||||||
SELECT a.id,
|
SELECT a.id,
|
||||||
|
|||||||
@ -13,8 +13,13 @@ export function setJWT(cookies: Cookies, user: User) {
|
|||||||
if (process.env.JWT_SECRET === undefined) {
|
if (process.env.JWT_SECRET === undefined) {
|
||||||
throw new Error('JWT_SECRET not defined');
|
throw new Error('JWT_SECRET not defined');
|
||||||
}
|
}
|
||||||
|
if (process.env.BASE_URL === undefined) {
|
||||||
|
throw new Error('BASE_URL not defined');
|
||||||
|
}
|
||||||
|
|
||||||
|
const secure: boolean = process.env.BASE_URL?.includes('https://');
|
||||||
|
|
||||||
const maxAge = 60 * 60 * 24 * 30; // 30 days
|
const maxAge = 60 * 60 * 24 * 30; // 30 days
|
||||||
const JWT = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '30d' });
|
const JWT = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '30d' });
|
||||||
cookies.set('jwt', JWT, { maxAge, path: '/', httpOnly: false });
|
cookies.set('jwt', JWT, { maxAge, path: '/', httpOnly: secure, secure: secure });
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export function telFormatter(initial: string) {
|
|||||||
return initial;
|
return initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getCookieValue = (name: String) =>
|
export const getCookieValue = (name: string) =>
|
||||||
document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)')?.pop() || '';
|
document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)')?.pop() || '';
|
||||||
|
|
||||||
export function updateUserState() {
|
export function updateUserState() {
|
||||||
|
|||||||
@ -22,8 +22,13 @@
|
|||||||
<p>This one is on our end...</p>
|
<p>This one is on our end...</p>
|
||||||
<p>We are working to resolve this as fast as possible.</p>
|
<p>We are working to resolve this as fast as possible.</p>
|
||||||
{/if}
|
{/if}
|
||||||
{#if $page.status !== 404 && $page.status !== 403 && $page.status !== 401 && $page.status !== 500}
|
{#if $page.status === 400}
|
||||||
|
<p>Invalid request!</p>
|
||||||
|
<p>Make sure you have correctly inputted all information.</p>
|
||||||
|
{/if}
|
||||||
|
{#if $page.status !== 404 && $page.status !== 403 && $page.status !== 401 && $page.status !== 500 && $page.status !== 400}
|
||||||
<p>An unexpected error has occurred.</p>
|
<p>An unexpected error has occurred.</p>
|
||||||
<p>Please try again later</p>
|
<p>Please try again later</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
<p class="mt-8">Error: {$page.error?.message}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import type { PageProps } from './$types';
|
import type { PageProps } from './$types';
|
||||||
|
import type { Company } from '$lib/types';
|
||||||
|
|
||||||
let applicationToDelete: number = $state(0);
|
let applicationToDelete: number = $state(0);
|
||||||
let { data }: PageProps = $props();
|
let { data }: PageProps = $props();
|
||||||
@ -13,6 +14,25 @@
|
|||||||
if (window.location.search.includes('refresh')) {
|
if (window.location.search.includes('refresh')) {
|
||||||
location.replace(location.pathname);
|
location.replace(location.pathname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const acc = document.getElementsByClassName('accordion');
|
||||||
|
|
||||||
|
for (let i = 0; i < acc.length; i++) {
|
||||||
|
acc[i].addEventListener('click', function (this: HTMLElement) {
|
||||||
|
this.classList.toggle('active');
|
||||||
|
this.children[1].innerHTML = this.classList.contains('active')
|
||||||
|
? 'arrow_drop_up'
|
||||||
|
: 'arrow_drop_down';
|
||||||
|
|
||||||
|
/* Toggle between hiding and showing the active panel */
|
||||||
|
let panel = this.nextElementSibling as HTMLElement;
|
||||||
|
if (panel.style.display === 'flex') {
|
||||||
|
panel.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
panel.style.display = 'flex';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const dateFormatOptions: Intl.DateTimeFormatOptions = {
|
const dateFormatOptions: Intl.DateTimeFormatOptions = {
|
||||||
@ -26,11 +46,16 @@
|
|||||||
`https://ui-avatars.com/api/?background=random&format=svg&name=${data.user.fullName ? encodeURIComponent(data.user.fullName) : encodeURIComponent(data.user.username)}`;
|
`https://ui-avatars.com/api/?background=random&format=svg&name=${data.user.fullName ? encodeURIComponent(data.user.fullName) : encodeURIComponent(data.user.username)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function logoFallback(e: Event) {
|
function logoFallback(e: Event, company: Company) {
|
||||||
(e.target as HTMLImageElement).src =
|
(e.target as HTMLImageElement).src =
|
||||||
`https://ui-avatars.com/api/?background=random&format=svg&name=${encodeURIComponent(data.user.company!.name!)}`;
|
`https://ui-avatars.com/api/?background=random&format=svg&name=${encodeURIComponent(company.name!)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// function logoFallback(e: Event) {
|
||||||
|
// (e.target as HTMLImageElement).src =
|
||||||
|
// `https://ui-avatars.com/api/?background=random&format=svg&name=${encodeURIComponent(data.user.company!.name!)}`;
|
||||||
|
// }
|
||||||
|
|
||||||
function signOut() {
|
function signOut() {
|
||||||
document.cookie = 'jwt=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
|
document.cookie = 'jwt=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
|
||||||
window.location.href = '/signin';
|
window.location.href = '/signin';
|
||||||
@ -198,7 +223,7 @@
|
|||||||
class="mb-2 inline-block rounded"
|
class="mb-2 inline-block rounded"
|
||||||
src="/uploads/logos/{data.user.company.id}.jpg?timestamp=${Date.now()}"
|
src="/uploads/logos/{data.user.company.id}.jpg?timestamp=${Date.now()}"
|
||||||
alt="Company Logo"
|
alt="Company Logo"
|
||||||
onerror={logoFallback}
|
onerror={(e) => logoFallback(e, data.user.company!)}
|
||||||
height="32"
|
height="32"
|
||||||
width="32"
|
width="32"
|
||||||
/>
|
/>
|
||||||
@ -236,28 +261,43 @@
|
|||||||
<div class="elevated separator-borders m-2 inline-block h-min w-full rounded">
|
<div class="elevated separator-borders m-2 inline-block h-min w-full rounded">
|
||||||
<div class="p-3 font-semibold">Pending applications</div>
|
<div class="p-3 font-semibold">Pending applications</div>
|
||||||
{#each data.applications as application}
|
{#each data.applications as application}
|
||||||
<div class="top-border flex justify-between p-3">
|
<button class="top-border flex justify-between p-2 accordion">
|
||||||
<div class="inline-block">
|
<div class="inline-block">
|
||||||
<div class="font-semibold">
|
<div class="font-semibold text-left">
|
||||||
Applied to: <a
|
Applied to: <a
|
||||||
class="hover-hyperlink font-normal"
|
class="hover-hyperlink font-normal"
|
||||||
href="/postings/{application.postingId}">{application.postingTitle}</a
|
href="/postings/{application.postingId}">{application.postingTitle}</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="font-semibold">
|
<div class="font-semibold text-left">
|
||||||
Applied on: <span class="font-normal"
|
Applied on: <span class="font-normal"
|
||||||
>{application.createdAt.toLocaleDateString('en-US', dateFormatOptions)}</span
|
>{application.createdAt.toLocaleDateString('en-US', dateFormatOptions)}</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<div class="material-symbols-outlined align-top pt-3 pr-3">arrow_drop_down</div>
|
||||||
class="material-symbols-outlined danger-color inline-block"
|
</button>
|
||||||
onclick={() => {
|
<div class="panel hidden p-2 justify-between">
|
||||||
|
<div class="inline-block">
|
||||||
|
|
||||||
|
<!-- <h2>Candidate Statement</h2>-->
|
||||||
|
<h3 class="low-emphasis-text">
|
||||||
|
Why do you believe you are the best fit for this role?
|
||||||
|
</h3>
|
||||||
|
<p class="whitespace-pre-wrap">{application.candidateStatement}</p>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 mr-3">
|
||||||
|
|
||||||
|
<a href="account/editapplication?id={application.id}" class="mr-3 material-symbols-outlined hyperlink-color">edit</a>
|
||||||
|
<button
|
||||||
|
class="material-symbols-outlined danger-color inline-block"
|
||||||
|
onclick={() => {
|
||||||
applicationToDelete = application.id;
|
applicationToDelete = application.id;
|
||||||
openConfirm();
|
openConfirm();
|
||||||
}}
|
}}
|
||||||
>delete
|
>delete
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
47
src/routes/account/editapplication/+page.server.ts
Normal file
47
src/routes/account/editapplication/+page.server.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import { type Actions, error, fail, redirect } from '@sveltejs/kit';
|
||||||
|
import type { PageServerLoad } from './$types';
|
||||||
|
import { editApplication, getEditApplicationPageData } from '$lib/db/index.server';
|
||||||
|
import { getUserId, getUserPerms } from '$lib/index.server';
|
||||||
|
import { PERMISSIONS } from '$lib/consts';
|
||||||
|
import type { Application } from '$lib/types';
|
||||||
|
|
||||||
|
export const load: PageServerLoad = async ({ url, cookies }) => {
|
||||||
|
if (!url.searchParams.has('id')) {
|
||||||
|
error(400, 'Missing required parameter: id');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Permission check (apply perm)
|
||||||
|
const id = parseInt(url.searchParams.get('id')!);
|
||||||
|
const perms = getUserPerms(cookies);
|
||||||
|
if (perms >= 0 && (perms & PERMISSIONS.APPLY_FOR_JOBS) > 0) {
|
||||||
|
return await getEditApplicationPageData(id);
|
||||||
|
}
|
||||||
|
error(403, 'Unauthorized');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const actions: Actions = {
|
||||||
|
// Application submission
|
||||||
|
submit: async ({ request, cookies, params, url }) => {
|
||||||
|
// Permission check (apply perm)
|
||||||
|
if (!((getUserPerms(cookies) & PERMISSIONS.APPLY_FOR_JOBS) > 0)) {
|
||||||
|
return fail(403, { errorMessage: 'Unauthorized' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await request.formData();
|
||||||
|
const candidateStatement = data.get('candidateStatement')?.toString().trim();
|
||||||
|
|
||||||
|
// Statement data validation
|
||||||
|
if (!candidateStatement || candidateStatement === '') {
|
||||||
|
return fail(400, { errorMessage: 'Candidate statement is required' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push to DB and redirect
|
||||||
|
if (!url.searchParams.has('id')) {
|
||||||
|
error(400, 'Missing required parameter: id');
|
||||||
|
}
|
||||||
|
const id: number = parseInt(url.searchParams.get('id')!);
|
||||||
|
|
||||||
|
await editApplication(<Application>{ id, candidateStatement });
|
||||||
|
redirect(301, `/postings`);
|
||||||
|
}
|
||||||
|
};
|
||||||
117
src/routes/account/editapplication/+page.svelte
Normal file
117
src/routes/account/editapplication/+page.svelte
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { enhance } from '$app/forms';
|
||||||
|
import type { PageProps } from './$types';
|
||||||
|
import { employmentTypeDisplayName } from '$lib/shared.svelte';
|
||||||
|
import type { Posting } from '$lib/types';
|
||||||
|
|
||||||
|
const dateFormatOptions: Intl.DateTimeFormatOptions = {
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'short',
|
||||||
|
day: 'numeric'
|
||||||
|
};
|
||||||
|
|
||||||
|
function logoFallback(e: Event, posting: Posting) {
|
||||||
|
(e.target as HTMLImageElement).src =
|
||||||
|
`https://ui-avatars.com/api/?background=random&format=svg&name=${encodeURIComponent(posting.company.name || 'COMPANY')}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { data, form }: PageProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="base-container">
|
||||||
|
<div class="content flex">
|
||||||
|
<div class="elevated separator-borders ml-4 mt-4 inline-block h-min w-1/2 rounded p-4">
|
||||||
|
<div class="bottom-border elevated-bg flex justify-between pb-2">
|
||||||
|
<div class="inline-block">
|
||||||
|
<img
|
||||||
|
alt="Company Logo"
|
||||||
|
class="inline-block rounded"
|
||||||
|
height="64"
|
||||||
|
onerror={(e) => logoFallback(e, data.posting)}
|
||||||
|
src="/uploads/logos/{data.posting?.company.id}.jpg"
|
||||||
|
width="64"
|
||||||
|
/>
|
||||||
|
<div class="inline-block pl-2 align-top">
|
||||||
|
<h1>{data.posting.title}</h1>
|
||||||
|
<h2>Company: {data.posting.company.name}</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="scrollbar-on-elevated details-height overflow-y-scroll">
|
||||||
|
<h2 class="pt-2 font-semibold">Contact</h2>
|
||||||
|
<p>{data.posting.employer?.fullName} ({data.posting.employer?.username})</p>
|
||||||
|
<a class="hover-hyperlink" href="mailto:{data.posting.employer?.email}"
|
||||||
|
>{data.posting.employer?.email}</a
|
||||||
|
>
|
||||||
|
<a class="hover-hyperlink" href="tel:{data.posting.employer?.phone}"
|
||||||
|
>{data.posting.employer?.phone}</a
|
||||||
|
>
|
||||||
|
<h2 class="pt-2 font-semibold">Details</h2>
|
||||||
|
{#if data.posting.employmentType}
|
||||||
|
<p>{employmentTypeDisplayName(data.posting.employmentType)}</p>
|
||||||
|
{/if}
|
||||||
|
{#if data.posting.address}
|
||||||
|
<a
|
||||||
|
href="https://www.google.com/maps/search/?api=1&query={data.posting.address}"
|
||||||
|
class="block w-max"
|
||||||
|
>Address: <span class="hover-hyperlink">{data.posting.address}</span></a
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
|
{#if data.posting.wage}
|
||||||
|
<p>Wage: {data.posting.wage}</p>
|
||||||
|
{/if}
|
||||||
|
{#if data.posting.createdAt}
|
||||||
|
<p>Posted: {data.posting.createdAt.toLocaleDateString('en-US', dateFormatOptions)}</p>
|
||||||
|
{/if}
|
||||||
|
{#if data.posting.link}
|
||||||
|
<a href={data.posting.link} class="block w-max"
|
||||||
|
>More information: <span class="hyperlink-color hyperlink-underline"
|
||||||
|
>{data.posting.link}</span
|
||||||
|
></a
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
|
{#if data.posting.flyerLink}
|
||||||
|
<a href={data.posting.flyerLink} class="block w-max"
|
||||||
|
>Flyer: <span class="hyperlink-color hyperlink-underline">{data.posting.flyerLink}</span
|
||||||
|
></a
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
|
<h2 class="pt-2 font-semibold">Job Description</h2>
|
||||||
|
<p class="whitespace-pre-wrap">{data.posting.description}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="elevated separator-borders m-4 inline-block h-min w-1/2 rounded">
|
||||||
|
<div class="bottom-border flex place-content-between">
|
||||||
|
<div class="p-3 font-semibold">Edit Application</div>
|
||||||
|
</div>
|
||||||
|
<form autocomplete="off" class="px-4" method="POST" use:enhance>
|
||||||
|
<div class="mt-4 text-sm font-semibold">
|
||||||
|
Why do you believe you are the best fit for this role? <span class="text-red-500">*</span>
|
||||||
|
<textarea
|
||||||
|
class="w-full rounded font-normal"
|
||||||
|
id="candidateStatement"
|
||||||
|
name="candidateStatement"
|
||||||
|
placeholder="Answer here"
|
||||||
|
required
|
||||||
|
rows="4"
|
||||||
|
>{data.application.candidateStatement}</textarea>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
Your account information and résumé (if supplied) will be submitted along with this
|
||||||
|
application. If there is any other information you would like the employer to know, please
|
||||||
|
add it in the box above.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{#if form?.errorMessage}
|
||||||
|
<div class="mb-2 text-red-500">{form.errorMessage}</div>
|
||||||
|
{/if}
|
||||||
|
<button
|
||||||
|
class="dull-primary-bg-color mb-4 mt-6 rounded px-2 py-1"
|
||||||
|
formaction="?/submit&id={data.application.id}"
|
||||||
|
type="submit"
|
||||||
|
>Save application
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -10,7 +10,7 @@
|
|||||||
let passwordVisible = $state(false);
|
let passwordVisible = $state(false);
|
||||||
|
|
||||||
function showPassword() {
|
function showPassword() {
|
||||||
const password = document.querySelector('input[name="password"]');
|
const password = document.querySelector('input[name="newPassword"]');
|
||||||
if (password) {
|
if (password) {
|
||||||
if (password.getAttribute('type') === 'password') {
|
if (password.getAttribute('type') === 'password') {
|
||||||
password.setAttribute('type', 'text');
|
password.setAttribute('type', 'text');
|
||||||
@ -122,8 +122,8 @@
|
|||||||
New password (optional)
|
New password (optional)
|
||||||
<input
|
<input
|
||||||
class="w-full rounded font-normal"
|
class="w-full rounded font-normal"
|
||||||
id="password"
|
id="newPassword"
|
||||||
name="password"
|
name="newPassword"
|
||||||
placeholder="New password"
|
placeholder="New password"
|
||||||
type="password"
|
type="password"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
let passwordVisible = $state(false);
|
let passwordVisible = $state(false);
|
||||||
|
|
||||||
function showPassword() {
|
function showPassword() {
|
||||||
const password = document.querySelector('input[name="password"]');
|
const password = document.querySelector('input[name="newPassword"]');
|
||||||
if (password) {
|
if (password) {
|
||||||
if (password.getAttribute('type') === 'password') {
|
if (password.getAttribute('type') === 'password') {
|
||||||
password.setAttribute('type', 'text');
|
password.setAttribute('type', 'text');
|
||||||
@ -102,8 +102,8 @@
|
|||||||
Password <span class="text-red-500">*</span>
|
Password <span class="text-red-500">*</span>
|
||||||
<input
|
<input
|
||||||
class="w-full rounded font-normal"
|
class="w-full rounded font-normal"
|
||||||
id="password"
|
id="newPassword"
|
||||||
name="password"
|
name="newPassword"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
required
|
required
|
||||||
type="password"
|
type="password"
|
||||||
|
|||||||
@ -112,7 +112,7 @@
|
|||||||
{#if userState.perms >= 0 && ((userState.perms & PERMISSIONS.MANAGE_POSTINGS) > 0 || ((userState.perms & PERMISSIONS.SUBMIT_POSTINGS) > 0 && userState.companyId === details.company.id))}
|
{#if userState.perms >= 0 && ((userState.perms & PERMISSIONS.MANAGE_POSTINGS) > 0 || ((userState.perms & PERMISSIONS.SUBMIT_POSTINGS) > 0 && userState.companyId === details.company.id))}
|
||||||
<a
|
<a
|
||||||
class="dull-primary-bg-color inline-block h-min rounded-md px-2.5 py-1 align-top"
|
class="dull-primary-bg-color inline-block h-min rounded-md px-2.5 py-1 align-top"
|
||||||
href="/postings/{details.id}/manage">Manage posting</a
|
href="/postings/{details.id}/manage/applications/">Manage posting</a
|
||||||
>
|
>
|
||||||
{:else if (userState.perms & PERMISSIONS.APPLY_FOR_JOBS) > 0}
|
{:else if (userState.perms & PERMISSIONS.APPLY_FOR_JOBS) > 0}
|
||||||
<a
|
<a
|
||||||
|
|||||||
@ -41,7 +41,7 @@
|
|||||||
{#if userState.perms >= 0 && ((userState.perms & PERMISSIONS.MANAGE_POSTINGS) > 0 || ((userState.perms & PERMISSIONS.SUBMIT_POSTINGS) > 0 && userState.companyId === data.posting.company.id))}
|
{#if userState.perms >= 0 && ((userState.perms & PERMISSIONS.MANAGE_POSTINGS) > 0 || ((userState.perms & PERMISSIONS.SUBMIT_POSTINGS) > 0 && userState.companyId === data.posting.company.id))}
|
||||||
<a
|
<a
|
||||||
class="dull-primary-bg-color inline-block h-min rounded-md px-2.5 py-1 align-top"
|
class="dull-primary-bg-color inline-block h-min rounded-md px-2.5 py-1 align-top"
|
||||||
href="/postings/{data.posting.id}/manage">Manage posting</a
|
href="/postings/{data.posting.id}/manage/applications/">Manage posting</a
|
||||||
>
|
>
|
||||||
{:else if (userState.perms & PERMISSIONS.APPLY_FOR_JOBS) > 0}
|
{:else if (userState.perms & PERMISSIONS.APPLY_FOR_JOBS) > 0}
|
||||||
<a
|
<a
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<script>
|
<script>editApplication
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
|
|||||||
@ -26,16 +26,16 @@
|
|||||||
|
|
||||||
/* Toggle between hiding and showing the active panel */
|
/* Toggle between hiding and showing the active panel */
|
||||||
let panel = this.nextElementSibling as HTMLElement;
|
let panel = this.nextElementSibling as HTMLElement;
|
||||||
if (panel.style.display === 'block') {
|
if (panel.style.display === 'flex') {
|
||||||
panel.style.display = 'none';
|
panel.style.display = 'none';
|
||||||
} else {
|
} else {
|
||||||
panel.style.display = 'block';
|
panel.style.display = 'flex';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let { data, form }: PageProps = $props();
|
let { data }: PageProps = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
@ -52,7 +52,7 @@
|
|||||||
<img
|
<img
|
||||||
class="m-2 inline-block rounded"
|
class="m-2 inline-block rounded"
|
||||||
src="/uploads/avatars/{application.user?.id || 'default'}.svg"
|
src="/uploads/avatars/{application.user?.id || 'default'}.svg"
|
||||||
alt="Company Logo"
|
alt="User Avatar"
|
||||||
height="32"
|
height="32"
|
||||||
width="32"
|
width="32"
|
||||||
onerror={(e) => logoFallback(e, application)}
|
onerror={(e) => logoFallback(e, application)}
|
||||||
@ -70,36 +70,34 @@
|
|||||||
</button>
|
</button>
|
||||||
<div class="panel hidden p-2">
|
<div class="panel hidden p-2">
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<div class="inline-block">
|
<div class="inline-block pr-4 min-w-max">
|
||||||
<div class="inline-block pr-4 align-top">
|
{#if application.user?.email}
|
||||||
{#if application.user?.email}
|
<p>Email: {application.user.email}</p>
|
||||||
<p>Email: {application.user.email}</p>
|
{/if}
|
||||||
{/if}
|
{#if application.user?.phone}
|
||||||
{#if application.user?.phone}
|
<p>Phone: {application.user.phone}</p>
|
||||||
<p>Phone: {application.user.phone}</p>
|
{/if}
|
||||||
{/if}
|
{#if application.createdAt}
|
||||||
{#if application.createdAt}
|
<p>
|
||||||
<p>
|
Applied: {application.createdAt.toLocaleDateString('en-US', dateFormatOptions)}
|
||||||
Applied: {application.createdAt.toLocaleDateString('en-US', dateFormatOptions)}
|
</p>
|
||||||
</p>
|
{/if}
|
||||||
{/if}
|
{#if application.user?.resume}
|
||||||
{#if application.user?.resume}
|
<a
|
||||||
<a
|
class="hyperlink-underline hyperlink-color"
|
||||||
class="hyperlink-underline hyperlink-color"
|
href="/uploads/resumes/{application.user.id}.pdf"
|
||||||
href="/uploads/resumes/{application.user.id}.pdf"
|
target="_blank"
|
||||||
target="_blank"
|
>
|
||||||
>
|
Résumé
|
||||||
Résumé
|
</a>
|
||||||
</a>
|
{/if}
|
||||||
{/if}
|
</div>
|
||||||
</div>
|
<div class="left-border inline-block pl-4">
|
||||||
<div class="left-border inline-block pl-4">
|
<h2>Candidate Statement</h2>
|
||||||
<h2>Candidate Statement</h2>
|
<h3 class="low-emphasis-text">
|
||||||
<h3 class="low-emphasis-text">
|
Why do you believe you are the best fit for this role?
|
||||||
Why do you believe you are the best fit for this role?
|
</h3>
|
||||||
</h3>
|
<p class="whitespace-pre-wrap">{application.candidateStatement}</p>
|
||||||
<p class="whitespace-pre-wrap">{application.candidateStatement}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<button
|
<button
|
||||||
|
|||||||
@ -149,7 +149,7 @@
|
|||||||
<div class="mt-4 flex justify-between">
|
<div class="mt-4 flex justify-between">
|
||||||
<button
|
<button
|
||||||
class="danger-bg-color rounded px-2 py-1"
|
class="danger-bg-color rounded px-2 py-1"
|
||||||
formaction="?/delete&id={data.posting.id}"
|
formaction="?/delete"
|
||||||
type="submit"
|
type="submit"
|
||||||
>Delete posting
|
>Delete posting
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user