Bugfixes, Kundendaten, Datenbank Anpassung

This commit is contained in:
Moritz Utcke
2024-01-10 15:09:30 +07:00
parent ee5133b3f8
commit b20b857a7d
60 changed files with 737 additions and 1647 deletions

View File

@@ -1,6 +1,6 @@
import { defineConfig } from "astro/config";
import svelte from "@astrojs/svelte";
import astroI18next from "astro-i18next";
// import astroI18next from "astro-i18next";
import tailwind from "@astrojs/tailwind";
@@ -12,7 +12,7 @@ import mdx from "@astrojs/mdx";
// https://astro.build/config
export default defineConfig({
integrations: [astroI18next(),svelte(), tailwind(), mdx()],
integrations: [/*astroI18next(),*/svelte(), tailwind(), mdx()],
outDir: "./dist",
output: "server",
adapter: node({

View File

@@ -1,9 +0,0 @@
POSTGRES_DB=main
POSTGRES_HOST=database
POSTGRES_PORT=5432
POSTGRES_USER=main
POSTGRES_PASSWORD=hHMP8cd^N3SnzGRR
DB_CONTAINER_NAME=database
POSTGRES_DATABASE_URL="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}"

View File

@@ -1,11 +1,9 @@
version: '3'
services:
online-energieausweis:
ibcornelsen-online-energieausweis:
build: ./
container_name: online-energieausweis
command: bun run dev --host
depends_on:
- database
environment:
PORT: 3000
NODE_ENV: "development"
@@ -14,9 +12,5 @@ services:
- ./:/online-energieausweis
- ./node_modules/@ibcornelsen/ui:/online-energieausweis/node_modules/@ibcornelsen/ui
- ./node_modules/@ibcornelsen/database:/online-energieausweis/node_modules/@ibcornelsen/database
- ./node_modules/@ibcornelsen/api:/online-energieausweis/node_modules/@ibcornelsen/api
- ./persistent:/persistent
database:
network_mode: host
build: ../database
env_file:
- ../database/.env

View File

@@ -28,6 +28,7 @@
"@trpc/server": "^10.45.0",
"astro": "^2.5.1",
"astro-i18next": "1.0.0-beta.21",
"buffer": "^6.0.3",
"bun": "^1.0.2",
"cookiejs": "^2.1.2",
"csvtojson": "^2.0.10",

View File

@@ -1,12 +1,19 @@
<script lang="ts">
import { VerbrauchsausweisWohnen } from "@ibcornelsen/database";
import { GebaeudeStammdaten, VerbrauchsausweisWohnen } from "@ibcornelsen/database";
import { Buffer } from "buffer";
export let ausweis: VerbrauchsausweisWohnen;
export let gebaeude: GebaeudeStammdaten;
const base64 = btoa(JSON.stringify(ausweis));
let base64: string = "";
$: {
if (ausweis && gebaeude) {
base64 = Buffer.from(JSON.stringify({...ausweis, gebaeude_stammdaten: gebaeude}), "utf-8").toString("base64");
}
}
</script>
<a class="border-2 rounded-lg w-[30%] bg-white text-center hover:shadow-md no-underline p-6 cursor-pointer" target="_blank" href="/pdf/datenblatt?base64={base64}">
<a class="border-2 rounded-lg w-[30%] bg-white text-center hover:shadow-md no-underline p-6 cursor-pointer" target="_blank" href="/pdf/ansichtsausweis?base64={base64}">
<img src="/images/ausweis.webp" alt="Ausweis" />
<span class="text-black font-medium text-lg">Ansichtsausweis</span>
</a>

View File

@@ -4,9 +4,10 @@
import HelpLabel from "#components/HelpLabel.svelte";
export let ausweis: VerbrauchsausweisWohnen;
export let gebaeude: GebaeudeStammdaten;
import ImageGrid from "../ImageGrid.svelte";
import { VerbrauchsausweisWohnen } from "@ibcornelsen/database";
import { GebaeudeStammdaten, VerbrauchsausweisWohnen } from "@ibcornelsen/database";
let images: (File & { data: string })[] = [];
</script>
@@ -33,8 +34,8 @@
<hr class="trenner_form_100" />
<div class="flex flex-row gap-4">
<AnsichtsausweisButton {ausweis} />
<DatenblattButton {ausweis} />
<AnsichtsausweisButton {ausweis} {gebaeude} />
<DatenblattButton {ausweis} {gebaeude} />
</div>
</div>
</div>

View File

@@ -348,4 +348,4 @@
als PDF anschauen</Label
>
<AusweisPreviewContainer {ausweis} />
<AusweisPreviewContainer {ausweis} {gebaeude} />

View File

@@ -1,9 +1,16 @@
<script lang="ts">
import { VerbrauchsausweisWohnen } from "@ibcornelsen/database";
import { GebaeudeStammdaten, VerbrauchsausweisWohnen } from "@ibcornelsen/database";
import { Buffer } from "buffer";
export let ausweis: VerbrauchsausweisWohnen;
export let gebaeude: GebaeudeStammdaten;
const base64 = btoa(JSON.stringify(ausweis));
let base64: string = "";
$: {
if (ausweis && gebaeude) {
base64 = Buffer.from(JSON.stringify({...ausweis, gebaeude_stammdaten: gebaeude}), "utf-8").toString("base64");
}
}
</script>
<a class="border-2 rounded-lg w-[30%] bg-white text-center hover:shadow-md no-underline p-6 cursor-pointer" target="_blank" href="/pdf/datenblatt?base64={base64}">

View File

@@ -1,9 +1,9 @@
---
import i18next from "i18next";
import {localizeUrl} from "astro-i18next"
import { t } from "i18next";
// import i18next from "i18next";
// import {localizeUrl} from "astro-i18next"
// import { t } from "i18next";
import { isLoggedIn } from "../lib/UI/isLoggedIn";
import LanguageDropdown from "./LanguageDropdown.svelte";
// import LanguageDropdown from "./LanguageDropdown.svelte";
const loggedIn = isLoggedIn(Astro);
---
@@ -38,7 +38,7 @@ const loggedIn = isLoggedIn(Astro);
</div>
<div class="nav-head">
<LanguageDropdown
<!--<LanguageDropdown
countries={[
{ iso: "de", flag: "de", name: "Deutsch" },
{ iso: "en", flag: "us", name: "English" },
@@ -49,7 +49,7 @@ const loggedIn = isLoggedIn(Astro);
})}
current={i18next.language}
client:load
/>
/> -->
<a
class="headerButton"
href="/energieausweis-erstellen/verbrauchsausweis-erstellen.php"

View File

@@ -0,0 +1,15 @@
<script lang="ts">
import { Bezahlmethoden } from "@ibcornelsen/database";
export let name: string;
export let icon: string;
export let paymentType: Bezahlmethoden;
export let selectedPaymentType: Bezahlmethoden;
</script>
<button class="flex flex-col items-center cursor-pointer" class:bg-gray-100={paymentType == selectedPaymentType} on:click={() => selectedPaymentType = paymentType}>
<img src={icon} alt={name} />
<span aria-label={name}>
{name}
</span>
</button>

View File

@@ -1,7 +1,3 @@
---
import { localizePath } from "astro-i18next"
---
<div class="flex flex-col gap-6">
<nav>
<div class="nav-card">
@@ -10,9 +6,9 @@ import { localizePath } from "astro-i18next"
>Energieausweis erstellen</a
>
<div class="dropdown-content">
<a href={localizePath("/verbrauchsausweis")}>Verbrauchsausweis erstellen</a>
<a href={localizePath("/bedarfsausweis")}>Bedarfsausweis erstellen</a>
<a href={localizePath("/verbrauchsausweis-gewerbe")}
<a href="/verbrauchsausweis">Verbrauchsausweis erstellen</a>
<a href="/bedarfsausweis">Bedarfsausweis erstellen</a>
<a href="/verbrauchsausweis-gewerbe"
>Verbrauchsausweis Gewerbe erstellen</a
>
<a href="/bedarfsausweis-gewerbe"

View File

@@ -9,10 +9,10 @@
import ZipSearch from "../ZIPSearch.svelte";
import { buildingTypes } from "./BuildingTypes";
import BilderZusatzsysteme from "../Ausweis/BilderZusatzsysteme.svelte";
import { VerbrauchsausweisGewerbe } from "src/lib/Ausweis/VerbrauchsausweisGewerbe";
import moment from "moment";
import { VerbrauchsausweisGewerbe } from "@ibcornelsen/database";
let ausweis = new VerbrauchsausweisGewerbe();
let ausweis: VerbrauchsausweisGewerbe = {};
let additionalHeating: boolean = false;
let heatedWaterIncluded: boolean = false;

View File

@@ -43,8 +43,6 @@ const schema = JSON.stringify({
<meta name="viewport" content="width=device-width" />
<script type="application/ld+json" set:html={schema}></script>
<link rel="icon" type="image/svg+xml" href="/favicon.jpg" />
<link rel="stylesheet" href="style/main.css" />
<link rel="stylesheet" href="style/bootstrap.min.css" />
<meta
name="description"

View File

@@ -47,8 +47,6 @@ const schema = JSON.stringify({
<meta name="viewport" content="width=device-width" />
<script type="application/ld+json" set:html={schema}></script>
<link rel="icon" type="image/svg+xml" href="/favicon.jpg" />
<link rel="stylesheet" href="style/main.css" />
<link rel="stylesheet" href="style/bootstrap.min.css" />
<meta
name="description"

View File

@@ -1,4 +1,4 @@
import { getKlimafaktoren } from "#lib/getKlimafaktoren";
import { getKlimafaktoren } from "#lib/Klimafaktoren";
import { getHeizwertfaktor } from "#lib/server/Heizwertfaktor";
import { GebaeudeStammdaten, VerbrauchsausweisWohnen } from "@ibcornelsen/database";

View File

@@ -1,12 +0,0 @@
import jwt from "jwt-simple";
type TokenData = { uid: string, exp: number }
export function encodeToken(data: TokenData) {
const token = jwt.encode(data, "yIvbgS$k7Bfc+mpV%TWDZAhje9#uJad4", "HS256");
return token;
}
export function decodeToken(token: string): Partial<TokenData> {
return jwt.decode(token, "yIvbgS$k7Bfc+mpV%TWDZAhje9#uJad4");
}

View File

@@ -1,19 +0,0 @@
import * as crypto from "crypto";
export function hashPassword(password: string): string {
const salt = crypto.randomBytes(16).toString("hex");
const hash = hashWithGivenSalt(password, salt) + salt;
return hash;
}
export function hashWithGivenSalt(password: string, salt: string): string {
const hash = crypto.scryptSync(password, salt, 32).toString("hex");
return hash;
}
export function validatePassword(known: string, unknown: string): boolean {
const salt = known.slice(64);
const originalPasswordHash = known.slice(0, 64);
const currentPasswordHash = hashWithGivenSalt(unknown, salt)
return originalPasswordHash == currentPasswordHash;
}

View File

@@ -2,7 +2,7 @@ import {
endEnergieVerbrauchVerbrauchsausweis_2016,
energetischeNutzflaecheVerbrauchsausweisWohnen_2016,
} from "#lib/Berechnungen/VerbrauchsausweisWohnen/VerbrauchsausweisWohnen_2016";
import { getKlimafaktoren } from "#lib/getKlimafaktoren";
import { getKlimafaktoren } from "#lib/Klimafaktoren";
import { getHeizwertfaktor } from "#lib/server/Heizwertfaktor";
import {
GebaeudeStammdaten,

View File

@@ -1 +0,0 @@
export { validateAuthorizationHeader } from "./validate";

View File

@@ -1,62 +0,0 @@
import { decodeToken } from "src/lib/JsonWebToken";
import { validatePassword } from "src/lib/Password";
import { User } from "src/lib/User";
export async function validateAuthorizationHeader(
request: Request,
validAuthenticationMethods: ("Bearer" | "Basic")[]
): Promise<User | null> {
if (!request.headers.has("authorization")) {
return null;
}
const header = request.headers.get("authorization") as string;
const [authorizationType, value] = header.split(" ");
if (authorizationType == "Basic" && validAuthenticationMethods.indexOf("Basic") > -1) {
// Basic user validation;
try {
const [email, password] = Buffer.from(value, "base64")
.toString()
.split(":");
const user = await User.fromEmail(email);
if (!user) {
return null;
}
if (!validatePassword(user.passwort, password)) {
return null;
}
return user;
} catch (e) {
return null;
}
} else if (authorizationType == "Bearer" && validAuthenticationMethods.indexOf("Bearer") > -1) {
const stringToken = Buffer.from(value, "base64").toString();
try {
const token = decodeToken<{ id: number; uid: string; exp: string }>(
stringToken
);
const id = token.id;
if (!id) {
return null;
}
const user = User.fromPrivateId(id);
if (!user) {
return null;
}
return user;
} catch (e) {
return null;
}
} else {
return null;
}
}

View File

@@ -1,26 +0,0 @@
import { initTRPC } from "@trpc/server";
import { ZodError } from "zod";
import { OpenApiMeta } from "trpc-openapi";
type Context = {
authorization: string | null;
ip: string;
req: Request;
}
export const t = initTRPC.context<Context>().meta<OpenApiMeta>().create({
errorFormatter(opts) {
const { shape, error } = opts;
return {
success: false,
...shape,
data: {
zodError:
error.code === 'BAD_REQUEST' && error.cause instanceof ZodError
? error.cause.flatten()
: null,
},
};
}
});

View File

@@ -1,26 +0,0 @@
import { prisma } from "@ibcornelsen/database";
import { privateProcedure } from "./privateProcedure";
// NOTE: Muss noch mit der Datenbank eingebunden werden.
export const loggedProcedure = privateProcedure.use(async (opts) => {
const start = Date.now();
const result = await opts.next();
const durationMs = Date.now() - start;
await prisma.apiRequests.create({
data: {
ip: opts.ctx.ip,
method: opts.type,
path: opts.path,
responseSize: JSON.stringify(result).length,
responseTime: durationMs,
userAgent: opts.ctx.req.headers["user-agent"] || "",
status: result.ok ? 200 : 500,
user_id: opts.ctx.user.id
}
})
return result;
});

View File

@@ -1,44 +0,0 @@
import { TRPCError } from "@trpc/server";
import { publicProcedure } from "./publicProcedure";
import { decodeToken } from "#lib/JsonWebToken";
import { User } from "#lib/User";
export const privateProcedure = publicProcedure.use(async (opts) => {
const { ctx } = opts;
if (!ctx.authorization) {
throw new TRPCError({ code: "UNAUTHORIZED", message: "Für diese Action ist ein Bearer Token verpflichtend." });
}
const [authorizationType, value] = ctx.authorization.split(" ");
if (authorizationType != "Bearer") {
throw new TRPCError({ code: "UNAUTHORIZED", message: "Für diese Action ist ein Bearer Token verpflichtend." });
}
const stringToken = Buffer.from(value, "base64").toString();
try {
const token = decodeToken(
stringToken
);
const uid = token.uid;
if (!uid) {
throw new TRPCError({ code: "UNAUTHORIZED", message: "Der gegebene Token ist fehlerhaft." });
}
const user = await User.fromUID(uid);
if (!user) {
throw new TRPCError({ code: "UNAUTHORIZED", message: "Der gegebene Token ist fehlerhaft." });
}
return opts.next({
ctx: {
user,
},
});
} catch (e) {
throw new TRPCError({ code: "UNAUTHORIZED", message: "Der gegebene Token ist fehlerhaft." });
}
});

View File

@@ -1,3 +0,0 @@
import { t } from "#lib/trpc/context";
export const publicProcedure = t.procedure;

View File

@@ -1,64 +0,0 @@
import { z } from "zod";
import moment from "moment";
import { prisma } from "@ibcornelsen/database";
import { publicProcedure } from "#lib/trpc/middlewares/publicProcedure";
import { encodeToken } from "#lib/JsonWebToken";
import { hashPassword } from "#lib/Password";
import { TRPCError } from "@trpc/server";
export const tRPC_V1_BenutzerErstellenProcedure = publicProcedure
.input(
z.object({
email: z.string().email(),
passwort: z.string().min(8).max(100),
vorname: z.string().min(1).max(100),
name: z.string().min(1).max(100),
})
)
.output(
z.object({
uid: z.string().uuid(),
token: z.string(),
exp: z.number(),
})
)
.query(async (opts) => {
const hashedPassword = hashPassword(opts.input.passwort);
// Vielleicht existiert der Benutzer ja schon?
const existingUser = await prisma.benutzer.findUnique({
where: {
email: opts.input.email
}
})
if (existingUser) {
throw new TRPCError({ code: "CONFLICT", message: "Der Benutzer existiert bereits." });
}
const user = await prisma.benutzer.create({
data: {
email: opts.input.email,
passwort: hashedPassword,
vorname: opts.input.vorname,
name: opts.input.name
},
select: {
id: true,
uid: true
}
})
if (!user) {
throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "Der Benutzer konnte nicht erstellt werden." });
}
const expiry = moment().add(2, "days").unix();
const token = encodeToken({ uid: user.uid, exp: expiry })
return {
uid: user.uid,
token: token,
exp: expiry
}
});

View File

@@ -1,31 +0,0 @@
import { z } from "zod";
import { BenutzerSchema, prisma } from "@ibcornelsen/database";
import { TRPCError } from "@trpc/server";
import { loggedProcedure } from "#lib/trpc/middlewares/loggedProcedure";
export const tRPC_V1_BenutzerFromPrivateIdProcedure = loggedProcedure
.input(
z.object({
id: z.number(),
})
)
.output(
BenutzerSchema
)
.query(async (opts) => {
if (opts.ctx.user.id !== opts.input.id) {
throw new TRPCError({ code: "UNAUTHORIZED", message: "Sie sind nicht dazu authorisiert die Daten dieses Benutzers einzusehen." });
}
const user = await prisma.benutzer.findUnique({
where: {
id: opts.input.id,
},
});
if (!user) {
throw new TRPCError({ code: "BAD_REQUEST", message: "Der gesuchte Benutzer existiert nicht." });
}
return user;
});

View File

@@ -1,31 +0,0 @@
import { z } from "zod";
import { BenutzerSchema, prisma } from "@ibcornelsen/database";
import { TRPCError } from "@trpc/server";
import { loggedProcedure } from "#lib/trpc/middlewares/loggedProcedure";
export const tRPC_V1_BenutzerFromPublicIdProcedure = loggedProcedure
.input(
z.object({
uid: z.string().uuid(),
})
)
.output(
BenutzerSchema
)
.query(async (opts) => {
if (opts.ctx.user.uid !== opts.input.uid) {
throw new TRPCError({ code: "UNAUTHORIZED", message: "Sie sind nicht dazu authorisiert die Daten dieses Benutzers einzusehen." });
}
const user = await prisma.benutzer.findUnique({
where: {
uid: opts.input.uid,
},
});
if (!user) {
throw new TRPCError({ code: "BAD_REQUEST", message: "Der gesuchte Benutzer existiert nicht." });
}
return user;
});

View File

@@ -1,50 +0,0 @@
import { z } from "zod";
import moment from "moment";
import { prisma } from "@ibcornelsen/database";
import { publicProcedure } from "#lib/trpc/middlewares/publicProcedure";
import { encodeToken } from "#lib/JsonWebToken";
import { hashPassword } from "#lib/Password";
import { TRPCError } from "@trpc/server";
export const tRPC_V1_BenutzerTokenErneuernProcedure = publicProcedure
.input(
z.object({
email: z.string().email(),
passwort: z.string().min(8).max(100),
})
)
.output(
z.object({
uid: z.string().uuid(),
token: z.string(),
exp: z.number(),
})
)
.query(async (opts) => {
const hashedPassword = hashPassword(opts.input.passwort);
// Falls der Nutzer nicht existiert, wird eine Fehlermeldung zurückgegeben.
const user = await prisma.benutzer.findUnique({
where: {
email: opts.input.email
}
})
if (!user) {
throw new TRPCError({ code: "BAD_REQUEST", message: "Der gesuchte Benutzer existiert nicht oder das Password ist falsch." });
}
// Falls das Passwort nicht stimmt, wird eine Fehlermeldung zurückgegeben.
if (user.passwort !== hashedPassword) {
throw new TRPCError({ code: "BAD_REQUEST", message: "Der gesuchte Benutzer existiert nicht oder das Password ist falsch." });
}
const expiry = moment().add(2, "days").unix();
const token = encodeToken({ uid: user.uid, exp: expiry })
return {
uid: user.uid,
token: token,
exp: expiry
}
});

View File

@@ -1,49 +0,0 @@
import { z } from "zod";
import { prisma } from "@ibcornelsen/database";
import { publicProcedure } from "#lib/trpc/middlewares/publicProcedure";
import { decodeToken } from "#lib/JsonWebToken";
export const tRPC_V1_BenutzerTokenValidierenProcedure = publicProcedure
.input(
z.object({
token: z.string(),
})
)
.output(
z.object({
uid: z.string().uuid(),
valid: z.boolean(),
exp: z.number()
})
)
.query(async (opts) => {
const decodedToken = decodeToken(opts.input.token);
if (!decodedToken || !decodedToken.uid || !decodedToken.exp) {
return {
uid: "",
valid: false,
exp: 0,
};
}
const user = await prisma.benutzer.findUnique({
where: {
uid: decodedToken.uid,
},
});
if (!user) {
return {
uid: "",
valid: false,
exp: 0,
};
}
return {
uid: decodedToken.uid,
valid: true,
exp: decodedToken.exp
};
});

View File

@@ -1,45 +0,0 @@
import { t } from "#lib/trpc/context";
import { tRPC_V1_KlimafaktorenProcedure } from "./klimafaktoren";
import { VerbrauchsausweisWohnen2016Erstellen } from "./verbrauchsausweis-wohnen/2016/erstellen";
import { tRPC_V1_BenutzerErstellenProcedure } from "./benutzer/erstellen";
import { tRPC_V1_BenutzerTokenErneuernProcedure } from "./benutzer/tokenErneuern";
import { tRPC_V1_BenutzerTokenValidierenProcedure } from "./benutzer/tokenValidieren";
import { tRPC_V1_BenutzerFromPublicIdProcedure } from "./benutzer/fromPublicId";
import { tRPC_V1_BenutzerFromPrivateIdProcedure } from "./benutzer/fromPrivateId";
const router = t.router;
export const v1Router = router({
verbrauchsausweisWohnen: router({
2016: router({
erstellen: VerbrauchsausweisWohnen2016Erstellen
}),
2023: router({
})
}),
verbrauchsausweisGewerbe: router({
2016: router({
}),
2023: router({
})
}),
bedarfsausweisWohen: router({
2016: router({
}),
2023: router({
})
}),
klimafaktoren: tRPC_V1_KlimafaktorenProcedure,
benutzer: router({
erstellen: tRPC_V1_BenutzerErstellenProcedure,
tokenErneuern: tRPC_V1_BenutzerTokenErneuernProcedure,
tokenValidieren: tRPC_V1_BenutzerTokenValidierenProcedure,
fromPublicId: tRPC_V1_BenutzerFromPublicIdProcedure,
fromPrivateId: tRPC_V1_BenutzerFromPrivateIdProcedure
})
})

View File

@@ -1,78 +0,0 @@
import { z } from "zod";
import moment from "moment";
import { TRPCError } from "@trpc/server";
import { prisma } from "@ibcornelsen/database";
import { publicProcedure } from "#lib/trpc/middlewares/publicProcedure";
export const tRPC_V1_KlimafaktorenProcedure = publicProcedure
.input(
z.object({
plz: z.string().min(4).max(5),
startdatum: z.coerce.date(),
enddatum: z.coerce.date(),
genauigkeit: z.enum(["months", "years"]),
})
)
.output(
z.array(
z.object({
month: z.number(),
year: z.number(),
klimafaktor: z.number(),
})
)
)
.query(async (opts) => {
const start = moment(opts.input.startdatum);
const end = moment(opts.input.enddatum);
if (start.isSameOrAfter(end)) {
throw new TRPCError({
code: "PRECONDITION_FAILED",
message: "Das Startdatum kann nicht vor dem Enddatum liegen.",
});
}
const intervals = [];
let currentDate = start.clone();
while (currentDate.isSameOrBefore(end)) {
let copy = currentDate.clone();
intervals.push(copy);
currentDate.add(1, opts.input.genauigkeit);
}
let klimafaktoren = await prisma.klimafaktoren.findMany({
where: {
plz: opts.input.plz,
month: intervals[0].month(),
OR: intervals.map((date) => {
return {
year: date.year(),
};
}),
},
});
if (!klimafaktoren) {
throw new TRPCError({
code: "NOT_FOUND",
message:
"Die Klimafaktoren konnten nicht geladen werden. Das kann daran liegen, dass sie für diesen Zeitraum oder Ort nicht verfügbar sind.",
});
}
if (klimafaktoren.length !== intervals.length) {
throw new TRPCError({
code: "NOT_FOUND",
message:
"Für diesen Zeitraum konnten nicht alle Klimafaktoren gefunden werden.",
});
}
return klimafaktoren.map((klimafaktor) => ({
month: klimafaktor.month,
year: klimafaktor.year,
klimafaktor: klimafaktor.klimafaktor,
}));
});

View File

@@ -1,143 +0,0 @@
import { z } from "zod";
import { prisma } from "@ibcornelsen/database";
import { publicProcedure } from "#lib/trpc/middlewares/publicProcedure";
export const VerbrauchsausweisWohnen2016Erstellen = publicProcedure
.meta({
openapi: {
method: "POST",
path: "/v1/verbrauchsausweis-wohnen/2016/erstellen",
contentTypes: ["application/json"],
description: "Erstellt einen neuen Verbrauchsausweis für Wohngebäude nach dem Schema der EnEV von 2016.",
tags: ["Verbrauchsausweis Wohnen"],
}
})
.input(z.object({
baujahr_heizung: z.array(z.number()).optional(),
zusaetzliche_heizquelle: z.boolean().optional(),
brennstoff_1: z.string().max(50).optional(),
einheit_1: z.string().max(50).optional(),
brennstoff_2: z.string().max(50).optional(),
einheit_2: z.string().max(50).optional(),
startdatum: z.coerce.date().optional(),
enddatum: z.coerce.date().optional(),
verbrauch_1: z.number().optional(),
verbrauch_2: z.number().optional(),
verbrauch_3: z.number().optional(),
verbrauch_4: z.number().optional(),
verbrauch_5: z.number().optional(),
verbrauch_6: z.number().optional(),
warmwasser_enthalten: z.boolean().optional(),
warmwasser_anteil_bekannt: z.boolean().optional(),
wird_gekuehlt: z.boolean().optional(),
keller_beheizt: z.boolean().optional(),
alternative_heizung: z.boolean().optional(),
alternative_warmwasser: z.boolean().optional(),
alternative_lueftung: z.boolean().optional(),
alternative_kuehlung: z.boolean().optional(),
anteil_warmwasser_1: z.number().optional(),
anteil_warmwasser_2: z.number().optional(),
gebaeude_stammdaten: z.string().uuid().or(z.object({
gebaeudetyp: z.string().max(255).optional(), // Adjust max length as needed
gebaeudeteil: z.string().max(255).optional(), // Adjust max length as needed
baujahr_gebaeude: z.array(z.number()).optional(),
baujahr_heizung: z.array(z.number()).optional(),
baujahr_klima: z.array(z.number()).optional(),
einheiten: z.number().optional(),
flaeche: z.number().optional(),
saniert: z.boolean().optional(),
keller: z.number().optional(),
dachgeschoss: z.number().optional(),
lueftung: z.string().max(50).optional(), // Adjust max length as needed
kuehlung: z.string().max(50).optional(), // Adjust max length as needed
leerstand: z.number().optional(),
plz: z.string().max(5).optional(), // Adjust max length as needed
ort: z.string().max(50).optional(), // Adjust max length as needed
adresse: z.string().max(100).optional(), // Adjust max length as needed
zentralheizung: z.boolean().optional(),
solarsystem_warmwasser: z.boolean().optional(),
warmwasser_rohre_gedaemmt: z.boolean().optional(),
niedertemperatur_kessel: z.boolean().optional(),
brennwert_kessel: z.boolean().optional(),
heizungsrohre_gedaemmt: z.boolean().optional(),
standard_kessel: z.boolean().optional(),
waermepumpe: z.boolean().optional(),
raum_temperatur_regler: z.boolean().optional(),
photovoltaik: z.boolean().optional(),
durchlauf_erhitzer: z.boolean().optional(),
einzelofen: z.boolean().optional(),
zirkulation: z.boolean().optional(),
einfach_verglasung: z.boolean().optional(),
dreifach_verglasung: z.boolean().optional(),
fenster_teilweise_undicht: z.boolean().optional(),
doppel_verglasung: z.boolean().optional(),
fenster_dicht: z.boolean().optional(),
rolllaeden_kaesten_gedaemmt: z.boolean().optional(),
isolier_verglasung: z.boolean().optional(),
tueren_undicht: z.boolean().optional(),
tueren_dicht: z.boolean().optional(),
dachgeschoss_gedaemmt: z.boolean().optional(),
keller_decke_gedaemmt: z.boolean().optional(),
keller_wand_gedaemmt: z.boolean().optional(),
aussenwand_gedaemmt: z.boolean().optional(),
oberste_geschossdecke_gedaemmt: z.boolean().optional(),
aussenwand_min_12cm_gedaemmt: z.boolean().optional(),
dachgeschoss_min_12cm_gedaemmt: z.boolean().optional(),
oberste_geschossdecke_min_12cm_gedaemmt: z.boolean().optional(),
}))
}))
.output(
z.object({
uid: z.string().uuid(),
})
)
.mutation(async (opts) => {
// Es kann sein, dass ein Gebäude bereits existiert. In diesem Fall wird es nicht neu erstellt, sondern nur der Verbrauchsausweis.
// Das können wir ganz einfach überprüfen, indem wir schauen, ob eine UUID für das Gebäude übergeben wurde.
if (typeof opts.input.gebaeude_stammdaten === "string") {
// Gebäude existiert bereits
const gebaeude = await prisma.gebaeudeStammdaten.findUnique({
where: {
uid: opts.input.gebaeude_stammdaten
}
});
if (!gebaeude) {
throw new Error("Das Gebäude mit der übergebenen UUID existiert nicht.");
}
const verbrauchsausweis = await prisma.verbrauchsausweisWohnen.create({
data: {
...opts.input,
gebaeude_stammdaten: {
connect: {
uid: opts.input.gebaeude_stammdaten
}
}
}
});
return { uid: verbrauchsausweis.uid };
} else {
// Gebäude existiert noch nicht
const gebaeude = await prisma.gebaeudeStammdaten.create({
data: opts.input.gebaeude_stammdaten
});
const verbrauchsausweis = await prisma.verbrauchsausweisWohnen.create({
data: {
...opts.input,
gebaeude_stammdaten: {
connect: {
uid: gebaeude.uid
}
}
}
});
return { uid: verbrauchsausweis.uid };
}
});

View File

@@ -1,41 +0,0 @@
import type { APIRoute } from "astro";
import { MissingEntityError, error } from "src/lib/APIResponse";
import { prisma } from "@ibcornelsen/database";
import { xmlVerbrauchsausweisWohnen_2016 } from "#lib/XML/VerbrauchsausweisWohnen/xmlVerbrauchsausweisWohnen_2016";
import uuid from "uuid";
export const get: APIRoute = async ({ url }) => {
const body = url.searchParams;
const uid = body.get("uid");
if (!body.has("uid") || !uid) {
return error(["Missing 'uid' in request body."]);
}
if (!uuid.validate(uid)) {
return error(["'uid' in request body must follow the UUID v4 format."]);
}
const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
where: {
uid,
},
include: {
gebaeude_stammdaten: true,
},
});
if (!ausweis) {
return MissingEntityError(uid);
}
const xml = await xmlVerbrauchsausweisWohnen_2016(ausweis);
const response = new Response(xml, {
headers: {
"Content-Type": "application/xml",
},
});
return response;
};

View File

@@ -63,16 +63,13 @@
async function ausweisAbschicken() {
console.log(ausweis);
overlay.ariaHidden = "false";
const response = await client.v1.verbrauchsausweisWohnen[2016].erstellen.mutate({
...ausweis,
gebaeude_stammdaten: gebaeude
})
console.log(response.uid);
window.location.href = `/kundendaten?uid=${response.uid}`;
}
let overlay: HTMLDivElement;

View File

@@ -1,25 +1,17 @@
<script lang="ts">
import ProgressBar from "#components/Ausweis/Progressbar.svelte";
import HelpLabel from "#components/HelpLabel.svelte";
import ZipSearch from "../ZIPSearch.svelte";
import Label from "../Label.svelte";
import ZipSearch from "../components/ZIPSearch.svelte";
import Label from "../components/Label.svelte";
import PriceContainer from "#components/Kaufabschluss/PriceContainer.svelte";
import { Benutzer, Bezahlmethoden, Enums, Rechnungen, VerbrauchsausweisWohnen } from "@ibcornelsen/database";
import PaymentOption from "#components/PaymentOption.svelte";
let deliveryAddress: boolean = false;
export let user: Benutzer;
export let ausweis: VerbrauchsausweisWohnen
let rechnung: Rechnungen = {} as Rechnungen;
let mailAddressCity: string = "";
let mailAddressZipCode: string = "";
let invoiceAddressCity: string = "";
let invoiceAddressZipCode: string = "";
export let paymentType:
| "paypal"
| "kreditkarte"
| "giropay"
| "sofort"
| "rechnung"
| "sepa" = "paypal";
export let selectedPaymentType: Bezahlmethoden = Enums.Bezahlmethoden.PAYPAL;
let agbAkzeptiert: boolean;
let datenschutzAkzeptiert: boolean;
@@ -33,24 +25,20 @@
</div>
</div>
<form
method="post"
target="_self"
novalidate
<div
class="w-full"
action="/kaufabschluss"
>
<fieldset class="flex flex-row gap-8">
<div class="flex flex-row gap-8">
<div class="w-3/5">
<div class="GRB3">
<HelpLabel title="Ansprechpartner" />
<hr />
<div class="grid grid-cols-5 gap-4">
<div class="grid grid-cols-3 gap-4">
<!-- Anrede -->
<div>
<Label>Anrede *</Label>
<div>
<select name="Aanrede" class="">
<select name="anrede" bind:value={user.anrede}>
<option>bitte auswählen</option>
<option value="Herr">Herr</option>
<option value="Frau">Frau</option>
@@ -61,25 +49,26 @@
<!-- Vorname -->
<div>
<Label>Vorname *</Label>
<input name="Avorname" type="text" required />
<input name="vorname" type="text" bind:value={user.vorname} required />
</div>
<!-- Nachname -->
<div>
<Label>Nachname *</Label>
<input name="Anachname" type="text" required />
<input name="nachname" type="text" bind:value={user.name} required />
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<!-- Telefon -->
<div>
<Label>Telefon</Label>
<input name="Atelefon" class="" type="text" />
<input name="telefon" bind:value={user.telefon} type="text" />
</div>
<!-- Email -->
<div>
<Label>E-Mail *</Label>
<input name="Aemail" type="email" required />
<input name="email" type="email" bind:value={user.email} required />
</div>
</div>
</div>
@@ -91,12 +80,13 @@
<hr />
<!-- Empfänger -->
<div class="grid grid-cols-5 gap-4">
<div class="grid grid-cols-2 gap-4">
<div>
<Label>Empfänger *</Label>
<input
name="Rempfaenger"
type="text"
bind:value={rechnung.empfaenger}
required
data-rule-maxlength="100"
data-msg-maxlength="max. 100 Zeichen"
@@ -113,12 +103,14 @@
data-msg-maxlength="max. 80 Zeichen"
/>
</div>
</div>
<div class="grid grid-cols-3 gap-4">
<!-- Strasse -->
<div>
<Label>Straße, Hausnummer *</Label>
<input
name="Rstrasse"
bind:value={rechnung.strasse}
type="text"
required
data-rule-maxlength="40"
@@ -128,33 +120,34 @@
<!-- PLZ -->
<ZipSearch
name="vplz"
bind:zip={invoiceAddressZipCode}
bind:city={invoiceAddressCity}
name="versand_plz"
bind:zip={rechnung.plz}
bind:city={rechnung.ort}
/>
<!-- Ort -->
<div>
<Label>Ort *</Label>
<input
name="Rort"
name="rechnung_ort"
readonly
type="text"
required
value={invoiceAddressCity}
value={rechnung.ort}
/>
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<!-- Telefon -->
<div>
<Label>Telefon</Label>
<input name="Rtelefon" class="" type="text" />
<input name="Rtelefon" bind:value={rechnung.telefon} type="text" />
</div>
<!-- Email -->
<div>
<Label>E-Mail</Label>
<input name="Remail" type="email" />
<input name="Remail" bind:value={rechnung.email} type="email" />
</div>
</div>
</div>
@@ -164,24 +157,24 @@
<div class="GRB3">
<HelpLabel title="Versandadresse" />
<hr />
<div class="grid grid-cols-5 gap-4">
<div class="flex flex-row gap-2 items-center">
<input
class="w-[15px] h-[15px]"
type="checkbox"
id="deliveryAddress"
bind:checked={deliveryAddress}
bind:checked={rechnung.abweichende_versand_adresse}
/>
<Label>Abweichende Versandadresse</Label>
</div>
<div class="grid grid-cols-2 gap-4">
<!-- Empfänger -->
<div>
<Label>Empfänger *</Label>
<input
name="Vempfaenger"
type="text"
readonly={!deliveryAddress}
readonly={!rechnung.abweichende_versand_adresse}
bind:value={rechnung.versand_empfaenger}
required
data-rule-maxlength="100"
data-msg-maxlength="max. 100 Zeichen"
@@ -194,19 +187,22 @@
<input
name="Vzusatzzeile"
type="text"
readonly={!deliveryAddress}
readonly={!rechnung.abweichende_versand_adresse}
bind:value={rechnung.versand_zusatzzeile}
data-rule-maxlength="80"
data-msg-maxlength="max. 80 Zeichen"
/>
</div>
</div>
<div class="grid grid-cols-3 gap-4">
<!-- Strasse -->
<div>
<Label>Straße, Hausnummer *</Label>
<input
name="Vstrasse"
type="text"
readonly={!deliveryAddress}
readonly={!rechnung.abweichende_versand_adresse}
bind:value={rechnung.strasse}
required
data-rule-maxlength="40"
data-msg-maxlength="max. 40 Zeichen"
@@ -216,9 +212,9 @@
<!-- PLZ -->
<ZipSearch
name="rplz"
readonly={!deliveryAddress}
bind:zip={mailAddressZipCode}
bind:city={mailAddressCity}
readonly={!rechnung.abweichende_versand_adresse}
bind:zip={rechnung.versand_plz}
bind:city={rechnung.versand_ort}
/>
<!-- Ort -->
@@ -229,7 +225,7 @@
type="text"
readonly
required
value={mailAddressCity}
bind:value={rechnung.versand_ort}
/>
</div>
</div>
@@ -237,96 +233,28 @@
<hr />
<div class="yellow-box">
<h4>Bitte wählen sie ihre Bezahlmethode aus.</h4>
<div class="flex flex-row gap-4">
<div class="w-1/2">
<div>
<div class="payment-option-card">
<img
src="/images/paypal.png"
alt="PayPal"
/>
<div
class="payment-option-label"
aria-label="Zahlen mit PayPal"
>
Zahlen mit PayPal
</div>
</div>
<div class="payment-option-card">
<img
src="/images/giropay.png"
alt="Giropay"
/>
<div
class="payment-option-label"
aria-label="Zahlen mit Giropay"
>
Zahlen mit Giropay
</div>
</div>
<div class="payment-option-card">
<img
src="/images/sofort.png"
alt="Sofort"
/>
<div
class="payment-option-label"
aria-label="Zahlen mit Sofort"
>
Zahlen mit Sofort
</div>
</div>
</div>
<div>
<div class="payment-option-card">
<img
src="/images/mastercard.png"
alt="Mastercard"
/>
<div
class="payment-option-label"
aria-label="Zahlen mit Kreditkarte"
>
Zahlen mit Kreditkarte
</div>
</div>
<div class="payment-option-card">
<img
src="/images/rechnung.png"
alt="Rechnung"
/>
<div
class="payment-option-label"
aria-label="Zahlen mit Rechnung"
>
Zahlen mit Rechnung
</div>
</div>
<div class="payment-option-card">
<img src="/images/sepa.png" alt="SEPA" />
<div
class="payment-option-label"
aria-label="Zahlen mit SEPA über PayPal"
>
SEPA über PayPal
</div>
</div>
</div>
<div class="GRB3">
<HelpLabel title="Bezahlmethode" />
<hr />
<div class="flex flex-row justify-between gap-4">
<PaymentOption paymentType={Enums.Bezahlmethoden.PAYPAL} bind:selectedPaymentType name={"PayPal"} icon={"/images/paypal.png"}></PaymentOption>
<PaymentOption paymentType={Enums.Bezahlmethoden.SOFORT} bind:selectedPaymentType name={"Sofort"} icon={"/images/sofort.png"}></PaymentOption>
<PaymentOption paymentType={Enums.Bezahlmethoden.GIROPAY} bind:selectedPaymentType name={"Giropay"} icon={"/images/giropay.png"}></PaymentOption>
<PaymentOption paymentType={Enums.Bezahlmethoden.KREDITKARTE} bind:selectedPaymentType name={"Kreditkarte"} icon={"/images/mastercard.png"}></PaymentOption>
<PaymentOption paymentType={Enums.Bezahlmethoden.RECHNUNG} bind:selectedPaymentType name={"Rechnung"} icon={"/images/rechnung.png"}></PaymentOption>
</div>
<div class="w-1/2">
<div class="flex-row justify-between">
<h5>{paymentType}</h5>
<h5>{selectedPaymentType}</h5>
<img
src="../../images/{paymentType ==
'kreditkarte'
src="../../images/{selectedPaymentType ==
Enums.Bezahlmethoden.KREDITKARTE
? 'mastercard'
: paymentType}.png"
: selectedPaymentType}.png"
class="payment-option-logo"
/>
</div>
{#if paymentType == "rechnung"}
{#if selectedPaymentType == Enums.Bezahlmethoden.RECHNUNG}
<p>
Sobald sie AGB und Datenschutzerklärung
gelesen und akzeptiert haben können sie den
@@ -342,7 +270,7 @@
gelesen und akzeptiert haben können sie den
Kauf fortsetzen. Durch das Klicken auf
'Kostenpflichtig Bestellen' werden sie zu <strong
>{paymentType}</strong
>{selectedPaymentType}</strong
> weitergeleitet.
</p>
{/if}
@@ -379,7 +307,6 @@
>
</div>
</div>
</div>
<hr />
@@ -390,8 +317,8 @@
<div class="w-2/5">
<PriceContainer prices={[45, 60, 160]} />
</div>
</fieldset>
</form>
</div>
</div>
</div>
<style>

View File

@@ -7,12 +7,20 @@
let passwort: string;
async function login() {
const response = await client.v1.benutzer.tokenErneuern.query({
try {
const response = await client.v1.benutzer.getRefreshToken.query({
email,
passwort
})
if (!response.token || !response.exp) {
const options = {
domain: `.${window.location.hostname}`,
path: "/",
expires: response.exp
}
Cookies.set("accessToken", response.accessToken, options);
Cookies.set("refreshToken", response.refreshToken, options);
window.location.href = "/user";
} catch (e) {
addNotification({
message: "Ups...",
subtext: "Das hat leider nicht geklappt, haben sie ihr Passwort und ihre Email Adresse richtig eingegeben?",
@@ -20,16 +28,7 @@
timeout: 6000,
dismissable: true
})
return;
}
const options = {
domain: `.${window.location.hostname}`,
path: "/",
expires: response.exp
}
Cookies.set("token", response.token, options);
window.location.href = "/user";
}
</script>

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import { addNotification } from "@ibcornelsen/ui";
import Cookies from "js-cookie";
import {client} from "src/trpc";
let passwort: string;
@@ -9,22 +8,15 @@
let name: string;
async function login() {
try {
const response = await client.v1.benutzer.erstellen.query({
email,
passwort,
vorname,
name
})
if (response.token) {
const options = {
domain: `.${window.location.hostname}`,
path: "/",
expires: response.exp
}
Cookies.set("token", response.token, options);
window.location.href = "/login";
} else {
} catch (e) {
addNotification({
message: "Ups...",
subtext: "Da ist wohl etwas schiefgelaufen... Diese Email Adresse ist bereits in Benutzung, haben sie vielleicht bereits ein Konto bei uns?",

View File

@@ -1,42 +0,0 @@
// NOTE: Öffentliche API benötigt OpenApiMeta. Das Package bräuchte momentan noch einen extra Server, deshalb nehmen wir es momentan noch nicht mit rein.
//import { OpenApiMeta } from "trpc-openapi";
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
import { APIRoute } from "astro";
import { t } from "../../lib/trpc/context";
import { v1Router } from "#lib/trpc/procedures/v1";
export const appRouter = t.router({
v1: v1Router,
});
export const all: APIRoute = ({ request }) => {
return fetchRequestHandler({
req: request,
endpoint: "/api",
router: appRouter,
createContext: async ({ req }) => {
const ip = req.headers.get("x-forwarded-for");
const authorization = req.headers.get("authorization") || null;
return {
authorization,
ip: ip?.toString() || "",
req: req,
};
},
});
};
export function tRPCCaller(request: Request) {
const { authorization } = {
authorization: request.headers.get("authorization") || "",
};
const createCaller = t.createCallerFactory(appRouter);
return createCaller({
authorization,
req: request,
ip: request.headers.get("x-forwarded-for") || "",
});
}
export type AppRouter = typeof appRouter;

View File

@@ -1,46 +0,0 @@
import type { APIRoute } from "astro";
import {
MissingEntityError,
error,
} from "src/lib/APIResponse";
import * as path from "path";
import * as fs from "fs";
import { prisma } from "@ibcornelsen/database";
export const get: APIRoute = async ({ url }) => {
const body = url.searchParams
const uid = body.get("uid")
if (!body.has("uid") || !uid) {
return error(["Missing 'uid' in request body."])
}
const image = await prisma.gebaeudeBilder.findUnique({
where: {
uid
},
select: {
uid: true,
kategorie: true
}
})
if (!image) {
return MissingEntityError("image")
}
// Check if the image exists on disk
const location = path.join("/persistent/uploads/images", `${image.uid}.jpg`);
if (!fs.existsSync(location)) {
return MissingEntityError("image")
}
const data = fs.readFileSync(location);
return new Response(data, {
headers: {
"Content-Type": "image/jpeg"
}
});
};

View File

@@ -1,131 +0,0 @@
import type { APIRoute } from "astro";
import {
ActionFailedError,
MissingEntityError,
error,
success,
} from "src/lib/APIResponse";
import * as jimp from "jimp";
import { z } from "zod";
import * as path from "path";
import * as fs from "fs";
import { prisma } from "@ibcornelsen/database";
const ImageUploadChecker = z.object({
data: z.string(),
name: z.string(),
gebaeude_uid: z.string().optional(),
kategorie: z.string(),
});
export const get: APIRoute = async ({ url }) => {
const body = url.searchParams
const uid = body.get("uid")
if (!body.has("uid") || !uid) {
return error(["Missing 'uid' in request body."])
}
const image = await prisma.gebaeudeBilder.findUnique({
where: {
uid
},
select: {
uid: true,
kategorie: true
}
})
if (!image) {
return MissingEntityError("image")
}
// Check if the image exists on disk
const location = path.join("/persistent/uploads/images", `${image.uid}.jpg`);
if (!fs.existsSync(location)) {
return MissingEntityError("image")
}
const data = fs.readFileSync(location, { encoding: "base64" });
return success(data);
};
/**
* Speichert ein Bild auf unserem Server ab und gibt die UID des Bildes zurück
* @param param0
* @returns
*/
export const put: APIRoute = async ({ request }) => {
const body: z.infer<typeof ImageUploadChecker> = await request.json();
const validation = ImageUploadChecker.safeParse(body);
if (!validation.success) {
return error(validation.error.issues);
}
const image = Buffer.from(body.data, "base64url");
let jimpResult;
try {
jimpResult = await jimp.read(image);
} catch (e) {
return ActionFailedError();
}
let gebaeude;
if (!body.gebaeude_uid) {
gebaeude = await prisma.gebaeudeStammdaten.create({
data: {},
select: {
uid: true,
id: true
}
})
if (!gebaeude) {
return ActionFailedError();
}
} else {
gebaeude = await prisma.gebaeudeStammdaten.findUnique({
where: {
uid: body.gebaeude_uid
}
})
if (!gebaeude) {
return MissingEntityError("gebaeude");
}
}
const result = await prisma.gebaeudeBilder.create({
data: {
gebaeude_stammdaten_id: gebaeude.id,
kategorie: body.kategorie
},
select: {
uid: true
}
})
if (!result) {
return ActionFailedError();
}
const location = path.join("/persistent/uploads", `${result.uid}.jpg`);
const buffer = await jimpResult.getBufferAsync(jimp.MIME_JPEG)
if (buffer.length > 3_000_000) {
jimpResult.quality(75).write(location);
} else {
jimpResult.write(location);
}
return success({
uid: result.uid,
gebaeude_uid: gebaeude.uid,
});
};

View File

@@ -1,9 +1,9 @@
---
import { changeLanguage } from "i18next";
import AusweisLayout from "#layouts/AusweisLayout.astro";
import BedarfsausweisContent from "#components/Bedarfsausweis/BedarfsausweisContent.svelte";
changeLanguage("de");
---
<AusweisLayout title="Bedarfsausweis erstellen | IBCornelsen">
<BedarfsausweisContent client:load></BedarfsausweisContent>

View File

@@ -1,8 +1,8 @@
---
import { changeLanguage } from "i18next";
import Layout from "#layouts/Layout.astro";
changeLanguage("de");
---
<Layout title="Für Entwickler - IBCornelsen">

View File

@@ -1,8 +1,8 @@
---
import { changeLanguage } from "i18next";
import Layout from "#layouts/Layout.astro";
changeLanguage("de");
---
<Layout title="FAQ - IBCornelsen"></Layout>

View File

@@ -1,11 +1,11 @@
---
import { changeLanguage } from "i18next";
import { BoxWithHeading } from "@ibcornelsen/ui";
import Widget from "#components/Widget.svelte";
import Layout from "#layouts/Layout.astro";
import FeatureCard from "#components/FeatureCard.svelte";
changeLanguage("de");
---
<Layout title="Energieausweis online erstellen - Online Energieausweis">

View File

@@ -1,11 +0,0 @@
---
import { changeLanguage } from "i18next";
import Kaufabschluss from "#components/Kaufabschluss/Kaufabschluss.svelte";
import AusweisLayout from "#layouts/AusweisLayout.astro";
changeLanguage("de");
---
<AusweisLayout title="Kaufabschluss Verbrauchsausweis - IBCornelsen">
<Kaufabschluss client:load></Kaufabschluss>
</AusweisLayout>

View File

@@ -1,12 +1,40 @@
---
import { changeLanguage } from "i18next";
import Kundendaten from "#components/Ausweis/Kundendaten.svelte";
import AusweisLayout from "#layouts/AusweisLayout.astro";
changeLanguage("de");
import KundendatenModule from "#modules/KundendatenModule.svelte";
import AusweisLayout from "#layouts/AusweisLayout.astro";
import { Benutzer, Enums, prisma } from "@ibcornelsen/database";
const user = await prisma.benutzer.findUnique({
where: {
id: 1,
},
}) as Benutzer;
// Man sollte nur auf diese Seite kommen, wenn ein Ausweis bereits vorliegt und in der Datenbank abgespeichert wurde.
const uid = Astro.url.searchParams.get("uid");
if (!uid) {
return Astro.redirect("/");
}
// NOTE: Muss umgestellt werden, wir brauchen einen Kundendaten Abschluss für jede Ausweisart.
const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
where: {
uid,
},
});
if (!ausweis) {
return Astro.redirect("/");
}
---
<AusweisLayout title="Kundendaten Aufnehmen - IBCornelsen">
<Kundendaten client:load></Kundendaten>
<KundendatenModule user={user} ausweis={ausweis} selectedPaymentType={Enums.Bezahlmethoden.PAYPAL} client:load></KundendatenModule>
</AusweisLayout>

View File

@@ -2,13 +2,6 @@
import moment from "moment";
import LoginModule from "../modules/LoginModule.svelte";
import Layout from "../layouts/Layout.astro";
const token = Astro.cookies.get("token").value;
const expires = Astro.cookies.get("expires").number();
const now = moment().unix();
if (token && now < expires) {
return Astro.redirect(`/user`);
}
---
<Layout title="Login">

View File

@@ -1,7 +1,7 @@
---
import { changeLanguage } from "i18next";
changeLanguage("de");
Astro.cookies.delete("token");
Astro.cookies.delete("expires");

View File

@@ -1,23 +1,42 @@
---
import { changeLanguage } from "i18next";
import moment from "moment";
import { Ausweis } from "src/lib/Ausweis";
import { Verbrauchsausweis } from "src/lib/Ausweis/Verbrauchsausweis";
import Checkbox from "#components/Checkbox.svelte";
import PDFHeader from "#components/PDF/PDFHeader.svelte";
import PDFSectionHeader from "#components/PDF/PDFSectionHeader.svelte";
import PDFLayout from "#layouts/PDFLayout.astro";
import { VerbrauchsausweisWohnen, GebaeudeStammdaten, prisma } from "@ibcornelsen/database";
changeLanguage("de");
const base64 = Astro.url.searchParams.get("base64");
if (!base64) {
let ausweis: (Partial<VerbrauchsausweisWohnen> & { gebaeude_stammdaten: Partial<GebaeudeStammdaten> }) | null = null;
if (base64) {
const buffer = Buffer.from(base64, "base64");
const json = buffer.toString("utf-8");
ausweis = JSON.parse(json);
} else {
const uidAusweis = Astro.url.searchParams.get("ausweis_uid");
if (!uidAusweis) {
return Astro.redirect("/404");
}
const ausweis = Verbrauchsausweis.fromBase64(base64);
ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
where: {
uid: uidAusweis,
},
include: {
gebaeude_stammdaten: true,
},
});
}
if (!ausweis) {
return Astro.redirect("/404");
}
const gebaeude = ausweis.gebaeude_stammdaten;
---
<PDFLayout title="Ansichtsausweis">
@@ -45,30 +64,30 @@ if (!ausweis) {
<table>
<tr>
<td>Gebäudetyp</td>
<td>{ausweis.objekt_typ}</td>
<td>{gebaeude.gebaeudetyp}</td>
</tr>
<tr>
<td>Adresse</td>
<td>{ausweis.objekt_strasse}</td>
<td>{gebaeude.adresse}</td>
</tr>
<tr>
<td>Gebäudeteil</td>
<td>{ausweis.objekt_gebaeudeteil}</td>
<td>{gebaeude.gebaeudeteil}</td>
</tr>
<tr>
<td>Baujahr Gebäude ³</td>
<td>{ausweis.baujahr_gebaeude}</td>
<td>{gebaeude.baujahr_gebaeude}</td>
</tr>
<tr>
<td
>Baujahr Wärmeerzeuger <sup>3</sup>
<sup>4</sup></td
>
<td>{ausweis.baujahr_anlage}</td>
<td>{gebaeude.baujahr_heizung}</td>
</tr>
<tr>
<td>Anzahl Wohnungen</td>
<td>{ausweis.anzahl_einheiten}</td>
<td>{gebaeude.einheiten}</td>
</tr>
<tr>
<td>Gebäudenutzfläche (A<sub>N</sub>)</td>

View File

@@ -1,79 +1,136 @@
---
import { changeLanguage } from "i18next";
import moment from "moment";
import { Verbrauchsausweis } from "src/lib/Ausweis/Verbrauchsausweis";
import { Dachgeschoss } from "src/lib/Ausweis/types";
import Checkbox from "#components/Checkbox.svelte";
import DatenblattFooter from "#components/DatenblattFooter.svelte";
import DatenblattHeader from "#components/DatenblattHeader.svelte";
import PDFHeader from "#components/PDF/PDFHeader.svelte";
import PDFSectionHeader from "#components/PDF/PDFSectionHeader.svelte";
import PDFLayout from "#layouts/PDFLayout.astro";
changeLanguage("de");
import { GebaeudeStammdaten, VerbrauchsausweisWohnen, prisma } from "@ibcornelsen/database";
const base64 = Astro.url.searchParams.get("base64");
if (!base64) {
let ausweis: (Partial<VerbrauchsausweisWohnen> & { gebaeude_stammdaten: Partial<GebaeudeStammdaten> }) | null = null;
if (base64) {
const buffer = Buffer.from(base64, "base64");
const json = buffer.toString("utf-8");
ausweis = JSON.parse(json);
} else {
const uidAusweis = Astro.url.searchParams.get("ausweis_uid");
if (!uidAusweis) {
return Astro.redirect("/404");
}
const ausweis = Verbrauchsausweis.fromBase64(base64);
ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
where: {
uid: uidAusweis,
},
include: {
gebaeude_stammdaten: true,
},
});
}
if (!ausweis) {
return Astro.redirect("/404");
}
const gebaeude = ausweis.gebaeude_stammdaten;
---
<PDFLayout title="Datenblatt">
<div class="flex flex-col gap-20">
<div class="flex flex-col gap-4">
<DatenblattHeader></DatenblattHeader>
<DatenblattHeader />
<div class="px-12 py-20 flex flex-col gap-2">
<div class="flex flex-row justify-between items-center">
<h2>Datenblatt Energieausweis</h2>
<h2>Ausweis ID:</h2>
</div>
<h3>Gebäudedaten:</h3>
<p>Adresse: {ausweis.objekt_strasse}, {ausweis.objekt_plz} {ausweis.objekt_ort}</p>
<p>
Adresse: {gebaeude.adresse}, {
gebaeude.plz
}
{gebaeude.ort}
</p>
<div class="flex justify-between">
<Checkbox checked={ausweis.ausstellgrund == "Neubau"}>Neubau</Checkbox>
<Checkbox checked={ausweis.ausstellgrund == "Vermietung" || ausweis.ausstellgrund == "Verkauf"}>Vermietung/Verkauf</Checkbox>
<Checkbox checked={ausweis.ausstellgrund == "Modernisierung"}>Modernisierung</Checkbox>
<Checkbox checked={ausweis.ausstellgrund == "Sonstiges"}>Sonstiges</Checkbox>
<Checkbox checked={ausweis.ausstellgrund == "Neubau"}>
Neubau
</Checkbox>
<Checkbox
checked={ausweis.ausstellgrund == "Vermietung" ||
ausweis.ausstellgrund == "Verkauf"}
>
Vermietung/Verkauf
</Checkbox>
<Checkbox
checked={ausweis.ausstellgrund == "Modernisierung"}
>
Modernisierung
</Checkbox>
<Checkbox checked={ausweis.ausstellgrund == "Sonstiges"}>
Sonstiges
</Checkbox>
</div>
<div class="flex justify-between gap-4">
<table>
<tbody><tr>
<tbody
><tr>
<td>Baujahr Gebäude:</td>
<td>{ausweis.baujahr_gebaeude}</td>
<td
>{
gebaeude.baujahr_gebaeude
}</td
>
</tr>
<tr>
<td>Baujahr Heizung:</td>
<td>{ausweis.baujahr_anlage}</td>
<td
>{
gebaeude.baujahr_heizung
}</td
>
</tr>
<tr>
<td>Wohnfläche:</td>
<td>{ausweis.wohnflaeche}</td>
<td>{gebaeude.flaeche}</td>
</tr>
<tr>
<td>Lüftungskonzept:</td>
<td>{ausweis.lueftungskonzept}</td>
<td>{gebaeude.lueftung}</td>
</tr>
<tr>
<td>Gebäudetyp:</td>
<td>{ausweis.objekt_typ}</td>
</tr></tbody>
<td
>{
gebaeude.gebaeudetyp
}</td
>
</tr></tbody
>
</table>
<table>
<tbody><tr>
<tbody
><tr>
<td>Dachgeschoss:</td>
<td>{ausweis.dachgeschoss == Dachgeschoss.BEHEIZT ? "Beheizt" : (ausweis.dachgeschoss == Dachgeschoss.UNBEHEIZT ? "Unbeheizt" : "Nicht Vorhanden")}</td>
<td
>{
gebaeude.dachgeschoss
? "Beheizt"
: gebaeude
.dachgeschoss
? "Unbeheizt"
: "Nicht Vorhanden"
}</td
>
</tr>
<tr>
<td>Beheizter Keller:</td>
<td>{ausweis.keller_beheizt ? "Ja" : "Nein"}</td>
<td>{ausweis.keller_beheizt ? "Ja" : "Nein"}</td
>
</tr>
<tr>
<td>Wohnungen:</td>
<td>{ausweis.anzahl_einheiten}</td>
<td>{gebaeude.einheiten}</td>
</tr>
<tr>
<td>Anlage zur Kühlung:</td>
@@ -81,40 +138,75 @@ if (!ausweis) {
</tr>
<tr>
<td>Leerstand:</td>
<td>{ausweis.leerstand}%</td>
</tr></tbody>
<td>{gebaeude.leerstand}%</td
>
</tr></tbody
>
</table>
</div>
<div class="flex flex-row gap-8">
<div class="flex flex-col">
<h2>Heizverbrauch</h2>
<div class="flex flex-row justify-between gap-4">
<p>Von: {moment(ausweis.energieverbrauch_zeitraum).format("MM.YYYY")}</p>
<p>Bis: {moment(ausweis.energieverbrauch_zeitraum).add("1", "year").format("MM.YYYY")}</p>
<p>
Von: {
moment(ausweis.startdatum).format("MM.YYYY")
}
</p>
<p>
Bis: {
moment(ausweis.startdatum)
.add("1", "year")
.format("MM.YYYY")
}
</p>
</div>
<div class="flex flex-row justify-between gap-4">
<p>Von: {moment(ausweis.energieverbrauch_zeitraum).add("1", "year").format("MM.YYYY")}</p>
<p>Bis: {moment(ausweis.energieverbrauch_zeitraum).add("2", "years").format("MM.YYYY")}</p>
<p>
Von: {
moment(ausweis.startdatum)
.add("1", "year")
.format("MM.YYYY")
}
</p>
<p>
Bis: {
moment(ausweis.startdatum)
.add("2", "years")
.format("MM.YYYY")
}
</p>
</div>
<div class="flex flex-row justify-between gap-4">
<p>Von: {moment(ausweis.energieverbrauch_zeitraum).add("2", "years").format("MM.YYYY")}</p>
<p>Bis: {moment(ausweis.energieverbrauch_zeitraum).add("3", "years").format("MM.YYYY")}</p>
<p>
Von: {
moment(ausweis.startdatum)
.add("2", "years")
.format("MM.YYYY")
}
</p>
<p>
Bis: {
moment(ausweis.startdatum)
.add("3", "years")
.format("MM.YYYY")
}
</p>
</div>
</div>
<div class="flex flex-col">
<h2>{ausweis.energietraeger_1}</h2>
<h2>{ausweis.brennstoff_1}</h2>
<div class="flex flex-row justify-between gap-4">
<p>{ausweis.energieverbrauch_1_heizquelle_1}</p>
<p>{ausweis.energietraeger_einheit_heizquelle_1}</p>
<p>{ausweis.verbrauch_1}</p>
<p>{ausweis.einheit_1}</p>
</div>
<div class="flex flex-row justify-between gap-4">
<p>{ausweis.energieverbrauch_2_heizquelle_1}</p>
<p>{ausweis.energietraeger_einheit_heizquelle_1}</p>
<p>{ausweis.verbrauch_2}</p>
<p>{ausweis.einheit_1}</p>
</div>
<div class="flex flex-row justify-between gap-4">
<p>{ausweis.energieverbrauch_3_heizquelle_1}</p>
<p>{ausweis.energietraeger_einheit_heizquelle_1}</p>
<p>{ausweis.verbrauch_3}</p>
<p>{ausweis.einheit_1}</p>
</div>
</div>
</div>
@@ -122,85 +214,266 @@ if (!ausweis) {
<div class="flex flex-col">
<h2>Heizverbrauch (Heizwert)</h2>
<div class="flex flex-row justify-between gap-4">
<p>Von: {moment(ausweis.energieverbrauch_zeitraum).format("MM.YYYY")}</p>
<p>Bis: {moment(ausweis.energieverbrauch_zeitraum).add("1", "year").format("MM.YYYY")}</p>
<p>
Von: {
moment(ausweis.startdatum).format("MM.YYYY")
}
</p>
<p>
Bis: {
moment(ausweis.startdatum)
.add("1", "year")
.format("MM.YYYY")
}
</p>
</div>
<div class="flex flex-row justify-between gap-4">
<p>Von: {moment(ausweis.energieverbrauch_zeitraum).add("1", "year").format("MM.YYYY")}</p>
<p>Bis: {moment(ausweis.energieverbrauch_zeitraum).add("2", "years").format("MM.YYYY")}</p>
<p>
Von: {
moment(ausweis.startdatum)
.add("1", "year")
.format("MM.YYYY")
}
</p>
<p>
Bis: {
moment(ausweis.startdatum)
.add("2", "years")
.format("MM.YYYY")
}
</p>
</div>
<div class="flex flex-row justify-between gap-4">
<p>Von: {moment(ausweis.energieverbrauch_zeitraum).add("2", "years").format("MM.YYYY")}</p>
<p>Bis: {moment(ausweis.energieverbrauch_zeitraum).add("3", "years").format("MM.YYYY")}</p>
<p>
Von: {
moment(ausweis.startdatum)
.add("2", "years")
.format("MM.YYYY")
}
</p>
<p>
Bis: {
moment(ausweis.startdatum)
.add("3", "years")
.format("MM.YYYY")
}
</p>
</div>
</div>
<div class="flex flex-col">
<h2>{ausweis.energietraeger_1}</h2>
<h2>{ausweis.brennstoff_1}</h2>
<div class="flex flex-row justify-between gap-4">
<p>{ausweis.energieverbrauch_1_heizquelle_1}</p>
<p>{ausweis.energietraeger_einheit_heizquelle_1}</p>
<p>{ausweis.verbrauch_1}</p>
<p>{ausweis.einheit_1}</p>
</div>
<div class="flex flex-row justify-between gap-4">
<p>{ausweis.energieverbrauch_2_heizquelle_1}</p>
<p>{ausweis.energietraeger_einheit_heizquelle_1}</p>
<p>{ausweis.verbrauch_2}</p>
<p>{ausweis.einheit_1}</p>
</div>
<div class="flex flex-row justify-between gap-4">
<p>{ausweis.energieverbrauch_3_heizquelle_1}</p>
<p>{ausweis.energietraeger_einheit_heizquelle_1}</p>
<p>{ausweis.verbrauch_3}</p>
<p>{ausweis.einheit_1}</p>
</div>
</div>
</div>
<p>Warmwasser enthalten: {ausweis.warmwasser_enthalten ? "Ja" : "Nein"}</p>
<p>
Warmwasser enthalten: {
ausweis.warmwasser_enthalten ? "Ja" : "Nein"
}
</p>
</div>
<DatenblattFooter></DatenblattFooter>
<DatenblattFooter />
</div>
<div class="flex flex-col gap-4">
<DatenblattHeader></DatenblattHeader>
<DatenblattHeader />
<div class="px-12 py-20 flex flex-col gap-2">
<h2>Modernisierungsstand</h2>
<h3>Heizungsanlage</h3>
<div class="grid grid-cols-3">
<Checkbox checked={ausweis.versorgungssysteme[0]}>Zentral/Etage</Checkbox>
<Checkbox checked={ausweis.versorgungssysteme[1]}>Einzelöfen</Checkbox>
<Checkbox checked={ausweis.versorgungssysteme[2]}>Durchlauferhitzer</Checkbox>
<Checkbox checked={ausweis.versorgungssysteme[3]}>Standardkessel</Checkbox>
<Checkbox checked={ausweis.versorgungssysteme[4]}>Solarsystem für Warmwasser</Checkbox>
<Checkbox checked={ausweis.versorgungssysteme[5]}>Wärmepumpe</Checkbox>
<Checkbox checked={ausweis.versorgungssysteme[6]}>Niedertemperaturkessel</Checkbox>
<Checkbox checked={ausweis.versorgungssysteme[7]}>Brennwertkessel/Therme</Checkbox>
<Checkbox checked={ausweis.versorgungssysteme[8]}>Warmwasserrohre gedämmt</Checkbox>
<Checkbox checked={ausweis.versorgungssysteme[9]}>Heizungsrohre gedämmt</Checkbox>
<Checkbox checked={ausweis.versorgungssysteme[10]}>Zirkulation</Checkbox>
<Checkbox checked={ausweis.versorgungssysteme[11]}>Raumtemperraturregler</Checkbox>
<Checkbox
checked={gebaeude.zentralheizung ||
false}
>
Zentral/Etage
</Checkbox>
<Checkbox
checked={gebaeude.einzelofen ||
false}
>
Einzelöfen
</Checkbox>
<Checkbox
checked={gebaeude
.durchlauf_erhitzer || false}
>
Durchlauferhitzer
</Checkbox>
<Checkbox
checked={gebaeude.standard_kessel ||
false}
>
Standardkessel
</Checkbox>
<Checkbox
checked={gebaeude
.solarsystem_warmwasser || false}
>
Solarsystem für Warmwasser
</Checkbox>
<Checkbox
checked={gebaeude.waermepumpe ||
false}
>
Wärmepumpe
</Checkbox>
<Checkbox
checked={gebaeude
.niedertemperatur_kessel || false}
>
Niedertemperaturkessel
</Checkbox>
<Checkbox
checked={gebaeude.brennwert_kessel ||
false}
>
Brennwertkessel/Therme
</Checkbox>
<Checkbox
checked={gebaeude
.warmwasser_rohre_gedaemmt || false}
>
Warmwasserrohre gedämmt
</Checkbox>
<Checkbox
checked={gebaeude
.heizungsrohre_gedaemmt || false}
>
Heizungsrohre gedämmt
</Checkbox>
<Checkbox
checked={gebaeude.zirkulation ||
false}
>
Zirkulation
</Checkbox>
<Checkbox
checked={gebaeude
.raum_temperatur_regler || false}
>
Raumtemperraturregler
</Checkbox>
</div>
<h3>Fenster/Dachfenster/Türen</h3>
<div class="grid grid-cols-3">
<Checkbox checked={ausweis.fenster_dach[0]}>Einfachglas</Checkbox>
<Checkbox checked={ausweis.fenster_dach[1]}>Doppelverglasung</Checkbox>
<Checkbox checked={ausweis.fenster_dach[2]}>Isolierverglasung</Checkbox>
<Checkbox checked={ausweis.fenster_dach[3]}>Dreifachverglasung</Checkbox>
<Checkbox checked={ausweis.fenster_dach[4]}>Alle Fenster dicht</Checkbox>
<Checkbox checked={ausweis.fenster_dach[5]}>Fenster teilweise undicht</Checkbox>
<Checkbox checked={ausweis.fenster_dach[6]}>Alle Türen dicht</Checkbox>
<Checkbox checked={ausweis.fenster_dach[7]}>Türen teilweise undicht</Checkbox>
<Checkbox checked={ausweis.fenster_dach[8]}>Rolladenkästen gedämmt</Checkbox>
<Checkbox
checked={gebaeude
.einfach_verglasung || false}
>
Einfachglas
</Checkbox>
<Checkbox
checked={gebaeude
.doppel_verglasung || false}
>
Doppelverglasung
</Checkbox>
<Checkbox
checked={gebaeude
.isolier_verglasung || false}
>
Isolierverglasung
</Checkbox>
<Checkbox
checked={gebaeude
.dreifach_verglasung || false}
>
Dreifachverglasung
</Checkbox>
<Checkbox
checked={gebaeude.fenster_dicht ||
false}
>
Alle Fenster dicht
</Checkbox>
<Checkbox
checked={gebaeude
.fenster_teilweise_undicht || false}
>
Fenster teilweise undicht
</Checkbox>
<Checkbox
checked={gebaeude.tueren_dicht ||
false}
>
Alle Türen dicht
</Checkbox>
<Checkbox
checked={gebaeude.tueren_undicht ||
false}
>
Türen teilweise undicht
</Checkbox>
<Checkbox
checked={gebaeude
.rolllaeden_kaesten_gedaemmt || false}
>
Rolladenkästen gedämmt
</Checkbox>
</div>
<h3>Wärmedämmung</h3>
<div class="grid grid-cols-2">
<Checkbox checked={ausweis.daemmung[0]}>Außenwand gedämmt</Checkbox>
<Checkbox checked={ausweis.daemmung[1]}>Kelleraußenwand gedämmt</Checkbox>
<Checkbox checked={ausweis.daemmung[2]}>Kellerdecke gedämmt</Checkbox>
<Checkbox checked={ausweis.daemmung[3]}>Dachgeschoss gedämmt</Checkbox>
<Checkbox checked={ausweis.daemmung[4]}>Oberste Geschossdecke gedämmt</Checkbox>
<Checkbox checked={ausweis.daemmung[5]}>Oberste Geschossdecke min. 12cm gedämmt</Checkbox>
<Checkbox
checked={gebaeude
.aussenwand_gedaemmt || false}
>
Außenwand gedämmt
</Checkbox>
<Checkbox
checked={gebaeude
.keller_wand_gedaemmt || false}
>
Kelleraußenwand gedämmt
</Checkbox>
<Checkbox
checked={gebaeude
.keller_decke_gedaemmt || false}
>
Kellerdecke gedämmt
</Checkbox>
<Checkbox
checked={gebaeude
.dachgeschoss_gedaemmt || false}
>
Dachgeschoss gedämmt
</Checkbox>
<Checkbox
checked={gebaeude
.oberste_geschossdecke_gedaemmt || false}
>
Oberste Geschossdecke gedämmt
</Checkbox>
<Checkbox
checked={gebaeude
.oberste_geschossdecke_min_12cm_gedaemmt || false}
>
Oberste Geschossdecke min. 12cm gedämmt
</Checkbox>
</div>
<Checkbox checked={true}>Die Angaben sind richtig und entsprechen dem aktuellen Stand.</Checkbox>
<Checkbox checked={true}>Ich habe die AGB gelesen und akzeptiert.</Checkbox>
<p>Die Angaben auf diesem Datenblatt wurden uns übermittelt und werden zur Berechnung und
Ausstellung des Ausweises herangezogen.</p>
<Checkbox checked={true}>
Die Angaben sind richtig und entsprechen dem aktuellen
Stand.
</Checkbox>
<Checkbox checked={true}>
Ich habe die AGB gelesen und akzeptiert.
</Checkbox>
<p>
Die Angaben auf diesem Datenblatt wurden uns übermittelt und
werden zur Berechnung und Ausstellung des Ausweises
herangezogen.
</p>
</div>
<DatenblattFooter></DatenblattFooter>
<DatenblattFooter />
</div>
</div>
</PDFLayout>

View File

@@ -1,11 +1,8 @@
---
import { changeLanguage } from "i18next";
import moment from "moment";
import RegisterView from "../modules/RegisterModule.svelte";
import Layout from "../layouts/Layout.astro";
changeLanguage("de");
const token = Astro.cookies.get("token").value;
const expires = Astro.cookies.get("expires").number();
const now = moment().unix();

View File

@@ -1,32 +1,10 @@
---
import UserLayout from "#layouts/UserLayout.astro";
import { User } from "#lib/User";
import { tRPCCaller } from "../api/[trpc]";
const token = Astro.cookies.get("token").value;
if (!token) {
Astro.cookies.delete("token");
return Astro.redirect(`/login`);
}
const response = await tRPCCaller(Astro.request).v1.benutzer.tokenValidieren({ token });
if (!response.valid) {
Astro.cookies.delete("token");
return Astro.redirect(`/login`);
}
const user = await User.fromUID(response.uid);
if (!user) {
Astro.cookies.delete("token");
return Astro.redirect(`/login`);
}
---
<UserLayout title="Dashboard">
<h1>Willkommen zurück <b>{user.email}</b></h1>
<h1>Willkommen zurück</h1>
<h2>Ihre Ausweise</h2>
<div class="grid grid-flow-row grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">

View File

@@ -1,9 +1,9 @@
---
import { changeLanguage } from "i18next";
import AusweisLayout from "#layouts/AusweisLayout.astro";
import VerbrauchsausweisGewerbeContent from "#components/VerbrauchsausweisGewerbe/VerbrauchsausweisGewerbeContent.svelte";
changeLanguage("de");
---
<AusweisLayout title="Verbrauchsausweis Gewerbe erstellen | IBCornelsen">

View File

@@ -1,9 +1,9 @@
---
import { changeLanguage } from "i18next";
import AusweisLayout from "#layouts/AusweisLayout.astro";
import VerbrauchsausweisWohnenModule from "#modules/Ausweise/VerbrauchsausweisWohnenModule.svelte";
changeLanguage("de");
const uid = Astro.cookies.get("ausweis_uid").value;
---

View File

@@ -31,9 +31,6 @@ body {
}
.stretch-2 {
-ms-grid-row: 1;
-ms-grid-column: 1;
-ms-grid-column-span: 4;
grid-area: 1/1/1/4;
}
@@ -43,9 +40,6 @@ body {
.right-sidebar {
display: none;
-ms-grid-row: 1;
-ms-grid-column: 1;
-ms-grid-column-span: 3;
grid-area: 1/1/1/3;
padding-top: 0px;
margin-top: 0px;
@@ -62,7 +56,7 @@ body {
}
.mainContent a {
color: #3A4AB5;
color: #3a4ab5;
text-decoration: none;
display: inline;
}
@@ -78,8 +72,6 @@ body {
text-transform: none;
}
footer a {
display: inline;
color: #fff;
@@ -87,7 +79,6 @@ footer a {
font-size: 14px;
}
/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/*- Branding: -*/
/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
@@ -130,12 +121,11 @@ footer a {
}
.nav-head {
background-color: #444F94;
display: -webkit-box;
display: -ms-flexbox;
background-color: #444f94;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: end;
@@ -156,13 +146,12 @@ footer a {
max-height: 100%;
padding-bottom: 0px;
padding-top: 0px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
background-color: #444F94;
background-color: #444f94;
}
header a {
@@ -186,31 +175,17 @@ header a {
background-color: #ff7d26;
}
.headerButton.active {
background-color: rgb(58, 74, 181);
}
/*-----------------------------------------------------------------*/
/*- -*/
.justify-between {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
}
@@ -225,12 +200,12 @@ header a {
hr {
border: none;
border-bottom: 1px solid #CECECE;
border-bottom: 1px solid #cecece;
margin: 1em 0 1em 0;
}
ul hr {
margin: .5em 0 !important;
margin: 0.5em 0 !important;
}
.nopad {
@@ -263,9 +238,7 @@ ul hr {
padding: 0;
margin: 0 10px 0 0;
border-radius: 50%;
vertical-align: middle;
-webkit-box-shadow: 0 0 2px rgba(0, 0, 0, .12), 0 2px 4px rgba(0, 0, 0, .24);
box-shadow: 0 0 2px rgba(0, 0, 0, .12), 0 2px 4px rgba(0, 0, 0, .24);
box-shadow: 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24);
}
.rplg .rplg-social-logo svg {
@@ -280,10 +253,8 @@ ul hr {
}
.rplgsw-wrapper {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
overflow: hidden
overflow: hidden;
}
.rplg-box * {
@@ -312,8 +283,6 @@ ul hr {
}
.rplg-row {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
@@ -321,8 +290,6 @@ ul hr {
}
.rplg-trim {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
@@ -338,7 +305,6 @@ ul hr {
vertical-align: middle;
}
/*
Login - Hausbox
@@ -347,8 +313,7 @@ Login - Hausbox
.haus_info_box {
width: 100%;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
@@ -384,8 +349,8 @@ Login - Hausbox
.haus-box {
border-radius: 8px;
-webkit-box-shadow: 0 0 .5em #ccc;
box-shadow: 0 0 .5em #ccc;
-webkit-box-shadow: 0 0 0.5em #ccc;
box-shadow: 0 0 0.5em #ccc;
width: 300px !important;
}
@@ -408,8 +373,7 @@ Login - Hausbox
.image-box {
width: auto;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
gap: 10px;
-webkit-box-align: center;
@@ -427,8 +391,8 @@ Login - Hausbox
.ampel-img {
height: 100px;
width: 35px !important;
-webkit-box-shadow: 0 0 .5em #ccc;
box-shadow: 0 0 .5em #ccc;
-webkit-box-shadow: 0 0 0.5em #ccc;
box-shadow: 0 0 0.5em #ccc;
}
.haus-content {
@@ -451,8 +415,8 @@ Login - Hausbox
.energieausweis-img {
width: 33%;
-webkit-box-shadow: 0 0 .5em #ccc;
box-shadow: 0 0 .5em #ccc;
-webkit-box-shadow: 0 0 0.5em #ccc;
box-shadow: 0 0 0.5em #ccc;
}
.energieausweis-img img {
@@ -468,15 +432,14 @@ Login - Hausbox
cursor: pointer;
font-weight: normal;
border-radius: 1em;
-webkit-box-shadow: .1em .1em .2em #bbb;
box-shadow: .1em .1em .2em #bbb;
-webkit-box-shadow: 0.1em 0.1em 0.2em #bbb;
box-shadow: 0.1em 0.1em 0.2em #bbb;
}
.kbutton:focus {
background-color: #384da3;
}
/*
Input, textarea styling (forms)
@@ -524,7 +487,7 @@ textarea {
width: -webkit-max-content;
width: -moz-max-content;
width: max-content;
padding: .375rem .75rem;
padding: 0.375rem 0.75rem;
border-radius: 4px;
border: none;
font-size: 1rem;
@@ -554,7 +517,7 @@ textarea {
.caption-text {
font-size: 75%;
padding-top: 5px;
opacity: .8;
opacity: 0.8;
}
.image-list img {
@@ -570,15 +533,15 @@ textarea {
width: 1.3em;
height: auto;
background: none;
left: -.6em;
top: .3em;
left: -0.6em;
top: 0.3em;
}
.kost-tbl {
width: 100%;
margin: 0 0 2em 0;
-webkit-box-shadow: .2em .2em .4em #ccc;
box-shadow: .2em .2em .4em #ccc;
-webkit-box-shadow: 0.2em 0.2em 0.4em #ccc;
box-shadow: 0.2em 0.2em 0.4em #ccc;
}
.haus_ul1,
@@ -592,7 +555,7 @@ textarea {
.haus_ul2 li {
position: relative;
font-size: 1.1em;
padding: .3em .3em .3em 1.3em;
padding: 0.3em 0.3em 0.3em 1.3em;
}
.haus_ul1 li::before {
@@ -604,8 +567,8 @@ textarea {
width: 1.3em;
height: auto;
background: none;
left: -.6em;
top: .3em;
left: -0.6em;
top: 0.3em;
}
.kost-tbl thead td {
@@ -631,8 +594,6 @@ table {
grid-gap: 20px;
}
.start_infobox_img {
float: right;
width: 23% !important;
@@ -653,23 +614,23 @@ table {
.start_infobox_button a:hover {
background-color: #ff7d26;
color: #fff !important;
padding: .15em 1em .15em 1em;
border-radius: .8em;
padding: 0.15em 1em 0.15em 1em;
border-radius: 0.8em;
font-size: 1.3em;
font-weight: 600;
-webkit-box-shadow: .1em .1em .2em #bbb;
box-shadow: .1em .1em .2em #bbb;
-webkit-box-shadow: 0.1em 0.1em 0.2em #bbb;
box-shadow: 0.1em 0.1em 0.2em #bbb;
}
.start_infobox_button a {
background-color: #3a4ab5;
color: #fff !important;
padding: .2em 1em .2em 1em;
border-radius: .8em;
padding: 0.2em 1em 0.2em 1em;
border-radius: 0.8em;
font-size: 1.3em;
font-weight: 600;
-webkit-box-shadow: .1em .1em .2em #bbb;
box-shadow: .1em .1em .2em #bbb;
-webkit-box-shadow: 0.1em 0.1em 0.2em #bbb;
box-shadow: 0.1em 0.1em 0.2em #bbb;
}
.start_infobox_button {
@@ -682,8 +643,8 @@ table {
margin: 2em auto;
border: 2px dotted #ff7d26;
border-radius: 1em;
-webkit-box-shadow: 0 0 .5em #ccc;
box-shadow: 0 0 .5em #ccc;
-webkit-box-shadow: 0 0 0.5em #ccc;
box-shadow: 0 0 0.5em #ccc;
}
.start_infobox ul li::before {
@@ -694,7 +655,7 @@ table {
height: 7px;
background-color: #ddd;
position: absolute;
border-radius: .1em;
border-radius: 0.1em;
}
.start_infobox .title,
@@ -702,7 +663,7 @@ table {
color: #ff7d26 !important;
margin: 0;
font-size: 1.4em;
margin-bottom: -.3em;
margin-bottom: -0.3em;
position: relative;
}
@@ -728,7 +689,7 @@ table {
.pdf {
position: relative;
padding: 0 0 .5em 3.5em;
padding: 0 0 0.5em 3.5em;
text-align: left !important;
}
@@ -742,9 +703,9 @@ table {
.bedarfsausweis-wohngebaeude-beispiel,
.verbrauchsausweis-wohngebaeude-beispiel {
width: 100%;
margin: 0 .5% 2em .5%;
margin: 0 0.5% 2em 0.5%;
font-size: 1.1em;
padding: .5em .5%;
padding: 0.5em 0.5%;
float: left;
text-align: center;
border-top-left-radius: 1em;
@@ -762,9 +723,9 @@ table {
.buynow-btn {
background-color: #4251a3;
border-radius: 1em;
padding: .2em 1em;
-webkit-box-shadow: .1em .1em .2em #bbb;
box-shadow: .1em .1em .2em #bbb;
padding: 0.2em 1em;
-webkit-box-shadow: 0.1em 0.1em 0.2em #bbb;
box-shadow: 0.1em 0.1em 0.2em #bbb;
white-space: nowrap;
border: 2px solid #fff;
color: #fff !important;
@@ -774,13 +735,11 @@ table {
.buynow-btn:hover {
background-color: #ff7d26;
-webkit-box-shadow: .1em .1em .2em #bbb;
box-shadow: .1em .1em .2em #bbb;
-webkit-box-shadow: 0.1em 0.1em 0.2em #bbb;
box-shadow: 0.1em 0.1em 0.2em #bbb;
white-space: nowrap;
}
.row * {
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -800,9 +759,6 @@ table {
}
.row {
display: -ms-flexbox;
display: -webkit-box;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
@@ -811,18 +767,14 @@ table {
}
.flex-row {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
}
.align-center {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
@@ -833,16 +785,11 @@ table {
}
.flex-column {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
}
block {
display: block;
position: relative;
@@ -870,14 +817,9 @@ cbutton {
width: -moz-min-content;
width: min-content;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
:root {
--theme-primary: #fff;
--theme-orange: rgb(255, 125, 38);
@@ -886,8 +828,6 @@ cbutton {
--std-font: Abel, Roboto, sand-serif;
}
.section_1 > *:nth-child(1) {
-ms-grid-row: 1;
-ms-grid-column: 1;
@@ -936,18 +876,9 @@ cbutton {
}
.block_4 {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-align: start;
-ms-flex-align: start;
align-items: start;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
align-items: flex-start;
justify-content: space-between;
width: inherit;
padding: 0px;
@@ -955,21 +886,16 @@ cbutton {
}
.block_5 {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
width: 100%;
padding: 0px;
margin: 0px;
-webkit-box-align: start;
-ms-flex-align: start;
align-items: start;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
align-items: flex-start;
justify-content: space-between;
}
@@ -1064,12 +990,8 @@ content {
margin: 10px auto;
display: -ms-grid;
display: grid;
-webkit-column-gap: 20px;
-moz-column-gap: 20px;
column-gap: 20px;
-ms-grid-columns: 2fr 20px 6fr 20px 2fr;
grid-template-columns: 2fr 6fr 2fr;
-ms-grid-rows: auto;
grid-template-rows: auto;
}
@@ -1093,7 +1015,6 @@ content>*:nth-child(3) {
margin-bottom: 0;
}
.rpt_plan img {
width: 50%;
margin: 15px auto;
@@ -1107,20 +1028,17 @@ content>*:nth-child(3) {
text-align: center;
font-weight: bold;
line-height: 1.2em;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
padding: 14px 18px;
background: #4251a3;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
border-top-left-radius: .4em;
border-top-right-radius: .4em;
border-top-left-radius: 0.4em;
border-top-right-radius: 0.4em;
margin-bottom: 0;
}
@@ -1128,10 +1046,10 @@ content>*:nth-child(3) {
padding: 6px 10px;
text-align: center;
color: #fff;
text-shadow: 1px 2px 7px rgba(0, 0, 0, .6);
text-shadow: 1px 2px 7px rgba(0, 0, 0, 0.6);
font-size: 5em;
font-weight: bold;
padding-bottom: .2em;
padding-bottom: 0.2em;
margin-bottom: 0;
}
@@ -1206,17 +1124,12 @@ content>*:nth-child(3) {
width: 100%;
min-width: 152px;
@apply border shadow-md;
border-radius: .4em;
border-radius: 0.4em;
background: #f5f5f5;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
@@ -1229,7 +1142,7 @@ content>*:nth-child(3) {
height: 7px;
background-color: #ddd;
position: absolute;
border-radius: .1em;
border-radius: 0.1em;
}
.widget_nav ul li {
@@ -1262,12 +1175,11 @@ content>*:nth-child(3) {
.large-button {
background: #3a4ab5;
color: #fff;
padding: .2em 1em .2em 1em;
border-radius: .8em;
padding: 0.2em 1em 0.2em 1em;
border-radius: 0.8em;
font-size: 1em;
font-weight: 600;
text-decoration: none;
-webkit-box-shadow: 0.1em 0.1em 0.2em #bbb;
box-shadow: 0.1em 0.1em 0.2em #bbb;
margin-top: 10px;
white-space: nowrap;
@@ -1305,7 +1217,7 @@ ul li {
}
ul li::before {
content: '';
content: "";
width: 10px;
height: 10px;
left: 0;
@@ -1313,7 +1225,7 @@ ul li::before {
margin-left: 0;
background: #ff7d26;
position: absolute;
border-radius: .1em;
border-radius: 0.1em;
}
.img-subtitle {
@@ -1323,18 +1235,13 @@ ul li::before {
text-align: center;
}
footer {
background: rgb(255, 125, 38);
height: 40px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
padding: 0 30px;
width: auto;
@@ -1344,17 +1251,10 @@ footer {
}
#pwtester {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
width: 100%;
margin: 10px 0 0 0;
-webkit-box-pack: space-evenly;
-ms-flex-pack: space-evenly;
justify-content: space-evenly;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
}
@@ -1363,17 +1263,14 @@ footer {
width: 24%;
height: 4px;
border-radius: 4px;
background: #B7B7B7;
background: #b7b7b7;
}
.objekt_card {
display: -ms-grid;
display: grid;
-ms-grid-columns: 1fr 1fr;
grid-template-columns: 1fr 1fr;
-ms-grid-rows: 375px 5px 125px;
grid-template-rows: 375px 125px;
-webkit-box-shadow: rgb(162, 162, 162) 1px 1px 3px 1px;
box-shadow: rgb(162, 162, 162) 1px 1px 3px 1px;
background: #fff;
margin: 0 auto;
@@ -1383,9 +1280,6 @@ footer {
grid-row-gap: 5px;
max-width: 1100px;
position: relative;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
cursor: pointer;
margin-bottom: 30px;
@@ -1432,8 +1326,7 @@ body .objekt_card:first-of-type {
.objekt_previewImage {
-o-object-fit: contain;
object-fit: contain;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
@@ -1462,22 +1355,14 @@ body .objekt_card:first-of-type {
.objekt_makler {
margin: 0 20px 20px 20px;
padding-left: 20px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
border-top: 1px solid rgb(223, 223, 223);
}
.objekt_images {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
border-bottom-left-radius: 5px;
}
@@ -1494,12 +1379,8 @@ body .objekt_card:first-of-type {
/* NOTE MAKLER SYSTEM */
.card_container {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
}
@@ -1513,8 +1394,6 @@ body .objekt_card:first-of-type {
}
.justify_left {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
justify-content: flex-end;
}
@@ -1564,9 +1443,7 @@ body .objekt_card:first-of-type {
display: -ms-grid;
display: grid;
grid-template-areas: "main detail" "main info";
-ms-grid-columns: 3.8fr 20px 1.2fr;
grid-template-columns: 3.8fr 1.2fr;
-ms-grid-rows: 250px 20px auto;
grid-template-rows: 250px auto;
grid-gap: 20px;
}
@@ -1583,7 +1460,6 @@ body .objekt_card:first-of-type {
.text_container {
-ms-grid-row: 1;
-ms-grid-row-span: 3;
-ms-grid-column: 1;
grid-area: main;
background: #fff;
@@ -1606,18 +1482,11 @@ body .objekt_card:first-of-type {
}
.image_slideshow {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
margin-right: 10px;
gap: 10px;
overflow: hidden;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
--image-width: 1200px;
--image-margin: 6px;
@@ -1630,31 +1499,20 @@ body .objekt_card:first-of-type {
.image_slideshow img {
width: 1200px;
height: 500px;
-o-object-fit: cover;
object-fit: cover;
border-radius: 8px;
-webkit-transition: all .4s ease;
-o-transition: all .4s ease;
transition: all .4s ease;
-webkit-box-shadow: 1px 1px 2px 1px rgba(24, 24, 24, 0.178);
transition: all 0.4s ease;
box-shadow: 1px 1px 2px 1px rgba(24, 24, 24, 0.178);
}
.image_slideshow .control_wrapper {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
position: absolute;
width: calc(1200px + 60px);
height: 500px;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-transition: all 0.4s ease;
-o-transition: all 0.4s ease;
transition: all 0.4s ease;
}
@@ -1662,9 +1520,6 @@ body .objekt_card:first-of-type {
position: relative;
width: 1200px;
height: 530px;
/*margin: 0 6px;*/
-webkit-transition: all 0.4s ease;
-o-transition: all 0.4s ease;
transition: all 0.4s ease;
}
@@ -1679,21 +1534,13 @@ body .objekt_card:first-of-type {
border-radius: 50%;
height: 16px;
width: 16px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
color: #000;
-webkit-transition: all .3s ease;
-o-transition: all .3s ease;
transition: all .3s ease;
transition: all 0.3s ease;
cursor: pointer;
-webkit-box-shadow: 1px 1px 2px 1px rgba(24, 24, 24, 0.178);
box-shadow: 1px 1px 2px 1px rgba(24, 24, 24, 0.178);
}
@@ -1711,7 +1558,6 @@ body .objekt_card:first-of-type {
-ms-grid-columns: 2fr 20px 1fr;
grid-template-columns: 2fr 1fr;
grid-gap: 20px;
-ms-grid-rows: auto;
grid-template-rows: auto;
grid-template-areas: "profile_info menu_buttons" ". menu_buttons";
}
@@ -1725,7 +1571,6 @@ body .objekt_card:first-of-type {
.span-2 {
-ms-grid-row: 1;
-ms-grid-row-span: 2;
-ms-grid-column: 1;
grid-area: 1/1 / span 2 / 1;
}
@@ -1803,7 +1648,6 @@ body .objekt_card:first-of-type {
display: none;
}
.login-container {
grid-template-columns: repeat(2, 1fr);
}

View File

@@ -127,11 +127,11 @@
.nav-head {
background-color: rgb(255, 125, 38);
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: end;
@@ -154,8 +154,8 @@
max-height: 100%;
padding-bottom: 0px;
padding-top: 0px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;

View File

@@ -1,14 +1,14 @@
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
import cookies from 'js-cookie';
import type { AppRouter } from 'src/pages/api/[trpc]';
import type { AppRouter } from '@ibcornelsen/api';
export const client = createTRPCProxyClient<AppRouter>({
links: [
httpBatchLink({
url: 'http://localhost:3000/api',
url: 'http://localhost:3001/',
headers() {
return {
'Authorization': `Bearer ${cookies.get('uid')}`,
'Authorization': `Bearer ${cookies.get('accessToken')}`,
};
},
}),

10
test.ts
View File

@@ -1,10 +0,0 @@
import { AppRouter } from "src/pages/api/[trpc]"
import { createOpenApiExpressMiddleware } from "trpc-openapi"
import express from 'express';
const app = express();
app.use(createOpenApiExpressMiddleware({ router: AppRouter }));
app.listen(5555);
console.log("Server listening on port 80");