Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f56c0f83c2 | ||
|
|
35a849913e | ||
|
|
e01b9b5445 | ||
|
|
e3484718a0 |
2
.env
2
.env
@@ -4,8 +4,6 @@
|
|||||||
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
|
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
|
||||||
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
|
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
|
||||||
|
|
||||||
SECRET="jg57cya4mrNkGlnb2R85X1gI8LdY7iNZ9MF0Jbn0K5zQBshOxv"
|
|
||||||
|
|
||||||
POSTGRES_DB=main
|
POSTGRES_DB=main
|
||||||
POSTGRES_HOST=localhost
|
POSTGRES_HOST=localhost
|
||||||
POSTGRES_PORT=5432
|
POSTGRES_PORT=5432
|
||||||
|
|||||||
39
.github/workflows/prod-pipeline.yml
vendored
39
.github/workflows/prod-pipeline.yml
vendored
@@ -5,33 +5,8 @@ on:
|
|||||||
branches: [main]
|
branches: [main]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-migrations:
|
|
||||||
name: Check for new Prisma migrations
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
has_new_migrations: ${{ steps.diff.outputs.has_new_migrations }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0 # get full history so git diff works properly
|
|
||||||
|
|
||||||
- name: Detect new migration files
|
|
||||||
id: diff
|
|
||||||
run: |
|
|
||||||
# Compare the last two commits on main
|
|
||||||
if git diff --quiet HEAD~1 -- prisma/migrations/; then
|
|
||||||
echo "✅ No new Prisma migrations detected."
|
|
||||||
echo "has_new_migrations=false" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "⚠️ New Prisma migrations detected! Blocking deployment."
|
|
||||||
echo "has_new_migrations=true" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
name: Deploy to production
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: check-migrations
|
|
||||||
if: needs.check-migrations.outputs.has_new_migrations == 'false'
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Install Bun
|
- name: Install Bun
|
||||||
@@ -53,16 +28,4 @@ jobs:
|
|||||||
git clean -f -d
|
git clean -f -d
|
||||||
git pull origin main
|
git pull origin main
|
||||||
git status
|
git status
|
||||||
make prod
|
make prod
|
||||||
|
|
||||||
block-deploy:
|
|
||||||
name: Block deployment (new migrations detected)
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: check-migrations
|
|
||||||
if: needs.check-migrations.outputs.has_new_migrations == 'true'
|
|
||||||
steps:
|
|
||||||
- name: Stop deploy
|
|
||||||
run: |
|
|
||||||
echo "🚫 Deployment blocked because new Prisma migrations were detected."
|
|
||||||
echo "Please apply migrations on staging and verify before deploying to production."
|
|
||||||
exit 1
|
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -15,8 +15,6 @@ npm-debug.log*
|
|||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
pnpm-debug.log*
|
pnpm-debug.log*
|
||||||
error.log*
|
|
||||||
combined.log*
|
|
||||||
|
|
||||||
# lockfile
|
# lockfile
|
||||||
pnpm-lock.yaml
|
pnpm-lock.yaml
|
||||||
|
|||||||
3
Makefile
3
Makefile
@@ -62,8 +62,7 @@ all:
|
|||||||
bun run dev 2>&1 | tee ~/logs/`date '+%d-%m-%Y_%H:%M:%S'`.log
|
bun run dev 2>&1 | tee ~/logs/`date '+%d-%m-%Y_%H:%M:%S'`.log
|
||||||
|
|
||||||
update-dwd-klimafaktoren-cron:
|
update-dwd-klimafaktoren-cron:
|
||||||
- pm2 delete update-dwd-klimafaktoren-cron
|
pm2 start bun --name "update-dwd-klimafaktoren-cron" --cron "0 12 28 * *" -- src/cronjobs/update-dwd-klimafaktoren.ts
|
||||||
pm2 start --no-autorestart bun --name "update-dwd-klimafaktoren-cron" --cron "0 12 28 * *" -- src/cronjobs/update-dwd-klimafaktoren.ts
|
|
||||||
|
|
||||||
prod: prod-no-backup backup-database-cronjob
|
prod: prod-no-backup backup-database-cronjob
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,8 @@ import tailwind from "@astrojs/tailwind";
|
|||||||
import node from "@astrojs/node";
|
import node from "@astrojs/node";
|
||||||
import mdx from "@astrojs/mdx";
|
import mdx from "@astrojs/mdx";
|
||||||
import astroTypesafeAPI from "astro-typesafe-api"
|
import astroTypesafeAPI from "astro-typesafe-api"
|
||||||
import { logger } from "./src/lib/logger";
|
|
||||||
|
|
||||||
logger.info("Astro config loaded");
|
// https://astro.build/config
|
||||||
|
|
||||||
// https://astro.build/config
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
integrations: [svelte(), tailwind(), mdx(), astroTypesafeAPI()],
|
integrations: [svelte(), tailwind(), mdx(), astroTypesafeAPI()],
|
||||||
outDir: "./dist",
|
outDir: "./dist",
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
if [[ -z "$prev_restart_delay" && -n "$cron_restart" ]]; then
|
|
||||||
echo "skipping initial launch...."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
FILE_NAME=data-dump_`date +%Y-%m-%d"_"%H_%M_%S`.sql.br
|
FILE_NAME=data-dump_`date +%Y-%m-%d"_"%H_%M_%S`.sql.br
|
||||||
FILE_NAME_COMPLETE=full-dump_`date +%Y-%m-%d"_"%H_%M_%S`.sql.br
|
FILE_NAME_COMPLETE=full-dump_`date +%Y-%m-%d"_"%H_%M_%S`.sql.br
|
||||||
DATABASE_NAME=database
|
DATABASE_NAME=database
|
||||||
|
|||||||
29
bun.lock
29
bun.lock
@@ -29,6 +29,7 @@
|
|||||||
"fontkit": "^2.0.4",
|
"fontkit": "^2.0.4",
|
||||||
"handlebars": "^4.7.8",
|
"handlebars": "^4.7.8",
|
||||||
"heic2any": "^0.0.4",
|
"heic2any": "^0.0.4",
|
||||||
|
"highlight.run": "^9.14.0",
|
||||||
"is-base64": "^1.1.0",
|
"is-base64": "^1.1.0",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"js-interpolate": "^1.3.2",
|
"js-interpolate": "^1.3.2",
|
||||||
@@ -55,7 +56,7 @@
|
|||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"trpc-openapi": "^1.2.0",
|
"trpc-openapi": "^1.2.0",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
"winston": "^3.18.3",
|
"winston": "^3.17.0",
|
||||||
"zod": "^3.24.1",
|
"zod": "^3.24.1",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -269,7 +270,7 @@
|
|||||||
|
|
||||||
"@cypress/xvfb": ["@cypress/xvfb@1.2.4", "", { "dependencies": { "debug": "^3.1.0", "lodash.once": "^4.1.1" } }, "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q=="],
|
"@cypress/xvfb": ["@cypress/xvfb@1.2.4", "", { "dependencies": { "debug": "^3.1.0", "lodash.once": "^4.1.1" } }, "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q=="],
|
||||||
|
|
||||||
"@dabh/diagnostics": ["@dabh/diagnostics@2.0.8", "", { "dependencies": { "@so-ric/colorspace": "^1.1.6", "enabled": "2.0.x", "kuler": "^2.0.0" } }, "sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q=="],
|
"@dabh/diagnostics": ["@dabh/diagnostics@2.0.3", "", { "dependencies": { "colorspace": "1.1.x", "enabled": "2.0.x", "kuler": "^2.0.0" } }, "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA=="],
|
||||||
|
|
||||||
"@daybrush/utils": ["@daybrush/utils@1.13.0", "", {}, "sha512-ALK12C6SQNNHw1enXK+UO8bdyQ+jaWNQ1Af7Z3FNxeAwjYhQT7do+TRE4RASAJ3ObaS2+TJ7TXR3oz2Gzbw0PQ=="],
|
"@daybrush/utils": ["@daybrush/utils@1.13.0", "", {}, "sha512-ALK12C6SQNNHw1enXK+UO8bdyQ+jaWNQ1Af7Z3FNxeAwjYhQT7do+TRE4RASAJ3ObaS2+TJ7TXR3oz2Gzbw0PQ=="],
|
||||||
|
|
||||||
@@ -713,8 +714,6 @@
|
|||||||
|
|
||||||
"@smithy/util-waiter": ["@smithy/util-waiter@4.0.2", "", { "dependencies": { "@smithy/abort-controller": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-piUTHyp2Axx3p/kc2CIJkYSv0BAaheBQmbACZgQSSfWUumWNW+R1lL+H9PDBxKJkvOeEX+hKYEFiwO8xagL8AQ=="],
|
"@smithy/util-waiter": ["@smithy/util-waiter@4.0.2", "", { "dependencies": { "@smithy/abort-controller": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-piUTHyp2Axx3p/kc2CIJkYSv0BAaheBQmbACZgQSSfWUumWNW+R1lL+H9PDBxKJkvOeEX+hKYEFiwO8xagL8AQ=="],
|
||||||
|
|
||||||
"@so-ric/colorspace": ["@so-ric/colorspace@1.1.6", "", { "dependencies": { "color": "^5.0.2", "text-hex": "1.0.x" } }, "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw=="],
|
|
||||||
|
|
||||||
"@svelte-plugins/datepicker": ["@svelte-plugins/datepicker@1.0.11", "", {}, "sha512-Tqc07QLyRkCpc3Glg6oRLTUApLtCrOh52d6vJ7L32QI17HrwvcDDjaH3LF3X1SBm3CWdMrnqfJp3xjUZmB4wzw=="],
|
"@svelte-plugins/datepicker": ["@svelte-plugins/datepicker@1.0.11", "", {}, "sha512-Tqc07QLyRkCpc3Glg6oRLTUApLtCrOh52d6vJ7L32QI17HrwvcDDjaH3LF3X1SBm3CWdMrnqfJp3xjUZmB4wzw=="],
|
||||||
|
|
||||||
"@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@2.5.3", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^1.0.4", "debug": "^4.3.4", "deepmerge": "^4.3.1", "kleur": "^4.1.5", "magic-string": "^0.30.3", "svelte-hmr": "^0.15.3", "vitefu": "^0.2.4" }, "peerDependencies": { "svelte": "^3.54.0 || ^4.0.0 || ^5.0.0-next.0", "vite": "^4.0.0" } }, "sha512-erhNtXxE5/6xGZz/M9eXsmI7Pxa6MS7jyTy06zN3Ck++ldrppOnOlJwHHTsMC7DHDQdgUp4NAc4cDNQ9eGdB/w=="],
|
"@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@2.5.3", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^1.0.4", "debug": "^4.3.4", "deepmerge": "^4.3.1", "kleur": "^4.1.5", "magic-string": "^0.30.3", "svelte-hmr": "^0.15.3", "vitefu": "^0.2.4" }, "peerDependencies": { "svelte": "^3.54.0 || ^4.0.0 || ^5.0.0-next.0", "vite": "^4.0.0" } }, "sha512-erhNtXxE5/6xGZz/M9eXsmI7Pxa6MS7jyTy06zN3Ck++ldrppOnOlJwHHTsMC7DHDQdgUp4NAc4cDNQ9eGdB/w=="],
|
||||||
@@ -1107,6 +1106,8 @@
|
|||||||
|
|
||||||
"colorette": ["colorette@2.0.19", "", {}, "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ=="],
|
"colorette": ["colorette@2.0.19", "", {}, "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ=="],
|
||||||
|
|
||||||
|
"colorspace": ["colorspace@1.1.4", "", { "dependencies": { "color": "^3.1.3", "text-hex": "1.0.x" } }, "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w=="],
|
||||||
|
|
||||||
"combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
|
"combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
|
||||||
|
|
||||||
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
|
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
|
||||||
@@ -1559,6 +1560,8 @@
|
|||||||
|
|
||||||
"hexoid": ["hexoid@2.0.0", "", {}, "sha512-qlspKUK7IlSQv2o+5I7yhUd7TxlOG2Vr5LTa3ve2XSNVKAL/n/u/7KLvKmFNimomDIKvZFXWHv0T12mv7rT8Aw=="],
|
"hexoid": ["hexoid@2.0.0", "", {}, "sha512-qlspKUK7IlSQv2o+5I7yhUd7TxlOG2Vr5LTa3ve2XSNVKAL/n/u/7KLvKmFNimomDIKvZFXWHv0T12mv7rT8Aw=="],
|
||||||
|
|
||||||
|
"highlight.run": ["highlight.run@9.14.0", "", {}, "sha512-ZR+ZLHlVU8lXqsuto0ZEMAOuvptaTBBf1jradnKDIn9OfAXupcYFbkASDlbsZtyBh2SYJSK50xwrucXujhksRg=="],
|
||||||
|
|
||||||
"hosted-git-info": ["hosted-git-info@2.8.9", "", {}, "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw=="],
|
"hosted-git-info": ["hosted-git-info@2.8.9", "", {}, "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw=="],
|
||||||
|
|
||||||
"hotkeys-js": ["hotkeys-js@3.13.9", "", {}, "sha512-3TRCj9u9KUH6cKo25w4KIdBfdBfNRjfUwrljCLDC2XhmPDG0SjAZFcFZekpUZFmXzfYoGhFDcdx2gX/vUVtztQ=="],
|
"hotkeys-js": ["hotkeys-js@3.13.9", "", {}, "sha512-3TRCj9u9KUH6cKo25w4KIdBfdBfNRjfUwrljCLDC2XhmPDG0SjAZFcFZekpUZFmXzfYoGhFDcdx2gX/vUVtztQ=="],
|
||||||
@@ -2765,7 +2768,7 @@
|
|||||||
|
|
||||||
"widest-line": ["widest-line@5.0.0", "", { "dependencies": { "string-width": "^7.0.0" } }, "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA=="],
|
"widest-line": ["widest-line@5.0.0", "", { "dependencies": { "string-width": "^7.0.0" } }, "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA=="],
|
||||||
|
|
||||||
"winston": ["winston@3.18.3", "", { "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.8", "async": "^3.2.3", "is-stream": "^2.0.0", "logform": "^2.7.0", "one-time": "^1.0.0", "readable-stream": "^3.4.0", "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", "winston-transport": "^4.9.0" } }, "sha512-NoBZauFNNWENgsnC9YpgyYwOVrl2m58PpQ8lNHjV3kosGs7KJ7Npk9pCUE+WJlawVSe8mykWDKWFSVfs3QO9ww=="],
|
"winston": ["winston@3.17.0", "", { "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.2", "async": "^3.2.3", "is-stream": "^2.0.0", "logform": "^2.7.0", "one-time": "^1.0.0", "readable-stream": "^3.4.0", "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", "winston-transport": "^4.9.0" } }, "sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw=="],
|
||||||
|
|
||||||
"winston-transport": ["winston-transport@4.9.0", "", { "dependencies": { "logform": "^2.7.0", "readable-stream": "^3.6.2", "triple-beam": "^1.3.0" } }, "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A=="],
|
"winston-transport": ["winston-transport@4.9.0", "", { "dependencies": { "logform": "^2.7.0", "readable-stream": "^3.6.2", "triple-beam": "^1.3.0" } }, "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A=="],
|
||||||
|
|
||||||
@@ -2885,8 +2888,6 @@
|
|||||||
|
|
||||||
"@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
"@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
||||||
|
|
||||||
"@so-ric/colorspace/color": ["color@5.0.2", "", { "dependencies": { "color-convert": "^3.0.1", "color-string": "^2.0.0" } }, "sha512-e2hz5BzbUPcYlIRHo8ieAhYgoajrJr+hWoceg6E345TPsATMUKqDgzt8fSXZJJbxfpiPzkWyphz8yn8At7q3fA=="],
|
|
||||||
|
|
||||||
"@sveltejs/vite-plugin-svelte/vitefu": ["vitefu@0.2.5", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" }, "optionalPeers": ["vite"] }, "sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q=="],
|
"@sveltejs/vite-plugin-svelte/vitefu": ["vitefu@0.2.5", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" }, "optionalPeers": ["vite"] }, "sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q=="],
|
||||||
|
|
||||||
"@types/ssh2/@types/node": ["@types/node@18.19.86", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ=="],
|
"@types/ssh2/@types/node": ["@types/node@18.19.86", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ=="],
|
||||||
@@ -2933,6 +2934,8 @@
|
|||||||
|
|
||||||
"co-body/qs": ["qs@6.14.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w=="],
|
"co-body/qs": ["qs@6.14.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w=="],
|
||||||
|
|
||||||
|
"colorspace/color": ["color@3.2.1", "", { "dependencies": { "color-convert": "^1.9.3", "color-string": "^1.6.0" } }, "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA=="],
|
||||||
|
|
||||||
"csvtojson/strip-bom": ["strip-bom@2.0.0", "", { "dependencies": { "is-utf8": "^0.2.0" } }, "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g=="],
|
"csvtojson/strip-bom": ["strip-bom@2.0.0", "", { "dependencies": { "is-utf8": "^0.2.0" } }, "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g=="],
|
||||||
|
|
||||||
"cypress/buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
|
"cypress/buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
|
||||||
@@ -3177,10 +3180,6 @@
|
|||||||
|
|
||||||
"@prisma/internals/globby/slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
|
"@prisma/internals/globby/slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
|
||||||
|
|
||||||
"@so-ric/colorspace/color/color-convert": ["color-convert@3.1.2", "", { "dependencies": { "color-name": "^2.0.0" } }, "sha512-UNqkvCDXstVck3kdowtOTWROIJQwafjOfXSmddoDrXo4cewMKmusCeF22Q24zvjR8nwWib/3S/dfyzPItPEiJg=="],
|
|
||||||
|
|
||||||
"@so-ric/colorspace/color/color-string": ["color-string@2.1.2", "", { "dependencies": { "color-name": "^2.0.0" } }, "sha512-RxmjYxbWemV9gKu4zPgiZagUxbH3RQpEIO77XoSSX0ivgABDZ+h8Zuash/EMFLTI4N9QgFPOJ6JQpPZKFxa+dA=="],
|
|
||||||
|
|
||||||
"@types/ssh2/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
|
"@types/ssh2/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree/globby/slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
|
"@typescript-eslint/typescript-estree/globby/slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
|
||||||
@@ -3201,6 +3200,8 @@
|
|||||||
|
|
||||||
"boxen/wrap-ansi/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
|
"boxen/wrap-ansi/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
|
||||||
|
|
||||||
|
"colorspace/color/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
||||||
|
|
||||||
"express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
"express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||||
|
|
||||||
"express/send/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="],
|
"express/send/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="],
|
||||||
@@ -3347,14 +3348,12 @@
|
|||||||
|
|
||||||
"@prisma/internals/@prisma/debug/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="],
|
"@prisma/internals/@prisma/debug/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="],
|
||||||
|
|
||||||
"@so-ric/colorspace/color/color-convert/color-name": ["color-name@2.0.2", "", {}, "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A=="],
|
|
||||||
|
|
||||||
"@so-ric/colorspace/color/color-string/color-name": ["color-name@2.0.2", "", {}, "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A=="],
|
|
||||||
|
|
||||||
"boxen/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
|
"boxen/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
|
||||||
|
|
||||||
"boxen/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
|
"boxen/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
|
||||||
|
|
||||||
|
"colorspace/color/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||||
|
|
||||||
"form-render/color/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
"form-render/color/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||||
|
|
||||||
"npm-packlist/glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
|
"npm-packlist/glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
"fontkit": "^2.0.4",
|
"fontkit": "^2.0.4",
|
||||||
"handlebars": "^4.7.8",
|
"handlebars": "^4.7.8",
|
||||||
"heic2any": "^0.0.4",
|
"heic2any": "^0.0.4",
|
||||||
|
"highlight.run": "^9.14.0",
|
||||||
"is-base64": "^1.1.0",
|
"is-base64": "^1.1.0",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"js-interpolate": "^1.3.2",
|
"js-interpolate": "^1.3.2",
|
||||||
@@ -69,7 +70,7 @@
|
|||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"trpc-openapi": "^1.2.0",
|
"trpc-openapi": "^1.2.0",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
"winston": "^3.18.3",
|
"winston": "^3.17.0",
|
||||||
"zod": "^3.24.1"
|
"zod": "^3.24.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
/*
|
|
||||||
Warnings:
|
|
||||||
|
|
||||||
- You are about to drop the column `anrede` on the `benutzer` table. All the data in the column will be lost.
|
|
||||||
|
|
||||||
*/
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE "benutzer" DROP COLUMN "anrede",
|
|
||||||
ADD COLUMN "empfaenger" VARCHAR(100);
|
|
||||||
@@ -17,7 +17,7 @@ model Benutzer {
|
|||||||
ort String? @db.VarChar(50)
|
ort String? @db.VarChar(50)
|
||||||
adresse String? @db.VarChar(150)
|
adresse String? @db.VarChar(150)
|
||||||
telefon String? @db.VarChar(50)
|
telefon String? @db.VarChar(50)
|
||||||
empfaenger String? @db.VarChar(100)
|
anrede String? @db.VarChar(50)
|
||||||
rolle BenutzerRolle @default(USER)
|
rolle BenutzerRolle @default(USER)
|
||||||
firma String?
|
firma String?
|
||||||
lex_office_id String?
|
lex_office_id String?
|
||||||
|
|||||||
@@ -5,6 +5,12 @@ export const createCaller = createCallerFactory({
|
|||||||
"klimafaktoren": await import("../src/pages/api/klimafaktoren.ts"),
|
"klimafaktoren": await import("../src/pages/api/klimafaktoren.ts"),
|
||||||
"postleitzahlen": await import("../src/pages/api/postleitzahlen.ts"),
|
"postleitzahlen": await import("../src/pages/api/postleitzahlen.ts"),
|
||||||
"unterlage": await import("../src/pages/api/unterlage.ts"),
|
"unterlage": await import("../src/pages/api/unterlage.ts"),
|
||||||
|
"ausweise": await import("../src/pages/api/ausweise/index.ts"),
|
||||||
|
"bedarfsausweis-gewerbe/[id]": await import("../src/pages/api/bedarfsausweis-gewerbe/[id].ts"),
|
||||||
|
"bedarfsausweis-gewerbe": await import("../src/pages/api/bedarfsausweis-gewerbe/index.ts"),
|
||||||
|
"aufnahme": await import("../src/pages/api/aufnahme/index.ts"),
|
||||||
|
"bedarfsausweis-wohnen/[id]": await import("../src/pages/api/bedarfsausweis-wohnen/[id].ts"),
|
||||||
|
"bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"),
|
||||||
"admin/ausstellen": await import("../src/pages/api/admin/ausstellen.ts"),
|
"admin/ausstellen": await import("../src/pages/api/admin/ausstellen.ts"),
|
||||||
"admin/bedarfsausweis-ausstellen": await import("../src/pages/api/admin/bedarfsausweis-ausstellen.ts"),
|
"admin/bedarfsausweis-ausstellen": await import("../src/pages/api/admin/bedarfsausweis-ausstellen.ts"),
|
||||||
"admin/bestellbestaetigung": await import("../src/pages/api/admin/bestellbestaetigung.ts"),
|
"admin/bestellbestaetigung": await import("../src/pages/api/admin/bestellbestaetigung.ts"),
|
||||||
@@ -12,25 +18,16 @@ export const createCaller = createCallerFactory({
|
|||||||
"admin/nicht-ausstellen": await import("../src/pages/api/admin/nicht-ausstellen.ts"),
|
"admin/nicht-ausstellen": await import("../src/pages/api/admin/nicht-ausstellen.ts"),
|
||||||
"admin/registriernummer": await import("../src/pages/api/admin/registriernummer.ts"),
|
"admin/registriernummer": await import("../src/pages/api/admin/registriernummer.ts"),
|
||||||
"admin/stornieren": await import("../src/pages/api/admin/stornieren.ts"),
|
"admin/stornieren": await import("../src/pages/api/admin/stornieren.ts"),
|
||||||
"ausweise": await import("../src/pages/api/ausweise/index.ts"),
|
|
||||||
"aufnahme": await import("../src/pages/api/aufnahme/index.ts"),
|
|
||||||
"auth/access-token": await import("../src/pages/api/auth/access-token.ts"),
|
|
||||||
"auth/passwort-vergessen": await import("../src/pages/api/auth/passwort-vergessen.ts"),
|
|
||||||
"auth/refresh-token": await import("../src/pages/api/auth/refresh-token.ts"),
|
|
||||||
"bedarfsausweis-gewerbe/[id]": await import("../src/pages/api/bedarfsausweis-gewerbe/[id].ts"),
|
|
||||||
"bedarfsausweis-gewerbe": await import("../src/pages/api/bedarfsausweis-gewerbe/index.ts"),
|
|
||||||
"geg-nachweis-gewerbe/[id]": await import("../src/pages/api/geg-nachweis-gewerbe/[id].ts"),
|
|
||||||
"geg-nachweis-gewerbe": await import("../src/pages/api/geg-nachweis-gewerbe/index.ts"),
|
|
||||||
"bilder/[id]": await import("../src/pages/api/bilder/[id].ts"),
|
"bilder/[id]": await import("../src/pages/api/bilder/[id].ts"),
|
||||||
"geg-nachweis-wohnen/[id]": await import("../src/pages/api/geg-nachweis-wohnen/[id].ts"),
|
"geg-nachweis-wohnen/[id]": await import("../src/pages/api/geg-nachweis-wohnen/[id].ts"),
|
||||||
"geg-nachweis-wohnen": await import("../src/pages/api/geg-nachweis-wohnen/index.ts"),
|
"geg-nachweis-wohnen": await import("../src/pages/api/geg-nachweis-wohnen/index.ts"),
|
||||||
"bedarfsausweis-wohnen/[id]": await import("../src/pages/api/bedarfsausweis-wohnen/[id].ts"),
|
|
||||||
"bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"),
|
|
||||||
"objekt": await import("../src/pages/api/objekt/index.ts"),
|
"objekt": await import("../src/pages/api/objekt/index.ts"),
|
||||||
|
"auth/access-token": await import("../src/pages/api/auth/access-token.ts"),
|
||||||
|
"auth/passwort-vergessen": await import("../src/pages/api/auth/passwort-vergessen.ts"),
|
||||||
|
"auth/refresh-token": await import("../src/pages/api/auth/refresh-token.ts"),
|
||||||
"rechnung/[id]": await import("../src/pages/api/rechnung/[id].ts"),
|
"rechnung/[id]": await import("../src/pages/api/rechnung/[id].ts"),
|
||||||
"rechnung/anfordern": await import("../src/pages/api/rechnung/anfordern.ts"),
|
"rechnung/anfordern": await import("../src/pages/api/rechnung/anfordern.ts"),
|
||||||
"rechnung": await import("../src/pages/api/rechnung/index.ts"),
|
"rechnung": await import("../src/pages/api/rechnung/index.ts"),
|
||||||
"user/autocreate": await import("../src/pages/api/user/autocreate.ts"),
|
|
||||||
"user": await import("../src/pages/api/user/index.ts"),
|
"user": await import("../src/pages/api/user/index.ts"),
|
||||||
"user/self": await import("../src/pages/api/user/self.ts"),
|
"user/self": await import("../src/pages/api/user/self.ts"),
|
||||||
"ticket": await import("../src/pages/api/ticket/index.ts"),
|
"ticket": await import("../src/pages/api/ticket/index.ts"),
|
||||||
@@ -38,6 +35,9 @@ export const createCaller = createCallerFactory({
|
|||||||
"verbrauchsausweis-wohnen": await import("../src/pages/api/verbrauchsausweis-wohnen/index.ts"),
|
"verbrauchsausweis-wohnen": await import("../src/pages/api/verbrauchsausweis-wohnen/index.ts"),
|
||||||
"verbrauchsausweis-gewerbe/[id]": await import("../src/pages/api/verbrauchsausweis-gewerbe/[id].ts"),
|
"verbrauchsausweis-gewerbe/[id]": await import("../src/pages/api/verbrauchsausweis-gewerbe/[id].ts"),
|
||||||
"verbrauchsausweis-gewerbe": await import("../src/pages/api/verbrauchsausweis-gewerbe/index.ts"),
|
"verbrauchsausweis-gewerbe": await import("../src/pages/api/verbrauchsausweis-gewerbe/index.ts"),
|
||||||
|
"ticket": await import("../src/pages/api/ticket/index.ts"),
|
||||||
|
"verbrauchsausweis-wohnen/[id]": await import("../src/pages/api/verbrauchsausweis-wohnen/[id].ts"),
|
||||||
|
"verbrauchsausweis-wohnen": await import("../src/pages/api/verbrauchsausweis-wohnen/index.ts"),
|
||||||
"webhooks/mollie": await import("../src/pages/api/webhooks/mollie.ts"),
|
"webhooks/mollie": await import("../src/pages/api/webhooks/mollie.ts"),
|
||||||
"aufnahme/[id]/bilder": await import("../src/pages/api/aufnahme/[id]/bilder.ts"),
|
"aufnahme/[id]/bilder": await import("../src/pages/api/aufnahme/[id]/bilder.ts"),
|
||||||
"aufnahme/[id]": await import("../src/pages/api/aufnahme/[id]/index.ts"),
|
"aufnahme/[id]": await import("../src/pages/api/aufnahme/[id]/index.ts"),
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
import { api } from "astro-typesafe-api/client";
|
import { api } from "astro-typesafe-api/client";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
|
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
|
||||||
|
import {
|
||||||
|
AufnahmeClient,
|
||||||
|
BedarfsausweisWohnenClient,
|
||||||
|
BildClient,
|
||||||
|
ObjektClient,
|
||||||
|
VerbrauchsausweisGewerbeClient,
|
||||||
|
VerbrauchsausweisWohnenClient,
|
||||||
|
} from "#components/Ausweis/types.js";
|
||||||
import {
|
import {
|
||||||
Aufnahme,
|
Aufnahme,
|
||||||
BedarfsausweisWohnen,
|
BedarfsausweisWohnen,
|
||||||
|
|||||||
@@ -170,6 +170,7 @@ export async function benutzerSpeichern(benutzer: Partial<Benutzer>): Promise<st
|
|||||||
email: benutzer.email,
|
email: benutzer.email,
|
||||||
passwort: "",
|
passwort: "",
|
||||||
adresse: benutzer.adresse ?? null,
|
adresse: benutzer.adresse ?? null,
|
||||||
|
anrede: benutzer.anrede ?? null,
|
||||||
firma: benutzer.firma ?? null,
|
firma: benutzer.firma ?? null,
|
||||||
vorname: benutzer.vorname ?? null,
|
vorname: benutzer.vorname ?? null,
|
||||||
ort: benutzer.ort ?? null,
|
ort: benutzer.ort ?? null,
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
|
|||||||
>
|
>
|
||||||
<option disabled selected value={null}>Bitte auswählen</option>
|
<option disabled selected value={null}>Bitte auswählen</option>
|
||||||
|
|
||||||
{#if ausweisart==Enums.Ausweisart.VerbrauchsausweisWohnen || ausweisart === Enums.Ausweisart.GEGNachweisWohnen || ausweisart === Enums.Ausweisart.BedarfsausweisWohnen}
|
{#if ausweisart==Enums.Ausweisart.VerbrauchsausweisWohnen || ausweisart === Enums.Ausweisart.GEGNachweisWohnen || ausweisart === Enums.Ausweisart.BedarfsausweisWohnen || ausweisart === Enums.Ausweisart.BedarfsausweisGewerbe}
|
||||||
<option value="Einfamilienhaus">Einfamilienhaus</option>
|
<option value="Einfamilienhaus">Einfamilienhaus</option>
|
||||||
<option value="Freistehendes Einfamilienhaus">Freistehendes Einfamilienhaus</option>
|
<option value="Freistehendes Einfamilienhaus">Freistehendes Einfamilienhaus</option>
|
||||||
<option value="Freistehendes Zweifamilienhaus">Freistehendes Zweifamilienhaus</option>
|
<option value="Freistehendes Zweifamilienhaus">Freistehendes Zweifamilienhaus</option>
|
||||||
@@ -87,7 +87,7 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
|
|||||||
<option value="Atrium-Bungalow">Atrium-Bungalow</option>
|
<option value="Atrium-Bungalow">Atrium-Bungalow</option>
|
||||||
<option value="Winkelbungalow">Winkelbungalow</option>
|
<option value="Winkelbungalow">Winkelbungalow</option>
|
||||||
|
|
||||||
{:else if ausweisart==Enums.Ausweisart.VerbrauchsausweisGewerbe || ausweisart=== Enums.Ausweisart.GEGNachweisGewerbe || ausweisart === Enums.Ausweisart.BedarfsausweisGewerbe}
|
{:else if ausweisart==Enums.Ausweisart.VerbrauchsausweisGewerbe || ausweisart=== Enums.Ausweisart.GEGNachweisGewerbe}
|
||||||
<option value="Verwaltungsgebäude (allgemein)">Verwaltungsgebäude (allgemein)</option>
|
<option value="Verwaltungsgebäude (allgemein)">Verwaltungsgebäude (allgemein)</option>
|
||||||
<option value="Parlaments- und Gerichtsgebäude">Parlaments- und Gerichtsgebäude</option>
|
<option value="Parlaments- und Gerichtsgebäude">Parlaments- und Gerichtsgebäude</option>
|
||||||
<option value="Ministerien u. Ämter u. Behörden">Ministerien u. Ämter u. Behörden</option>
|
<option value="Ministerien u. Ämter u. Behörden">Ministerien u. Ämter u. Behörden</option>
|
||||||
@@ -186,7 +186,6 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
|
|||||||
onlyUnique={true}
|
onlyUnique={true}
|
||||||
minlength={4}
|
minlength={4}
|
||||||
maxlength={4}
|
maxlength={4}
|
||||||
required={true}
|
|
||||||
onFocusIn={() => {
|
onFocusIn={() => {
|
||||||
addNotification({
|
addNotification({
|
||||||
message: "Info",
|
message: "Info",
|
||||||
@@ -250,7 +249,6 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
|
|||||||
minlength={4}
|
minlength={4}
|
||||||
maxlength={4}
|
maxlength={4}
|
||||||
onlyUnique={true}
|
onlyUnique={true}
|
||||||
required={true}
|
|
||||||
onFocusIn={() => {
|
onFocusIn={() => {
|
||||||
addNotification({
|
addNotification({
|
||||||
message: "Info",
|
message: "Info",
|
||||||
@@ -289,7 +287,6 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
|
|||||||
onlyUnique={true}
|
onlyUnique={true}
|
||||||
minlength={4}
|
minlength={4}
|
||||||
maxlength={4}
|
maxlength={4}
|
||||||
required={true}
|
|
||||||
onFocusIn={() => {
|
onFocusIn={() => {
|
||||||
addNotification({
|
addNotification({
|
||||||
message: "Info",
|
message: "Info",
|
||||||
|
|||||||
@@ -44,17 +44,11 @@
|
|||||||
// Wir holen uns die Daten aus dem Formular
|
// Wir holen uns die Daten aus dem Formular
|
||||||
const data = new FormData(form);
|
const data = new FormData(form);
|
||||||
// Und gleichen diese mit allen Feldern ab die "required" sind, damit stellen wir sicher, dass alles richtig ausgefüllt wurde.
|
// Und gleichen diese mit allen Feldern ab die "required" sind, damit stellen wir sicher, dass alles richtig ausgefüllt wurde.
|
||||||
(form.querySelectorAll("select[name][required], input[name][required]") as NodeListOf<HTMLInputElement | HTMLSelectElement>).forEach((element) => {
|
(form.querySelectorAll("select[name][required],input[name][required]") as NodeListOf<HTMLInputElement | HTMLSelectElement>).forEach((element) => {
|
||||||
const value = data.get(element.getAttribute("name") as string)
|
const value = data.get(element.getAttribute("name") as string)
|
||||||
|
|
||||||
if (!value && element.required) {
|
if (!value && element.required) {
|
||||||
element.setCustomValidity("Eine Auswahl ist verpflichtend.")
|
element.setCustomValidity("Eine Auswahl ist verpflichtend.")
|
||||||
element.dataset["isinvalid"] = "true"
|
|
||||||
|
|
||||||
element.addEventListener("change", () => {
|
|
||||||
element.setCustomValidity("")
|
|
||||||
element.dataset["isinvalid"] = "false"
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
element.setCustomValidity("")
|
element.setCustomValidity("")
|
||||||
}
|
}
|
||||||
@@ -184,15 +178,7 @@ sm:grid-cols-[1fr_min-content_min-content_min-content] sm:justify-self-end">
|
|||||||
|
|
||||||
<Overlay bind:hidden={loginOverlayHidden}>
|
<Overlay bind:hidden={loginOverlayHidden}>
|
||||||
<div class="bg-white w-full max-w-screen-sm py-8">
|
<div class="bg-white w-full max-w-screen-sm py-8">
|
||||||
<EmbeddedAuthFlowModule onLogin={loginAction} email={""} route="signup" title={
|
<EmbeddedAuthFlowModule onLogin={loginAction} email={""}></EmbeddedAuthFlowModule>
|
||||||
{
|
|
||||||
login: "Ausweisdaten speichern",
|
|
||||||
signup: "Ausweisdaten speichern"
|
|
||||||
}
|
|
||||||
} buttonText={{
|
|
||||||
login: "Speichern",
|
|
||||||
signup: "Speichern"
|
|
||||||
}}></EmbeddedAuthFlowModule>
|
|
||||||
</div>
|
</div>
|
||||||
</Overlay>
|
</Overlay>
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import HelpLabel from "#components/labels/HelpLabel.svelte";
|
import HelpLabel from "#components/labels/HelpLabel.svelte";
|
||||||
import Inputlabel from "#components/labels/InputLabel.svelte";
|
import Inputlabel from "#components/labels/InputLabel.svelte";
|
||||||
import PlzSuche from "#components/PlzSuche.svelte";
|
|
||||||
|
|
||||||
|
|
||||||
|
import ZipSearch from "#components/PlzSuche.svelte";
|
||||||
import { Enums } from "#lib/client/prisma.js";
|
import { Enums } from "#lib/client/prisma.js";
|
||||||
import { AufnahmeClient, ObjektClient } from "./types.js";
|
import { AufnahmeClient, ObjektClient } from "./types.js";
|
||||||
|
|
||||||
@@ -26,8 +27,6 @@
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let ortInput: HTMLInputElement;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -70,12 +69,9 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
|
|||||||
<div class="input-noHelp">
|
<div class="input-noHelp">
|
||||||
<Inputlabel title="PLZ *"></Inputlabel>
|
<Inputlabel title="PLZ *"></Inputlabel>
|
||||||
|
|
||||||
<PlzSuche
|
<ZipSearch
|
||||||
bind:zip={objekt.plz}
|
bind:zip={objekt.plz}
|
||||||
bind:city={objekt.ort}
|
bind:city={objekt.ort}
|
||||||
onchange={(e) => {
|
|
||||||
ortInput.dispatchEvent(new Event('change'));
|
|
||||||
}}
|
|
||||||
name="plz"
|
name="plz"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -89,7 +85,6 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
|
|||||||
readonly={false}
|
readonly={false}
|
||||||
required
|
required
|
||||||
bind:value={objekt.ort}
|
bind:value={objekt.ort}
|
||||||
bind:this={ortInput}
|
|
||||||
type="text"
|
type="text"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ xl:grid-cols-2 xl:gap-x-8 xl:gap-y-8
|
|||||||
>
|
>
|
||||||
<option>Bitte auswählen</option>
|
<option>Bitte auswählen</option>
|
||||||
{#each arrayRange(2.1, 4.5, 0.1) as step}
|
{#each arrayRange(2.1, 4.5, 0.1) as step}
|
||||||
<option value={step} selected={ausweis.geschosshoehe === step}>{step.toFixed(2)} m</option>
|
<option value={step}>{step.toFixed(2)} m</option>
|
||||||
{/each}
|
{/each}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|||||||
@@ -746,29 +746,24 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="flex flex-col flex-wrap items-left gap-2">
|
<div class="flex flex-col flex-wrap items-left gap-2">
|
||||||
|
|
||||||
{#if aufnahme.bilder.length > 0}
|
<h3 class="font-semibold text-lg">Bilder</h3>
|
||||||
<h3 class="font-semibold text-lg">Bilder</h3>
|
<div class="grid grid-cols-[1fr] md:grid-cols-[1fr,1fr,1fr] lg:grid-cols-[1fr,1fr,1fr] justify-start items-center gap-2">
|
||||||
<div class="grid grid-cols-[1fr] md:grid-cols-[1fr,1fr,1fr] lg:grid-cols-[1fr,1fr,1fr] justify-start items-center gap-2">
|
{#each aufnahme.bilder as bild, i (i)}
|
||||||
{#each aufnahme.bilder as bild, i (i)}
|
<img src="/bilder/{bild.id}.jpg" alt={bild.kategorie} loading="lazy" class="max-h-[10vh] h-full w-full object-contain">
|
||||||
<img src="/bilder/{bild.id}.jpg" alt={bild.kategorie} loading="lazy" class="max-h-[10vh] h-full w-full object-contain">
|
{/each}
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<h3 class="font-semibold text-lg">Unterlagen</h3>
|
||||||
|
<div class="text-sm">
|
||||||
|
{#if aufnahme.unterlagen.length > 0}
|
||||||
|
{#each aufnahme.unterlagen as unterlage}
|
||||||
|
<a href="/unterlagen/{unterlage.id}.{mime.getExtension(unterlage.mime)}" target="_blank" class="text-black flex flex-row items-center gap-2 bg-base-200 p-2 rounded-lg"><FileText size={32}></FileText> {unterlage.name}</a>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
{/if}
|
||||||
<hr>
|
</div>
|
||||||
{/if}
|
|
||||||
{#if aufnahme.unterlagen.length > 0}
|
|
||||||
<h3 class="font-semibold text-lg">Unterlagen</h3>
|
|
||||||
<div class="text-sm">
|
|
||||||
{#if aufnahme.unterlagen.length > 0}
|
|
||||||
{#each aufnahme.unterlagen as unterlage}
|
|
||||||
<a href="/unterlagen/{unterlage.id}.{mime.getExtension(unterlage.mime)}" target="_blank" class="text-black flex flex-row items-center gap-2 bg-base-200 p-2 rounded-lg"><FileText size={32}></FileText> {unterlage.name}</a>
|
|
||||||
{/each}
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Benachrichtigungen -->
|
<div class="dropdown dropdown-top items-end absolute bottom-4 right-4 z-50">
|
||||||
<!-- <div class="dropdown dropdown-top items-end absolute bottom-4 right-4 z-50">
|
|
||||||
<div class="indicator">
|
<div class="indicator">
|
||||||
{#if Object.keys($notifications).length > 0}
|
{#if Object.keys($notifications).length > 0}
|
||||||
<span class="indicator-item badge badge-accent text-xs"
|
<span class="indicator-item badge badge-accent text-xs"
|
||||||
@@ -787,7 +782,7 @@
|
|||||||
>
|
>
|
||||||
<NotificationProvider component={DashboardNotification} />
|
<NotificationProvider component={DashboardNotification} />
|
||||||
</ul>
|
</ul>
|
||||||
</div> -->
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { BedarfsausweisWohnenClient, ObjektClient, VerbrauchsausweisGewerbeClient, VerbrauchsausweisWohnenClient } from "./Ausweis/types.js";
|
import { BedarfsausweisWohnenClient, GEGNachweisWohnenClient, ObjektClient, UnterlageClient, VerbrauchsausweisGewerbeClient, VerbrauchsausweisWohnenClient } from "./Ausweis/types.js";
|
||||||
import { Trash, Upload } from "radix-svelte-icons";
|
import { Trash, Upload } from "radix-svelte-icons";
|
||||||
import HelpLabel from "#components/labels/HelpLabel.svelte";
|
import HelpLabel from "#components/labels/HelpLabel.svelte";
|
||||||
|
|
||||||
export let kategorie: string = "";
|
export let kategorie: string = "";
|
||||||
export let files: (Unterlage & { preview?: boolean })[] = [];
|
export let files: Unterlage[] = [];
|
||||||
export let max: number = Infinity;
|
export let max: number = Infinity;
|
||||||
export let min: number = 1;
|
export let min: number = 1;
|
||||||
export let name: string = "";
|
export let name: string = "";
|
||||||
@@ -26,8 +26,6 @@
|
|||||||
|
|
||||||
for (let i = 0; i < fileArray.length; i++) {
|
for (let i = 0; i < fileArray.length; i++) {
|
||||||
const file = fileArray[i];
|
const file = fileArray[i];
|
||||||
files.push({ preview: true, kategorie, name: file.name, mime: file.type, aufnahme_id: null, id: "" });
|
|
||||||
files = files;
|
|
||||||
|
|
||||||
if (i == max) {
|
if (i == max) {
|
||||||
break;
|
break;
|
||||||
@@ -63,14 +61,8 @@
|
|||||||
mime: mimeType,
|
mime: mimeType,
|
||||||
name: file.name
|
name: file.name
|
||||||
})
|
})
|
||||||
|
|
||||||
const placeholder = files.find((f) => f.name === fileArray[i].name && f.preview === true && f.kategorie === kategorie);
|
files.push({ id, kategorie, name: file.name, mime: mimeType, aufnahme_id: null });
|
||||||
if (!placeholder) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
placeholder!.preview = false;
|
|
||||||
placeholder!.id = id;
|
|
||||||
placeholder!.aufnahme_id = ausweis.id;
|
|
||||||
files = files;
|
files = files;
|
||||||
|
|
||||||
|
|
||||||
@@ -118,37 +110,23 @@
|
|||||||
<div class="grid grid-cols-2 gap-2">
|
<div class="grid grid-cols-2 gap-2">
|
||||||
{#each files as file, i}
|
{#each files as file, i}
|
||||||
{#if file.kategorie == kategorie}
|
{#if file.kategorie == kategorie}
|
||||||
{#if file.preview === true}
|
<div class="relative group">
|
||||||
<!-- Show loading spinner -->
|
<div
|
||||||
<div class="relative group">
|
class="h-full max-h-96 w-full rounded-lg border-2 group-hover:contrast-50 object-cover transition-all text-center items-center flex p-4 text-opacity-75 text-black"
|
||||||
<div
|
>{file.name}</div>
|
||||||
class="h-full max-h-96 w-full rounded-lg border-2 group-hover:contrast-50 object-cover transition-all text-center items-center justify-center flex p-4 text-opacity-75 text-black"
|
<div class="invisible group-hover:visible absolute left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] flex flex-row gap-2">
|
||||||
>
|
<button
|
||||||
<div class="flex flex-row gap-4">
|
type="button"
|
||||||
<span>{file.name}</span>
|
class="rounded-full w-[30px] h-[30px] flex items-center justify-center p-0 bg-[rgba(0,0,0,0.4)]"
|
||||||
<span class="loader"></span>
|
on:click={() => {
|
||||||
</div>
|
delete files[i];
|
||||||
</div>
|
files = files.filter((x) => x);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Trash size={20} color="#fff"></Trash>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
</div>
|
||||||
<div class="relative group">
|
|
||||||
<div
|
|
||||||
class="h-full max-h-96 w-full rounded-lg border-2 group-hover:contrast-50 object-cover transition-all text-center items-center flex p-4 text-opacity-75 text-black"
|
|
||||||
>{file.name}</div>
|
|
||||||
<div class="invisible group-hover:visible absolute left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] flex flex-row gap-2">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="rounded-full w-[30px] h-[30px] flex items-center justify-center p-0 bg-[rgba(0,0,0,0.4)]"
|
|
||||||
on:click={() => {
|
|
||||||
delete files[i];
|
|
||||||
files = files.filter((x) => x);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Trash size={20} color="#fff"></Trash>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
|
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
|
||||||
|
|
||||||
export let images: (BildClient & { preview?: boolean })[] = [];
|
export let images: BildClient[] = [];
|
||||||
export let max: number = Infinity;
|
export let max: number = Infinity;
|
||||||
export let min: number = 1;
|
export let min: number = 1;
|
||||||
export let name: string = "";
|
export let name: string = "";
|
||||||
@@ -35,43 +35,40 @@
|
|||||||
<div class="grid grid-cols-2 gap-2">
|
<div class="grid grid-cols-2 gap-2">
|
||||||
{#each images as image, i}
|
{#each images as image, i}
|
||||||
{#if image.kategorie == kategorie}
|
{#if image.kategorie == kategorie}
|
||||||
{#if image.preview === true}
|
<div class="relative group">
|
||||||
<!-- Show loading spinner -->
|
<img
|
||||||
<div class="relative group">
|
src="/bilder/{image.id}.jpg"
|
||||||
<div
|
alt={kategorie}
|
||||||
class="h-full max-h-96 w-full rounded-lg border-2 group-hover:contrast-50 object-cover transition-all text-center items-center justify-center flex p-4 text-opacity-75 text-black"
|
class="h-full max-h-96 w-full rounded-lg border-2 group-hover:contrast-50 object-cover transition-all"
|
||||||
>
|
/>
|
||||||
<div class="flex flex-row gap-4">
|
<div class="invisible group-hover:visible absolute left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] flex flex-row gap-2">
|
||||||
<span class="loader"></span>
|
<button
|
||||||
</div>
|
type="button"
|
||||||
</div>
|
class="rounded-full w-[30px] h-[30px] flex items-center justify-center p-0 bg-[rgba(0,0,0,0.4)]"
|
||||||
</div>
|
on:click={() => {
|
||||||
{:else}
|
deleteImage(images[i])
|
||||||
<div class="relative group">
|
}}
|
||||||
<img
|
>
|
||||||
src="/bilder/{image.id}.jpg"
|
<Trash size={20} color="#fff"></Trash>
|
||||||
alt={kategorie}
|
</button>
|
||||||
class="h-full max-h-96 w-full rounded-lg border-2 group-hover:contrast-50 object-cover transition-all"
|
<!-- <button
|
||||||
/>
|
type="button"
|
||||||
<div class="invisible group-hover:visible absolute left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] flex flex-row gap-2">
|
class="rounded-full w-[30px] h-[30px] flex items-center justify-center p-0 bg-[rgba(0,0,0,0.4)]"
|
||||||
<button
|
on:click={async () => {
|
||||||
type="button"
|
let image = await rotateImage(images[i]);
|
||||||
class="rounded-full w-[30px] h-[30px] flex items-center justify-center p-0 bg-[rgba(0,0,0,0.4)]"
|
images[i] = image;
|
||||||
on:click={() => {
|
images = images
|
||||||
deleteImage(images[i])
|
}}
|
||||||
}}
|
>
|
||||||
>
|
<RotateCounterClockwise size={20} color="#fff"></RotateCounterClockwise>
|
||||||
<Trash size={20} color="#fff"></Trash>
|
</button> -->
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
<!-- Wir zeigen Platzhalter an, damit der Nutzer sieht wie viele Bilder er hochladen soll -->
|
<!-- Wir zeigen Platzhalter an, damit der Nutzer sieht wie viele Bilder er hochladen soll -->
|
||||||
{#each { length: Math.max(0, Math.min(max, 4) - images.filter(image => image.kategorie === kategorie).length) } as _, i}
|
{#each { length: Math.max(0, Math.min(max, 4) - images.filter(image => image.kategorie === kategorie).length) } as _, i}
|
||||||
|
|
||||||
<div class="relative group">
|
<div class="relative group">
|
||||||
<img
|
<img
|
||||||
src="/placeholder.png"
|
src="/placeholder.png"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
export let readonly: boolean = false;
|
export let readonly: boolean = false;
|
||||||
export let city: string | null | undefined;
|
export let city: string | null | undefined;
|
||||||
export let zip: string | null = "";
|
export let zip: string | null = "";
|
||||||
export let onchange: (event: Event) => void = () => {};
|
|
||||||
|
|
||||||
let hideZipDropdown: boolean = true;
|
let hideZipDropdown: boolean = true;
|
||||||
let zipCodes: inferOutput<API["postleitzahlen"]["GET"]> = [];
|
let zipCodes: inferOutput<API["postleitzahlen"]["GET"]> = [];
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
export let onFocusIn: () => any = () => {};
|
export let onFocusIn: () => any = () => {};
|
||||||
export let onFocusOut: () => any = () => {};
|
export let onFocusOut: () => any = () => {};
|
||||||
export let className: string = "";
|
export let className: string = "";
|
||||||
export let required: boolean = false;
|
|
||||||
|
|
||||||
function addTag(tag: string) {
|
function addTag(tag: string) {
|
||||||
if ((onlyUnique && tags.indexOf(tag) > -1) || maxTags == tags.length) {
|
if ((onlyUnique && tags.indexOf(tag) > -1) || maxTags == tags.length) {
|
||||||
@@ -49,8 +48,6 @@
|
|||||||
tag = ""
|
tag = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$: required = tags.length > 0 ? false : required;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -86,7 +83,6 @@
|
|||||||
class="input input-bordered h-10 px-2 py-1.5 {className}"
|
class="input input-bordered h-10 px-2 py-1.5 {className}"
|
||||||
{minlength}
|
{minlength}
|
||||||
{maxlength}
|
{maxlength}
|
||||||
{required}
|
|
||||||
disabled={disable}
|
disabled={disable}
|
||||||
readonly={readonly}
|
readonly={readonly}
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
import { addNotification } from "./Notifications/shared.js";
|
import { addNotification } from "./Notifications/shared.js";
|
||||||
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
|
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
|
||||||
|
|
||||||
export let images: (BildClient & { preview?: boolean })[] = [];
|
export let images: BildClient[] = [];
|
||||||
export let ausweis:
|
export let ausweis:
|
||||||
| VerbrauchsausweisWohnenClient
|
| VerbrauchsausweisWohnenClient
|
||||||
| VerbrauchsausweisGewerbeClient
|
| VerbrauchsausweisGewerbeClient
|
||||||
@@ -39,6 +39,8 @@
|
|||||||
|
|
||||||
for (let i = 0; i < files.length; i++) {
|
for (let i = 0; i < files.length; i++) {
|
||||||
const file = files[i];
|
const file = files[i];
|
||||||
|
console.log(file);
|
||||||
|
|
||||||
|
|
||||||
if (file.type !== "image/jpeg" && file.type !== "image/png" && file.type !== "image/webp" && file.type !== "image/heif" && file.type !== "image/heic") {
|
if (file.type !== "image/jpeg" && file.type !== "image/png" && file.type !== "image/webp" && file.type !== "image/heif" && file.type !== "image/heic") {
|
||||||
continue;
|
continue;
|
||||||
@@ -48,9 +50,6 @@
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
images.push({ preview: true, benutzer_id: null, kategorie, created_at: new Date(), updated_at: new Date(), id: "" });
|
|
||||||
images = images;
|
|
||||||
|
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
|
|
||||||
reader.onload = async () => {
|
reader.onload = async () => {
|
||||||
@@ -120,19 +119,8 @@
|
|||||||
dismissable: true
|
dismissable: true
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
const index = images.findIndex((img) => img.preview === true);
|
images.push({ id: result.id, kategorie });
|
||||||
|
images = images;
|
||||||
if (index !== -1) {
|
|
||||||
delete images[index];
|
|
||||||
images = images.filter((img) => img);
|
|
||||||
}
|
|
||||||
images = [...images, {
|
|
||||||
benutzer_id: null,
|
|
||||||
created_at: new Date(),
|
|
||||||
updated_at: new Date(),
|
|
||||||
id: result.id,
|
|
||||||
kategorie
|
|
||||||
}];
|
|
||||||
|
|
||||||
if (i == Math.min(files.length, max) - 1) {
|
if (i == Math.min(files.length, max) - 1) {
|
||||||
this.value = "";
|
this.value = "";
|
||||||
|
|||||||
@@ -2,11 +2,6 @@ import { prisma } from "#lib/server/prisma.js";
|
|||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import csv from "csvtojson"
|
import csv from "csvtojson"
|
||||||
|
|
||||||
if (!process.env.prev_restart_delay && process.env.cron_restart) {
|
|
||||||
console.log('skipping initial launch....');
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Als erstes schauen wir, welches das letzte Jahr ist, für das wir einen Verbrauchsausweis haben.
|
// Als erstes schauen wir, welches das letzte Jahr ist, für das wir einen Verbrauchsausweis haben.
|
||||||
// Das machen wir, indem wir die Ausweise nach Jahr und Monat sortieren und dann den letzten Eintrag nehmen.
|
// Das machen wir, indem wir die Ausweise nach Jahr und Monat sortieren und dann den letzten Eintrag nehmen.
|
||||||
const newestDate = await prisma.klimafaktoren.findFirst({
|
const newestDate = await prisma.klimafaktoren.findFirst({
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export const BenutzerSchema = z.object({
|
|||||||
ort: z.string().nullish(),
|
ort: z.string().nullish(),
|
||||||
adresse: z.string().nullish(),
|
adresse: z.string().nullish(),
|
||||||
telefon: z.string().nullish(),
|
telefon: z.string().nullish(),
|
||||||
empfaenger: z.string().nullish(),
|
anrede: z.string().nullish(),
|
||||||
rolle: z.nativeEnum(BenutzerRolle),
|
rolle: z.nativeEnum(BenutzerRolle),
|
||||||
firma: z.string().nullish(),
|
firma: z.string().nullish(),
|
||||||
lex_office_id: z.string().nullish(),
|
lex_office_id: z.string().nullish(),
|
||||||
|
|||||||
@@ -18,6 +18,20 @@ const { title } = Astro.props;
|
|||||||
---
|
---
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
// import { H } from "highlight.run";
|
||||||
|
|
||||||
|
// if (import.meta.env.PROD) {
|
||||||
|
// H.init("1jdkoe52", {
|
||||||
|
// serviceName: "online-energieausweis",
|
||||||
|
// backendUrl: "https://highlight-backend.online-energieausweis.org/public",
|
||||||
|
// tracingOrigins: true,
|
||||||
|
// networkRecording: {
|
||||||
|
// enabled: true,
|
||||||
|
// recordHeadersAndBody: true
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
window.addEventListener("scroll", () => {
|
window.addEventListener("scroll", () => {
|
||||||
const skala = document.getElementById("skala");
|
const skala = document.getElementById("skala");
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,22 @@ export interface Props {
|
|||||||
const { title } = Astro.props;
|
const { title } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// import { H } from "highlight.run";
|
||||||
|
|
||||||
|
// if (import.meta.env.PROD) {
|
||||||
|
// H.init("1jdkoe52", {
|
||||||
|
// serviceName: "online-energieausweis",
|
||||||
|
// backendUrl: "https://highlight-backend.online-energieausweis.org/public",
|
||||||
|
// tracingOrigins: true,
|
||||||
|
// networkRecording: {
|
||||||
|
// enabled: true,
|
||||||
|
// recordHeadersAndBody: true
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="de">
|
<html lang="de">
|
||||||
|
|||||||
@@ -34,6 +34,22 @@ const schema = JSON.stringify({
|
|||||||
});
|
});
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// import { H } from "highlight.run";
|
||||||
|
|
||||||
|
// if (import.meta.env.PROD) {
|
||||||
|
// H.init("1jdkoe52", {
|
||||||
|
// serviceName: "online-energieausweis",
|
||||||
|
// backendUrl: "https://highlight-backend.online-energieausweis.org/public",
|
||||||
|
// tracingOrigins: true,
|
||||||
|
// networkRecording: {
|
||||||
|
// enabled: true,
|
||||||
|
// recordHeadersAndBody: true
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
</script>
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="de">
|
<html lang="de">
|
||||||
<head>
|
<head>
|
||||||
|
|||||||
@@ -45,6 +45,31 @@ const schema = JSON.stringify({
|
|||||||
let lightTheme = Astro.cookies.get("theme")?.value === "light";
|
let lightTheme = Astro.cookies.get("theme")?.value === "light";
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<script >
|
||||||
|
// import { H } from "highlight.run";
|
||||||
|
|
||||||
|
// const user = JSON.parse(document.body.dataset.user);
|
||||||
|
|
||||||
|
// if (import.meta.env.PROD) {
|
||||||
|
// H.init("1jdkoe52", {
|
||||||
|
// serviceName: "online-energieausweis",
|
||||||
|
// backendUrl:
|
||||||
|
// "https://highlight-backend.online-energieausweis.org/public",
|
||||||
|
// tracingOrigins: true,
|
||||||
|
// networkRecording: {
|
||||||
|
// enabled: true,
|
||||||
|
// recordHeadersAndBody: true,
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// if (user) {
|
||||||
|
// H.identify(user.email, {
|
||||||
|
// id: user.id
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
</script>
|
||||||
|
|
||||||
<html lang="de">
|
<html lang="de">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
|
|||||||
@@ -19,6 +19,19 @@ const { title } = Astro.props;
|
|||||||
---
|
---
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
// import { H } from "highlight.run";
|
||||||
|
|
||||||
|
// if (import.meta.env.PROD) {
|
||||||
|
// H.init("1jdkoe52", {
|
||||||
|
// serviceName: "online-energieausweis",
|
||||||
|
// backendUrl: "https://highlight-backend.online-energieausweis.org/public",
|
||||||
|
// tracingOrigins: true,
|
||||||
|
// networkRecording: {
|
||||||
|
// enabled: true,
|
||||||
|
// recordHeadersAndBody: true
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
window.addEventListener("scroll", (event) => {
|
window.addEventListener("scroll", (event) => {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { memoize } from "./Memoization.js";
|
|||||||
import { api } from "astro-typesafe-api/client"
|
import { api } from "astro-typesafe-api/client"
|
||||||
|
|
||||||
export const getKlimafaktoren = memoize(async (date: Date, plz: string) => {
|
export const getKlimafaktoren = memoize(async (date: Date, plz: string) => {
|
||||||
if (!plz || plz.length < 5 || !date) {
|
if (!plz || !date) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
import winston, { format} from "winston";
|
|
||||||
|
|
||||||
const { combine, timestamp } = format;
|
|
||||||
|
|
||||||
const loggingFormat = format.printf(({ level, message, timestamp }) => {
|
|
||||||
return `${timestamp} [${level}]: ${message}`;
|
|
||||||
});
|
|
||||||
|
|
||||||
export const logger = winston.createLogger({
|
|
||||||
level: "info",
|
|
||||||
format: combine(
|
|
||||||
timestamp(),
|
|
||||||
loggingFormat
|
|
||||||
),
|
|
||||||
transports: [
|
|
||||||
new winston.transports.File({ filename: "error.log", level: "error" }),
|
|
||||||
new winston.transports.File({ filename: "combined.log" }),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== "production") {
|
|
||||||
logger.add(new winston.transports.Console({
|
|
||||||
format: combine(timestamp(), loggingFormat),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,6 @@ import os from "os"
|
|||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
|
|
||||||
export const PERSISTENT_DIR = `${os.homedir()}/persistent/online-energieausweis`
|
export const PERSISTENT_DIR = `${os.homedir()}/persistent/online-energieausweis`
|
||||||
export const SECRET = process.env.SECRET as string
|
|
||||||
|
|
||||||
if (!fs.existsSync(PERSISTENT_DIR)) {
|
if (!fs.existsSync(PERSISTENT_DIR)) {
|
||||||
fs.mkdirSync(PERSISTENT_DIR, {recursive: true})
|
fs.mkdirSync(PERSISTENT_DIR, {recursive: true})
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
import { transport } from "#lib/mail.js";
|
|
||||||
import {
|
|
||||||
Benutzer,
|
|
||||||
} from "#lib/client/prisma.js";
|
|
||||||
|
|
||||||
export async function sendAutoRegisterMail(
|
|
||||||
user: Benutzer,
|
|
||||||
password: string
|
|
||||||
) {
|
|
||||||
await transport.sendMail({
|
|
||||||
from: `"IBCornelsen" <info@online-energieausweis.org>`,
|
|
||||||
to: user.email,
|
|
||||||
subject: `Ihre Registrierung bei IBCornelsen`,
|
|
||||||
bcc: "info@online-energieausweis.org",
|
|
||||||
html: `<p>Sehr geehrte/r Kund/in,</p>
|
|
||||||
<p>vielen Dank für Ihre Registrierung bei IBCornelsen. Ihr Benutzerkonto wurde erfolgreich erstellt.<br><br>
|
|
||||||
|
|
||||||
Nachfolgend finden Sie Ihre Zugangsdaten:<br><br>
|
|
||||||
E-Mail: ${user.email}<br>
|
|
||||||
Passwort: ${password}<br><br>
|
|
||||||
|
|
||||||
Sollten Sie diese Registrierung nicht vorgenommen haben, können Sie diese E-Mail einfach ignorieren. Ihr Benutzerkonto wird in diesem Fall nicht aktiviert.<br><br>
|
|
||||||
|
|
||||||
Falls Sie Fragen haben oder Unterstützung benötigen, stehen wir Ihnen gerne zur Verfügung. Kontaktieren Sie uns einfach unter <a href="mailto:support@online-energieausweis.org">support@online-energieausweis.org</a>.
|
|
||||||
<p>
|
|
||||||
Mit freundlichen Grüßen,
|
|
||||||
<br>
|
|
||||||
Dipl.-Ing. Jens Cornelsen
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
<strong>IB Cornelsen</strong>
|
|
||||||
<br>
|
|
||||||
Katendeich 5A
|
|
||||||
<br>
|
|
||||||
21035 Hamburg
|
|
||||||
<br>
|
|
||||||
www.online-energieausweis.org
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
fon 040 · 209339850
|
|
||||||
<br>
|
|
||||||
fax 040 · 209339859
|
|
||||||
</p>`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -75,6 +75,6 @@ export async function sendInvoiceMail(
|
|||||||
name: rechnung.empfaenger || "",
|
name: rechnung.empfaenger || "",
|
||||||
},
|
},
|
||||||
bcc: "info@online-energieausweis.org",
|
bcc: "info@online-energieausweis.org",
|
||||||
html: `<p>Sehr geehrte/r ${user.vorname} ${user.name},</p>` + getPaymentInvoiceBody(ausweis, rechnung, ausweisart),
|
html: `<p>Sehr geehrte*r ${user.vorname} ${user.name},</p>` + getPaymentInvoiceBody(ausweis, rechnung, ausweisart),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,6 @@ export async function sendPaymentSuccessMail(
|
|||||||
name: rechnung.empfaenger || "",
|
name: rechnung.empfaenger || "",
|
||||||
},
|
},
|
||||||
bcc: "info@online-energieausweis.org",
|
bcc: "info@online-energieausweis.org",
|
||||||
html: `<p>Sehr geehrte/r ${user.vorname} ${user.name},</p>` + getPaymentSuccessBody(ausweis, rechnung, ausweisart),
|
html: `<p>Sehr geehrte*r ${user.vorname} ${user.name},</p>` + getPaymentSuccessBody(ausweis, rechnung, ausweisart),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,31 @@
|
|||||||
|
import { BASE_URI } from "#lib/constants.js";
|
||||||
import { transport } from "#lib/mail.js";
|
import { transport } from "#lib/mail.js";
|
||||||
import {
|
import {
|
||||||
Benutzer,
|
Benutzer,
|
||||||
} from "#lib/client/prisma.js";
|
} from "#lib/client/prisma.js";
|
||||||
|
import { encodeToken } from "#lib/auth/token.js";
|
||||||
|
import { TokenType } from "#lib/auth/types.js";
|
||||||
|
|
||||||
export async function sendRegisterMail(
|
export async function sendRegisterMail(
|
||||||
user: Benutzer,
|
user: Benutzer
|
||||||
passwort: string
|
|
||||||
) {
|
) {
|
||||||
|
const verificationJwt = encodeToken({
|
||||||
|
typ: TokenType.Verify,
|
||||||
|
exp: Date.now() + (15 * 60 * 1000),
|
||||||
|
id: user.id
|
||||||
|
})
|
||||||
|
|
||||||
await transport.sendMail({
|
await transport.sendMail({
|
||||||
from: `"IBCornelsen" <info@online-energieausweis.org>`,
|
from: `"IBCornelsen" <info@online-energieausweis.org>`,
|
||||||
to: user.email,
|
to: user.email,
|
||||||
subject: `Ihre Registrierung bei IBCornelsen`,
|
subject: `Ihre Registrierung bei IBCornelsen`,
|
||||||
bcc: "info@online-energieausweis.org",
|
bcc: "info@online-energieausweis.org",
|
||||||
html: `<p>Sehr geehrte/r ${user.vorname} ${user.name},</p>
|
html: `<p>Sehr geehrte*r ${user.vorname} ${user.name},</p>
|
||||||
<p>vielen Dank für Ihre Registrierung bei IBCornelsen. Ihr Benutzerkonto wurde erfolgreich erstellt.<br><br>
|
<p>vielen Dank für Ihre Registrierung bei IBCornelsen. Ihr Benutzerkonto wurde erfolgreich erstellt.<br><br>
|
||||||
|
|
||||||
Nachfolgend finden Sie Ihre Zugangsdaten:<br><br>
|
Um Ihre Registrierung abzuschließen, klicken Sie bitte auf den folgenden Link, um Ihre E-Mail-Adresse zu bestätigen:<br><br>
|
||||||
E-Mail: ${user.email}<br>
|
|
||||||
Passwort: ${passwort}<br><br>
|
|
||||||
|
|
||||||
Aus Sicherheitsgründen empfehlen wir Ihnen, Ihr Passwort nach dem ersten Login zu ändern.<br><br>
|
|
||||||
Um sich anzumelden, besuchen Sie bitte unsere Website unter <a href="https://online-energieausweis.org/auth/login">online-energieausweis.org/auth/login</a>.<br><br>
|
|
||||||
|
|
||||||
Sollten Sie diese Registrierung nicht vorgenommen haben, können Sie diese E-Mail einfach ignorieren. Ihr Benutzerkonto wird in diesem Fall nicht aktiviert.<br><br>
|
<a href="${BASE_URI}/auth/verify?t=${verificationJwt}">E-Mail-Adresse bestätigen</a><br></p>
|
||||||
|
|
||||||
Falls Sie Fragen haben oder Unterstützung benötigen, stehen wir Ihnen gerne zur Verfügung. Kontaktieren Sie uns einfach unter <a href="mailto:support@online-energieausweis.org">support@online-energieausweis.org</a>.
|
|
||||||
<p>
|
<p>
|
||||||
Mit freundlichen Grüßen,
|
Mit freundlichen Grüßen,
|
||||||
<br>
|
<br>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export async function sendAusweisGespeichertMail(user: Benutzer, ausweis_id: str
|
|||||||
from: `"IBCornelsen" <info@online-energieausweis.org>`,
|
from: `"IBCornelsen" <info@online-energieausweis.org>`,
|
||||||
to: user.email,
|
to: user.email,
|
||||||
subject: `Ihr Ausweis wurde gespeichert - IBCornelsen - (ID: ${ausweis_id})`,
|
subject: `Ihr Ausweis wurde gespeichert - IBCornelsen - (ID: ${ausweis_id})`,
|
||||||
html: `<p>Sehr geehrte/r ${user.vorname} ${user.name},</p>
|
html: `<p>Sehr geehrte*r ${user.vorname} ${user.name},</p>
|
||||||
<p>Ihr Energieausweis wurde erfolgreich in Ihrem Konto gespeichert. Sie können ihn jederzeit in Ihrem Kundenbereich abrufen.<br><br>
|
<p>Ihr Energieausweis wurde erfolgreich in Ihrem Konto gespeichert. Sie können ihn jederzeit in Ihrem Kundenbereich abrufen.<br><br>
|
||||||
|
|
||||||
Ihre Vorgänge und Ausweise können Sie in Ihrem Kundenkonto einsehen und bearbeiten:<br><br>
|
Ihre Vorgänge und Ausweise können Sie in Ihrem Kundenkonto einsehen und bearbeiten:<br><br>
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
try {
|
try {
|
||||||
sent = true
|
sent = true
|
||||||
const response = await api.auth["passwort-vergessen"].GET.fetch({
|
const response = await api.auth["passwort-vergessen"].GET.fetch({
|
||||||
redirect,
|
|
||||||
email
|
email
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -58,7 +57,7 @@
|
|||||||
{#if showEmailSuccess}
|
{#if showEmailSuccess}
|
||||||
<div class="flex-row justify-between" style="margin-top: 10px">
|
<div class="flex-row justify-between" style="margin-top: 10px">
|
||||||
<a class="link link-hover"
|
<a class="link link-hover"
|
||||||
href="/auth/login{redirect ? `?r=${redirect}` : ""}">Einloggen</a
|
href="/auth/login{redirect ? `?redirect=${redirect}` : ""}">Einloggen</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
let passwortWiederholen: string;
|
let passwortWiederholen: string;
|
||||||
|
|
||||||
export let token: string;
|
export let token: string;
|
||||||
export let redirect: string | null = null;
|
|
||||||
|
|
||||||
let disabled = false;
|
let disabled = false;
|
||||||
|
|
||||||
@@ -29,7 +28,7 @@
|
|||||||
})
|
})
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location.href = "/auth/login?r=" + encodeURIComponent(redirect ?? "/dashboard")
|
window.location.href = "/auth/login"
|
||||||
}, 5000)
|
}, 5000)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
disabled = false
|
disabled = false
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {
|
import {
|
||||||
|
Reader,
|
||||||
|
EnvelopeClosed,
|
||||||
|
Cube,
|
||||||
Person,
|
Person,
|
||||||
} from "radix-svelte-icons";
|
} from "radix-svelte-icons";
|
||||||
import { Tabs, Tab, TabList, TabPanel } from "../../components/Tabs/index.js";
|
import { Tabs, Tab, TabList, TabPanel } from "../../components/Tabs/index.js";
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { addNotification } from "#components/Notifications/shared.js";
|
|
||||||
import { loginClient } from "#lib/login.js";
|
import { loginClient } from "#lib/login.js";
|
||||||
import EmbeddedLoginModule from "./EmbeddedLoginModule.svelte"
|
import EmbeddedLoginModule from "./EmbeddedLoginModule.svelte"
|
||||||
import EmbeddedRegisterModule from "./EmbeddedRegisterModule.svelte"
|
import EmbeddedRegisterModule from "./EmbeddedRegisterModule.svelte"
|
||||||
@@ -8,31 +7,22 @@
|
|||||||
export let email: string = "";
|
export let email: string = "";
|
||||||
export let password: string = "";
|
export let password: string = "";
|
||||||
export let route: "login" | "signup" = "login"
|
export let route: "login" | "signup" = "login"
|
||||||
export let title: Record<typeof route, string> = {
|
|
||||||
login: "Einloggen",
|
|
||||||
signup: "Registrieren"
|
|
||||||
}
|
|
||||||
export let buttonText: Record<typeof route, string> = {
|
|
||||||
login: "Einloggen",
|
|
||||||
signup: "Registrieren"
|
|
||||||
}
|
|
||||||
|
|
||||||
const navigate = (target: string) => {
|
const navigate = (target: string) => {
|
||||||
route = target as typeof route;
|
route = target as typeof route;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loginData = {
|
||||||
|
email,
|
||||||
|
passwort: "",
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if route == "login"}
|
{#if route == "login"}
|
||||||
<EmbeddedLoginModule onLogin={onLogin} bind:email bind:password {navigate} title={title.login} buttonText={buttonText.login} />
|
<EmbeddedLoginModule onLogin={onLogin} bind:email bind:password {navigate} />
|
||||||
{:else if route == "signup"}
|
{:else}
|
||||||
<EmbeddedRegisterModule bind:email onRegister={(response) => {
|
<EmbeddedRegisterModule bind:email bind:password onRegister={(response) => {
|
||||||
addNotification({
|
email = response.email
|
||||||
message: "Registrierung erfolgreich",
|
navigate("login")
|
||||||
subtext: "Ein Passwort wurde an ihre Email Adresse gesendet, sie werden nun automatisch weitergeleitet..",
|
}} {navigate} />
|
||||||
type: "success",
|
|
||||||
timeout: 6000,
|
|
||||||
dismissable: true
|
|
||||||
})
|
|
||||||
onLogin(response)
|
|
||||||
}} {navigate} title={title.signup} buttonText={buttonText.signup} />
|
|
||||||
{/if}
|
{/if}
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { addNotification } from "@ibcornelsen/ui";
|
||||||
import { loginClient } from "#lib/login.js";
|
import { loginClient } from "#lib/login.js";
|
||||||
|
|
||||||
export let navigate: (target: string) => void;
|
export let navigate: (target: string) => void;
|
||||||
export let email: string;
|
export let email: string;
|
||||||
export let password: string;
|
export let password: string;
|
||||||
export let title: string = "Einloggen";
|
|
||||||
export let buttonText: string = "Einloggen";
|
|
||||||
|
|
||||||
export let onLogin: (response: Awaited<ReturnType<typeof loginClient>>) => any;
|
export let onLogin: (response: Awaited<ReturnType<typeof loginClient>>) => any;
|
||||||
|
|
||||||
@@ -14,19 +13,21 @@
|
|||||||
const response = await loginClient(email, password)
|
const response = await loginClient(email, password)
|
||||||
|
|
||||||
if (response === null) {
|
if (response === null) {
|
||||||
error = true;
|
addNotification({
|
||||||
errorMessage = "Das hat leider nicht geklappt, haben sie ihr Passwort und ihre Email Adresse richtig eingegeben?"
|
message: "Ups...",
|
||||||
|
subtext: "Das hat leider nicht geklappt, haben sie ihr Passwort und ihre Email Adresse richtig eingegeben?",
|
||||||
|
type: "error",
|
||||||
|
timeout: 6000,
|
||||||
|
dismissable: true
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
onLogin(response);
|
onLogin(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let error = false;
|
|
||||||
let errorMessage = "";
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<form class="max-w-md mx-auto" on:submit={login} name="login">
|
<form style="width:50%;margin: 0 auto" on:submit={login} name="login">
|
||||||
<h1 class="text-3xl mb-4 p-0">{title}</h1>
|
<h1 class="text-2xl font-semibold mb-6">Einloggen</h1>
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<div>
|
<div>
|
||||||
<h4>Email</h4>
|
<h4>Email</h4>
|
||||||
@@ -36,7 +37,6 @@
|
|||||||
placeholder="Email"
|
placeholder="Email"
|
||||||
name="email"
|
name="email"
|
||||||
bind:value={email}
|
bind:value={email}
|
||||||
on:focus={() => (error = false)}
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -48,19 +48,13 @@
|
|||||||
placeholder="********"
|
placeholder="********"
|
||||||
name="passwort"
|
name="passwort"
|
||||||
bind:value={password}
|
bind:value={password}
|
||||||
on:focus={() => (error = false)}
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{#if error}
|
<button class="button" type="submit">Einloggen</button>
|
||||||
<div class="bg-red-200 p-4 rounded-lg w-full">
|
|
||||||
<p class="text-red-800">{errorMessage}</p>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
<button class="button" type="submit">{buttonText}</button>
|
|
||||||
<div class="flex flex-row justify-between" style="margin-top: 10px">
|
<div class="flex flex-row justify-between" style="margin-top: 10px">
|
||||||
<a on:click={() => navigate("signup")} class="cursor-pointer" data-cy="registrieren">Registrieren</a>
|
<a on:click={() => navigate("signup")} class="cursor-pointer" data-cy="registrieren">Registrieren</a>
|
||||||
<a href="/auth/passwort-vergessen?r={window.location.href}">Passwort Vergessen?</a>
|
<a href="/user/passwort_vergessen">Passwort Vergessen?</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -1,51 +1,74 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { loginClient } from "#lib/login.js";
|
import { addNotification } from "@ibcornelsen/ui";
|
||||||
import { api } from "astro-typesafe-api/client";
|
import { api } from "astro-typesafe-api/client";
|
||||||
|
|
||||||
export let navigate: (target: string) => void;
|
export let navigate: (target: string) => void;
|
||||||
export let onRegister: (response: Awaited<ReturnType<typeof loginClient>>) => void;
|
export let onRegister: (response: { email: string, name: string, vorname: string }) => void;
|
||||||
|
export let password: string;
|
||||||
export let email: string;
|
export let email: string;
|
||||||
export let title: string = "Registrieren";
|
let vorname: string;
|
||||||
export let buttonText: string = "Registrieren";
|
let name: string;
|
||||||
let repeatEmail: string;
|
|
||||||
|
|
||||||
async function signup(e: SubmitEvent) {
|
async function signUp(e: SubmitEvent) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
if (email !== repeatEmail) {
|
|
||||||
error = true;
|
|
||||||
errorMessage = "Die eingegebenen Email Adressen stimmen nicht überein.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { id, passwort } = await api.user.autocreate.PUT.fetch({
|
const response = await api.user.PUT.fetch({
|
||||||
email,
|
email,
|
||||||
|
passwort: password,
|
||||||
|
vorname,
|
||||||
|
name,
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await loginClient(email, passwort)
|
onRegister({
|
||||||
onRegister(response);
|
email,
|
||||||
|
name,
|
||||||
|
vorname
|
||||||
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = true;
|
addNotification({
|
||||||
errorMessage = "Sie besitzen bereits ein Konto bei IBC. Bitte loggen Sie sich mit Ihrem Passwort ein oder vergeben sich über “Passwort vergessen” ein neues."
|
message: "Ups...",
|
||||||
navigate("login");
|
subtext:
|
||||||
|
"Da ist wohl etwas schiefgelaufen. Diese Email Adresse ist bereits in Benutzung, haben sie vielleicht bereits ein Konto bei uns?",
|
||||||
|
type: "error",
|
||||||
|
timeout: 0,
|
||||||
|
dismissable: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let error: boolean = false;
|
|
||||||
let errorMessage: string = "";
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<form class="max-w-md mx-auto" name="signup" on:submit={signup}>
|
<form style="width:50%;margin: 0 auto" name="signup" on:submit={signUp}>
|
||||||
<h1 class="text-3xl mb-4 p-0">{title}</h1>
|
<h1>Registrieren</h1>
|
||||||
<p class="p-0 text-base">Ihre Ausweisdaten werden bei uns gespeichert und Ihnen wird ein vorläufiges Passwort erstellt. Sollte Ihre E-Mail bereits bei uns registriert sein, dann loggen Sie sich bitte mit Ihrem vorhandenen Passwort ein oder vergeben sich ein neues über “Passwort vergessen”.</p>
|
|
||||||
<hr>
|
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
|
<div class="flex flex-row gap-4 w-full">
|
||||||
|
<div class="w-1/2">
|
||||||
|
<h4>Vorname</h4>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Vorname"
|
||||||
|
name="vorname"
|
||||||
|
class="px-2.5 py-1.5 rounded-lg border bg-gray-50"
|
||||||
|
bind:value={vorname}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="w-1/2">
|
||||||
|
<h4>Nachname</h4>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Nachname"
|
||||||
|
name="nachname"
|
||||||
|
class="px-2.5 py-1.5 rounded-lg border bg-gray-50"
|
||||||
|
bind:value={name}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h4>Email</h4>
|
<h4>Email</h4>
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
placeholder="max.mustermann@email.de"
|
placeholder="Email"
|
||||||
name="email"
|
name="email"
|
||||||
class="px-2.5 py-1.5 rounded-lg border bg-gray-50"
|
class="px-2.5 py-1.5 rounded-lg border bg-gray-50"
|
||||||
bind:value={email}
|
bind:value={email}
|
||||||
@@ -53,27 +76,21 @@
|
|||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2">
|
<div>
|
||||||
<h4>Email erneut eingeben</h4>
|
<h4>Passwort</h4>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="password"
|
||||||
placeholder="max.mustermann@email.de"
|
placeholder="********"
|
||||||
name="email"
|
name="passwort"
|
||||||
class="input input-bordered text-base text-base-content font-medium"
|
class="px-2.5 py-1.5 rounded-lg border bg-gray-50"
|
||||||
bind:value={repeatEmail}
|
bind:value={password}
|
||||||
on:keyup={() => (repeatEmail = repeatEmail.toLowerCase())}
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{#if error}
|
<button class="button" type="submit">Registrieren</button>
|
||||||
<div class="bg-red-200 p-4 rounded-lg w-full">
|
<div class="flex-row justify-between" style="margin-top: 10px">
|
||||||
<p class="text-red-800">{errorMessage}</p>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
<button class="button" type="submit">{buttonText}</button>
|
|
||||||
<div class="flex flex-row justify-between" style="margin-top: 10px">
|
|
||||||
<button on:click={() => navigate("login")}>Einloggen</button>
|
<button on:click={() => navigate("login")}>Einloggen</button>
|
||||||
<a href="/auth/passwort-vergessen?r={window.location.href}">Passwort Vergessen?</a>
|
<a href="/user/passwort_vergessen">Passwort Vergessen?</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import PerformanceScore from "#components/Ausweis/PerformanceScore.svelte";
|
import PerformanceScore from "#components/Ausweis/PerformanceScore.svelte";
|
||||||
import Progressbar from "#components/Ausweis/Progressbar.svelte";
|
import Progressbar from "#components/Ausweis/Progressbar.svelte";
|
||||||
import Bereich from "#components/labels/Bereich.svelte";
|
import Bereich from "#components/labels/Bereich.svelte";
|
||||||
import type { BedarfsausweisGewerbe, BedarfsausweisWohnen, Benutzer, Bezahlmethoden, GEGNachweisGewerbe, GEGNachweisWohnen, Unterlage, VerbrauchsausweisGewerbe, VerbrauchsausweisWohnen } from "#lib/client/prisma.js";
|
import type { BedarfsausweisGewerbe, BedarfsausweisWohnen, Bezahlmethoden, GEGNachweisGewerbe, GEGNachweisWohnen, Unterlage, VerbrauchsausweisGewerbe, VerbrauchsausweisWohnen } from "#lib/client/prisma.js";
|
||||||
import { Enums } from "#lib/client/prisma.js";
|
import { Enums } from "#lib/client/prisma.js";
|
||||||
import {
|
import {
|
||||||
API_ACCESS_TOKEN_COOKIE_NAME,
|
API_ACCESS_TOKEN_COOKIE_NAME,
|
||||||
@@ -34,6 +34,7 @@
|
|||||||
import { endEnergieVerbrauchVerbrauchsausweisGewerbe_2016_Client } from "#lib/Berechnungen/VerbrauchsausweisGewerbe/VerbrauchsausweisGewerbe_2016_Client.js";
|
import { endEnergieVerbrauchVerbrauchsausweisGewerbe_2016_Client } from "#lib/Berechnungen/VerbrauchsausweisGewerbe/VerbrauchsausweisGewerbe_2016_Client.js";
|
||||||
import { benutzerSpeichern } from "#client/lib/speichern.js";
|
import { benutzerSpeichern } from "#client/lib/speichern.js";
|
||||||
import { benutzerLesen } from "#client/lib/lesen.js";
|
import { benutzerLesen } from "#client/lib/lesen.js";
|
||||||
|
import { exclude } from "#lib/exclude.js";
|
||||||
|
|
||||||
export let user: Partial<BenutzerClient>;
|
export let user: Partial<BenutzerClient>;
|
||||||
export let impersonatedUser: Partial<BenutzerClient> | null = null;
|
export let impersonatedUser: Partial<BenutzerClient> | null = null;
|
||||||
@@ -55,7 +56,7 @@
|
|||||||
email = rechnung?.email || localStorage.getItem("kundendaten.email") || user.email || "";
|
email = rechnung?.email || localStorage.getItem("kundendaten.email") || user.email || "";
|
||||||
vorname = localStorage.getItem("kundendaten.vorname") || user.vorname || "";
|
vorname = localStorage.getItem("kundendaten.vorname") || user.vorname || "";
|
||||||
name = localStorage.getItem("kundendaten.name") || user.name || "";
|
name = localStorage.getItem("kundendaten.name") || user.name || "";
|
||||||
empfaenger = rechnung?.empfaenger || localStorage.getItem("kundendaten.empfaenger") || user.empfaenger
|
empfaenger = rechnung?.empfaenger || localStorage.getItem("kundendaten.empfaenger") || (user.vorname && user.name ? `${user.vorname} ${user.name}` : "")
|
||||||
strasse = rechnung?.strasse || localStorage.getItem("kundendaten.strasse") || user.adresse || "";
|
strasse = rechnung?.strasse || localStorage.getItem("kundendaten.strasse") || user.adresse || "";
|
||||||
plz = rechnung?.plz || localStorage.getItem("kundendaten.plz") || user.plz || "";
|
plz = rechnung?.plz || localStorage.getItem("kundendaten.plz") || user.plz || "";
|
||||||
ort = rechnung?.ort || localStorage.getItem("kundendaten.ort") || user.ort || "";
|
ort = rechnung?.ort || localStorage.getItem("kundendaten.ort") || user.ort || "";
|
||||||
@@ -170,7 +171,6 @@
|
|||||||
|
|
||||||
async function anfordern() {
|
async function anfordern() {
|
||||||
if (!form.checkValidity()) {
|
if (!form.checkValidity()) {
|
||||||
displayFormValidity()
|
|
||||||
addNotification({
|
addNotification({
|
||||||
dismissable: true,
|
dismissable: true,
|
||||||
message: "Fehlende Daten.",
|
message: "Fehlende Daten.",
|
||||||
@@ -345,30 +345,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayFormValidity() {
|
async function bestellen(authuser = null) {
|
||||||
(form.querySelectorAll("select[name][required], input[name][required]") as NodeListOf<HTMLInputElement | HTMLSelectElement>).forEach((element) => {
|
|
||||||
if (element.willValidate && !element.checkValidity()) {
|
|
||||||
element.dataset["isinvalid"] = "true"
|
|
||||||
|
|
||||||
const onChange = () => {
|
|
||||||
console.log(element, element.value, element.checkValidity());
|
|
||||||
|
|
||||||
if (!element.checkValidity()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
element.dataset["isinvalid"] = "false"
|
|
||||||
element.removeEventListener("change", onChange)
|
|
||||||
}
|
|
||||||
|
|
||||||
element.addEventListener("change", onChange)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async function bestellen(authuser: Benutzer | null = null) {
|
|
||||||
if (!form.checkValidity()) {
|
if (!form.checkValidity()) {
|
||||||
displayFormValidity()
|
|
||||||
|
|
||||||
addNotification({
|
addNotification({
|
||||||
dismissable: true,
|
dismissable: true,
|
||||||
message: "Fehlende Daten.",
|
message: "Fehlende Daten.",
|
||||||
@@ -439,7 +417,6 @@
|
|||||||
const merged_versand_plz = versand_plz || plz;
|
const merged_versand_plz = versand_plz || plz;
|
||||||
const merged_versand_ort = versand_ort || ort;
|
const merged_versand_ort = versand_ort || ort;
|
||||||
const merged_versand_zusatzzeile = versand_zusatzzeile || zusatzzeile;
|
const merged_versand_zusatzzeile = versand_zusatzzeile || zusatzzeile;
|
||||||
|
|
||||||
|
|
||||||
if (rechnung) {
|
if (rechnung) {
|
||||||
const result = await api.rechnung._id.PATCH.fetch({
|
const result = await api.rechnung._id.PATCH.fetch({
|
||||||
@@ -527,14 +504,6 @@
|
|||||||
let loginOverlayHidden = true;
|
let loginOverlayHidden = true;
|
||||||
let loginAction = () => {};
|
let loginAction = () => {};
|
||||||
let form: HTMLFormElement;
|
let form: HTMLFormElement;
|
||||||
let ortInput: HTMLInputElement;
|
|
||||||
|
|
||||||
$: {
|
|
||||||
if (ort && ortInput) {
|
|
||||||
ortInput.value = ort
|
|
||||||
ortInput.dispatchEvent(new Event("change"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if !nurRechnungsadresseUpdate}
|
{#if !nurRechnungsadresseUpdate}
|
||||||
@@ -693,9 +662,6 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
|
|||||||
name="rechnung_plz"
|
name="rechnung_plz"
|
||||||
bind:zip={plz}
|
bind:zip={plz}
|
||||||
bind:city={ort}
|
bind:city={ort}
|
||||||
onchange={(e) => {
|
|
||||||
ortInput.dispatchEvent(new Event('change'));
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -707,7 +673,6 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
|
|||||||
type="text"
|
type="text"
|
||||||
required
|
required
|
||||||
bind:value={ort}
|
bind:value={ort}
|
||||||
bind:this={ortInput}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="help-label">
|
<div class="help-label">
|
||||||
@@ -1248,23 +1213,13 @@ sm:grid-cols-[min-content_min-content_min-content] sm:justify-self-end sm:mt-8"
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Overlay bind:hidden={loginOverlayHidden}>
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<Overlay bind:hidden={loginOverlayHidden}>
|
|
||||||
<div class="bg-white w-full max-w-screen-sm py-8">
|
<div class="bg-white w-full max-w-screen-sm py-8">
|
||||||
<EmbeddedAuthFlowModule onLogin={loginAction} email={email} route="signup" title={
|
<EmbeddedAuthFlowModule onLogin={loginAction} email={email} route="signup"></EmbeddedAuthFlowModule>
|
||||||
{
|
|
||||||
login: "Ausweis bestellen",
|
|
||||||
signup: "Ausweis bestellen"
|
|
||||||
}
|
|
||||||
} buttonText={{
|
|
||||||
login: "Bestellen",
|
|
||||||
signup: "Bestellen"
|
|
||||||
}}></EmbeddedAuthFlowModule>
|
|
||||||
</div>
|
</div>
|
||||||
</Overlay>
|
</Overlay>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
<NotificationWrapper></NotificationWrapper>
|
<NotificationWrapper></NotificationWrapper>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { loginClient } from "#lib/login.js";
|
import { loginClient } from "#lib/login.js";
|
||||||
|
import CrossCircled from "radix-svelte-icons/src/lib/icons/CrossCircled.svelte";
|
||||||
|
import { fade } from "svelte/transition";
|
||||||
|
|
||||||
let email: string;
|
let email: string;
|
||||||
let passwort: string;
|
let passwort: string;
|
||||||
|
|
||||||
@@ -11,8 +13,7 @@
|
|||||||
const response = await loginClient(email, passwort);
|
const response = await loginClient(email, passwort);
|
||||||
|
|
||||||
if (response === null) {
|
if (response === null) {
|
||||||
error = true
|
errorHidden = false;
|
||||||
errorMessage = "Das hat leider nicht geklappt, haben sie ihr Passwort und ihre Email Adresse richtig eingegeben?"
|
|
||||||
} else {
|
} else {
|
||||||
if (redirect) {
|
if (redirect) {
|
||||||
window.location.href = redirect;
|
window.location.href = redirect;
|
||||||
@@ -23,8 +24,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let error = false;
|
let errorHidden = true;
|
||||||
let errorMessage = "";
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="mx-auto w-1/3 bg-base-200 p-8 border border-base-300 rounded-lg">
|
<div class="mx-auto w-1/3 bg-base-200 p-8 border border-base-300 rounded-lg">
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
placeholder="nutzer@email.com"
|
placeholder="nutzer@email.com"
|
||||||
name="email"
|
name="email"
|
||||||
bind:value={email}
|
bind:value={email}
|
||||||
on:focus={() => (error = false)}
|
on:focus={() => (errorHidden = true)}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -51,19 +51,20 @@
|
|||||||
placeholder="********"
|
placeholder="********"
|
||||||
name="passwort"
|
name="passwort"
|
||||||
bind:value={passwort}
|
bind:value={passwort}
|
||||||
on:focus={() => (error = false)}
|
on:focus={() => (errorHidden = true)}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{#if error}
|
{#if !errorHidden}
|
||||||
<div class="bg-red-200 p-4 rounded-lg w-full">
|
<div role="alert" class="alert alert-error" in:fade out:fade={{delay: 400}}>
|
||||||
<p class="text-red-800">{errorMessage}</p>
|
<CrossCircled size={24} />
|
||||||
</div>
|
<span class="font-semibold">Das hat leider nicht geklappt, haben sie ihr Passwort und ihre Email Adresse richtig eingegeben?</span>
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<button class="button" type="submit">Einloggen</button>
|
<button class="button" type="submit">Einloggen</button>
|
||||||
<div class="flex flex-row justify-between" style="margin-top: 10px">
|
<div class="flex-row justify-between" style="margin-top: 10px">
|
||||||
<a class="link link-hover" href="/auth/signup{redirect ? `?r=${redirect}` : ""}">Registrieren</a>
|
<a class="link link-hover" href="/auth/signup{redirect ? `?redirect=${redirect}` : ""}">Registrieren</a>
|
||||||
<a class="link link-hover" href="/auth/passwort-vergessen{redirect ? `?r=${redirect}` : ""}"
|
<a class="link link-hover" href="/auth/passwort-vergessen{redirect ? `?redirect=${redirect}` : ""}"
|
||||||
>Passwort Vergessen?</a
|
>Passwort Vergessen?</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,58 +1,55 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { addNotification } from "#components/Notifications/shared.js";
|
||||||
|
import { CrossCircled } from "radix-svelte-icons";
|
||||||
|
import { fade } from "svelte/transition";
|
||||||
import { api } from "astro-typesafe-api/client";
|
import { api } from "astro-typesafe-api/client";
|
||||||
import NotificationWrapper from "#components/Notifications/NotificationWrapper.svelte";
|
import NotificationWrapper from "#components/Notifications/NotificationWrapper.svelte";
|
||||||
import { loginClient } from "#lib/login.js";
|
|
||||||
import PlzSuche from "#components/PlzSuche.svelte";
|
|
||||||
|
|
||||||
|
let passwort: string;
|
||||||
let email: string;
|
let email: string;
|
||||||
let vorname: string;
|
let vorname: string;
|
||||||
let name: string;
|
let name: string;
|
||||||
let repeatEmail: string;
|
|
||||||
let adresse: string;
|
|
||||||
let plz: string;
|
|
||||||
let ort: string;
|
|
||||||
let empfaenger: string;
|
|
||||||
|
|
||||||
export let redirect: string | null = null;
|
export let redirect: string | null = null;
|
||||||
|
|
||||||
async function login(e: SubmitEvent) {
|
async function login(e: SubmitEvent) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
if (passwort.length < 8) {
|
||||||
if (email !== repeatEmail) {
|
addNotification({
|
||||||
error = true;
|
message: "Passwort muss mindestens 6 Zeichen enthalten.",
|
||||||
errorMessage = "Die eingegebenen Email Adressen stimmen nicht überein.";
|
dismissable: true,
|
||||||
|
timeout: 3000,
|
||||||
|
type: "error"
|
||||||
|
})
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { id, passwort } = await api.user.PUT.fetch({
|
const { id } = await api.user.PUT.fetch({
|
||||||
|
email,
|
||||||
|
passwort,
|
||||||
vorname,
|
vorname,
|
||||||
name, email,
|
name
|
||||||
adresse, plz, ort, empfaenger
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await loginClient(email, passwort)
|
|
||||||
|
|
||||||
if (redirect) {
|
if (redirect) {
|
||||||
window.location.href = redirect
|
window.location.href = redirect
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
window.location.href = "/dashboard";
|
window.location.href = "/auth/login";
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = true
|
errorHidden = false;
|
||||||
errorMessage = "Sie besitzen bereits ein Konto bei IBC. Bitte loggen Sie sich mit Ihrem Passwort ein oder vergeben sich über “Passwort vergessen” ein neues."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let error = false;
|
|
||||||
let errorMessage = "";
|
let errorHidden = true;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="mx-auto w-1/3 bg-base-200 p-8 border border-base-300 rounded-lg">
|
<div class="mx-auto w-1/3 bg-base-200 p-8 border border-base-300 rounded-lg">
|
||||||
<h1 class="text-3xl mb-4">Registrieren</h1>
|
<h1 class="text-3xl mb-4">Registrieren</h1>
|
||||||
<p>Bitte geben sie Email, Ansprechpartner und Adressdaten ein, um einen Account beim IBC zu erstellen, ein Passwort wird ihnen per Email zugesendet, dieses können sie im Nachhinein jederzeit ändern.</p>
|
<form class="flex flex-col gap-4" on:submit={login}>
|
||||||
<form class="flex flex-col gap-4 mt-8" on:submit={login}>
|
|
||||||
<div class="flex flex-row gap-4 w-full">
|
<div class="flex flex-row gap-4 w-full">
|
||||||
<div class="w-1/2 flex flex-col gap-2">
|
<div class="w-1/2 flex flex-col gap-2">
|
||||||
<h4>Vorname</h4>
|
<h4>Vorname</h4>
|
||||||
@@ -77,51 +74,11 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row gap-4 w-full">
|
|
||||||
<div class="w-1/2 flex flex-col gap-2">
|
|
||||||
<h4>Straße</h4>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
placeholder="Straße"
|
|
||||||
name="strasse"
|
|
||||||
class="input input-bordered text-base text-base-content font-medium"
|
|
||||||
bind:value={adresse}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="w-1/2 flex flex-col gap-2">
|
|
||||||
<h4>PLZ</h4>
|
|
||||||
<PlzSuche bind:zip={plz} bind:city={ort} name="plz" readonly={false} />
|
|
||||||
</div>
|
|
||||||
<div class="w-1/2 flex flex-col gap-2">
|
|
||||||
<h4>Ort</h4>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
placeholder="Ort"
|
|
||||||
name="ort"
|
|
||||||
class="input input-bordered text-base text-base-content font-medium"
|
|
||||||
bind:value={ort}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
<h4>Empfänger</h4>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
placeholder="Max Mustermann"
|
|
||||||
name="empfaenger"
|
|
||||||
class="input input-bordered text-base text-base-content font-medium"
|
|
||||||
bind:value={empfaenger}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<h4>Email</h4>
|
<h4>Email</h4>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="max.mustermann@email.de"
|
placeholder="Email"
|
||||||
name="email"
|
name="email"
|
||||||
class="input input-bordered text-base text-base-content font-medium"
|
class="input input-bordered text-base text-base-content font-medium"
|
||||||
bind:value={email}
|
bind:value={email}
|
||||||
@@ -130,29 +87,31 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<h4>Email erneut eingeben</h4>
|
<h4>Passwort</h4>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="password"
|
||||||
placeholder="max.mustermann@email.de"
|
placeholder="********"
|
||||||
name="email"
|
minlength="8"
|
||||||
|
name="passwort"
|
||||||
class="input input-bordered text-base text-base-content font-medium"
|
class="input input-bordered text-base text-base-content font-medium"
|
||||||
bind:value={repeatEmail}
|
bind:value={passwort}
|
||||||
on:keyup={() => (repeatEmail = repeatEmail.toLowerCase())}
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{#if error}
|
{#if !errorHidden}
|
||||||
<div class="bg-red-200 p-4 rounded-lg w-full">
|
<div role="alert" class="alert alert-error" in:fade out:fade={{delay: 400}}>
|
||||||
<p class="text-red-800">{errorMessage}</p>
|
<CrossCircled size={24} />
|
||||||
</div>
|
<span class="font-semibold">Da ist wohl etwas schiefgelaufen. Diese Email Adresse ist bereits in Benutzung, haben sie vielleicht bereits ein Konto bei uns?</span>
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<button type="submit" class="button"
|
<button type="submit" class="button"
|
||||||
>Registrieren</button>
|
>Registrieren</button
|
||||||
<div class="flex flex-row justify-between" style="margin-top: 10px">
|
|
||||||
<a class="link link-hover"
|
|
||||||
href="/auth/login{redirect ? `?r=${redirect}` : ""}">Einloggen</a
|
|
||||||
>
|
>
|
||||||
<a class="link link-hover" href="/auth/passwort-vergessen{redirect ? `?r=${redirect}` : ""}">Passwort Vergessen?</a>
|
<div class="flex-row justify-between" style="margin-top: 10px">
|
||||||
|
<a class="link link-hover"
|
||||||
|
href="/auth/login{redirect ? `?redirect=${redirect}` : ""}">Einloggen</a
|
||||||
|
>
|
||||||
|
<a class="link link-hover" href="/auth/passwort-vergessen{redirect ? `?redirect=${redirect}` : ""}">Passwort Vergessen?</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<NotificationWrapper></NotificationWrapper>
|
<NotificationWrapper></NotificationWrapper>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const user = await getCurrentUser(Astro)
|
|||||||
if (id) {
|
if (id) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return Astro.redirect(
|
return Astro.redirect(
|
||||||
`/auth/login?r=${Astro.url.toString()}`
|
`/auth/login?redirect=${Astro.url.toString()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ if (id) {
|
|||||||
} else if (aufnahme_id) {
|
} else if (aufnahme_id) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return Astro.redirect(
|
return Astro.redirect(
|
||||||
`/auth/login?r=${Astro.url.toString()}`
|
`/auth/login?redirect=${Astro.url.toString()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const user = await getCurrentUser(Astro)
|
|||||||
if (id) {
|
if (id) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return Astro.redirect(
|
return Astro.redirect(
|
||||||
`/auth/login?r=${Astro.url.toString()}`
|
`/auth/login?redirect=${Astro.url.toString()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ if (id) {
|
|||||||
} else if (aufnahme_id) {
|
} else if (aufnahme_id) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return Astro.redirect(
|
return Astro.redirect(
|
||||||
`/auth/login?r=${Astro.url.toString()}`
|
`/auth/login?redirect=${Astro.url.toString()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const user = await getCurrentUser(Astro)
|
|||||||
if (id) {
|
if (id) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return Astro.redirect(
|
return Astro.redirect(
|
||||||
`/auth/login?r=${Astro.url.toString()}`
|
`/auth/login?redirect=${Astro.url.toString()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ if (id) {
|
|||||||
} else if (aufnahme_id) {
|
} else if (aufnahme_id) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return Astro.redirect(
|
return Astro.redirect(
|
||||||
`/auth/login?r=${Astro.url.toString()}`
|
`/auth/login?redirect=${Astro.url.toString()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ let loadFromDatabase = false;
|
|||||||
|
|
||||||
if (typ === AusstellungsTyp.Neuausstellung) {
|
if (typ === AusstellungsTyp.Neuausstellung) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return Astro.redirect(`/auth/login?r=${Astro.url.toString()}`);
|
return Astro.redirect(`/auth/login?redirect=${Astro.url.toString()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ausweis_id) {
|
if (!ausweis_id) {
|
||||||
@@ -115,7 +115,7 @@ if (typ === AusstellungsTyp.Neuausstellung) {
|
|||||||
loadFromDatabase = true;
|
loadFromDatabase = true;
|
||||||
} else if (typ === AusstellungsTyp.Speichern) {
|
} else if (typ === AusstellungsTyp.Speichern) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return Astro.redirect(`/auth/login?r=${Astro.url.toString()}`);
|
return Astro.redirect(`/auth/login?redirect=${Astro.url.toString()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ausweis_id) {
|
if (!ausweis_id) {
|
||||||
@@ -151,7 +151,7 @@ if (typ === AusstellungsTyp.Neuausstellung) {
|
|||||||
loadFromDatabase = true;
|
loadFromDatabase = true;
|
||||||
} else if (typ === AusstellungsTyp.Alternativdokument) {
|
} else if (typ === AusstellungsTyp.Alternativdokument) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return Astro.redirect(`/auth/login?r=${Astro.url.toString()}`);
|
return Astro.redirect(`/auth/login?redirect=${Astro.url.toString()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ausweis_id) {
|
if (!ausweis_id) {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const user = await getCurrentUser(Astro)
|
|||||||
if (id) {
|
if (id) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return Astro.redirect(
|
return Astro.redirect(
|
||||||
`/auth/login?r=${Astro.url.toString()}`
|
`/auth/login?redirect=${Astro.url.toString()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ if (id) {
|
|||||||
} else if (aufnahme_id) {
|
} else if (aufnahme_id) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return Astro.redirect(
|
return Astro.redirect(
|
||||||
`/auth/login?r=${Astro.url.toString()}`
|
`/auth/login?redirect=${Astro.url.toString()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const user = await getCurrentUser(Astro)
|
|||||||
if (id) {
|
if (id) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return Astro.redirect(
|
return Astro.redirect(
|
||||||
`/auth/login?r=${Astro.url.toString()}`
|
`/auth/login?redirect=${Astro.url.toString()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ if (id) {
|
|||||||
} else if (aufnahme_id) {
|
} else if (aufnahme_id) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return Astro.redirect(
|
return Astro.redirect(
|
||||||
`/auth/login?r=${Astro.url.toString()}`
|
`/auth/login?redirect=${Astro.url.toString()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const user = await getCurrentUser(Astro)
|
|||||||
if (id) {
|
if (id) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return Astro.redirect(
|
return Astro.redirect(
|
||||||
`/auth/login?r=${Astro.url.toString()}`
|
`/auth/login?redirect=${Astro.url.toString()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ if (id) {
|
|||||||
} else if (aufnahme_id) {
|
} else if (aufnahme_id) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return Astro.redirect(
|
return Astro.redirect(
|
||||||
`/auth/login?r=${Astro.url.toString()}`
|
`/auth/login?redirect=${Astro.url.toString()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ export const GET = defineApiRoute({
|
|||||||
|
|
||||||
if (rechnung.status === Enums.Rechnungsstatus.paid) {
|
if (rechnung.status === Enums.Rechnungsstatus.paid) {
|
||||||
html = `
|
html = `
|
||||||
<p>Sehr geehrte/r ${rechnung.empfaenger},</p>
|
<p>Sehr geehrte*r ${rechnung.empfaenger},</p>
|
||||||
|
|
||||||
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${
|
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${
|
||||||
post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : ""
|
post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : ""
|
||||||
@@ -323,7 +323,7 @@ export const GET = defineApiRoute({
|
|||||||
</p>`;
|
</p>`;
|
||||||
} else {
|
} else {
|
||||||
html = `
|
html = `
|
||||||
<p>Sehr geehrte/r ${rechnung.empfaenger},</p>
|
<p>Sehr geehrte*r ${rechnung.empfaenger},</p>
|
||||||
|
|
||||||
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${
|
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${
|
||||||
post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : ""
|
post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : ""
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ export const POST = defineApiRoute({
|
|||||||
|
|
||||||
if (rechnung.status === Enums.Rechnungsstatus.paid) {
|
if (rechnung.status === Enums.Rechnungsstatus.paid) {
|
||||||
html = `
|
html = `
|
||||||
<p>Sehr geehrte/r ${rechnung.empfaenger},</p>
|
<p>Sehr geehrte*r ${rechnung.empfaenger},</p>
|
||||||
|
|
||||||
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${
|
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${
|
||||||
post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : ""
|
post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : ""
|
||||||
@@ -332,7 +332,7 @@ export const POST = defineApiRoute({
|
|||||||
</p>`;
|
</p>`;
|
||||||
} else {
|
} else {
|
||||||
html = `
|
html = `
|
||||||
<p>Sehr geehrte/r ${rechnung.empfaenger},</p>
|
<p>Sehr geehrte*r ${rechnung.empfaenger},</p>
|
||||||
|
|
||||||
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${
|
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${
|
||||||
post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : ""
|
post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : ""
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ export const PUT = defineApiRoute({
|
|||||||
to: rechnung.email || user.email,
|
to: rechnung.email || user.email,
|
||||||
bcc: "info@online-energieausweis.org",
|
bcc: "info@online-energieausweis.org",
|
||||||
subject: `Stornierung des Energieausweises vom Ingenieurbüro Cornelsen (ID: ${ausweis.id})`,
|
subject: `Stornierung des Energieausweises vom Ingenieurbüro Cornelsen (ID: ${ausweis.id})`,
|
||||||
html: `<p>Sehr geehrte/r ${user.vorname} ${user.name},</p>
|
html: `<p>Sehr geehrte*r ${user.vorname} ${user.name},</p>
|
||||||
|
|
||||||
<p>Ihr Energieausweis wurde soeben storniert.
|
<p>Ihr Energieausweis wurde soeben storniert.
|
||||||
<br>
|
<br>
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ import { transport } from "#lib/mail.js";
|
|||||||
|
|
||||||
export const GET = defineApiRoute({
|
export const GET = defineApiRoute({
|
||||||
input: z.object({
|
input: z.object({
|
||||||
email: z.string().email(),
|
email: z.string().email()
|
||||||
redirect: z.string().optional()
|
|
||||||
}),
|
}),
|
||||||
output: z.void(),
|
output: z.void(),
|
||||||
async fetch(input, context, transfer) {
|
async fetch(input, context, transfer) {
|
||||||
@@ -43,7 +42,7 @@ export const GET = defineApiRoute({
|
|||||||
|
|
||||||
sie haben eine Anfrage zum Zurücksetzen ihres Passworts gestellt. Klicken sie auf den folgenden Link, um ein neues Passwort festzulegen:
|
sie haben eine Anfrage zum Zurücksetzen ihres Passworts gestellt. Klicken sie auf den folgenden Link, um ein neues Passwort festzulegen:
|
||||||
|
|
||||||
https://online-energieausweis.org/auth/passwort-zuruecksetzen?t=${resetToken}${input.redirect ? `&r=${input.redirect}` : ""}
|
https://online-energieausweis.org/auth/passwort-zuruecksetzen?t=${resetToken}
|
||||||
|
|
||||||
Dieser Link ist für die nächsten 15 Minuten gültig. Falls du diese Anfrage nicht gestellt hast, kannst du diese E-Mail ignorieren - dein Passwort bleibt unverändert.
|
Dieser Link ist für die nächsten 15 Minuten gültig. Falls du diese Anfrage nicht gestellt hast, kannst du diese E-Mail ignorieren - dein Passwort bleibt unverändert.
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import { PutObjectCommand } from "@aws-sdk/client-s3";
|
|||||||
import { s3Client } from "#lib/s3.js";
|
import { s3Client } from "#lib/s3.js";
|
||||||
import { generateIDWithPrefix } from "#lib/db.js";
|
import { generateIDWithPrefix } from "#lib/db.js";
|
||||||
import { VALID_UUID_PREFIXES } from "#lib/constants.js";
|
import { VALID_UUID_PREFIXES } from "#lib/constants.js";
|
||||||
import { logger } from "#lib/logger.js";
|
|
||||||
|
|
||||||
export const PUT = defineApiRoute({
|
export const PUT = defineApiRoute({
|
||||||
input: BildSchema.pick({
|
input: BildSchema.pick({
|
||||||
@@ -70,7 +69,6 @@ export const PUT = defineApiRoute({
|
|||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
logger.error("Fehler beim Speichern des Bildes in S3: " + e);
|
|
||||||
// Und geben einen Fehler zurück
|
// Und geben einen Fehler zurück
|
||||||
throw new APIError({
|
throw new APIError({
|
||||||
code: "INTERNAL_SERVER_ERROR",
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
@@ -111,7 +109,8 @@ export const DELETE = defineApiRoute({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error("Fehler beim Löschen des Bildes: " + e);
|
console.log(e);
|
||||||
|
|
||||||
throw new APIError({
|
throw new APIError({
|
||||||
code: "INTERNAL_SERVER_ERROR",
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
message: "Bild konnte nicht gelöscht werden.",
|
message: "Bild konnte nicht gelöscht werden.",
|
||||||
|
|||||||
@@ -96,41 +96,6 @@ export const PATCH = defineApiRoute({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
|
|
||||||
// Wir aktualisieren auch die Rechnungsdaten des Benutzers
|
|
||||||
// Das sollte allerdings nur passieren, falls diese noch nicht gesetzt sind.
|
|
||||||
const data = {
|
|
||||||
ort: input.ort,
|
|
||||||
plz: input.plz,
|
|
||||||
adresse: input.strasse,
|
|
||||||
telefon: input.telefon,
|
|
||||||
empfaenger: input.empfaenger
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user.ort) {
|
|
||||||
delete data.ort;
|
|
||||||
}
|
|
||||||
if (user.plz) {
|
|
||||||
delete data.plz;
|
|
||||||
}
|
|
||||||
if (user.adresse) {
|
|
||||||
delete data.adresse;
|
|
||||||
}
|
|
||||||
if (user.telefon) {
|
|
||||||
delete data.telefon;
|
|
||||||
}
|
|
||||||
if (user.empfaenger) {
|
|
||||||
delete data.empfaenger;
|
|
||||||
}
|
|
||||||
|
|
||||||
await prisma.benutzer.update({
|
|
||||||
data,
|
|
||||||
where: {
|
|
||||||
id: user.id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input.bezahlmethode === Enums.Bezahlmethoden.rechnung) {
|
if (input.bezahlmethode === Enums.Bezahlmethoden.rechnung) {
|
||||||
return { id: rechnung.id }
|
return { id: rechnung.id }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export const PUT = defineApiRoute({
|
|||||||
if (!adapter) {
|
if (!adapter) {
|
||||||
throw new APIError({
|
throw new APIError({
|
||||||
code: "BAD_REQUEST",
|
code: "BAD_REQUEST",
|
||||||
message: "Ungültige Ausweis ID"
|
message: "Ungültige Ausweis UID"
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,41 +214,6 @@ export const PUT = defineApiRoute({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
|
|
||||||
// Wir aktualisieren auch die Rechnungsdaten des Benutzers
|
|
||||||
// Das sollte allerdings nur passieren, falls diese noch nicht gesetzt sind.
|
|
||||||
const data = {
|
|
||||||
ort: input.ort,
|
|
||||||
plz: input.plz,
|
|
||||||
adresse: input.strasse,
|
|
||||||
telefon: input.telefon,
|
|
||||||
empfaenger: input.empfaenger
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user.ort) {
|
|
||||||
delete data.ort;
|
|
||||||
}
|
|
||||||
if (user.plz) {
|
|
||||||
delete data.plz;
|
|
||||||
}
|
|
||||||
if (user.adresse) {
|
|
||||||
delete data.adresse;
|
|
||||||
}
|
|
||||||
if (user.telefon) {
|
|
||||||
delete data.telefon;
|
|
||||||
}
|
|
||||||
if (user.empfaenger) {
|
|
||||||
delete data.empfaenger;
|
|
||||||
}
|
|
||||||
|
|
||||||
await prisma.benutzer.update({
|
|
||||||
data,
|
|
||||||
where: {
|
|
||||||
id: user.id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bezahlmethode === Enums.Bezahlmethoden.rechnung) {
|
if (bezahlmethode === Enums.Bezahlmethoden.rechnung) {
|
||||||
return { id }
|
return { id }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
import { IDWithPrefix } from "#components/Ausweis/types.js";
|
|
||||||
import { VALID_UUID_PREFIXES } from "#lib/constants.js";
|
|
||||||
import { generateIDWithPrefix } from "#lib/db.js";
|
|
||||||
import { hashPassword } from "#lib/password.js";
|
|
||||||
import { createLexOfficeCustomer } from "#lib/server/lexoffice.js";
|
|
||||||
import { sendAutoRegisterMail } from "#lib/server/mail/auto-registrierung.js";
|
|
||||||
import { sendRegisterMail } from "#lib/server/mail/registrierung.js";
|
|
||||||
import { prisma } from "#lib/server/prisma.js";
|
|
||||||
import { defineApiRoute, APIError } from "astro-typesafe-api/server";
|
|
||||||
import { z } from "astro:content";
|
|
||||||
|
|
||||||
export const PUT = defineApiRoute({
|
|
||||||
input: z.object({
|
|
||||||
email: z.string().email(),
|
|
||||||
}),
|
|
||||||
output: z.object({
|
|
||||||
email: z.string().email(),
|
|
||||||
id: IDWithPrefix,
|
|
||||||
passwort: z.string().min(8).max(100)
|
|
||||||
}),
|
|
||||||
async fetch(input) {
|
|
||||||
let { email } = input;
|
|
||||||
email = email.toLowerCase();
|
|
||||||
|
|
||||||
const existingUser = await prisma.benutzer.findUnique({
|
|
||||||
where: {
|
|
||||||
email
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (existingUser) {
|
|
||||||
throw new APIError({
|
|
||||||
code: "CONFLICT",
|
|
||||||
message: "Email Adresse ist bereits vergeben."
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const id = generateIDWithPrefix(9, VALID_UUID_PREFIXES.User);
|
|
||||||
const passwort = crypto.randomUUID().slice(0, 8);
|
|
||||||
|
|
||||||
const user = await prisma.benutzer.create({
|
|
||||||
data: {
|
|
||||||
email,
|
|
||||||
passwort: hashPassword(passwort),
|
|
||||||
id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const lex_office_id = await createLexOfficeCustomer(user);
|
|
||||||
|
|
||||||
await prisma.benutzer.update({
|
|
||||||
where: {
|
|
||||||
id: user.id
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
lex_office_id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
await sendRegisterMail(user, passwort)
|
|
||||||
|
|
||||||
return { id, email: user.email, passwort }
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import { IDWithPrefix } from "#components/Ausweis/types.js";
|
import { IDWithPrefix } from "#components/Ausweis/types.js";
|
||||||
import { VALID_UUID_PREFIXES } from "#lib/constants.js";
|
import { VALID_UUID_PREFIXES } from "#lib/constants.js";
|
||||||
import { generateIDWithPrefix } from "#lib/db.js";
|
import { generateIDWithPrefix } from "#lib/db.js";
|
||||||
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
|
import { adminMiddleware, authorizationMiddleware } from "#lib/middleware/authorization.js";
|
||||||
import { hashPassword } from "#lib/password.js";
|
import { hashPassword } from "#lib/password.js";
|
||||||
import { createLexOfficeCustomer } from "#lib/server/lexoffice.js";
|
import { createLexOfficeCustomer } from "#lib/server/lexoffice.js";
|
||||||
import { sendRegisterMail } from "#lib/server/mail/registrierung.js";
|
import { sendRegisterMail } from "#lib/server/mail/registrierung.js";
|
||||||
import { prisma } from "#lib/server/prisma.js";
|
import { Benutzer, prisma } from "#lib/server/prisma.js";
|
||||||
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||||
import { BenutzerSchema } from "src/generated/zod/benutzer.js";
|
import { BenutzerSchema } from "src/generated/zod/benutzer.js";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
@@ -26,6 +26,7 @@ export const POST = defineApiRoute({
|
|||||||
const updateData: any = {};
|
const updateData: any = {};
|
||||||
updateData.id = user.id;
|
updateData.id = user.id;
|
||||||
if (input.adresse) updateData.adresse = input.adresse;
|
if (input.adresse) updateData.adresse = input.adresse;
|
||||||
|
if (input.anrede) updateData.anrede = input.anrede;
|
||||||
if (input.email) updateData.email = input.email;
|
if (input.email) updateData.email = input.email;
|
||||||
if (input.firma) updateData.firma = input.firma;
|
if (input.firma) updateData.firma = input.firma;
|
||||||
if (input.name) updateData.name = input.name;
|
if (input.name) updateData.name = input.name;
|
||||||
@@ -105,19 +106,15 @@ export const GET = defineApiRoute({
|
|||||||
export const PUT = defineApiRoute({
|
export const PUT = defineApiRoute({
|
||||||
input: z.object({
|
input: z.object({
|
||||||
email: z.string().email(),
|
email: z.string().email(),
|
||||||
|
passwort: z.string().min(8),
|
||||||
vorname: z.string(),
|
vorname: z.string(),
|
||||||
name: z.string(),
|
name: z.string()
|
||||||
adresse: z.string(),
|
|
||||||
plz: z.string(),
|
|
||||||
ort: z.string(),
|
|
||||||
empfaenger: z.string()
|
|
||||||
}),
|
}),
|
||||||
output: z.object({
|
output: z.object({
|
||||||
id: IDWithPrefix,
|
id: IDWithPrefix
|
||||||
passwort: z.string().min(8).max(100)
|
|
||||||
}),
|
}),
|
||||||
async fetch(input) {
|
async fetch(input) {
|
||||||
let { email, vorname, name, adresse, plz, ort, empfaenger } = input;
|
let { email, passwort, vorname, name } = input;
|
||||||
email = email.toLowerCase();
|
email = email.toLowerCase();
|
||||||
|
|
||||||
const existingUser = await prisma.benutzer.findUnique({
|
const existingUser = await prisma.benutzer.findUnique({
|
||||||
@@ -134,18 +131,13 @@ export const PUT = defineApiRoute({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const id = generateIDWithPrefix(9, VALID_UUID_PREFIXES.User);
|
const id = generateIDWithPrefix(9, VALID_UUID_PREFIXES.User);
|
||||||
const passwort = crypto.randomUUID().slice(0, 8);
|
|
||||||
|
|
||||||
const user = await prisma.benutzer.create({
|
const user = await prisma.benutzer.create({
|
||||||
data: {
|
data: {
|
||||||
email,
|
email,
|
||||||
vorname,
|
|
||||||
passwort: hashPassword(passwort),
|
passwort: hashPassword(passwort),
|
||||||
|
vorname,
|
||||||
name,
|
name,
|
||||||
adresse,
|
|
||||||
plz,
|
|
||||||
ort,
|
|
||||||
empfaenger,
|
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -161,8 +153,8 @@ export const PUT = defineApiRoute({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
await sendRegisterMail(user, passwort)
|
await sendRegisterMail(user)
|
||||||
|
|
||||||
return { id, passwort }
|
return { id }
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
9
src/pages/auth/embedded-login.astro
Normal file
9
src/pages/auth/embedded-login.astro
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
import BlankLayout from "#layouts/BlankLayout.astro";
|
||||||
|
import EmbeddedLoginModule from "#modules/EmbeddedLoginModule.svelte";
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<BlankLayout title="Login - IBCornelsen">
|
||||||
|
<EmbeddedLoginModule client:only></EmbeddedLoginModule>
|
||||||
|
</BlankLayout>
|
||||||
10
src/pages/auth/embedded-signup.astro
Normal file
10
src/pages/auth/embedded-signup.astro
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
import BlankLayout from "#layouts/BlankLayout.astro";
|
||||||
|
import EmbeddedRegisterModule from "#modules/EmbeddedRegisterModule.svelte";
|
||||||
|
|
||||||
|
const redirect = Astro.url.searchParams.get("redirect");
|
||||||
|
---
|
||||||
|
|
||||||
|
<BlankLayout title="Registrieren - IBCornelsen">
|
||||||
|
<EmbeddedRegisterModule client:only></EmbeddedRegisterModule>
|
||||||
|
</BlankLayout>
|
||||||
@@ -9,7 +9,7 @@ if (valid) {
|
|||||||
return Astro.redirect("/dashboard")
|
return Astro.redirect("/dashboard")
|
||||||
}
|
}
|
||||||
|
|
||||||
const redirect = Astro.url.searchParams.get("r")
|
const redirect = Astro.url.searchParams.get("redirect")
|
||||||
---
|
---
|
||||||
|
|
||||||
<MinimalLayout title="Login">
|
<MinimalLayout title="Login">
|
||||||
|
|||||||
@@ -5,13 +5,11 @@ import MinimalLayout from "#layouts/MinimalLayout.astro";
|
|||||||
|
|
||||||
const valid = await validateAccessTokenServer(Astro)
|
const valid = await validateAccessTokenServer(Astro)
|
||||||
|
|
||||||
// Es kann sein, dass ein Nutzer von dem Ausweisformular kommt und sein Passwort vergessen hat.
|
|
||||||
// In dem Fall sollte er auch auf das Formular zurückgeleitet werden wenn er sein Passwort zurückgesetzt hat.
|
|
||||||
const redirect = Astro.url.searchParams.get("r")
|
|
||||||
|
|
||||||
if (valid) {
|
if (valid) {
|
||||||
return Astro.redirect("/dashboard")
|
return Astro.redirect("/dashboard")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const redirect = Astro.url.searchParams.get("redirect")
|
||||||
---
|
---
|
||||||
|
|
||||||
<MinimalLayout title="Passwort Vergessen">
|
<MinimalLayout title="Passwort Vergessen">
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ if (valid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const token = Astro.url.searchParams.get("t")
|
const token = Astro.url.searchParams.get("t")
|
||||||
const redirect = Astro.url.searchParams.get("r")
|
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return Astro.redirect("/")
|
return Astro.redirect("/")
|
||||||
@@ -26,5 +25,5 @@ if (!decoded.exp || decoded.exp < Date.now() || decoded.typ !== TokenType.Reset)
|
|||||||
---
|
---
|
||||||
|
|
||||||
<MinimalLayout title="Passwort Vergessen">
|
<MinimalLayout title="Passwort Vergessen">
|
||||||
<PasswortZuruecksetzenModule token={token} redirect={redirect} client:load></PasswortZuruecksetzenModule>
|
<PasswortZuruecksetzenModule token={token} client:load></PasswortZuruecksetzenModule>
|
||||||
</MinimalLayout>
|
</MinimalLayout>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ if (valid) {
|
|||||||
return Astro.redirect("/dashboard")
|
return Astro.redirect("/dashboard")
|
||||||
}
|
}
|
||||||
|
|
||||||
const redirect = Astro.url.searchParams.get("r");
|
const redirect = Astro.url.searchParams.get("redirect");
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
32
src/pages/auth/verify.astro
Normal file
32
src/pages/auth/verify.astro
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
import Layout from "#layouts/Layout.astro";
|
||||||
|
import { decodeToken } from "#lib/auth/token";
|
||||||
|
import { TokenType } from "#lib/auth/types";
|
||||||
|
import { prisma } from "#lib/server/prisma";
|
||||||
|
|
||||||
|
const token = Astro.url.searchParams.get("t");
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
return Astro.redirect("/")
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = decodeToken(token)
|
||||||
|
|
||||||
|
if (payload.typ !== TokenType.Verify || !payload.uid || !payload.exp || payload.exp < Date.now()) {
|
||||||
|
return Astro.redirect("/")
|
||||||
|
}
|
||||||
|
|
||||||
|
await prisma.benutzer.update({
|
||||||
|
where: {
|
||||||
|
uid: payload.uid
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
verified: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
---
|
||||||
|
|
||||||
|
<Layout title="Bestätigung">
|
||||||
|
<h1>Vielen Dank</h1>
|
||||||
|
<p>Ihre Email Adresse wurde bestätigt, sie können diese Seite nun schließen.</p>
|
||||||
|
</Layout>
|
||||||
@@ -53,7 +53,7 @@ import Layout from "#layouts/Layout.astro";
|
|||||||
<div>
|
<div>
|
||||||
<h3 class="text-xl font-semibold text-gray-800 mb-2">Kontakt & Gebäudedaten</h3>
|
<h3 class="text-xl font-semibold text-gray-800 mb-2">Kontakt & Gebäudedaten</h3>
|
||||||
<ul class="list-disc list-inside text-gray-700">
|
<ul class="list-disc list-inside text-gray-700">
|
||||||
<li>Name & E-Mail des Ansprechpartners</li>
|
<li>Name, Anrede & E-Mail des Ansprechpartners</li>
|
||||||
<li>Rechnungs- & Versandadresse</li>
|
<li>Rechnungs- & Versandadresse</li>
|
||||||
<li>Gebäudeangaben: Wohnfläche, Baujahr, Anzahl Geschosse</li>
|
<li>Gebäudeangaben: Wohnfläche, Baujahr, Anzahl Geschosse</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import UserLayout from "#layouts/DashboardLayout.astro";
|
import UserLayout from "#layouts/DashboardLayout.astro";
|
||||||
import { getCurrentUser } from "#lib/server/user";
|
import { getCurrentUser } from "#lib/server/user";
|
||||||
import DashboardEinstellungenModule from "#modules/Dashboard/DashboardEinstellungenModule.svelte";
|
import DashboardEinstellungenModule from "#modules/Dashboard/DashboardEinstellungenModule.svelte";
|
||||||
|
import { validateAccessTokenServer } from "#server/lib/validateAccessToken";
|
||||||
|
|
||||||
const user = await getCurrentUser(Astro)
|
const user = await getCurrentUser(Astro)
|
||||||
|
|
||||||
|
|||||||
@@ -53,21 +53,5 @@ if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
|
|||||||
|
|
||||||
if (result.length > 0) {
|
if (result.length > 0) {
|
||||||
return Astro.redirect(`/dashboard/objekte/${result[0].id}?p=${page}`);
|
return Astro.redirect(`/dashboard/objekte/${result[0].id}?p=${page}`);
|
||||||
} else {
|
|
||||||
return Astro.redirect("/dashboard/objekte/leer");
|
|
||||||
}
|
}
|
||||||
|
---
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Document</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -8,7 +8,6 @@ import {
|
|||||||
Enums,
|
Enums,
|
||||||
Objekt,
|
Objekt,
|
||||||
prisma,
|
prisma,
|
||||||
Unterlage,
|
|
||||||
VerbrauchsausweisGewerbe,
|
VerbrauchsausweisGewerbe,
|
||||||
VerbrauchsausweisWohnen,
|
VerbrauchsausweisWohnen,
|
||||||
} from "#lib/server/prisma";
|
} from "#lib/server/prisma";
|
||||||
@@ -17,7 +16,6 @@ import {
|
|||||||
getBedarfsausweisWohnen,
|
getBedarfsausweisWohnen,
|
||||||
getBilder,
|
getBilder,
|
||||||
getObjekt,
|
getObjekt,
|
||||||
getUnterlagen,
|
|
||||||
getVerbrauchsausweisGewerbe,
|
getVerbrauchsausweisGewerbe,
|
||||||
getVerbrauchsausweisWohnen,
|
getVerbrauchsausweisWohnen,
|
||||||
} from "#lib/server/db";
|
} from "#lib/server/db";
|
||||||
@@ -54,18 +52,14 @@ let ausweis:
|
|||||||
let aufnahme: Aufnahme | null = {} as Aufnahme;
|
let aufnahme: Aufnahme | null = {} as Aufnahme;
|
||||||
let objekt: Objekt | null = {} as Objekt;
|
let objekt: Objekt | null = {} as Objekt;
|
||||||
let bilder: Bild[] = [];
|
let bilder: Bild[] = [];
|
||||||
let unterlagen: Unterlage[] = [];
|
|
||||||
let loadFromDatabase = false;
|
let loadFromDatabase = false;
|
||||||
|
|
||||||
if (typ === AusstellungsTyp.Neuausstellung) {
|
if (typ === AusstellungsTyp.Neuausstellung) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
// Der Nutzer muss eingeloggt sein um eine Neuausstellung anzufordern,
|
return Astro.redirect(`/auth/login?redirect=${Astro.url.toString()}`);
|
||||||
// sonst können wir nicht sicher sein, dass der Nutzer berechtigt ist auf den Ausweis zuzugreifen.
|
|
||||||
return Astro.redirect(`/auth/login?r=${Astro.url.toString()}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ausweis_id) {
|
if (!ausweis_id) {
|
||||||
// Falls es keine Ausweis ID gibt können wir nicht fortfahren.
|
|
||||||
return Astro.redirect("/400");
|
return Astro.redirect("/400");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,10 +94,9 @@ if (typ === AusstellungsTyp.Neuausstellung) {
|
|||||||
return Astro.redirect("/405");
|
return Astro.redirect("/405");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wir setzen alle Daten vom Ausweis zurück, sonst könnte es passieren, dass der Ausweis als der alte Ausweis gespeichert wird.
|
ausweis.id = null;
|
||||||
ausweis.id = "";
|
aufnahme.id = null;
|
||||||
aufnahme.id = "";
|
delete aufnahme.erstellungsdatum;
|
||||||
aufnahme.erstellungsdatum = null;
|
|
||||||
ausweis.created_at = new Date()
|
ausweis.created_at = new Date()
|
||||||
ausweis.updated_at = new Date();
|
ausweis.updated_at = new Date();
|
||||||
ausweis.alte_ausweis_id = null;
|
ausweis.alte_ausweis_id = null;
|
||||||
@@ -121,7 +114,7 @@ if (typ === AusstellungsTyp.Neuausstellung) {
|
|||||||
loadFromDatabase = true;
|
loadFromDatabase = true;
|
||||||
} else if (typ === AusstellungsTyp.Speichern) {
|
} else if (typ === AusstellungsTyp.Speichern) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return Astro.redirect(`/auth/login?r=${Astro.url.toString()}`);
|
return Astro.redirect(`/auth/login?redirect=${Astro.url.toString()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ausweis_id) {
|
if (!ausweis_id) {
|
||||||
@@ -136,11 +129,6 @@ if (typ === AusstellungsTyp.Neuausstellung) {
|
|||||||
ausweis = await getBedarfsausweisWohnen(ausweis_id);
|
ausweis = await getBedarfsausweisWohnen(ausweis_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ausweis) {
|
|
||||||
// Falls der Ausweis nicht gefunden wurde, können wir nicht fortfahren.
|
|
||||||
return Astro.redirect("/404");
|
|
||||||
}
|
|
||||||
|
|
||||||
ausweistyp = ausweis.ausweistyp;
|
ausweistyp = ausweis.ausweistyp;
|
||||||
|
|
||||||
aufnahme = (await getAufnahme(ausweis.aufnahme_id)) as Aufnahme;
|
aufnahme = (await getAufnahme(ausweis.aufnahme_id)) as Aufnahme;
|
||||||
@@ -159,11 +147,10 @@ if (typ === AusstellungsTyp.Neuausstellung) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bilder = await getBilder(aufnahme.id);
|
bilder = await getBilder(aufnahme.id);
|
||||||
unterlagen = await getUnterlagen(aufnahme.id);
|
|
||||||
loadFromDatabase = true;
|
loadFromDatabase = true;
|
||||||
} else if (typ === AusstellungsTyp.Alternativdokument) {
|
} else if (typ === AusstellungsTyp.Alternativdokument) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return Astro.redirect(`/auth/login?r=${Astro.url.toString()}`);
|
return Astro.redirect(`/auth/login?redirect=${Astro.url.toString()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ausweis_id) {
|
if (!ausweis_id) {
|
||||||
@@ -201,8 +188,8 @@ if (typ === AusstellungsTyp.Neuausstellung) {
|
|||||||
return Astro.redirect("/405");
|
return Astro.redirect("/405");
|
||||||
}
|
}
|
||||||
|
|
||||||
ausweis.id = "";
|
ausweis.id = null;
|
||||||
aufnahme.erstellungsdatum = null;
|
delete aufnahme.erstellungsdatum;
|
||||||
ausweis.created_at = new Date()
|
ausweis.created_at = new Date()
|
||||||
ausweis.updated_at = new Date();
|
ausweis.updated_at = new Date();
|
||||||
ausweis.alte_ausweis_id = null;
|
ausweis.alte_ausweis_id = null;
|
||||||
@@ -262,7 +249,6 @@ if (typ === AusstellungsTyp.Neuausstellung) {
|
|||||||
{aufnahme}
|
{aufnahme}
|
||||||
{bilder}
|
{bilder}
|
||||||
{ausweistyp}
|
{ausweistyp}
|
||||||
{unterlagen}
|
|
||||||
{ausweis_id}
|
{ausweis_id}
|
||||||
{user}
|
{user}
|
||||||
{loadFromDatabase}
|
{loadFromDatabase}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const caller = createCaller(Astro);
|
|||||||
if (uid) {
|
if (uid) {
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
return Astro.redirect(
|
return Astro.redirect(
|
||||||
`/auth/login?r=${Astro.url.toString()}`
|
`/auth/login?redirect=${Astro.url.toString()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const caller = createCaller(Astro);
|
|||||||
if (uid) {
|
if (uid) {
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
return Astro.redirect(
|
return Astro.redirect(
|
||||||
`/auth/login?r=${Astro.url.toString()}`
|
`/auth/login?redirect=${Astro.url.toString()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const caller = createCaller(Astro);
|
|||||||
if (uid) {
|
if (uid) {
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
return Astro.redirect(
|
return Astro.redirect(
|
||||||
`/auth/login?r=${Astro.url.toString()}`
|
`/auth/login?redirect=${Astro.url.toString()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const caller = createCaller(Astro);
|
|||||||
if (uid) {
|
if (uid) {
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
return Astro.redirect(
|
return Astro.redirect(
|
||||||
`/auth/login?r=${Astro.url.toString()}`
|
`/auth/login?redirect=${Astro.url.toString()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const caller = createCaller(Astro);
|
|||||||
if (uid) {
|
if (uid) {
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
return Astro.redirect(
|
return Astro.redirect(
|
||||||
`/auth/login?r=${Astro.url.toString()}`
|
`/auth/login?redirect=${Astro.url.toString()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const caller = createCaller(Astro);
|
|||||||
if (uid) {
|
if (uid) {
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
return Astro.redirect(
|
return Astro.redirect(
|
||||||
`/auth/login?r=${Astro.url.toString()}`
|
`/auth/login?redirect=${Astro.url.toString()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -363,7 +363,7 @@ import Layout from "#layouts/Layout.astro";
|
|||||||
eingegeben und an uns übermittelt und gespeichert. Eine Weitergabe der Daten an Dritte findet
|
eingegeben und an uns übermittelt und gespeichert. Eine Weitergabe der Daten an Dritte findet
|
||||||
nicht statt. Folgende Daten werden im Rahmen des Registrierungsprozesses erhoben:</p>
|
nicht statt. Folgende Daten werden im Rahmen des Registrierungsprozesses erhoben:</p>
|
||||||
<ol>
|
<ol>
|
||||||
<li>Vorname, Name und E-Mail des Ansprechpartners</li>
|
<li>Anrede, Vorname, Name und E-Mail des Ansprechpartners</li>
|
||||||
<li>Empfänger, E-Mail, Straße, <span class="caps">PLZ</span> und Ort der Rechnungsanschrift
|
<li>Empfänger, E-Mail, Straße, <span class="caps">PLZ</span> und Ort der Rechnungsanschrift
|
||||||
</li>
|
</li>
|
||||||
<li>Optional die Versandanschrift</li>
|
<li>Optional die Versandanschrift</li>
|
||||||
@@ -417,7 +417,7 @@ import Layout from "#layouts/Layout.astro";
|
|||||||
Kontaktaufnahme genutzt werden kann. Nimmt ein Nutzer diese Möglichkeit wahr, so werden die in
|
Kontaktaufnahme genutzt werden kann. Nimmt ein Nutzer diese Möglichkeit wahr, so werden die in
|
||||||
der Eingabemaske eingegeben Daten an uns übermittelt und gespeichert. Diese Daten sind:</p>
|
der Eingabemaske eingegeben Daten an uns übermittelt und gespeichert. Diese Daten sind:</p>
|
||||||
<ol>
|
<ol>
|
||||||
<li>Vorname, Name und E-Mail des Ansprechpartners</li>
|
<li>Anrede, Vorname, Name und E-Mail des Ansprechpartners</li>
|
||||||
</ol> Im Zeitpunkt der Absendung der Nachricht werden zudem folgende Daten gespeichert:<ol>
|
</ol> Im Zeitpunkt der Absendung der Nachricht werden zudem folgende Daten gespeichert:<ol>
|
||||||
<li>Die IP-Adresse des Nutzers</li>
|
<li>Die IP-Adresse des Nutzers</li>
|
||||||
<li>Datum und Uhrzeit der Registrierung</li>
|
<li>Datum und Uhrzeit der Registrierung</li>
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ import Layout from "#layouts/Layout.astro";
|
|||||||
<div>
|
<div>
|
||||||
<h3 class="text-xl font-semibold text-gray-800 mb-2">Kontakt und Gebäudedaten</h3>
|
<h3 class="text-xl font-semibold text-gray-800 mb-2">Kontakt und Gebäudedaten</h3>
|
||||||
<ul class="list-disc list-inside text-gray-700">
|
<ul class="list-disc list-inside text-gray-700">
|
||||||
<li>Vorname, Name und E-Mail des Ansprechpartners</li>
|
<li>Anrede, Vorname, Name und E-Mail des Ansprechpartners</li>
|
||||||
<li>Empfänger, E-Mail, Straße, PLZ und Ort der Rechnungsanschrift</li>
|
<li>Empfänger, E-Mail, Straße, PLZ und Ort der Rechnungsanschrift</li>
|
||||||
<li>Optionale Versandanschrift</li>
|
<li>Optionale Versandanschrift</li>
|
||||||
<li>Details zur Wohnfläche, Heizung, Baujahr usw.</li>
|
<li>Details zur Wohnfläche, Heizung, Baujahr usw.</li>
|
||||||
|
|||||||
@@ -279,31 +279,3 @@ article {
|
|||||||
/*SIDEBAR-RIGHT*/
|
/*SIDEBAR-RIGHT*/
|
||||||
|
|
||||||
/*FOOTER*/
|
/*FOOTER*/
|
||||||
|
|
||||||
|
|
||||||
/* LOADERS */
|
|
||||||
|
|
||||||
.loader {
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
border: 3px solid #444f94;
|
|
||||||
border-bottom-color: transparent;
|
|
||||||
border-radius: 50%;
|
|
||||||
display: inline-block;
|
|
||||||
box-sizing: border-box;
|
|
||||||
animation: rotation 1s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes rotation {
|
|
||||||
0% {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FORM VALIDATION MESSAGE */
|
|
||||||
[data-isinvalid="true"] {
|
|
||||||
border: 2px solid red !important;
|
|
||||||
}
|
|
||||||
@@ -45,6 +45,7 @@ Papa.parse(file, {
|
|||||||
email: user.email,
|
email: user.email,
|
||||||
passwort: user.password,
|
passwort: user.password,
|
||||||
adresse: user.adresse,
|
adresse: user.adresse,
|
||||||
|
anrede: user.anrede,
|
||||||
name: user.name,
|
name: user.name,
|
||||||
vorname: user.vorname,
|
vorname: user.vorname,
|
||||||
ort: user.ort,
|
ort: user.ort,
|
||||||
|
|||||||
@@ -338,6 +338,7 @@ export function fakeBenutzer() {
|
|||||||
ort: undefined,
|
ort: undefined,
|
||||||
adresse: undefined,
|
adresse: undefined,
|
||||||
telefon: undefined,
|
telefon: undefined,
|
||||||
|
anrede: undefined,
|
||||||
firma: undefined,
|
firma: undefined,
|
||||||
lex_office_id: undefined,
|
lex_office_id: undefined,
|
||||||
};
|
};
|
||||||
@@ -355,6 +356,7 @@ export function fakeBenutzerComplete() {
|
|||||||
ort: undefined,
|
ort: undefined,
|
||||||
adresse: undefined,
|
adresse: undefined,
|
||||||
telefon: undefined,
|
telefon: undefined,
|
||||||
|
anrede: undefined,
|
||||||
rolle: BenutzerRolle.USER,
|
rolle: BenutzerRolle.USER,
|
||||||
firma: undefined,
|
firma: undefined,
|
||||||
lex_office_id: undefined,
|
lex_office_id: undefined,
|
||||||
|
|||||||
@@ -45,14 +45,7 @@ fi
|
|||||||
|
|
||||||
echo "🧨 Alle Daten aus allen Tabellen werden gelöscht..."
|
echo "🧨 Alle Daten aus allen Tabellen werden gelöscht..."
|
||||||
|
|
||||||
# Erst müssen wir alle Verbindungen zur Datenbank trennen
|
# Generate and run TRUNCATE statements for all tables in the public schema
|
||||||
docker exec -i "$CONTAINER_NAME" psql -U "$DB_USER" "postgres" <<'EOSQL'
|
|
||||||
SELECT pg_terminate_backend(pid)
|
|
||||||
FROM pg_stat_activity
|
|
||||||
WHERE datname = 'main' AND pid <> pg_backend_pid();
|
|
||||||
EOSQL
|
|
||||||
|
|
||||||
# Dann löschen wir die Datenbank und erstellen sie neu
|
|
||||||
docker exec -i "$CONTAINER_NAME" psql -U "$DB_USER" "postgres" <<'EOSQL'
|
docker exec -i "$CONTAINER_NAME" psql -U "$DB_USER" "postgres" <<'EOSQL'
|
||||||
DROP DATABASE IF EXISTS main;
|
DROP DATABASE IF EXISTS main;
|
||||||
CREATE DATABASE main WITH OWNER main ENCODING 'UTF8';
|
CREATE DATABASE main WITH OWNER main ENCODING 'UTF8';
|
||||||
|
|||||||
Reference in New Issue
Block a user