3
bun.lock
3
bun.lock
@@ -28,6 +28,7 @@
|
||||
"flag-icons": "^6.15.0",
|
||||
"fontkit": "^2.0.4",
|
||||
"handlebars": "^4.7.8",
|
||||
"heic2any": "^0.0.4",
|
||||
"highlight.run": "^9.14.0",
|
||||
"is-base64": "^1.1.0",
|
||||
"js-cookie": "^3.0.5",
|
||||
@@ -1555,6 +1556,8 @@
|
||||
|
||||
"hastscript": ["hastscript@9.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-jzaLBGavEDKHrc5EfFImKN7nZKKBdSLIdGvCwDZ9TfzbF2ffXiov8CKE445L2Z1Ek2t/m4SKQ2j6Ipv7NyUolw=="],
|
||||
|
||||
"heic2any": ["heic2any@0.0.4", "", {}, "sha512-3lLnZiDELfabVH87htnRolZ2iehX9zwpRyGNz22GKXIu0fznlblf0/ftppXKNqS26dqFSeqfIBhAmAj/uSp0cA=="],
|
||||
|
||||
"hexoid": ["hexoid@2.0.0", "", {}, "sha512-qlspKUK7IlSQv2o+5I7yhUd7TxlOG2Vr5LTa3ve2XSNVKAL/n/u/7KLvKmFNimomDIKvZFXWHv0T12mv7rT8Aw=="],
|
||||
|
||||
"highlight.run": ["highlight.run@9.14.0", "", {}, "sha512-ZR+ZLHlVU8lXqsuto0ZEMAOuvptaTBBf1jradnKDIn9OfAXupcYFbkASDlbsZtyBh2SYJSK50xwrucXujhksRg=="],
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
"flag-icons": "^6.15.0",
|
||||
"fontkit": "^2.0.4",
|
||||
"handlebars": "^4.7.8",
|
||||
"heic2any": "^0.0.4",
|
||||
"highlight.run": "^9.14.0",
|
||||
"is-base64": "^1.1.0",
|
||||
"js-cookie": "^3.0.5",
|
||||
|
||||
@@ -5,7 +5,12 @@ export const createCaller = createCallerFactory({
|
||||
"klimafaktoren": await import("../src/pages/api/klimafaktoren.ts"),
|
||||
"postleitzahlen": await import("../src/pages/api/postleitzahlen.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/bedarfsausweis-ausstellen": await import("../src/pages/api/admin/bedarfsausweis-ausstellen.ts"),
|
||||
"admin/bestellbestaetigung": await import("../src/pages/api/admin/bestellbestaetigung.ts"),
|
||||
@@ -13,30 +18,26 @@ export const createCaller = createCallerFactory({
|
||||
"admin/nicht-ausstellen": await import("../src/pages/api/admin/nicht-ausstellen.ts"),
|
||||
"admin/registriernummer": await import("../src/pages/api/admin/registriernummer.ts"),
|
||||
"admin/stornieren": await import("../src/pages/api/admin/stornieren.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"),
|
||||
"ausweise": await import("../src/pages/api/ausweise/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"),
|
||||
"bedarfsausweis-gewerbe/[id]": await import("../src/pages/api/bedarfsausweis-gewerbe/[id].ts"),
|
||||
"bedarfsausweis-gewerbe": await import("../src/pages/api/bedarfsausweis-gewerbe/index.ts"),
|
||||
"bilder/[id]": await import("../src/pages/api/bilder/[id].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"),
|
||||
"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"),
|
||||
"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/anfordern": await import("../src/pages/api/rechnung/anfordern.ts"),
|
||||
"rechnung": await import("../src/pages/api/rechnung/index.ts"),
|
||||
"user": await import("../src/pages/api/user/index.ts"),
|
||||
"user/self": await import("../src/pages/api/user/self.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"),
|
||||
"user": await import("../src/pages/api/user/index.ts"),
|
||||
"user/self": await import("../src/pages/api/user/self.ts"),
|
||||
"verbrauchsausweis-gewerbe/[id]": await import("../src/pages/api/verbrauchsausweis-gewerbe/[id].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"),
|
||||
"aufnahme/[id]/bilder": await import("../src/pages/api/aufnahme/[id]/bilder.ts"),
|
||||
"aufnahme/[id]": await import("../src/pages/api/aufnahme/[id]/index.ts"),
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
import { dialogs } from "../../../svelte-dialogs.config";
|
||||
import { loginClient } from "#lib/login";
|
||||
import { addNotification } from "#components/Notifications/shared";
|
||||
|
||||
export async function spawnLoginPrompt() {
|
||||
const result = await dialogs.prompt(
|
||||
[
|
||||
{
|
||||
label: "Email",
|
||||
type: "email",
|
||||
required: true,
|
||||
placeholder: "Email",
|
||||
name: "email"
|
||||
},
|
||||
{
|
||||
label: "Passwort",
|
||||
type: "password",
|
||||
name: "passwort",
|
||||
required: true,
|
||||
placeholder: "********",
|
||||
},
|
||||
],
|
||||
{
|
||||
title: "Login",
|
||||
submitButtonText: "Einloggen",
|
||||
cancelButtonText: "Abbrechen",
|
||||
}
|
||||
);
|
||||
|
||||
if (!result) return false;
|
||||
|
||||
const [email, passwort] = result;
|
||||
|
||||
const loginResult = await loginClient(email, passwort);
|
||||
|
||||
if (loginResult === null) {
|
||||
addNotification({
|
||||
type: "error",
|
||||
message: "Einloggen fehlgeschlagen",
|
||||
dismissable: true,
|
||||
subtext: "Bitte überprüfen Sie ihre Eingaben und versuchen es erneut.",
|
||||
timeout: 5000,
|
||||
})
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
import { dialogs } from "../../../svelte-dialogs.config.js";
|
||||
import { addNotification } from "#components/Notifications/shared.js";
|
||||
import { api } from "astro-typesafe-api/client";
|
||||
|
||||
export async function spawnSignupPrompt() {
|
||||
const result = await dialogs.prompt(
|
||||
[
|
||||
{
|
||||
label: "Vorname",
|
||||
type: "text",
|
||||
required: true,
|
||||
placeholder: "Vorname",
|
||||
name: "vorname"
|
||||
},
|
||||
{
|
||||
label: "Name",
|
||||
type: "text",
|
||||
required: true,
|
||||
placeholder: "Name",
|
||||
name: "name"
|
||||
},
|
||||
{
|
||||
label: "Email",
|
||||
type: "email",
|
||||
required: true,
|
||||
placeholder: "Email",
|
||||
name: "email"
|
||||
},
|
||||
{
|
||||
label: "Passwort",
|
||||
type: "password",
|
||||
name: "passwort",
|
||||
required: true,
|
||||
placeholder: "********",
|
||||
},
|
||||
],
|
||||
{
|
||||
title: "Registrieren",
|
||||
submitButtonText: "Registrieren",
|
||||
cancelButtonText: "Abbrechen",
|
||||
}
|
||||
);
|
||||
|
||||
if (!result) return false;
|
||||
|
||||
const [vorname, name, email, passwort] = result;
|
||||
|
||||
try {
|
||||
const response = await api.user.PUT.fetch({
|
||||
email,
|
||||
passwort,
|
||||
vorname,
|
||||
name,
|
||||
});
|
||||
|
||||
return true;
|
||||
} catch(e) {
|
||||
addNotification({
|
||||
type: "error",
|
||||
message: "Registrieren fehlgeschlagen",
|
||||
dismissable: true,
|
||||
subtext: "Ein Fehler ist aufgetreten, vielleicht wird die angegebene Email bereits verwendet.",
|
||||
timeout: 5000,
|
||||
})
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,22 @@
|
||||
export let objekt: ObjektClient;
|
||||
|
||||
export let ausweisart: Enums.Ausweisart;
|
||||
|
||||
function onlyAllowIntegerInput(event: KeyboardEvent) {
|
||||
const charCode = event.which || event.keyCode;
|
||||
// Allow only numbers (0-9) and control keys (e.g., backspace)
|
||||
if (charCode < 48 || charCode > 57) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
function onlyAllowPastingIntegers(event: ClipboardEvent) {
|
||||
const clipboardData = event.clipboardData || (window as any).clipboardData;
|
||||
const pastedData = clipboardData.getData("Text");
|
||||
if (!/^\d+$/.test(pastedData)) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
@@ -100,6 +116,8 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
|
||||
step="1"
|
||||
required
|
||||
autocomplete="off"
|
||||
on:keypress={onlyAllowIntegerInput}
|
||||
on:paste={onlyAllowPastingIntegers}
|
||||
bind:value={aufnahme.flaeche}
|
||||
/>
|
||||
|
||||
@@ -125,6 +143,8 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
|
||||
type="number"
|
||||
step="1"
|
||||
required
|
||||
on:keypress={onlyAllowIntegerInput}
|
||||
on:paste={onlyAllowPastingIntegers}
|
||||
bind:value={aufnahme.nutzflaeche}
|
||||
/>
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ const brennstoffe: [
|
||||
["Flüssiggas", "kg", 13.0, 1.1, 0.27],
|
||||
["Braunkohle", "kg", 5.5, 1.2, 0.43],
|
||||
["Holzhackschnitzel", "SRm", 650.0, 0.2, 0.02],
|
||||
["Strommix", "kWh", 1.0, 2.4, 0.56],
|
||||
["Strommix", "kWh", 1.0, 1.8, 0.56],
|
||||
["Fernwärme KWK FB", "kWh", 1.0, 0.7, 0.3],
|
||||
["Nahwärme KWK FB", "kWh", 1.0, 0.7, 0.3],
|
||||
["Heizöl EL", "kWh", 1.0, 1.1, 0.31],
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import type { Enums } from "#lib/client/prisma.js";
|
||||
import Cookies from "js-cookie";
|
||||
import { tryCatch } from "#lib/tryCatch.js";
|
||||
import heic2any from "heic2any";
|
||||
|
||||
export let max: number = 2;
|
||||
export let min: number = 1;
|
||||
@@ -38,8 +39,10 @@
|
||||
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = files[i];
|
||||
console.log(file);
|
||||
|
||||
if (file.type !== "image/jpeg" && file.type !== "image/png") {
|
||||
|
||||
if (file.type !== "image/jpeg" && file.type !== "image/png" && file.type !== "image/webp" && file.type !== "image/heif" && file.type !== "image/heic") {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -49,7 +52,7 @@
|
||||
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = () => {
|
||||
reader.onload = async () => {
|
||||
if (reader.readyState != reader.DONE) {
|
||||
return;
|
||||
}
|
||||
@@ -59,6 +62,18 @@
|
||||
}
|
||||
|
||||
let blob = new Blob([reader.result as ArrayBuffer]);
|
||||
|
||||
if (file.type === "image/heif" || file.type === "image/heic") {
|
||||
// Heic files are not supported by canvas, so we convert them to jpeg first
|
||||
// using an external library.
|
||||
// This is a workaround until all browsers support heic natively.
|
||||
// For more information see: https://caniuse.com/?search=heic
|
||||
// and https://developer.apple.com/documentation/imageio/reading_heif_and_heic_images_on_ios
|
||||
// and https://stackoverflow.com/questions/65887402/how-to-convert-heic-to-jpeg-in-javascript
|
||||
// and https://github.com/mbitsnbites/heic2any
|
||||
blob = await heic2any({ blob, toType: "image/jpeg", quality: 0.8 });
|
||||
}
|
||||
|
||||
let url = URL.createObjectURL(blob);
|
||||
let image = new Image();
|
||||
image.onload = async () => {
|
||||
|
||||
@@ -12,7 +12,7 @@ export async function sendRegisterMail(
|
||||
const verificationJwt = encodeToken({
|
||||
typ: TokenType.Verify,
|
||||
exp: Date.now() + (15 * 60 * 1000),
|
||||
uid: user.uid
|
||||
id: user.id
|
||||
})
|
||||
|
||||
await transport.sendMail({
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
name="email"
|
||||
class="px-2.5 py-1.5 rounded-lg border bg-gray-50"
|
||||
bind:value={email}
|
||||
on:keyup={() => (email = email.toLowerCase())}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import { CrossCircled } from "radix-svelte-icons";
|
||||
import { fade } from "svelte/transition";
|
||||
import { api } from "astro-typesafe-api/client";
|
||||
import NotificationProvider from "#components/NotificationProvider/NotificationProvider.svelte";
|
||||
import NotificationWrapper from "#components/Notifications/NotificationWrapper.svelte";
|
||||
|
||||
let passwort: string;
|
||||
@@ -13,10 +12,6 @@
|
||||
|
||||
export let redirect: string | null = null;
|
||||
|
||||
function handleInput(event) {
|
||||
email = event.target.value.toLowerCase();
|
||||
}
|
||||
|
||||
async function login(e: SubmitEvent) {
|
||||
e.preventDefault()
|
||||
if (passwort.length < 8) {
|
||||
@@ -30,7 +25,7 @@
|
||||
}
|
||||
|
||||
try {
|
||||
const { uid } = await api.user.PUT.fetch({
|
||||
const { id } = await api.user.PUT.fetch({
|
||||
email,
|
||||
passwort,
|
||||
vorname,
|
||||
@@ -87,7 +82,7 @@
|
||||
name="email"
|
||||
class="input input-bordered text-base text-base-content font-medium"
|
||||
bind:value={email}
|
||||
on:input={handleInput}
|
||||
on:keyup={() => (email = email.toLowerCase())}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user