Compare commits

..
20 Commits
Author SHA1 Message Date
drake 60ad76d48a raise new item and increase height
ci / docker_image (push) Successful in 3m24s
ci / deploy (push) Successful in 1m2s
2026-07-01 13:02:21 -05:00
drake 38fe82731e t to i
ci / docker_image (push) Successful in 2m15s
ci / deploy (push) Successful in 30s
2026-06-30 13:12:56 -05:00
drake 5cce7928ec ordering
ci / docker_image (push) Successful in 2m17s
ci / deploy (push) Successful in 26s
2026-06-30 13:05:01 -05:00
drake 6f375cd990 propagation
ci / docker_image (push) Successful in 2m38s
ci / deploy (push) Successful in 29s
2026-06-30 12:57:04 -05:00
drake 681b15e793 autofocus
ci / docker_image (push) Successful in 2m21s
ci / deploy (push) Successful in 31s
2026-06-30 12:43:04 -05:00
drake 53a75f6573 ux updates
ci / docker_image (push) Successful in 3m0s
ci / deploy (push) Successful in 1m5s
2026-06-30 12:19:06 -05:00
drake eb40444e46 db fixed
ci / docker_image (push) Successful in 2m22s
ci / deploy (push) Successful in 29s
2026-06-29 17:09:32 -05:00
drake 1b179f9d16 downscale pre-ai
ci / docker_image (push) Successful in 2m28s
ci / deploy (push) Successful in 31s
2026-06-29 16:21:40 -05:00
drake 7e6e31aa83 updates before nlc
ci / docker_image (push) Successful in 2m55s
ci / deploy (push) Successful in 29s
2026-06-29 14:43:12 -05:00
drake ee19bd9dea round 2
ci / docker_image (push) Successful in 2m9s
ci / deploy (push) Successful in 25s
2026-04-13 03:45:02 +00:00
drake aa501b4c16 apostrophe
ci / deploy (push) Blocked by required conditions
ci / docker_image (push) Has been cancelled
2026-04-13 03:44:38 +00:00
drake feb80e41ea opacity
ci / docker_image (push) Successful in 2m9s
ci / deploy (push) Successful in 24s
2026-04-12 16:28:39 -05:00
drake d9607afd2c spinner sizing
ci / docker_image (push) Successful in 2m12s
ci / deploy (push) Successful in 28s
2026-04-12 15:43:20 -05:00
drake adaf9534b5 visuals
ci / docker_image (push) Successful in 2m9s
ci / deploy (push) Successful in 25s
2026-04-12 01:24:33 -05:00
drake 8ce4ff1210 unprint
ci / docker_image (push) Successful in 2m10s
ci / deploy (push) Successful in 24s
2026-04-11 23:54:15 -05:00
drake 8c26522ec2 test
ci / docker_image (push) Successful in 2m9s
ci / deploy (push) Successful in 25s
2026-04-11 23:49:59 -05:00
drake 264b44f555 fix stale stuff?
ci / docker_image (push) Successful in 2m7s
ci / deploy (push) Successful in 25s
2026-04-11 23:40:23 -05:00
drake bce9a19776 fix account save
ci / docker_image (push) Successful in 2m17s
ci / deploy (push) Successful in 50s
2026-04-11 09:28:45 -05:00
drake e6e4b068c9 Update .gitea/workflows/ci.yaml
ci / docker_image (push) Successful in 2m18s
ci / deploy (push) Successful in 57s
2026-04-04 22:50:19 +00:00
drake 9c221fa828 sonner
ci / docker_image (push) Failing after 2m25s
ci / deploy (push) Has been skipped
2026-04-04 17:37:54 -05:00
26 changed files with 638 additions and 467 deletions
-3
View File
@@ -12,9 +12,6 @@ jobs:
- name: Check out repository code - name: Check out repository code
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install Docker
run: curl -fsSL https://get.docker.com | sh
- name: Login to Docker Registry - name: Login to Docker Registry
uses: docker/login-action@v3 uses: docker/login-action@v3
with: with:
+255 -149
View File
@@ -8,6 +8,7 @@
"name": "fbla26", "name": "fbla26",
"version": "0.0.1", "version": "0.0.1",
"dependencies": { "dependencies": {
"@rive-app/canvas": "^2.37.1",
"bcrypt": "^6.0.0", "bcrypt": "^6.0.0",
"desm": "^1.3.1", "desm": "^1.3.1",
"dotenv": "^17.2.3", "dotenv": "^17.2.3",
@@ -1392,6 +1393,12 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@rive-app/canvas": {
"version": "2.37.1",
"resolved": "https://registry.npmjs.org/@rive-app/canvas/-/canvas-2.37.1.tgz",
"integrity": "sha512-Uw14b9vXD5g56ttUktlV+mXX1EOpAwqOoMS+DAVSs6EDoeaUYM4bRSKB1glDiOotqjshLSfNihua73mLPp10cQ==",
"license": "MIT"
},
"node_modules/@rollup/plugin-commonjs": { "node_modules/@rollup/plugin-commonjs": {
"version": "28.0.6", "version": "28.0.6",
"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.6.tgz", "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.6.tgz",
@@ -1489,9 +1496,9 @@
} }
}, },
"node_modules/@rollup/rollup-android-arm-eabi": { "node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz",
"integrity": "sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==", "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -1503,9 +1510,9 @@
] ]
}, },
"node_modules/@rollup/rollup-android-arm64": { "node_modules/@rollup/rollup-android-arm64": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz",
"integrity": "sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w==", "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1517,9 +1524,9 @@
] ]
}, },
"node_modules/@rollup/rollup-darwin-arm64": { "node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz",
"integrity": "sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg==", "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1531,9 +1538,9 @@
] ]
}, },
"node_modules/@rollup/rollup-darwin-x64": { "node_modules/@rollup/rollup-darwin-x64": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz",
"integrity": "sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw==", "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1545,9 +1552,9 @@
] ]
}, },
"node_modules/@rollup/rollup-freebsd-arm64": { "node_modules/@rollup/rollup-freebsd-arm64": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz",
"integrity": "sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ==", "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1559,9 +1566,9 @@
] ]
}, },
"node_modules/@rollup/rollup-freebsd-x64": { "node_modules/@rollup/rollup-freebsd-x64": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz",
"integrity": "sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw==", "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1573,13 +1580,16 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm-gnueabihf": { "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz",
"integrity": "sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ==", "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
"dev": true, "dev": true,
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1587,13 +1597,16 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm-musleabihf": { "node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz",
"integrity": "sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q==", "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
"dev": true, "dev": true,
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1601,13 +1614,16 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-gnu": { "node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz",
"integrity": "sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg==", "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true, "dev": true,
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1615,13 +1631,16 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-musl": { "node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz",
"integrity": "sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g==", "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true, "dev": true,
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1629,13 +1648,33 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-loong64-gnu": { "node_modules/@rollup/rollup-linux-loong64-gnu": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz",
"integrity": "sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ==", "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==",
"cpu": [ "cpu": [
"loong64" "loong64"
], ],
"dev": true, "dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-loong64-musl": {
"version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz",
"integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==",
"cpu": [
"loong64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1643,13 +1682,33 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-ppc64-gnu": { "node_modules/@rollup/rollup-linux-ppc64-gnu": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz",
"integrity": "sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g==", "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
"dev": true, "dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-ppc64-musl": {
"version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz",
"integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==",
"cpu": [
"ppc64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1657,13 +1716,16 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-riscv64-gnu": { "node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz",
"integrity": "sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg==", "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
"dev": true, "dev": true,
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1671,13 +1733,16 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-riscv64-musl": { "node_modules/@rollup/rollup-linux-riscv64-musl": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz",
"integrity": "sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA==", "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
"dev": true, "dev": true,
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1685,13 +1750,16 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-s390x-gnu": { "node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz",
"integrity": "sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA==", "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==",
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
"dev": true, "dev": true,
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1699,13 +1767,16 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-x64-gnu": { "node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz",
"integrity": "sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg==", "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true, "dev": true,
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -1713,9 +1784,26 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-x64-musl": { "node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz",
"integrity": "sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw==", "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==",
"cpu": [
"x64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-openbsd-x64": {
"version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz",
"integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1723,13 +1811,13 @@
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "openbsd"
] ]
}, },
"node_modules/@rollup/rollup-openharmony-arm64": { "node_modules/@rollup/rollup-openharmony-arm64": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz",
"integrity": "sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA==", "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1741,9 +1829,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-arm64-msvc": { "node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz",
"integrity": "sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ==", "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1755,9 +1843,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-ia32-msvc": { "node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz",
"integrity": "sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw==", "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@@ -1769,9 +1857,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-x64-gnu": { "node_modules/@rollup/rollup-win32-x64-gnu": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz",
"integrity": "sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ==", "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1783,9 +1871,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-x64-msvc": { "node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.4.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz",
"integrity": "sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w==", "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -2343,6 +2431,12 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/trusted-types": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.46.0", "version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.0.tgz",
@@ -2494,7 +2588,7 @@
"version": "8.46.0", "version": "8.46.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.0.tgz",
"integrity": "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==", "integrity": "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==",
"dev": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2534,9 +2628,9 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
"version": "2.0.2", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -2544,13 +2638,13 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
"version": "9.0.5", "version": "9.0.9",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
"dev": true, "dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"brace-expansion": "^2.0.1" "brace-expansion": "^2.0.2"
}, },
"engines": { "engines": {
"node": ">=16 || 14 >=14.17" "node": ">=16 || 14 >=14.17"
@@ -2798,9 +2892,9 @@
} }
}, },
"node_modules/ajv": { "node_modules/ajv": {
"version": "6.12.6", "version": "6.14.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -2947,9 +3041,9 @@
} }
}, },
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "1.1.12", "version": "1.1.14",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -3295,10 +3389,9 @@
} }
}, },
"node_modules/devalue": { "node_modules/devalue": {
"version": "5.6.2", "version": "5.7.1",
"resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.2.tgz", "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.7.1.tgz",
"integrity": "sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg==", "integrity": "sha512-MUbZ586EgQqdRnC4yDrlod3BEdyvE4TapGYHMW2CiaW+KkkFmWEFqBUaLltEZCGi0iFXCEjRF0OjF0DV2QHjOA==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/dom-accessibility-api": { "node_modules/dom-accessibility-api": {
@@ -3649,12 +3742,20 @@
} }
}, },
"node_modules/esrap": { "node_modules/esrap": {
"version": "2.1.0", "version": "2.2.5",
"resolved": "https://registry.npmjs.org/esrap/-/esrap-2.1.0.tgz", "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.5.tgz",
"integrity": "sha512-yzmPNpl7TBbMRC5Lj2JlJZNPml0tzqoqP5B1JXycNUwtqma9AKCO0M2wHrdgsHcy1WRW7S9rJknAMtByg3usgA==", "integrity": "sha512-/yLB1538mag+dn0wsePTe8C0rDIjUOaJpMs2McodSzmM2msWcZsBSdRtg6HOBt0A/r82BN+Md3pgwSc/uWt2Ig==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15" "@jridgewell/sourcemap-codec": "^1.4.15"
},
"peerDependencies": {
"@typescript-eslint/types": "^8.2.0"
},
"peerDependenciesMeta": {
"@typescript-eslint/types": {
"optional": true
}
} }
}, },
"node_modules/esrecurse": { "node_modules/esrecurse": {
@@ -3926,9 +4027,9 @@
} }
}, },
"node_modules/flatted": { "node_modules/flatted": {
"version": "3.3.3", "version": "3.4.2",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
"integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
@@ -4288,9 +4389,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/js-yaml": { "node_modules/js-yaml": {
"version": "4.1.0", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -4806,9 +4907,9 @@
} }
}, },
"node_modules/micromatch/node_modules/picomatch": { "node_modules/micromatch/node_modules/picomatch": {
"version": "2.3.1", "version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -4854,9 +4955,9 @@
} }
}, },
"node_modules/minimatch": { "node_modules/minimatch": {
"version": "3.1.2", "version": "3.1.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"dev": true, "dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
@@ -5175,9 +5276,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/path-to-regexp": { "node_modules/path-to-regexp": {
"version": "8.3.0", "version": "8.4.2",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz",
"integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==",
"license": "MIT", "license": "MIT",
"funding": { "funding": {
"type": "opencollective", "type": "opencollective",
@@ -5209,9 +5310,9 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/picomatch": { "node_modules/picomatch": {
"version": "4.0.3", "version": "4.0.4",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -5313,9 +5414,9 @@
} }
}, },
"node_modules/postcss-load-config/node_modules/yaml": { "node_modules/postcss-load-config/node_modules/yaml": {
"version": "1.10.2", "version": "1.10.3",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==",
"devOptional": true, "devOptional": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
@@ -5579,9 +5680,9 @@
} }
}, },
"node_modules/qs": { "node_modules/qs": {
"version": "6.14.1", "version": "6.15.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz",
"integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"side-channel": "^1.1.0" "side-channel": "^1.1.0"
@@ -5702,9 +5803,9 @@
} }
}, },
"node_modules/rollup": { "node_modules/rollup": {
"version": "4.52.4", "version": "4.60.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.4.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz",
"integrity": "sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==", "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -5718,28 +5819,31 @@
"npm": ">=8.0.0" "npm": ">=8.0.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.52.4", "@rollup/rollup-android-arm-eabi": "4.60.1",
"@rollup/rollup-android-arm64": "4.52.4", "@rollup/rollup-android-arm64": "4.60.1",
"@rollup/rollup-darwin-arm64": "4.52.4", "@rollup/rollup-darwin-arm64": "4.60.1",
"@rollup/rollup-darwin-x64": "4.52.4", "@rollup/rollup-darwin-x64": "4.60.1",
"@rollup/rollup-freebsd-arm64": "4.52.4", "@rollup/rollup-freebsd-arm64": "4.60.1",
"@rollup/rollup-freebsd-x64": "4.52.4", "@rollup/rollup-freebsd-x64": "4.60.1",
"@rollup/rollup-linux-arm-gnueabihf": "4.52.4", "@rollup/rollup-linux-arm-gnueabihf": "4.60.1",
"@rollup/rollup-linux-arm-musleabihf": "4.52.4", "@rollup/rollup-linux-arm-musleabihf": "4.60.1",
"@rollup/rollup-linux-arm64-gnu": "4.52.4", "@rollup/rollup-linux-arm64-gnu": "4.60.1",
"@rollup/rollup-linux-arm64-musl": "4.52.4", "@rollup/rollup-linux-arm64-musl": "4.60.1",
"@rollup/rollup-linux-loong64-gnu": "4.52.4", "@rollup/rollup-linux-loong64-gnu": "4.60.1",
"@rollup/rollup-linux-ppc64-gnu": "4.52.4", "@rollup/rollup-linux-loong64-musl": "4.60.1",
"@rollup/rollup-linux-riscv64-gnu": "4.52.4", "@rollup/rollup-linux-ppc64-gnu": "4.60.1",
"@rollup/rollup-linux-riscv64-musl": "4.52.4", "@rollup/rollup-linux-ppc64-musl": "4.60.1",
"@rollup/rollup-linux-s390x-gnu": "4.52.4", "@rollup/rollup-linux-riscv64-gnu": "4.60.1",
"@rollup/rollup-linux-x64-gnu": "4.52.4", "@rollup/rollup-linux-riscv64-musl": "4.60.1",
"@rollup/rollup-linux-x64-musl": "4.52.4", "@rollup/rollup-linux-s390x-gnu": "4.60.1",
"@rollup/rollup-openharmony-arm64": "4.52.4", "@rollup/rollup-linux-x64-gnu": "4.60.1",
"@rollup/rollup-win32-arm64-msvc": "4.52.4", "@rollup/rollup-linux-x64-musl": "4.60.1",
"@rollup/rollup-win32-ia32-msvc": "4.52.4", "@rollup/rollup-openbsd-x64": "4.60.1",
"@rollup/rollup-win32-x64-gnu": "4.52.4", "@rollup/rollup-openharmony-arm64": "4.60.1",
"@rollup/rollup-win32-x64-msvc": "4.52.4", "@rollup/rollup-win32-arm64-msvc": "4.60.1",
"@rollup/rollup-win32-ia32-msvc": "4.60.1",
"@rollup/rollup-win32-x64-gnu": "4.60.1",
"@rollup/rollup-win32-x64-msvc": "4.60.1",
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
} }
}, },
@@ -6180,21 +6284,23 @@
} }
}, },
"node_modules/svelte": { "node_modules/svelte": {
"version": "5.39.11", "version": "5.55.3",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.39.11.tgz", "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.55.3.tgz",
"integrity": "sha512-8MxWVm2+3YwrFbPaxOlT1bbMi6OTenrAgks6soZfiaS8Fptk4EVyRIFhJc3RpO264EeSNwgjWAdki0ufg4zkGw==", "integrity": "sha512-dS1N+i3bA1v+c4UDb750MlN5vCO82G6vxh8HeTsPsTdJ1BLsN1zxSyDlIdBBqUjqZ/BxEwM8UrFf98aaoVnZFQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/remapping": "^2.3.4", "@jridgewell/remapping": "^2.3.4",
"@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/sourcemap-codec": "^1.5.0",
"@sveltejs/acorn-typescript": "^1.0.5", "@sveltejs/acorn-typescript": "^1.0.5",
"@types/estree": "^1.0.5", "@types/estree": "^1.0.5",
"@types/trusted-types": "^2.0.7",
"acorn": "^8.12.1", "acorn": "^8.12.1",
"aria-query": "^5.3.1", "aria-query": "5.3.1",
"axobject-query": "^4.1.0", "axobject-query": "^4.1.0",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"devalue": "^5.6.4",
"esm-env": "^1.2.1", "esm-env": "^1.2.1",
"esrap": "^2.1.0", "esrap": "^2.2.4",
"is-reference": "^3.0.3", "is-reference": "^3.0.3",
"locate-character": "^3.0.0", "locate-character": "^3.0.0",
"magic-string": "^0.30.11", "magic-string": "^0.30.11",
@@ -6364,9 +6470,9 @@
} }
}, },
"node_modules/svelte/node_modules/aria-query": { "node_modules/svelte/node_modules/aria-query": {
"version": "5.3.2", "version": "5.3.1",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz",
"integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", "integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==",
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
@@ -6441,11 +6547,11 @@
} }
}, },
"node_modules/tar": { "node_modules/tar": {
"version": "7.5.1", "version": "7.5.13",
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.1.tgz", "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.13.tgz",
"integrity": "sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g==", "integrity": "sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng==",
"dev": true, "dev": true,
"license": "ISC", "license": "BlueOak-1.0.0",
"dependencies": { "dependencies": {
"@isaacs/fs-minipass": "^4.0.0", "@isaacs/fs-minipass": "^4.0.0",
"chownr": "^3.0.0", "chownr": "^3.0.0",
+2 -1
View File
@@ -64,6 +64,7 @@
"postgres": "^3.4.7", "postgres": "^3.4.7",
"sharp": "^0.34.5", "sharp": "^0.34.5",
"svelte-preprocess": "^6.0.3", "svelte-preprocess": "^6.0.3",
"valibot": "^1.2.0" "valibot": "^1.2.0",
"@rive-app/canvas": "^2.37.1"
} }
} }
+38 -31
View File
@@ -8,20 +8,22 @@
--radius: 0.65rem; --radius: 0.65rem;
--background: oklch(1 0 0); --background: oklch(1 0 0);
--foreground: oklch(0.141 0.005 285.823); --foreground: oklch(0.141 0.005 285.823);
--card: oklch(1 0 0); --card: oklch(0.95 0 0);
--card-foreground: oklch(0.141 0.005 285.823); --card-foreground: oklch(0.141 0.005 285.823);
--popover: oklch(1 0 0); --popover: oklch(1 0 0);
--popover-foreground: oklch(0.141 0.005 285.823); --popover-foreground: oklch(0.141 0.005 285.823);
--primary: oklch(0.5852 0.25 292.717); --primary: oklch(0.5852 0.25 292.717);
--primary-foreground: oklch(0.969 0.016 293.756); --primary-foreground: oklch(0.969 0.016 293.756);
--dull-primary: oklch(0.8225 0.0927 293.01);
--dull-primary-foreground: oklch(0.0 0.016 293.756);
--secondary: oklch(0.967 0.001 286.375); --secondary: oklch(0.967 0.001 286.375);
--secondary-foreground: oklch(0.21 0.006 285.885); --secondary-foreground: oklch(0.21 0.006 285.885);
--muted: oklch(0.967 0.001 286.375); --muted: oklch(0.967 0.001 286.375);
--muted-foreground: oklch(0.552 0.016 285.938); --muted-foreground: oklch(0.502 0.016 285.938);
--accent: oklch(0.967 0.001 286.375); --accent: oklch(0.967 0.001 286.375);
--accent-foreground: oklch(0.21 0.006 285.885); --accent-foreground: oklch(0.21 0.006 285.885);
--destructive: oklch(0.577 0.245 27.325); --destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.92 0.004 286.32); --border: oklch(0.9 0.004 286.32);
--input: oklch(0.92 0.004 286.32); --input: oklch(0.92 0.004 286.32);
--ring: oklch(0.606 0.25 292.717); --ring: oklch(0.606 0.25 292.717);
--chart-1: oklch(0.646 0.222 41.116); --chart-1: oklch(0.646 0.222 41.116);
@@ -37,10 +39,10 @@
--sidebar-accent-foreground: oklch(0.21 0.006 285.885); --sidebar-accent-foreground: oklch(0.21 0.006 285.885);
--sidebar-border: oklch(0.92 0.004 286.32); --sidebar-border: oklch(0.92 0.004 286.32);
--sidebar-ring: oklch(0.606 0.25 292.717); --sidebar-ring: oklch(0.606 0.25 292.717);
--warning: oklch(0.84 0.16 84); --warning: oklch(0.6 0.16 84);
--error: oklch(0.577 0.245 27.325); --error: oklch(0.577 0.245 27.325);
--positive: oklch(0.5 0.2067 147.18); --positive: oklch(0.5 0.2067 147.18);
--action: oklch(0.5852 0.2263 260.47); --action: oklch(0.4852 0.2263 260.47);
} }
.dark { .dark {
@@ -50,12 +52,15 @@
--card-foreground: oklch(0.985 0 0); --card-foreground: oklch(0.985 0 0);
--popover: oklch(0.21 0.006 285.885); --popover: oklch(0.21 0.006 285.885);
--popover-foreground: oklch(0.985 0 0); --popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.541 0.281 293.009); --primary: oklch(0.5 0.331 293.009);
--primary-foreground: oklch(0.969 0.016 293.756); --primary-foreground: oklch(0.0 0.016 293.756);
--dull-primary: oklch(0.3 0.281 293.009);
--dull-primary-foreground: oklch(0.969 0.016 293.756);
/*--primary-foreground: oklch(0.969 0.016 293.756);*/
--secondary: oklch(0.274 0.006 286.033); --secondary: oklch(0.274 0.006 286.033);
--secondary-foreground: oklch(0.985 0 0); --secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.274 0.006 286.033); --muted: oklch(0.274 0.006 286.033);
--muted-foreground: oklch(0.705 0.015 286.067); --muted-foreground: oklch(0.655 0.015 286.067);
--accent: oklch(0.274 0.006 286.033); --accent: oklch(0.274 0.006 286.033);
--accent-foreground: oklch(0.985 0 0); --accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216); --destructive: oklch(0.704 0.191 22.216);
@@ -78,7 +83,7 @@
--warning: oklch(0.84 0.16 84); --warning: oklch(0.84 0.16 84);
--error: oklch(0.704 0.191 22.216); --error: oklch(0.704 0.191 22.216);
--positive: oklch(0.7522 0.2067 147.18); --positive: oklch(0.7522 0.2067 147.18);
--action: oklch(0.6098 0.1872 260.47); --action: oklch(0.7098 0.1872 260.47);
} }
@theme inline { @theme inline {
@@ -94,6 +99,8 @@
--color-popover-foreground: var(--popover-foreground); --color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary); --color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground); --color-primary-foreground: var(--primary-foreground);
--color-dull-primary: var(--dull-primary);
--color-dull-primary-foreground: var(--dull-primary-foreground);
--color-secondary: var(--secondary); --color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground); --color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted); --color-muted: var(--muted);
@@ -134,63 +141,63 @@
} }
@custom-variant data-open { @custom-variant data-open {
&:where([data-state="open"]), &:where([data-open]:not([data-open="false"])) { &:where([data-state="open"]), &:where([data-open]:not([data-open="false"])) {
@slot; @slot;
} }
} }
@custom-variant data-closed { @custom-variant data-closed {
&:where([data-state="closed"]), &:where([data-closed]:not([data-closed="false"])) { &:where([data-state="closed"]), &:where([data-closed]:not([data-closed="false"])) {
@slot; @slot;
} }
} }
@custom-variant data-checked { @custom-variant data-checked {
&:where([data-state="checked"]), &:where([data-checked]:not([data-checked="false"])) { &:where([data-state="checked"]), &:where([data-checked]:not([data-checked="false"])) {
@slot; @slot;
} }
} }
@custom-variant data-unchecked { @custom-variant data-unchecked {
&:where([data-state="unchecked"]), &:where([data-unchecked]:not([data-unchecked="false"])) { &:where([data-state="unchecked"]), &:where([data-unchecked]:not([data-unchecked="false"])) {
@slot; @slot;
} }
} }
@custom-variant data-selected { @custom-variant data-selected {
&:where([data-selected]) { &:where([data-selected]) {
@slot; @slot;
} }
} }
@custom-variant data-disabled { @custom-variant data-disabled {
&:where([data-disabled="true"]), &:where([data-disabled]:not([data-disabled="false"])) { &:where([data-disabled="true"]), &:where([data-disabled]:not([data-disabled="false"])) {
@slot; @slot;
} }
} }
@custom-variant data-active { @custom-variant data-active {
&:where([data-state="active"]), &:where([data-active]:not([data-active="false"])) { &:where([data-state="active"]), &:where([data-active]:not([data-active="false"])) {
@slot; @slot;
} }
} }
@custom-variant data-horizontal { @custom-variant data-horizontal {
&:where([data-orientation="horizontal"]) { &:where([data-orientation="horizontal"]) {
@slot; @slot;
} }
} }
@custom-variant data-vertical { @custom-variant data-vertical {
&:where([data-orientation="vertical"]) { &:where([data-orientation="vertical"]) {
@slot; @slot;
} }
} }
@utility no-scrollbar { @utility no-scrollbar {
-ms-overflow-style: none; -ms-overflow-style: none;
scrollbar-width: none; scrollbar-width: none;
&::-webkit-scrollbar { &::-webkit-scrollbar {
display: none; display: none;
} }
} }
+3
View File
@@ -64,6 +64,9 @@ export async function login(email: string, password: string): Promise<User> {
SELECT * FROM users SELECT * FROM users
WHERE email = ${email}; WHERE email = ${email};
`; `;
if (typeof user.settings == 'string') {
user.settings = JSON.parse(user.settings);
}
if (user) { if (user) {
if (await bcrypt.compare(password, user.passwordHash!)) { if (await bcrypt.compare(password, user.passwordHash!)) {
delete user.passwordHash; delete user.passwordHash;
@@ -15,7 +15,7 @@
</script> </script>
<Dialog.Root bind:open> <Dialog.Root bind:open>
<Dialog.Content> <Dialog.Content onOpenAutoFocus={(e) => e.preventDefault()}>
<Dialog.Header> <Dialog.Header>
<Dialog.Title>Claim Item</Dialog.Title> <Dialog.Title>Claim Item</Dialog.Title>
<Dialog.Description> <Dialog.Description>
@@ -44,10 +44,7 @@
<div class="inline-block"> <div class="inline-block">
<div class="flex-1">{item?.description}</div> <div class="flex-1">{item?.description}</div>
{#if item?.foundLocation} {#if item?.foundLocation}
<div class="mt-2"> <span class="mt-2"><strong class="mr-1">Found at:</strong> {item.foundLocation}</span>
<LocationIcon class="float-left mr-1" size={24} />
<div>{item?.foundLocation}</div>
</div>
{/if} {/if}
</div> </div>
</div> </div>
@@ -117,10 +117,13 @@
<Dialog.Footer class="mt-4"> <Dialog.Footer class="mt-4">
<div class="flex justify-between w-full"> <div class="flex justify-between w-full">
<Button variant="destructive" <Dialog.Close
onclick={() => {approveDenyItem({id: item?.id || 0, approved: false}); invalidateAll();}}> type="button"
class={buttonVariants({ variant: "destructive" })}
onclick={async () => {await approveDenyItem({ id: item?.id || 0, approved: false }); await invalidateAll(); }}
>
Delete Delete
</Button> </Dialog.Close>
<div> <div>
@@ -16,7 +16,7 @@
</script> </script>
<Dialog.Root bind:open> <Dialog.Root bind:open>
<Dialog.Content> <Dialog.Content onOpenAutoFocus={(e) => e.preventDefault()}>
<Dialog.Header> <Dialog.Header>
<Dialog.Title>Item Inquiry</Dialog.Title> <Dialog.Title>Item Inquiry</Dialog.Title>
<Dialog.Description> <Dialog.Description>
@@ -45,10 +45,7 @@
<div class="inline-block"> <div class="inline-block">
<div class="flex-1">{item?.description}</div> <div class="flex-1">{item?.description}</div>
{#if item?.foundLocation} {#if item?.foundLocation}
<div class="mt-2"> <span class="mt-2 flex"><strong class="mr-1">Found at:</strong> {item.foundLocation}</span>
<LocationIcon class="float-left mr-1" size={24} />
<div>{item?.foundLocation}</div>
</div>
{/if} {/if}
</div> </div>
</div> </div>
+31 -28
View File
@@ -20,24 +20,30 @@
export let item: Item = <Item>{}; export let item: Item = <Item>{};
export let user: User | null = null; export let user: User | null = null;
// export let admin = false;
export let editCallback: (item: Item) => void; export let editCallback: (item: Item) => void;
export let inquireCallback: (item: Item) => void; export let inquireCallback: (item: Item) => void;
export let claimCallback: (item: Item) => void; export let claimCallback: (item: Item) => void;
let timeSincePosted: number | string = (new Date().getTime() - item.foundDate.getTime()) / 1000 / 60 / 60 / 24; // days // Normalize the foundDate in case it was serialized (string) in prod builds
// if (timeSincePosted < 1) { // (SSR/JSON serialization often turns Date objects into strings).
// timeSincePosted = '<1'; const foundDateObj: Date = item?.foundDate instanceof Date
// } else { ? item.foundDate
// timeSincePosted = Math.round(timeSincePosted); : new Date(item?.foundDate);
// }
// Compute days since posted as a number (always a number, fall back to 0 on invalid date)
let timeSincePosted: number = (() => {
const t = foundDateObj?.getTime?.();
if (!t || Number.isNaN(t)) return 0;
return (Date.now() - t) / 1000 / 60 / 60 / 24; // days (float)
})();
// If you want to round/display differently you can do that in the template.
</script> </script>
<div <div
class="h-full bg-card text-card-foreground flex flex-col gap-2 rounded-xl border shadow-sm max-w-sm overflow-hidden min-w-2xs"> class="text-left h-full bg-card text-card-foreground flex flex-col gap-2 rounded-xl border shadow-sm max-w-sm overflow-hidden min-w-2xs" onclick={() => {claimCallback(item)}}>
{#if item.image} {#if item.image}
<img src="https://fbla26.marinodev.com/uploads/{item.id}.jpg" class="object-cover min-h-48 max-h-48" <img src="https://fbla26.marinodev.com/uploads/{item.id}.jpg" class="object-cover min-h-56 max-h-56"
alt="Lost item"> alt="Lost item">
{:else} {:else}
<div class="min-h-48 w-full bg-accent flex flex-col justify-center"> <div class="min-h-48 w-full bg-accent flex flex-col justify-center">
@@ -59,13 +65,13 @@
<Tooltip.Trigger <Tooltip.Trigger
> >
<Badge variant="outline" <Badge variant="outline"
class="inline-block {user?.settings !== null && user?.settings !== undefined && timeSincePosted >= user.settings.staleItemDays ? 'text-warning' : ''}">{timeSincePosted < 1 ? "<1" : Math.round(timeSincePosted)} class="inline-block {user?.settings?.staleItemDays !== undefined && timeSincePosted >= user.settings.staleItemDays ? 'text-warning' : ''}">{timeSincePosted < 1 ? "<1" : Math.round(timeSincePosted)}
day{(timeSincePosted <= 1) ? '' : 's'} ago day{(timeSincePosted <= 1) ? '' : 's'} ago
</Badge> </Badge>
</Tooltip.Trigger </Tooltip.Trigger
> >
<Tooltip.Content> <Tooltip.Content>
<p>{item.foundDate.toLocaleDateString('en-US', dateFormatOptions)}</p> <p>{foundDateObj.toLocaleDateString('en-US', dateFormatOptions)}</p>
</Tooltip.Content> </Tooltip.Content>
</Tooltip.Root> </Tooltip.Root>
</Tooltip.Provider> </Tooltip.Provider>
@@ -77,10 +83,7 @@
<Tooltip.Provider> <Tooltip.Provider>
<Tooltip.Root> <Tooltip.Root>
<Tooltip.Trigger> <Tooltip.Trigger>
<div class="mt-2 text-muted-foreground flex"> <span class="mt-2 flex"><strong class="mr-1">Found at:</strong> {item.foundLocation}</span>
<LocationIcon class="float-left mr-1" size={24} />
<div>{item.foundLocation}</div>
</div>
</Tooltip.Trigger </Tooltip.Trigger
> >
<Tooltip.Content> <Tooltip.Content>
@@ -95,34 +98,34 @@
{#if item.approvedDate === null} {#if item.approvedDate === null}
<Button variant="ghost" class="text-positive" <Button variant="ghost" class="text-positive"
onclick={async () => {await approveDenyItem({id: item.id, approved: true}); onclick={async (e) => {e.stopPropagation(); await approveDenyItem({id: item.id, approved: true});
invalidateAll()}}> await invalidateAll()}}>
<CheckIcon /> <CheckIcon />
Approve Approve
</Button> </Button>
<Button variant="ghost" class="text-destructive" <Button variant="ghost" class="text-destructive"
onclick={async () => {await approveDenyItem({id: item.id, approved: false}); onclick={async (e) => {e.stopPropagation(); await approveDenyItem({id: item.id, approved: false});
invalidateAll()}}> await invalidateAll()}}>
<XIcon /> <XIcon />
Deny Deny
</Button> </Button>
{/if} {/if}
{#if item.claimedDate === null} {#if item.claimedDate === null}
<Button variant="ghost" class="text-action" <Button variant="ghost" class="text-action"
onclick={() => {editCallback(item)}}> onclick={(e) => {e.stopPropagation(); editCallback(item)}}>
<PencilIcon /> <PencilIcon />
{!item.approvedDate ? 'Edit' : 'Manage'} {!item.approvedDate ? 'Edit' : 'Manage'}
</Button> </Button>
{:else} {:else}
<Button variant="ghost" class="text-destructive" <Button variant="ghost" class="text-destructive"
onclick={async () => {await approveDenyItem({id: item.id, approved: false}); onclick={async (e) => {e.stopPropagation(); await approveDenyItem({id: item.id, approved: false});
invalidateAll()}}> await invalidateAll()}}>
<TrashIcon /> <TrashIcon />
Delete Delete
</Button> </Button>
<Button variant="ghost" class="text-action" <Button variant="ghost" class="text-action"
onclick={async () => {await restoreClaimedItem(item.id); onclick={async (e) => {e.stopPropagation(); await restoreClaimedItem(item.id);
invalidateAll()}}> await invalidateAll()}}>
<ArchiveRestoreIcon /> <ArchiveRestoreIcon />
Restore Restore
</Button> </Button>
@@ -131,13 +134,13 @@
</div> </div>
{:else} {:else}
<div class="mt-2 justify-between flex"> <div class="mt-2 justify-between flex">
<Button variant="ghost" class="text-action" <Button variant="ghost" class="text-action z-10"
onclick={() => {inquireCallback(item)}}> onclick={(e) => {e.stopPropagation(); inquireCallback(item)}}>
<NotebookPenIcon /> <NotebookPenIcon />
Inquire Inquire
</Button> </Button>
<Button variant="ghost" class="text-primary" <Button variant="ghost" class="text-primary z-10"
onclick={() => {claimCallback(item)}}> onclick={(e) => {e.stopPropagation(); claimCallback(item)}}>
<StarIcon /> <StarIcon />
Claim Claim
</Button> </Button>
@@ -0,0 +1,42 @@
<script>
import { onMount, onDestroy } from 'svelte';
export let src = '/mdev_triangle_loading.riv';
export let stateMachine = null;
export let size = 120;
export let classes = '';
let canvas;
let riveInstance;
onMount(async () => {
if (typeof window === 'undefined') return;
const mod = await import('@rive-app/canvas');
// Handle BOTH CJS and ESM shapes safely
const Rive = mod?.Rive || mod?.default?.Rive || mod?.default;
if (!Rive) {
console.error('Rive failed to load:', mod);
return;
}
riveInstance = new Rive({
src,
canvas,
autoplay: true,
// stateMachines: stateMachine || undefined,
onLoad: () => {
riveInstance.resizeDrawingSurfaceToCanvas();
}
});
});
onDestroy(() => {
riveInstance?.cleanup?.();
});
</script>
<canvas bind:this={canvas} class={classes} />
@@ -6,7 +6,7 @@
import { Label } from '$lib/components/ui/label'; import { Label } from '$lib/components/ui/label';
import * as Field from '$lib/components/ui/field'; import * as Field from '$lib/components/ui/field';
import { fileToBase64 } from '$lib/shared'; import { fileToBase64 } from '$lib/shared';
import LoadingSpinner from './loading-spinner.svelte';
import ImageUpload from '$lib/components/custom/image-upload/image-upload.svelte'; import ImageUpload from '$lib/components/custom/image-upload/image-upload.svelte';
import { genDescription } from '$lib/db/items.remote'; import { genDescription } from '$lib/db/items.remote';
import { EMAIL_REGEX_STRING } from '$lib/consts'; import { EMAIL_REGEX_STRING } from '$lib/consts';
@@ -17,12 +17,47 @@
let description: string | undefined = $state(); let description: string | undefined = $state();
let isGenerating = $state(false); let isGenerating = $state(false);
async function resizeImage(
file: File,
maxWidth = 300,
maxHeight = 300,
quality = 0.8
): Promise<File> {
const bitmap = await createImageBitmap(file);
let { width, height } = bitmap;
const scale = Math.min(maxWidth / width, maxHeight / height, 1);
width = Math.round(width * scale);
height = Math.round(height * scale);
const canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d")!;
ctx.drawImage(bitmap, 0, 0, width, height);
const blob = await new Promise<Blob>((resolve) =>
canvas.toBlob((blob) => resolve(blob!), "image/jpeg", quality)
);
return new File([blob], file.name, {
type: "image/jpeg",
lastModified: Date.now()
});
}
async function onSelect(file: File) { async function onSelect(file: File) {
isGenerating = true; isGenerating = true;
const base64 = await fileToBase64(file); const resized = await resizeImage(file, 300, 300, 0.7);
const base64 = await fileToBase64(resized);
description = await genDescription(base64); description = await genDescription(base64);
isGenerating = false; isGenerating = false;
} }
@@ -30,7 +65,7 @@
</script> </script>
<Dialog.Root bind:open> <Dialog.Root bind:open>
<Dialog.Content> <Dialog.Content onOpenAutoFocus={(e) => e.preventDefault()}>
<Dialog.Header> <Dialog.Header>
<Dialog.Title>Submit Found Item</Dialog.Title> <Dialog.Title>Submit Found Item</Dialog.Title>
<Dialog.Description> <Dialog.Description>
@@ -69,7 +104,11 @@
/> />
</Field.Field> </Field.Field>
<RadioGroup.Root name="location" bind:value={itemLocation}>
<RadioGroup.Root name="location" bind:value={itemLocation} required>
<Field.Label for="location">
Where is it? <span class="text-error">*</span>
</Field.Label>
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<RadioGroup.Item value="finderPossession" id="finderPossession" /> <RadioGroup.Item value="finderPossession" id="finderPossession" />
<Label for="finderPossession"> <Label for="finderPossession">
@@ -115,8 +154,11 @@
</Dialog.Root> </Dialog.Root>
{#if isGenerating} <div
<div class="fixed inset-0 bg-black/75 z-999999 w-screen h-screen justify-center items-center flex"> class="fixed inset-0 bg-black/85 z-[999999] w-screen h-screen flex justify-center items-center transition-opacity duration-150 flex-col md:flex-row"
<p class="text-6xl text-primary">Loading...</p> class:opacity-0={!isGenerating}
</div> class:pointer-events-none={!isGenerating}
{/if} >
<LoadingSpinner classes="w-28 md:w-48 mb-2 md:-mb-4" />
<p class="text-4xl md:text-6xl text-white">Loading...</p>
</div>
+2 -1
View File
@@ -7,7 +7,8 @@
base: 'focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\'size-\'])]:size-4', base: 'focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\'size-\'])]:size-4',
variants: { variants: {
variant: { variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90 shadow-xs', default: 'bg-dull-primary text-dull-primary-foreground hover:bg-primary/90 shadow-xs',
// dull_default: 'bg-dull-primary text-dull-primary-foreground hover:bg-dull-primary/90 shadow-xs',
destructive: destructive:
'bg-destructive hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60 text-white shadow-xs', 'bg-destructive hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60 text-white shadow-xs',
outline: outline:
+1
View File
@@ -0,0 +1 @@
export { default as Toaster } from "./sonner.svelte";
@@ -0,0 +1,34 @@
<script lang="ts">
import { Toaster as Sonner, type ToasterProps as SonnerProps } from "svelte-sonner";
import { mode } from "mode-watcher";
import Loader2Icon from '@lucide/svelte/icons/loader-2';
import CircleCheckIcon from '@lucide/svelte/icons/circle-check';
import OctagonXIcon from '@lucide/svelte/icons/octagon-x';
import InfoIcon from '@lucide/svelte/icons/info';
import TriangleAlertIcon from '@lucide/svelte/icons/triangle-alert';
let { ...restProps }: SonnerProps = $props();
</script>
<Sonner
theme={mode.current}
class="toaster group"
style="--normal-bg: var(--color-popover); --normal-text: var(--color-popover-foreground); --normal-border: var(--color-border);"
{...restProps}
>
{#snippet loadingIcon()}
<Loader2Icon class="size-4 animate-spin" />
{/snippet}
{#snippet successIcon()}
<CircleCheckIcon class="size-4" />
{/snippet}
{#snippet errorIcon()}
<OctagonXIcon class="size-4" />
{/snippet}
{#snippet infoIcon()}
<InfoIcon class="size-4" />
{/snippet}
{#snippet warningIcon()}
<TriangleAlertIcon class="size-4" />
{/snippet}
</Sonner>
+1 -1
View File
@@ -17,7 +17,7 @@ export const genDescription = command(v.string(), async (data) => {
const outputBuffer = await image const outputBuffer = await image
.rotate() .rotate()
.resize({ fit: 'outside', height: 300, width: 300 }) .resize({ fit: 'outside', height: 300, width: 300 })
.jpeg({ quality: 80 }) // adjust if needed .jpeg({ quality: 70 }) // adjust if needed
.toBuffer(); .toBuffer();
const description = await LLMDescribe( const description = await LLMDescribe(
+1 -1
View File
@@ -33,7 +33,7 @@ export async function LLMDescribe(imageData: string) {
); );
if (!res.ok) { if (!res.ok) {
console.log(await res.text()); console.error(await res.text());
// process.exit(1); // process.exit(1);
} }
+142 -46
View File
@@ -17,7 +17,7 @@
Westuffinder Westuffinder
</h1> </h1>
<p class="mx-auto mt-6 max-w-2xl text-lg text-muted-foreground"> <p class="mx-auto mt-6 max-w-2xl text-lg text-muted-foreground">
Lost something at school? Found something that isnt yours? Lost something at school? Found something that isn't yours?
This is the official place to reconnect items with their owners. This is the official place to reconnect items with their owners.
</p> </p>
@@ -56,69 +56,165 @@
</div> </div>
</section> </section>
<section class="mx-auto max-w-6xl px-6 py-20" aria-labelledby="info-cards-heading"> <!-- FEATURES -->
<h2 id="info-cards-heading" class="sr-only">Information</h2> <section class="mx-auto max-w-6xl px-6 py-12" aria-labelledby="features-heading">
<div class="grid gap-8 md:grid-cols-3"> <h2 id="features-heading" class="text-2xl font-semibold text-center mb-12">
<Card> Everything you need to get items back fast
<CardHeader> </h2>
<CardTitle id="found-item-heading">Found an Item?</CardTitle>
</CardHeader> <div class="grid gap-12 md:grid-cols-2 items-center">
<CardContent <!-- Left visual / emphasis block -->
class="space-y-3 text-sm text-muted-foreground" <div class="space-y-6">
aria-labelledby="found-item-heading" <div class="rounded-2xl border bg-muted/30 p-6">
> <h3 class="font-semibold text-lg">Built for speed</h3>
<p> <p class="text-sm text-muted-foreground mt-2">
Turn it in digitally in less than a minute. Add a description and where you found it. Report and browse items in seconds. The entire flow is designed to reduce friction.
</p> </p>
<Button </div>
class="mt-2 w-full"
variant="outline" <div class="rounded-2xl border bg-muted/20 p-6">
onclick={openCreateDialog} <h3 class="font-semibold text-lg">Organized listings</h3>
aria-label="Submit a found item" <p class="text-sm text-muted-foreground mt-2">
> Items are structured by location and category so nothing gets buried.
</p>
</div>
<div class="rounded-2xl border bg-muted/10 p-6">
<h3 class="font-semibold text-lg">Trusted process</h3>
<p class="text-sm text-muted-foreground mt-2">
Every submission is reviewed before it's visible.
</p>
</div>
</div>
<!-- Right visual anchor -->
<div class="rounded-2xl border p-10 bg-gradient-to-br from-primary/10 to-transparent">
<h3 class="text-xl font-semibold">Designed for school life</h3>
<p class="text-sm text-muted-foreground mt-4">
Backpacks, phones, notebooks, jackets — the things that actually get lost daily.
Everything here is tuned for real student use, not generic “lost & found” systems.
</p>
<div class="mt-6 text-xs text-muted-foreground">
Over <span class="font-medium text-foreground">120+</span> items successfully returned
</div>
</div>
</div>
</section>
<!-- HOW IT WORKS (Vertical Timeline Style) -->
<section class="mx-auto max-w-4xl px-6 py-12" aria-labelledby="how-heading">
<h2 id="how-heading" class="text-2xl font-semibold text-center mb-12">
How it works
</h2>
<div class="relative border-l pl-8 space-y-10">
<div class="relative">
<div class="absolute -left-[40px] top-1 h-4 w-4 rounded-full bg-primary"></div>
<h3 class="font-semibold">Someone finds something</h3>
<p class="text-sm text-muted-foreground mt-1">
An item is discovered in a classroom, hallway, locker room, or common area.
</p>
</div>
<div class="relative">
<div class="absolute -left-[40px] top-1 h-4 w-4 rounded-full bg-primary/70"></div>
<h3 class="font-semibold">It gets submitted</h3>
<p class="text-sm text-muted-foreground mt-1">
A quick submission captures what it is and where it was found.
</p>
</div>
<div class="relative">
<div class="absolute -left-[40px] top-1 h-4 w-4 rounded-full bg-primary/40"></div>
<h3 class="font-semibold">It makes its way home</h3>
<p class="text-sm text-muted-foreground mt-1">
The owner identifies it and retrieves it through staff.
</p>
</div>
</div>
</section>
<!-- ACTION / INFO (Staggered Bento Style Instead of 3 Equal Cards) -->
<section class="mx-auto max-w-6xl px-6 py-24" aria-labelledby="info-heading">
<h2 id="info-heading" class="sr-only">Actions</h2>
<div class="grid md:grid-cols-2 gap-6">
<!-- Large primary card -->
<Card class="">
<CardHeader>
<CardTitle>Found something?</CardTitle>
</CardHeader>
<CardContent class="space-y-4 text-sm text-muted-foreground">
<p>
Help return it in under a minute. Every submission makes a difference.
</p>
<Button variant="outline" class="w-full" onclick={openCreateDialog}>
Submit Item Submit Item
</Button> </Button>
</CardContent> </CardContent>
</Card> </Card>
<Card> <!-- Side card -->
<Card class="">
<CardHeader> <CardHeader>
<CardTitle id="lost-item-heading">Lost Something?</CardTitle> <CardTitle>Looking for yours?</CardTitle>
</CardHeader> </CardHeader>
<CardContent <CardContent class="space-y-4 text-sm text-muted-foreground">
class="space-y-3 text-sm text-muted-foreground"
aria-labelledby="lost-item-heading"
>
<p> <p>
Browse items that have been turned in by students and staff. Check the live list of items turned in around school.
</p> </p>
<a <a
href="/items" href="/items"
class={cn(buttonVariants({ variant: 'outline', size: 'lg' }), 'mt-2 w-full')} class={cn(buttonVariants({ variant: 'outline' }), 'w-full')}
aria-label="Browse found items"
> >
Browse Items Browse
</a> </a>
</CardContent> </CardContent>
</Card> </Card>
<Card>
<CardHeader>
<CardTitle id="safe-heading">Safe &amp; Effective</CardTitle>
</CardHeader>
<CardContent
class="space-y-3 text-sm text-muted-foreground"
aria-labelledby="safe-heading"
>
<p>
Managed by Waukesha West staff. Items are reviewed before being listed.
</p>
<p>
We've returned 120+ items back to their owners!
</p>
</CardContent>
</Card>
</div> </div>
<!-- Wide bottom emphasis card -->
<Card class="md:col-span-3 border-muted bg-muted/20 mt-6">
<CardContent class=" flex flex-col md:flex-row md:items-center md:justify-between gap-4">
<div>
<h3 class="font-semibold">Built on trust</h3>
<p class="text-sm text-muted-foreground">
A simple system powered by students and staff working together.
</p>
</div>
<div class="text-sm text-muted-foreground">
<span class="font-medium text-foreground">120+</span> items returned and counting
</div>
</CardContent>
</Card>
</section>
<!-- IMPORTANT DISCLAIMER -->
<section class="mx-auto max-w-6xl px-6 pb-20" aria-labelledby="policy-heading">
<Card class="border-amber-500/40 bg-amber-500/5">
<CardHeader>
<CardTitle id="policy-heading">Important Notice</CardTitle>
</CardHeader>
<CardContent class="text-sm text-muted-foreground space-y-3">
<p>
This platform is intended for everyday personal items such as notebooks, clothing,
water bottles, and similar belongings commonly misplaced at school.
</p>
<p>
Items of significant monetary, legal, or sensitive value (including but not limited to cash,
credit cards, IDs, or high-value electronics) should <strong>not</strong> be handled through
this system.
</p>
<p>
Such items must be immediately reported to the main office or appropriate school staff for
proper handling and documentation.
</p>
</CardContent>
</Card>
</section> </section>
<section class="mx-auto max-w-6xl px-6 pb-24" aria-labelledby="staff-heading"> <section class="mx-auto max-w-6xl px-6 pb-24" aria-labelledby="staff-heading">
+8 -8
View File
@@ -4,21 +4,22 @@ import type { User, UserSettings } from '$lib/types/user';
import { type Actions, error, fail } from '@sveltejs/kit'; import { type Actions, error, fail } from '@sveltejs/kit';
import { getFormString, getRequiredFormString } from '$lib/shared'; import { getFormString, getRequiredFormString } from '$lib/shared';
import bcrypt from 'bcrypt'; import bcrypt from 'bcrypt';
import { setJWTCookie } from '$lib/auth/index.server';
export const load: PageServerLoad = async ({ locals }) => { export const load: PageServerLoad = async ({ locals }) => {
if (!locals || !locals.user) { if (!locals || !locals.user) {
throw Error('Need to be logged in!'); throw Error('Need to be logged in!');
} }
const [userData]: User[] = await sql` const [userData] = await sql`
SELECT * FROM users WHERE id = ${locals.user.id} SELECT * FROM users WHERE id = ${locals.user.id}
`; `;
userData.settings = JSON.parse(userData.settings);
return { userData }; return { userData };
}; };
export const actions: Actions = { export const actions: Actions = {
default: async ({ request, url, locals, params }) => { default: async ({ request, url, locals, params, cookies }) => {
if (!locals || !locals.user) { if (!locals || !locals.user) {
throw error(403, 'Need to be logged in!'); throw error(403, 'Need to be logged in!');
} }
@@ -53,18 +54,17 @@ export const actions: Actions = {
notifyAllTurnedInInquiries notifyAllTurnedInInquiries
}; };
return await sql` const [res] = await sql`
UPDATE users SET name = ${name}, UPDATE users SET name = ${name},
email = ${email}, email = ${email},
${passwordHash ? sql`password_hash = ${passwordHash},` : sql``} ${passwordHash ? sql`password_hash = ${passwordHash},` : sql``}
settings = ${settings.toString()} settings = ${JSON.stringify(settings)}
WHERE id = ${locals.user.id} WHERE id = ${locals.user.id}
RETURNING *; RETURNING *;
`; `;
res.settings = JSON.parse(res.settings);
setJWTCookie(cookies, res as User);
} catch (e) { } catch (e) {
console.log('fails');
console.log(e);
return fail(400, { return fail(400, {
message: e instanceof Error ? e.message : 'Unknown error occurred', message: e instanceof Error ? e.message : 'Unknown error occurred',
success: false success: false
-2
View File
@@ -59,8 +59,6 @@
<!-- Editable Profile Form --> <!-- Editable Profile Form -->
<form method="POST" class="space-y-6" use:enhance={({ formElement, formData, action, cancel, submitter }) => { <form method="POST" class="space-y-6" use:enhance={({ formElement, formData, action, cancel, submitter }) => {
return async ({ result, update }) => { return async ({ result, update }) => {
console.log("bleh")
console.log(result.status)
if (result.status === 200) { if (result.status === 200) {
toast('Saved', { toast('Saved', {
icon: CheckIcon, icon: CheckIcon,
View File
-143
View File
@@ -1,143 +0,0 @@
<script lang="ts">
import { Button } from '$lib/components/ui/button/index.js';
import { Checkbox } from '$lib/components/ui/checkbox/index.js';
import * as Field from '$lib/components/ui/field/index.js';
import { Input } from '$lib/components/ui/input/index.js';
import * as Select from '$lib/components/ui/select/index.js';
import { Textarea } from '$lib/components/ui/textarea/index.js';
import ImageUpload from '$lib/components/custom/image-upload/image-upload.svelte';
let month = $state<string>();
let year = $state<string>();
</script>
<div class="w-full max-w-lg mt-8">
<form>
<Field.Group>
<Field.Set>
<Field.Legend>Submit Found Item</Field.Legend>
<Field.Description
>Your item will need to be approved before becoming public
</Field.Description>
<Field.Group>
<Field.Field>
<Field.Label for="image-upload">
Image
</Field.Label>
<ImageUpload></ImageUpload>
</Field.Field>
<Field.Field>
<Field.Label for="checkout-7j9-card-name-43j"
>Name on Card
</Field.Label
>
<Input
id="checkout-7j9-card-name-43j"
placeholder="John Doe"
required
/>
</Field.Field>
<div class="grid grid-cols-3 gap-4">
<Field.Field class="col-span-2">
<Field.Label for="checkout-7j9-card-number-uw1">
Card Number
</Field.Label>
<Input
id="checkout-7j9-card-number-uw1"
placeholder="1234 5678 9012 3456"
required
/>
<Field.Description>Enter your 16-digit number.</Field.Description>
</Field.Field>
<Field.Field class="col-span-1">
<Field.Label for="checkout-7j9-cvv">CVV</Field.Label>
<Input id="checkout-7j9-cvv" placeholder="123" required />
</Field.Field>
</div>
<div class="grid grid-cols-2 gap-4">
<Field.Field>
<Field.Label for="checkout-7j9-exp-month-ts6">Month</Field.Label>
<Select.Root type="single" bind:value={month}>
<Select.Trigger id="checkout-7j9-exp-month-ts6">
<span>
{month || "MM"}
</span>
</Select.Trigger>
<Select.Content>
<Select.Item value="01">01</Select.Item>
<Select.Item value="02">02</Select.Item>
<Select.Item value="03">03</Select.Item>
<Select.Item value="04">04</Select.Item>
<Select.Item value="05">05</Select.Item>
<Select.Item value="06">06</Select.Item>
<Select.Item value="07">07</Select.Item>
<Select.Item value="08">08</Select.Item>
<Select.Item value="09">09</Select.Item>
<Select.Item value="10">10</Select.Item>
<Select.Item value="11">11</Select.Item>
<Select.Item value="12">12</Select.Item>
</Select.Content>
</Select.Root>
</Field.Field>
<Field.Field>
<Field.Label for="checkout-7j9-exp-year-f59">Year</Field.Label>
<Select.Root type="single" bind:value={year}>
<Select.Trigger id="checkout-7j9-exp-year-f59">
<span>
{year || "YYYY"}
</span>
</Select.Trigger>
<Select.Content>
<Select.Item value="2024">2024</Select.Item>
<Select.Item value="2025">2025</Select.Item>
<Select.Item value="2026">2026</Select.Item>
<Select.Item value="2027">2027</Select.Item>
<Select.Item value="2028">2028</Select.Item>
<Select.Item value="2029">2029</Select.Item>
</Select.Content>
</Select.Root>
</Field.Field>
</div>
</Field.Group>
</Field.Set>
<Field.Separator />
<Field.Set>
<Field.Legend>Billing Address</Field.Legend>
<Field.Description>
The billing address associated with your payment method
</Field.Description>
<Field.Group>
<Field.Field orientation="horizontal">
<Checkbox id="checkout-7j9-same-as-shipping-wgm" checked={true} />
<Field.Label
for="checkout-7j9-same-as-shipping-wgm"
class="font-normal"
>
Same as shipping address
</Field.Label>
</Field.Field>
</Field.Group>
</Field.Set>
<Field.Separator />
<Field.Set>
<Field.Group>
<Field.Field>
<Field.Label for="checkout-7j9-optional-comments"
>Comments
</Field.Label
>
<Textarea
id="checkout-7j9-optional-comments"
placeholder="Add any additional comments"
class="resize-none"
/>
</Field.Field>
</Field.Group>
</Field.Set>
<Field.Field orientation="horizontal">
<Button type="submit">Submit</Button>
<Button variant="outline" type="button">Cancel</Button>
</Field.Field>
</Field.Group>
</form>
</div>
+3 -2
View File
@@ -35,7 +35,8 @@ export const load: PageServerLoad = async ({ url, locals }) => {
WHERE im.thread_id = t.id WHERE im.thread_id = t.id
) m ON TRUE ) m ON TRUE
${searchQuery ? sql`WHERE word_similarity(${searchQuery}, i.description) > 0.3` : sql``} ${searchQuery ? sql`WHERE word_similarity(${searchQuery}, i.description) > 0.3` : sql``}
GROUP BY i.id; GROUP BY i.id
ORDER BY i.found_date DESC;
`; `;
items.forEach((item) => items.forEach((item) =>
item.threads?.forEach((thread) => (thread.createdAt = new Date(thread.createdAt))) item.threads?.forEach((thread) => (thread.createdAt = new Date(thread.createdAt)))
@@ -110,7 +111,7 @@ export const load: PageServerLoad = async ({ url, locals }) => {
// Not logged in or fallback: simple item list (no threads) // Not logged in or fallback: simple item list (no threads)
let items: Item[]; let items: Item[];
if (!searchQuery) { if (!searchQuery) {
items = await sql`SELECT * FROM items;`; items = await sql`SELECT * FROM items ORDER BY found_date DESC;`;
} else { } else {
items = await sql` items = await sql`
SELECT * FROM items SELECT * FROM items
+1 -1
View File
@@ -125,7 +125,7 @@
{/if} {/if}
</div> </div>
<Button class="fixed shadow-lg bottom-6 right-6 rounded-xl md:hidden p-6 text-xl" size="default" <Button class="fixed shadow-lg bottom-6 right-6 rounded-xl md:hidden p-6 text-xl z-20" size="default"
onclick={openCreateDialog}> onclick={openCreateDialog}>
<PlusIcon size={32} /> <PlusIcon size={32} />
New item New item
@@ -9,6 +9,7 @@
import * as item from 'valibot'; import * as item from 'valibot';
import NoImagePlaceholder from '$lib/components/custom/no-image-placeholder.svelte'; import NoImagePlaceholder from '$lib/components/custom/no-image-placeholder.svelte';
import { Separator } from '$lib/components/ui/separator'; import { Separator } from '$lib/components/ui/separator';
import { dateFormatOptions } from '$lib/shared';
let { data } = $props(); let { data } = $props();
@@ -35,6 +36,14 @@
} }
}; };
const dateTimeFormatOptions: Intl.DateTimeFormatOptions = {
year: 'numeric',
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
};
</script> </script>
<div class="max-w-2xl mx-auto p-4"> <div class="max-w-2xl mx-auto p-4">
@@ -55,10 +64,7 @@
<div class=""> <div class="">
<div class="flex-1">{data.item.description}</div> <div class="flex-1">{data.item.description}</div>
{#if data.item.foundLocation} {#if data.item.foundLocation}
<div class="mt-2"> <span class="mt-2"><strong class="mr-1">Found at:</strong> {item.foundLocation}</span>
<LocationIcon class="float-left mr-1" size={24} />
<div>{data.item.foundLocation}</div>
</div>
{/if} {/if}
</div> </div>
</div> </div>
@@ -78,7 +84,7 @@
<div class="bg-card rounded-lg p-3 shadow-sm max-w-xl"> <div class="bg-card rounded-lg p-3 shadow-sm max-w-xl">
<p class="text-sm">{msg.body}</p> <p class="text-sm">{msg.body}</p>
<span class="text-xs text-muted-foreground mt-1 block">{msg.createdAt.toLocaleString()}</span> <span class="text-xs text-muted-foreground mt-1 block">{new Date(msg.createdAt as unknown as string).toLocaleDateString('en-US', dateTimeFormatOptions)}</span>
</div> </div>
</div> </div>
{/each} {/each}
@@ -88,11 +94,11 @@
<!-- Input area --> <!-- Input area -->
<form class="mt-6 flex flex-col gap-2" method="post" action="?/reply&token={page.url.searchParams.get('token')}"> <form class="mt-6 flex flex-col gap-2" method="post" action="?/reply&token={page.url.searchParams.get('token')}">
<Textarea <Input
type="text"
placeholder="Write a message..." placeholder="Write a message..."
class="resize-none" class="resize-none"
name="message" name="message"
rows={3}
/> />
<Button class="self-end" type="submit">Send <Button class="self-end" type="submit">Send
<SendIcon /> <SendIcon />
-21
View File
@@ -1,21 +0,0 @@
<script lang="ts">
import { toast } from 'svelte-sonner';
import { Button } from '$lib/components/ui/button/index.js';
import { Toaster } from '$lib/components/ui/sonner';
</script>
<Button
variant="outline"
onclick={() =>
toast("Event has been created", {
description: "Sunday, December 03, 2023 at 9:00 AM",
action: {
label: "Undo",
onClick: () => console.info("Undo")
}
})}
>
Show Toast
</Button>
<Toaster></Toaster>
Binary file not shown.