Compare commits
5 Commits
c4b635b702
...
0fe4e22c4b
| Author | SHA1 | Date | |
|---|---|---|---|
| 0fe4e22c4b | |||
| e9d1e9a319 | |||
| ff8f375955 | |||
| f731a7fce4 | |||
| f3b5dbbeee |
237
package-lock.json
generated
237
package-lock.json
generated
@ -9,9 +9,11 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@floating-ui/dom": "^1.6.12",
|
"@floating-ui/dom": "^1.6.12",
|
||||||
"pocketbase": "^0.22.1"
|
"pocketbase": "^0.22.1",
|
||||||
|
"uuid": "^11.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@fsouza/prettierd": "^0.25.4",
|
||||||
"@skeletonlabs/skeleton": "^2.10.3",
|
"@skeletonlabs/skeleton": "^2.10.3",
|
||||||
"@skeletonlabs/tw-plugin": "^0.4.0",
|
"@skeletonlabs/tw-plugin": "^0.4.0",
|
||||||
"@sveltejs/adapter-auto": "^3.0.0",
|
"@sveltejs/adapter-auto": "^3.0.0",
|
||||||
@ -19,6 +21,7 @@
|
|||||||
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
||||||
"@tailwindcss/forms": "^0.5.9",
|
"@tailwindcss/forms": "^0.5.9",
|
||||||
"@types/node": "^22.10.2",
|
"@types/node": "^22.10.2",
|
||||||
|
"@types/uuid": "^10.0.0",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"postcss": "^8.4.49",
|
"postcss": "^8.4.49",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
@ -58,6 +61,60 @@
|
|||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@babel/helper-string-parser": {
|
||||||
|
"version": "7.25.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
|
||||||
|
"integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-validator-identifier": {
|
||||||
|
"version": "7.25.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
|
||||||
|
"integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/parser": {
|
||||||
|
"version": "7.26.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz",
|
||||||
|
"integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/types": "^7.26.3"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"parser": "bin/babel-parser.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/types": {
|
||||||
|
"version": "7.26.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz",
|
||||||
|
"integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-string-parser": "^7.25.9",
|
||||||
|
"@babel/helper-validator-identifier": "^7.25.9"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@esbuild/aix-ppc64": {
|
"node_modules/@esbuild/aix-ppc64": {
|
||||||
"version": "0.24.0",
|
"version": "0.24.0",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz",
|
||||||
@ -491,6 +548,24 @@
|
|||||||
"integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==",
|
"integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@fsouza/prettierd": {
|
||||||
|
"version": "0.25.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fsouza/prettierd/-/prettierd-0.25.4.tgz",
|
||||||
|
"integrity": "sha512-y67VtstV11r2lD2ZF8owCPRgUXO4JjrBSAmqehzaaBBSXXzWtLEt3s6VQiHXXSgw0X2BBPUnyy+L2O21S4uiDA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"core_d": "^6.1.0",
|
||||||
|
"prettier": "^3.3.3"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"prettierd": "bin/prettierd"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@babel/parser": "^7.26.2",
|
||||||
|
"@typescript-eslint/typescript-estree": "^8.14.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@isaacs/cliui": {
|
"node_modules/@isaacs/cliui": {
|
||||||
"version": "8.0.2",
|
"version": "8.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||||
@ -1079,6 +1154,75 @@
|
|||||||
"optional": true,
|
"optional": true,
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/uuid": {
|
||||||
|
"version": "10.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
|
||||||
|
"integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@typescript-eslint/types": {
|
||||||
|
"version": "8.18.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.0.tgz",
|
||||||
|
"integrity": "sha512-FNYxgyTCAnFwTrzpBGq+zrnoTO4x0c1CKYY5MuUTzpScqmY5fmsh2o3+57lqdI3NZucBDCzDgdEbIaNfAjAHQA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@typescript-eslint/typescript-estree": {
|
||||||
|
"version": "8.18.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.0.tgz",
|
||||||
|
"integrity": "sha512-rqQgFRu6yPkauz+ms3nQpohwejS8bvgbPyIDq13cgEDbkXt4LH4OkDMT0/fN1RUtzG8e8AKJyDBoocuQh8qNeg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@typescript-eslint/types": "8.18.0",
|
||||||
|
"@typescript-eslint/visitor-keys": "8.18.0",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"fast-glob": "^3.3.2",
|
||||||
|
"is-glob": "^4.0.3",
|
||||||
|
"minimatch": "^9.0.4",
|
||||||
|
"semver": "^7.6.0",
|
||||||
|
"ts-api-utils": "^1.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": ">=4.8.4 <5.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@typescript-eslint/visitor-keys": {
|
||||||
|
"version": "8.18.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.0.tgz",
|
||||||
|
"integrity": "sha512-pCh/qEA8Lb1wVIqNvBke8UaRjJ6wrAWkJO5yyIbs8Yx6TNGYyfNjOo61tLv+WwLvoLPp4BQ8B7AHKijl8NGUfw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@typescript-eslint/types": "8.18.0",
|
||||||
|
"eslint-visitor-keys": "^4.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "8.14.0",
|
"version": "8.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
||||||
@ -1424,6 +1568,16 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/core_d": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/core_d/-/core_d-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-vYgenhJ8CYCj+7LPbPdyFo2u0Doavfbi/vhFpR/BsW9/iUAhuKd+sw2l4CHXhaXIo4/058p2nlsAtbL7iswm5A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"supports-color": "^8.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cross-spawn": {
|
"node_modules/cross-spawn": {
|
||||||
"version": "7.0.6",
|
"version": "7.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||||
@ -1616,6 +1770,20 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/eslint-visitor-keys": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/eslint"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/esm-env": {
|
"node_modules/esm-env": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.1.tgz",
|
||||||
@ -1806,6 +1974,16 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/has-flag": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hasown": {
|
"node_modules/hasown": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||||
@ -3240,6 +3418,20 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/semver": {
|
||||||
|
"version": "7.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
||||||
|
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"optional": true,
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/set-cookie-parser": {
|
"node_modules/set-cookie-parser": {
|
||||||
"version": "2.7.1",
|
"version": "2.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
|
||||||
@ -3435,6 +3627,22 @@
|
|||||||
"node": ">=16 || 14 >=14.17"
|
"node": ">=16 || 14 >=14.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/supports-color": {
|
||||||
|
"version": "8.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
|
||||||
|
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"has-flag": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"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",
|
||||||
@ -3656,6 +3864,20 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ts-api-utils": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz",
|
||||||
|
"integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": ">=4.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ts-interface-checker": {
|
"node_modules/ts-interface-checker": {
|
||||||
"version": "0.1.13",
|
"version": "0.1.13",
|
||||||
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
|
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
|
||||||
@ -3738,6 +3960,19 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/uuid": {
|
||||||
|
"version": "11.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz",
|
||||||
|
"integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==",
|
||||||
|
"funding": [
|
||||||
|
"https://github.com/sponsors/broofa",
|
||||||
|
"https://github.com/sponsors/ctavan"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/esm/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "6.0.3",
|
"version": "6.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-6.0.3.tgz",
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@fsouza/prettierd": "^0.25.4",
|
||||||
"@skeletonlabs/skeleton": "^2.10.3",
|
"@skeletonlabs/skeleton": "^2.10.3",
|
||||||
"@skeletonlabs/tw-plugin": "^0.4.0",
|
"@skeletonlabs/tw-plugin": "^0.4.0",
|
||||||
"@sveltejs/adapter-auto": "^3.0.0",
|
"@sveltejs/adapter-auto": "^3.0.0",
|
||||||
@ -17,6 +18,7 @@
|
|||||||
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
||||||
"@tailwindcss/forms": "^0.5.9",
|
"@tailwindcss/forms": "^0.5.9",
|
||||||
"@types/node": "^22.10.2",
|
"@types/node": "^22.10.2",
|
||||||
|
"@types/uuid": "^10.0.0",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"postcss": "^8.4.49",
|
"postcss": "^8.4.49",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
@ -30,6 +32,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@floating-ui/dom": "^1.6.12",
|
"@floating-ui/dom": "^1.6.12",
|
||||||
"pocketbase": "^0.22.1"
|
"pocketbase": "^0.22.1",
|
||||||
|
"uuid": "^11.0.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
86
src/lib/components/Dropdown.svelte
Normal file
86
src/lib/components/Dropdown.svelte
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { ListBox, ListBoxItem, popup, type PopupSettings } from "@skeletonlabs/skeleton";
|
||||||
|
import type { Snippet } from "svelte";
|
||||||
|
import type { HTMLInputAttributes } from "svelte/elements";
|
||||||
|
import { v4 as uuid } from "uuid";
|
||||||
|
import UserIcon from "./svg/UserIcon.svelte";
|
||||||
|
|
||||||
|
export interface DropdownOption {
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SearchProps extends HTMLInputAttributes {
|
||||||
|
children: Snippet;
|
||||||
|
|
||||||
|
/** Placeholder for the empty input element */
|
||||||
|
placeholder?: string;
|
||||||
|
|
||||||
|
/** Form name of the input element, to reference input data after form submission */
|
||||||
|
name?: string;
|
||||||
|
|
||||||
|
/** Manually set the label width, to align multiple inputs vertically. Supply value in CSS units. */
|
||||||
|
labelwidth?: string;
|
||||||
|
|
||||||
|
/** The variable to bind to the input element. Has to be a [$state] so its value can be updated with the input element's contents. */
|
||||||
|
input_variable: string;
|
||||||
|
|
||||||
|
/** The ID of the popup to trigger. UUID by default. */
|
||||||
|
popup_id?: string;
|
||||||
|
|
||||||
|
/** The [PopupSettings] object for the popup to trigger. */
|
||||||
|
popup_settings?: PopupSettings;
|
||||||
|
|
||||||
|
/** The options this autocomplete component allows to choose from.
|
||||||
|
* Example: [[{ label: "Aston", value: "0" }, { label: "VCARB", value: "1" }]].
|
||||||
|
*/
|
||||||
|
options: DropdownOption[];
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
children,
|
||||||
|
placeholder = "",
|
||||||
|
name = "",
|
||||||
|
labelwidth = "auto",
|
||||||
|
input_variable,
|
||||||
|
popup_id = uuid(),
|
||||||
|
popup_settings = {
|
||||||
|
event: "click",
|
||||||
|
target: popup_id,
|
||||||
|
placement: "bottom",
|
||||||
|
closeQuery: ".listbox-item",
|
||||||
|
},
|
||||||
|
options,
|
||||||
|
...restProps
|
||||||
|
}: SearchProps = $props();
|
||||||
|
|
||||||
|
const get_label = (value: string): string | undefined => {
|
||||||
|
return options.find((o) => o.value === value)?.label;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="input-group input-group-divider grid-cols-[auto_1fr_auto]">
|
||||||
|
<div
|
||||||
|
class="input-group-shim select-none text-nowrap text-neutral-900"
|
||||||
|
style="width: {labelwidth};"
|
||||||
|
>
|
||||||
|
{@render children()}
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
use:popup={popup_settings}
|
||||||
|
type="text"
|
||||||
|
value={get_label(input_variable) ?? placeholder}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div data-popup={popup_id} class="card z-10 w-auto p-2 shadow">
|
||||||
|
<ListBox>
|
||||||
|
{#each options as option}
|
||||||
|
<ListBoxItem bind:group={input_variable} {name} value={option.value}
|
||||||
|
>{option.label}</ListBoxItem
|
||||||
|
>
|
||||||
|
{/each}
|
||||||
|
</ListBox>
|
||||||
|
<div class="bg-surface-100-800-token arrow"></div>
|
||||||
|
</div>
|
||||||
83
src/lib/components/Search.svelte
Normal file
83
src/lib/components/Search.svelte
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import {
|
||||||
|
Autocomplete,
|
||||||
|
popup,
|
||||||
|
type AutocompleteOption,
|
||||||
|
type PopupSettings,
|
||||||
|
} from "@skeletonlabs/skeleton";
|
||||||
|
import type { Snippet } from "svelte";
|
||||||
|
import { v4 as uuid } from "uuid";
|
||||||
|
|
||||||
|
interface SearchProps {
|
||||||
|
children: Snippet;
|
||||||
|
|
||||||
|
/** Placeholder for the empty input element */
|
||||||
|
placeholder?: string;
|
||||||
|
|
||||||
|
/** Form name of the input element, to reference input data after form submission */
|
||||||
|
name?: string;
|
||||||
|
|
||||||
|
/** Manually set the label width, to align multiple inputs vertically. Supply value in CSS units. */
|
||||||
|
labelwidth?: string;
|
||||||
|
|
||||||
|
/** The variable to bind to the input element. Has to be a [$state] so its value can be updated with the input element's contents. */
|
||||||
|
input_variable: string;
|
||||||
|
|
||||||
|
/** The ID of the input element. UUID by default. */
|
||||||
|
input_id?: string;
|
||||||
|
|
||||||
|
/** The ID of the popup to trigger. UUID by default. */
|
||||||
|
popup_id?: string;
|
||||||
|
|
||||||
|
/** The [PopupSettings] object for the popup to trigger. */
|
||||||
|
popup_settings?: PopupSettings;
|
||||||
|
|
||||||
|
/** The event handler updating the [input_variable] after selection. */
|
||||||
|
selection_handler?: (event: CustomEvent<AutocompleteOption<string>>) => void;
|
||||||
|
|
||||||
|
/** The options this autocomplete component allows to choose from.
|
||||||
|
* Example: [[{ label: "Aston", value: "0" }, { label: "VCARB", value: "1" }]].
|
||||||
|
*/
|
||||||
|
options: AutocompleteOption<string, unknown>[];
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
children,
|
||||||
|
placeholder = "",
|
||||||
|
name = "",
|
||||||
|
labelwidth = "auto",
|
||||||
|
input_variable,
|
||||||
|
input_id = uuid(),
|
||||||
|
popup_id = uuid(),
|
||||||
|
popup_settings = {
|
||||||
|
event: "focus-click",
|
||||||
|
target: popup_id,
|
||||||
|
placement: "bottom",
|
||||||
|
},
|
||||||
|
selection_handler = (event: CustomEvent<AutocompleteOption<string>>): void => {
|
||||||
|
input_variable = event.detail.label;
|
||||||
|
},
|
||||||
|
options,
|
||||||
|
}: SearchProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="input-group input-group-divider grid-cols-[auto_1fr_auto]">
|
||||||
|
<div
|
||||||
|
class="input-group-shim select-none text-nowrap text-neutral-900"
|
||||||
|
style="width: {labelwidth};"
|
||||||
|
>
|
||||||
|
{@render children()}
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
id={input_id}
|
||||||
|
type="search"
|
||||||
|
{placeholder}
|
||||||
|
{name}
|
||||||
|
bind:value={input_variable}
|
||||||
|
use:popup={popup_settings}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div data-popup={popup_id} class="card z-10 w-auto p-2 shadow" tabindex="-1">
|
||||||
|
<Autocomplete bind:input={input_variable} {options} on:selection={selection_handler} />
|
||||||
|
</div>
|
||||||
@ -1,9 +1,22 @@
|
|||||||
import Input from "./Input.svelte";
|
import Input from "./Input.svelte";
|
||||||
import Button from "./Button.svelte";
|
import Button from "./Button.svelte";
|
||||||
import Card from "./Card.svelte";
|
import Card from "./Card.svelte";
|
||||||
|
import Search from "./Search.svelte";
|
||||||
|
import Dropdown from "./Dropdown.svelte";
|
||||||
|
// import type DropdownOption from "./Dropdown.svelte";
|
||||||
|
|
||||||
import MenuDrawerIcon from "./svg/MenuDrawerIcon.svelte";
|
import MenuDrawerIcon from "./svg/MenuDrawerIcon.svelte";
|
||||||
import UserIcon from "./svg/UserIcon.svelte";
|
import UserIcon from "./svg/UserIcon.svelte";
|
||||||
import PasswordIcon from "./svg/PasswordIcon.svelte";
|
import PasswordIcon from "./svg/PasswordIcon.svelte";
|
||||||
|
|
||||||
export { Input, Button, Card, MenuDrawerIcon, UserIcon, PasswordIcon };
|
export {
|
||||||
|
Input,
|
||||||
|
Button,
|
||||||
|
Card,
|
||||||
|
Search,
|
||||||
|
Dropdown,
|
||||||
|
// type DropdownOption,
|
||||||
|
MenuDrawerIcon,
|
||||||
|
UserIcon,
|
||||||
|
PasswordIcon,
|
||||||
|
};
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Retrieve an arbitrary object with a matching ID from an Array.
|
* Retrieve an arbitrary object with a matching ID from an Array.
|
||||||
* Supposed to use on collections returned by the PocketBase API.
|
* Supposed to be used on collections returned by the PocketBase API.
|
||||||
*/
|
*/
|
||||||
export const get_by_id = <T extends object>(objects: Array<T>, id: string): T | undefined => {
|
export const get_by_id = <T extends object>(objects: T[], id: string): T | undefined => {
|
||||||
return objects.find((o: T) => ("id" in o ? o.id === id : false));
|
return objects.find((o: T) => ("id" in o ? o.id === id : false));
|
||||||
};
|
};
|
||||||
|
|||||||
@ -38,12 +38,37 @@ export const actions = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
create_driver: async ({ request, locals }) => {
|
create_driver: async ({ request, locals }) => {
|
||||||
|
if (!locals.admin) return { unauthorized: true };
|
||||||
|
|
||||||
|
const data: FormData = form_data_clean(await request.formData());
|
||||||
|
form_data_ensure_keys(data, ["firstname", "lastname", "code", "team", "headshot", "active"]);
|
||||||
|
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
const record: Driver = await locals.pb.collection("drivers").create(data);
|
||||||
|
|
||||||
return { tab: 1 };
|
return { tab: 1 };
|
||||||
},
|
},
|
||||||
|
|
||||||
update_driver: async ({ request, locals }) => {
|
update_driver: async ({ request, locals }) => {
|
||||||
|
if (!locals.admin) return { unauthorized: true };
|
||||||
|
|
||||||
|
const data: FormData = form_data_clean(await request.formData());
|
||||||
|
const id: string = form_data_get_and_remove_id(data);
|
||||||
|
|
||||||
|
const record: Driver = await locals.pb.collection("drivers").update(id, data);
|
||||||
|
|
||||||
return { tab: 1 };
|
return { tab: 1 };
|
||||||
},
|
},
|
||||||
|
|
||||||
delete_driver: async ({ request, locals }) => {
|
delete_driver: async ({ request, locals }) => {
|
||||||
|
if (!locals.admin) return { unauthorized: true };
|
||||||
|
|
||||||
|
const data: FormData = form_data_clean(await request.formData());
|
||||||
|
const id: string = form_data_get_and_remove_id(data);
|
||||||
|
|
||||||
|
await locals.pb.collection("drivers").delete(id);
|
||||||
|
|
||||||
return { tab: 1 };
|
return { tab: 1 };
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -70,8 +95,8 @@ export const actions = {
|
|||||||
|
|
||||||
// This "load" function runs serverside only, as it's located inside +page.server.ts
|
// This "load" function runs serverside only, as it's located inside +page.server.ts
|
||||||
export const load: PageServerLoad = async ({ fetch, locals }) => {
|
export const load: PageServerLoad = async ({ fetch, locals }) => {
|
||||||
const fetch_teams = async (): Promise<Array<Team>> => {
|
const fetch_teams = async (): Promise<Team[]> => {
|
||||||
const teams: Array<Team> = await locals.pb.collection("teams").getFullList({
|
const teams: Team[] = await locals.pb.collection("teams").getFullList({
|
||||||
sort: "+name",
|
sort: "+name",
|
||||||
fetch: fetch,
|
fetch: fetch,
|
||||||
});
|
});
|
||||||
@ -83,8 +108,8 @@ export const load: PageServerLoad = async ({ fetch, locals }) => {
|
|||||||
return teams;
|
return teams;
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetch_drivers = async (): Promise<Array<Driver>> => {
|
const fetch_drivers = async (): Promise<Driver[]> => {
|
||||||
const drivers: Array<Driver> = await locals.pb.collection("drivers").getFullList({
|
const drivers: Driver[] = await locals.pb.collection("drivers").getFullList({
|
||||||
sort: "+lastname",
|
sort: "+lastname",
|
||||||
fetch: fetch,
|
fetch: fetch,
|
||||||
});
|
});
|
||||||
@ -96,11 +121,11 @@ export const load: PageServerLoad = async ({ fetch, locals }) => {
|
|||||||
return drivers;
|
return drivers;
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetch_races = async (): Promise<Array<Race>> => {
|
const fetch_races = async (): Promise<Race[]> => {
|
||||||
return [];
|
return [];
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetch_substitutions = async (): Promise<Array<Substitution>> => {
|
const fetch_substitutions = async (): Promise<Substitution[]> => {
|
||||||
return [];
|
return [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Input, Button, Card } from "$lib/components";
|
import { Input, Button, Card, Search, Dropdown } from "$lib/components";
|
||||||
import { get_image_preview_event_handler } from "$lib/image";
|
import { get_image_preview_event_handler } from "$lib/image";
|
||||||
import { get_by_id } from "$lib/database";
|
import { get_by_id } from "$lib/database";
|
||||||
import type { Team } from "$lib/schema";
|
import type { Driver, Team } from "$lib/schema";
|
||||||
|
|
||||||
import { type PageData, type ActionData } from "./$types";
|
import { type PageData, type ActionData } from "./$types";
|
||||||
import { FileDropzone, Tab, TabGroup } from "@skeletonlabs/skeleton";
|
import { FileDropzone, Tab, TabGroup, type AutocompleteOption } from "@skeletonlabs/skeleton";
|
||||||
|
|
||||||
|
// TODO: Why does this work but import { type DropdownOption } from "$lib/components" does not?
|
||||||
|
import type { DropdownOption } from "$lib/components/Dropdown.svelte";
|
||||||
|
|
||||||
let { data, form }: { data: PageData; form: ActionData } = $props();
|
let { data, form }: { data: PageData; form: ActionData } = $props();
|
||||||
|
|
||||||
@ -14,6 +16,17 @@
|
|||||||
// console.log(`Form returned current_tab=${form.current_tab}`);
|
// console.log(`Form returned current_tab=${form.current_tab}`);
|
||||||
current_tab = form.tab;
|
current_tab = form.tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Maps driver to team: <driver.id, team.id>
|
||||||
|
let create_driver_team_select_value: string = $state("");
|
||||||
|
let update_driver_team_select_values: { [key: string]: string } = $state({});
|
||||||
|
data.drivers.forEach((driver: Driver) => {
|
||||||
|
update_driver_team_select_values[driver.id] = driver.team;
|
||||||
|
});
|
||||||
|
|
||||||
|
const driver_team_select_options: DropdownOption[] = data.teams.map((team: Team) => {
|
||||||
|
return { label: team.name, value: team.id } as DropdownOption;
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
@ -121,8 +134,6 @@
|
|||||||
<!-- Drivers Tab -->
|
<!-- Drivers Tab -->
|
||||||
<!-- Drivers Tab -->
|
<!-- Drivers Tab -->
|
||||||
|
|
||||||
<!-- TODO: Team select -->
|
|
||||||
<!-- TODO: Active switch -->
|
|
||||||
<div class="mt-2 grid grid-cols-1 gap-2 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-6">
|
<div class="mt-2 grid grid-cols-1 gap-2 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-6">
|
||||||
<!-- List all drivers inside the database -->
|
<!-- List all drivers inside the database -->
|
||||||
{#each data.drivers as driver}
|
{#each data.drivers as driver}
|
||||||
@ -155,9 +166,14 @@
|
|||||||
labelwidth="120px"
|
labelwidth="120px"
|
||||||
disabled={!data.admin}>Driver Code</Input
|
disabled={!data.admin}>Driver Code</Input
|
||||||
>
|
>
|
||||||
<Button>
|
|
||||||
<img src={get_by_id<Team>(data.teams, driver.team)?.logo_url} alt="" />
|
<!-- Driver team input -->
|
||||||
</Button>
|
<Dropdown
|
||||||
|
name="team"
|
||||||
|
input_variable={update_driver_team_select_values[driver.id]}
|
||||||
|
labelwidth="120px"
|
||||||
|
options={driver_team_select_options}>Team</Dropdown
|
||||||
|
>
|
||||||
|
|
||||||
<!-- Headshot upload -->
|
<!-- Headshot upload -->
|
||||||
<FileDropzone
|
<FileDropzone
|
||||||
@ -201,7 +217,6 @@
|
|||||||
<Input
|
<Input
|
||||||
id="driver_first_name_create"
|
id="driver_first_name_create"
|
||||||
name="firstname"
|
name="firstname"
|
||||||
placeholder="First Name"
|
|
||||||
labelwidth="120px"
|
labelwidth="120px"
|
||||||
disabled={!data.admin}
|
disabled={!data.admin}
|
||||||
required>First Name</Input
|
required>First Name</Input
|
||||||
@ -209,7 +224,6 @@
|
|||||||
<Input
|
<Input
|
||||||
id="driver_last_name_create"
|
id="driver_last_name_create"
|
||||||
name="lastname"
|
name="lastname"
|
||||||
placeholder="Last Name"
|
|
||||||
labelwidth="120px"
|
labelwidth="120px"
|
||||||
disabled={!data.admin}
|
disabled={!data.admin}
|
||||||
required>Last Name</Input
|
required>Last Name</Input
|
||||||
@ -217,12 +231,22 @@
|
|||||||
<Input
|
<Input
|
||||||
id="driver_code_create"
|
id="driver_code_create"
|
||||||
name="code"
|
name="code"
|
||||||
placeholder="Driver Code"
|
|
||||||
labelwidth="120px"
|
labelwidth="120px"
|
||||||
disabled={!data.admin}
|
disabled={!data.admin}
|
||||||
|
maxlength={3}
|
||||||
|
minlength={3}
|
||||||
required>Driver Code</Input
|
required>Driver Code</Input
|
||||||
>
|
>
|
||||||
|
|
||||||
|
<!-- Driver team input -->
|
||||||
|
<Dropdown
|
||||||
|
input_variable={create_driver_team_select_value}
|
||||||
|
name="team"
|
||||||
|
labelwidth="120px"
|
||||||
|
options={driver_team_select_options}
|
||||||
|
required>Team</Dropdown
|
||||||
|
>
|
||||||
|
|
||||||
<!-- Headshot upload -->
|
<!-- Headshot upload -->
|
||||||
<FileDropzone
|
<FileDropzone
|
||||||
name="headshot"
|
name="headshot"
|
||||||
|
|||||||
Reference in New Issue
Block a user