Postleitzahlen Suche und e2e Tests
This commit is contained in:
@@ -17,7 +17,7 @@ export default defineConfig({
|
||||
output: "server",
|
||||
vite: {
|
||||
optimizeDeps: {
|
||||
exclude: ["@ibcornelsen/api"]
|
||||
exclude: ["@ibcornelsen/api", "@ibcornelsen/database"]
|
||||
}
|
||||
},
|
||||
adapter: node({
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
import { defineConfig } from 'cypress'
|
||||
import { defineConfig } from "cypress";
|
||||
|
||||
export default defineConfig({
|
||||
e2e: {
|
||||
baseUrl: 'http://localhost:3000',
|
||||
supportFile: false
|
||||
baseUrl: "http://localhost:3000",
|
||||
supportFile: false,
|
||||
viewportHeight: 900,
|
||||
viewportWidth: 1660,
|
||||
},
|
||||
})
|
||||
|
||||
component: {
|
||||
devServer: {
|
||||
framework: "svelte",
|
||||
bundler: "vite",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
describe('The Home page.', () => {
|
||||
it("successfully loads", () => {
|
||||
cy.visit("/")
|
||||
})
|
||||
})
|
||||
112
cypress/e2e/VerbrauchsausweisWohnen/erstellen.cy.ts
Normal file
112
cypress/e2e/VerbrauchsausweisWohnen/erstellen.cy.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import fuelList from "#components/Ausweis/fuelList";
|
||||
import { faker } from "@faker-js/faker";
|
||||
import { Enums } from "@ibcornelsen/database/client";
|
||||
|
||||
describe("Verbrauchsausweis erstellen Schritt 1", () => {
|
||||
it("erstellt einen neuen Verbrauchsausweis Wohngebäude.", () => {
|
||||
cy.visit("/verbrauchsausweis");
|
||||
|
||||
cy.wait(1000);
|
||||
|
||||
// Wir überprüfen, ob alle Ausstelgründe vorhanden sind, diese sollten genau so viele sein wie in der Datenbank vorhanden sind.
|
||||
cy.get("input[name='ausstellgrund']")
|
||||
.should("have.length", Object.values(Enums.Ausstellgrund).length)
|
||||
.eq(
|
||||
faker.number.int({
|
||||
min: 0,
|
||||
max: Object.values(Enums.Ausstellgrund).length - 1,
|
||||
})
|
||||
)
|
||||
.check();
|
||||
|
||||
// Jetzt Füllen wir das Baujahr vom Gebäude aus.
|
||||
cy.get("input[name='baujahr_gebaeude']")
|
||||
.should("have.attr", "type", "number")
|
||||
.type(
|
||||
faker.number.int({ min: 1900, max: 2021 }).toString() +
|
||||
"{enter}",
|
||||
{ delay: 50 }
|
||||
);
|
||||
|
||||
// Jetzt Füllen wir das Baujahr der Heizung aus.
|
||||
cy.get("input[name='baujahr_heizung']")
|
||||
.should("have.attr", "type", "number")
|
||||
.type(
|
||||
faker.number.int({ min: 1900, max: 2021 }).toString() +
|
||||
"{enter}",
|
||||
{ delay: 50 }
|
||||
);
|
||||
|
||||
// Anzahl Einheiten
|
||||
cy.get("input[name='einheiten']")
|
||||
.should("have.attr", "type", "number")
|
||||
.type(faker.number.int({ min: 1, max: 5 }).toString());
|
||||
|
||||
// Sanierungsstatus
|
||||
cy.get("select[name='saniert']").select(
|
||||
Math.random() > 0.5 ? "true" : "false"
|
||||
);
|
||||
|
||||
// Adresse
|
||||
cy.get("input[name='adresse']").type(faker.location.streetAddress());
|
||||
|
||||
// Postleitzahl
|
||||
cy.get("input[name='plz']").type(
|
||||
faker.location.zipCode({
|
||||
format: "#####",
|
||||
})
|
||||
);
|
||||
|
||||
// TODO: Ort - Dieser wird aus der Datenbank abgefragt, wir müssen also warten, bis der Dropdown da ist.
|
||||
|
||||
// Flaeche
|
||||
cy.get("input[name='flaeche']")
|
||||
.should("have.attr", "type", "number")
|
||||
.type(faker.number.int({ min: 50, max: 1000 }).toString());
|
||||
|
||||
// Keller
|
||||
cy.get("select[name='keller']").find("option:not([disabled])").should("have.length", Object.values(Enums.Heizungsstatus).length).parent().select(faker.number.int({
|
||||
max: Object.values(Enums.Heizungsstatus).length,
|
||||
min: 1
|
||||
}));
|
||||
|
||||
// Dachgeschoss
|
||||
cy.get("select[name='dachgeschoss']").find("option:not([disabled])").should("have.length", Object.values(Enums.Heizungsstatus).length).parent().select(faker.number.int({
|
||||
max: Object.values(Enums.Heizungsstatus).length,
|
||||
min: 1
|
||||
}));
|
||||
|
||||
// Brennstoff und Einheit 1
|
||||
const brennstoffKombo = fuelList[faker.number.int({ min: 0, max: fuelList.length - 1 })];
|
||||
|
||||
cy.get("select[name='brennstoff_1']").select(brennstoffKombo[0]);
|
||||
cy.get("select[name='einheit_1']").select(brennstoffKombo[1]);
|
||||
|
||||
// Verbrauchszeitraum
|
||||
cy.get("select[name='energieverbrauch_zeitraum_monat']").select(faker.number.int({ min: 1, max: 12 }).toString());
|
||||
cy.get("select[name='energieverbrauch_zeitraum_jahr']").select(faker.number.int({ min: 2018, max: 2019 }).toString());
|
||||
|
||||
// Verbrauch
|
||||
cy.get("input[name='verbrauch_1']").type(faker.number.int({ min: 4000, max: 15000 }).toString());
|
||||
cy.get("input[name='verbrauch_2']").type(faker.number.int({ min: 4000, max: 15000 }).toString());
|
||||
cy.get("input[name='verbrauch_3']").type(faker.number.int({ min: 4000, max: 15000 }).toString());
|
||||
|
||||
|
||||
const zusaetzlicheHeizquelle = Math.random() > 0.5;
|
||||
|
||||
if (zusaetzlicheHeizquelle) {
|
||||
cy.get("input[name='zusaetzliche_heizquelle']").check();
|
||||
|
||||
// Brennstoff und Einheit 2
|
||||
const brennstoffKombo2 = fuelList[faker.number.int({ min: 0, max: fuelList.length - 1 })];
|
||||
|
||||
cy.get("select[name='brennstoff_2']").select(brennstoffKombo2[0]);
|
||||
cy.get("select[name='einheit_2']").select(brennstoffKombo2[1]);
|
||||
|
||||
// Verbrauch
|
||||
cy.get("input[name='verbrauch_4']").type(faker.number.int({ min: 4000, max: 15000 }).toString());
|
||||
cy.get("input[name='verbrauch_5']").type(faker.number.int({ min: 4000, max: 15000 }).toString());
|
||||
cy.get("input[name='verbrauch_6']").type(faker.number.int({ min: 4000, max: 15000 }).toString());
|
||||
}
|
||||
});
|
||||
});
|
||||
38
cypress/e2e/auth/index.cy.ts
Normal file
38
cypress/e2e/auth/index.cy.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { API_ACCESS_TOKEN_COOKIE_NAME, API_REFRESH_TOKEN_COOKIE_NAME } from "#lib/constants";
|
||||
import {faker} from "@faker-js/faker";
|
||||
|
||||
describe('Benutzer Authentifizierung', () => {
|
||||
// Wir generieren uns einen zufälligen Nutzer
|
||||
const email = faker.internet.email()
|
||||
const password = faker.internet.password()
|
||||
const name = faker.person.firstName()
|
||||
const surname = faker.person.lastName()
|
||||
|
||||
it("erstellt einen Nutzer und leitet auf die Login Seite weiter", () => {
|
||||
cy.visit("/auth/signup")
|
||||
|
||||
cy.get('input[name="email"]').type(email)
|
||||
cy.get('input[name="passwort"]').type(password)
|
||||
cy.get('input[name="vorname"]').type(name)
|
||||
cy.get('input[name="name"]').type(surname)
|
||||
|
||||
cy.get('button[type="submit"]').click()
|
||||
|
||||
cy.url().should("include", "/auth/login")
|
||||
})
|
||||
|
||||
it("meldet einen Nutzer an und leitet auf die Startseite weiter", () => {
|
||||
cy.visit("/auth/login")
|
||||
|
||||
cy.get('input[name="email"]').type(email)
|
||||
cy.get('input[name="passwort"]').type(password)
|
||||
|
||||
cy.get('button[type="submit"]').click()
|
||||
|
||||
cy.url().should("include", "/user")
|
||||
|
||||
// Wir sollten nun einen Access Token und Refresh Token in unseren Cookies sehen.
|
||||
cy.getCookie(API_ACCESS_TOKEN_COOKIE_NAME).should("exist")
|
||||
cy.getCookie(API_REFRESH_TOKEN_COOKIE_NAME).should("exist")
|
||||
})
|
||||
})
|
||||
5
cypress/fixtures/example.json
Normal file
5
cypress/fixtures/example.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
||||
37
cypress/support/commands.ts
Normal file
37
cypress/support/commands.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
/// <reference types="cypress" />
|
||||
// ***********************************************
|
||||
// This example commands.ts shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add('login', (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||
//
|
||||
// declare global {
|
||||
// namespace Cypress {
|
||||
// interface Chainable {
|
||||
// login(email: string, password: string): Chainable<void>
|
||||
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
|
||||
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
|
||||
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
12
cypress/support/component-index.html
Normal file
12
cypress/support/component-index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<title>Components App</title>
|
||||
</head>
|
||||
<body>
|
||||
<div data-cy-root></div>
|
||||
</body>
|
||||
</html>
|
||||
39
cypress/support/component.ts
Normal file
39
cypress/support/component.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
// ***********************************************************
|
||||
// This example support/component.ts is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
|
||||
import { mount } from 'cypress/svelte'
|
||||
|
||||
// Augment the Cypress namespace to include type definitions for
|
||||
// your custom command.
|
||||
// Alternatively, can be defined in cypress/support/component.d.ts
|
||||
// with a <reference path="./component" /> at the top of your spec.
|
||||
declare global {
|
||||
namespace Cypress {
|
||||
interface Chainable {
|
||||
mount: typeof mount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Cypress.Commands.add('mount', mount)
|
||||
|
||||
// Example use:
|
||||
// cy.mount(MyComponent)
|
||||
@@ -58,12 +58,13 @@
|
||||
"zod": "^3.22.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^8.3.1",
|
||||
"@types/body-scroll-lock": "^3.1.2",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/uuid": "^9.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.6",
|
||||
"@typescript-eslint/parser": "^5.59.6",
|
||||
"cypress": "^13.6.1",
|
||||
"cypress": "^13.6.2",
|
||||
"eslint": "~8.15.0",
|
||||
"eslint-config-prettier": "8.1.0",
|
||||
"prettier": "^2.8.8",
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
{#each Object.entries(Enums.Ausstellgrund) as [name, ausstellgrund]}
|
||||
<label class="radio-inline">
|
||||
<input
|
||||
name="ausstellgrund"
|
||||
type="radio"
|
||||
value={ausstellgrund}
|
||||
bind:group={ausweis.ausstellgrund}
|
||||
@@ -45,7 +46,7 @@
|
||||
</HelpLabel>
|
||||
<div>
|
||||
<TagInput
|
||||
name="IGheizung"
|
||||
name="baujahr_heizung"
|
||||
type="number"
|
||||
onlyUnique={true}
|
||||
onFocusIn={() => {
|
||||
@@ -80,7 +81,7 @@
|
||||
</HelpLabel>
|
||||
<div>
|
||||
<TagInput
|
||||
name="IGbaujahr"
|
||||
name="baujahr_gebaeude"
|
||||
type="number"
|
||||
onlyUnique={true}
|
||||
onFocusIn={() => {
|
||||
@@ -113,10 +114,8 @@
|
||||
</HelpLabel>
|
||||
<div>
|
||||
<input
|
||||
id="IGanzahl"
|
||||
name="IGanzahl"
|
||||
class=" "
|
||||
type="text"
|
||||
name="einheiten"
|
||||
type="number"
|
||||
required
|
||||
autocomplete="off"
|
||||
data-msg="Pflichtfeld"
|
||||
@@ -135,8 +134,7 @@
|
||||
</HelpLabel>
|
||||
<div>
|
||||
<select
|
||||
id="IGsan"
|
||||
name="IGsan"
|
||||
name="saniert"
|
||||
class=""
|
||||
required
|
||||
bind:value={gebaeude.saniert}
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
</HelpLabel>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="IGzus1verbrauch1"
|
||||
name="zusaetzliche_heizquelle"
|
||||
bind:checked={ausweis.zusaetzliche_heizquelle}
|
||||
/>
|
||||
</div>
|
||||
@@ -90,8 +90,8 @@
|
||||
<b>Koks:</b> Stark kohlenstoffhaltiger Brennstoff.<br /><br />
|
||||
</HelpLabel>
|
||||
<div>
|
||||
<select name="energietraeger_1" required bind:value={ausweis.brennstoff_1}>
|
||||
<option>Bitte auswählen</option>
|
||||
<select name="brennstoff_1" required bind:value={ausweis.brennstoff_1}>
|
||||
<option disabled>Bitte auswählen</option>
|
||||
{#each Object.keys(fuelMap) as fuel}
|
||||
<option value={fuel}>{fuel}</option>
|
||||
{/each}
|
||||
@@ -111,7 +111,7 @@
|
||||
required
|
||||
bind:value={ausweis.einheit_1}
|
||||
>
|
||||
<option>Bitte auswählen</option>
|
||||
<option disabled>Bitte auswählen</option>
|
||||
{#each (fuelMap.hasOwnProperty(ausweis.brennstoff_1) ? fuelMap[ausweis.brennstoff_1] : []) as unit}
|
||||
<option value={unit}>{unit}</option>
|
||||
{/each}
|
||||
@@ -123,12 +123,12 @@
|
||||
<Label>Brennstoff *</Label>
|
||||
<div>
|
||||
<select
|
||||
name="energietraeger_2"
|
||||
name="brennstoff_2"
|
||||
bind:value={ausweis.brennstoff_2}
|
||||
disabled={!ausweis.zusaetzliche_heizquelle}
|
||||
required
|
||||
>
|
||||
<option> Bitte auswählen</option>
|
||||
<option disabled> Bitte auswählen</option>
|
||||
{#each Object.keys(fuelMap) as fuel}
|
||||
<option value={fuel}>{fuel}</option>
|
||||
{/each}
|
||||
@@ -145,7 +145,7 @@
|
||||
bind:value={ausweis.einheit_2}
|
||||
required
|
||||
>
|
||||
<option>Bitte auswählen</option>
|
||||
<option disabled>Bitte auswählen</option>
|
||||
{#each (fuelMap.hasOwnProperty(ausweis.brennstoff_2) ? fuelMap[ausweis.brennstoff_2] : []) as unit}
|
||||
<option value={unit}>{unit}</option>
|
||||
{/each}
|
||||
@@ -207,7 +207,7 @@
|
||||
<div class="column">
|
||||
<span>bis</span>
|
||||
<input
|
||||
class=""
|
||||
|
||||
value={moment(ausweis.startdatum)
|
||||
.add("1", "year")
|
||||
.format("MM.Y")}
|
||||
@@ -217,7 +217,7 @@
|
||||
<div class="column">
|
||||
<span>bis</span>
|
||||
<input
|
||||
class=""
|
||||
|
||||
value={moment(ausweis.startdatum)
|
||||
.add("2", "years")
|
||||
.format("MM.Y")}
|
||||
@@ -227,7 +227,7 @@
|
||||
<div class="column">
|
||||
<span>bis</span>
|
||||
<input
|
||||
class=""
|
||||
|
||||
value={moment(ausweis.startdatum)
|
||||
.add("3", "years")
|
||||
.format("MM.Y")}
|
||||
@@ -239,7 +239,7 @@
|
||||
<div class="column">
|
||||
<span>Verbrauch</span>
|
||||
<input
|
||||
name="energieverbrauch_1_heizquelle_1"
|
||||
name="verbrauch_1"
|
||||
type="number"
|
||||
class:linked={abweichung.indexOf(1) > -1}
|
||||
bind:value={ausweis.verbrauch_1}
|
||||
@@ -249,7 +249,7 @@
|
||||
<div class="column">
|
||||
<span>Verbrauch</span>
|
||||
<input
|
||||
name="energieverbrauch_2_heizquelle_1"
|
||||
name="verbrauch_2"
|
||||
type="number"
|
||||
class:linked={abweichung.indexOf(2) > -1}
|
||||
bind:value={ausweis.verbrauch_2}
|
||||
@@ -259,7 +259,7 @@
|
||||
<div class="column">
|
||||
<span>Verbrauch</span>
|
||||
<input
|
||||
name="energieverbrauch_3_heizquelle_1"
|
||||
name="verbrauch_3"
|
||||
type="number"
|
||||
class:linked={abweichung.indexOf(3) > -1}
|
||||
bind:value={ausweis.verbrauch_3}
|
||||
@@ -271,7 +271,7 @@
|
||||
<div class="column">
|
||||
<span>Verbrauch</span>
|
||||
<input
|
||||
name="energieverbrauch_1_heizquelle_2"
|
||||
name="verbrauch_4"
|
||||
type="number"
|
||||
bind:value={ausweis.verbrauch_4}
|
||||
class:linked={abweichung.indexOf(4) > -1}
|
||||
@@ -281,7 +281,7 @@
|
||||
<div class="column">
|
||||
<span>Verbrauch</span>
|
||||
<input
|
||||
name="energieverbrauch_2_heizquelle_2"
|
||||
name="verbrauch_5"
|
||||
type="number"
|
||||
bind:value={ausweis.verbrauch_5}
|
||||
class:linked={abweichung.indexOf(5) > -1}
|
||||
@@ -291,7 +291,7 @@
|
||||
<div class="column">
|
||||
<span>Verbrauch</span>
|
||||
<input
|
||||
name="energieverbrauch_3_heizquelle_2"
|
||||
name="verbrauch_6"
|
||||
type="number"
|
||||
bind:value={ausweis.verbrauch_6}
|
||||
class:linked={abweichung.indexOf(6) > -1}
|
||||
|
||||
@@ -61,7 +61,7 @@ const valid = await validateAccessTokenServer(Astro)
|
||||
Profil
|
||||
</a>
|
||||
) : (
|
||||
<a class="headerButton" href="/login">
|
||||
<a class="headerButton" href="/auth/login">
|
||||
Login
|
||||
</a>
|
||||
)
|
||||
|
||||
@@ -76,7 +76,8 @@
|
||||
{/each}
|
||||
{/if}
|
||||
<input
|
||||
type="text"
|
||||
type="number"
|
||||
{name}
|
||||
bind:value={tag}
|
||||
on:keydown={onKeydown}
|
||||
on:focusin={onFocusIn}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<script lang="ts">
|
||||
import type { ZIPInformation } from "src/lib/ZIPInformation";
|
||||
import Label from "./Label.svelte";
|
||||
import { client } from "src/trpc";
|
||||
import type { inferProcedureOutput } from "@trpc/server";
|
||||
import type { AppRouter } from "@ibcornelsen/api";
|
||||
|
||||
export let name: string;
|
||||
export let readonly: boolean = false;
|
||||
@@ -9,21 +11,22 @@
|
||||
|
||||
|
||||
let hideZipDropdown: boolean = true;
|
||||
let zipCodes: ZIPInformation[] = [];
|
||||
let zipCodes: inferProcedureOutput<AppRouter["v1"]["postleitzahlen"]> = [];
|
||||
|
||||
async function fetchZipCodeInformation() {
|
||||
const result = await fetch(`/api/zip?zip=${zip}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"authorization": "Basic " + btoa("user@ib-cornelsen.de:test")
|
||||
if (!zip || (zip.length < 2)) {
|
||||
return
|
||||
}
|
||||
}).then(r => r.json());
|
||||
|
||||
if (result.success === true) {
|
||||
zipCodes = result.data;
|
||||
if (zipCodes.length > 0) {
|
||||
try {
|
||||
const result = await client.v1.postleitzahlen.query({ plz: zip });
|
||||
|
||||
if (result.length > 0) {
|
||||
zipCodes = result;
|
||||
hideZipDropdown = false;
|
||||
}
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,12 +68,12 @@
|
||||
/>
|
||||
|
||||
<div class="absolute top-[calc(100%+4px)] left-0 w-full bg-white py-2 shadow-md rounded-lg" hidden={hideZipDropdown}>
|
||||
{#each zipCodes as {zip: z, city: c}}
|
||||
{#each zipCodes as zipCode}
|
||||
<div class="hover:bg-gray-100 cursor-pointer px-2 py-0.5" tabindex="-1" on:click={() => {
|
||||
zip = z;
|
||||
city = c;
|
||||
zip = zipCode.plz;
|
||||
city = zipCode.stadt;
|
||||
hideZipDropdown = true;
|
||||
}}>{z}, {c}</div>
|
||||
}}>{zipCode.plz}, {zipCode.stadt}</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
68
src/cronjobs/update-dwd-test.ts
Normal file
68
src/cronjobs/update-dwd-test.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import moment from "moment";
|
||||
import csv from "csvtojson";
|
||||
import * as fs from "fs";
|
||||
|
||||
const start = moment().set("year", 2019).set("month", 8).set("date", 1);
|
||||
|
||||
const end = moment().set("year", 2022).set("month", 10).set("date", 1);
|
||||
|
||||
let current = start.clone();
|
||||
|
||||
do {
|
||||
const lastYearString = current.clone().startOf("month").format("YYYYMMDD");
|
||||
const nextYearString = current
|
||||
.clone()
|
||||
.subtract(1, "month")
|
||||
.add(1, "year")
|
||||
.endOf("month")
|
||||
.format("YYYYMMDD");
|
||||
|
||||
const filename = `KF_${lastYearString}_${nextYearString}.csv`;
|
||||
|
||||
const url =
|
||||
"https://opendata.dwd.de/climate_environment/CDC/derived_germany/techn/monthly/climate_correction_factor/recent/";
|
||||
|
||||
const response = await fetch(`${url}${filename}`);
|
||||
|
||||
if (response.status !== 200) {
|
||||
console.error(`Could not fetch ${url}${filename}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const parser = csv({
|
||||
noheader: false,
|
||||
output: "json",
|
||||
delimiter: ";",
|
||||
});
|
||||
|
||||
const data: {
|
||||
DatAnf: string;
|
||||
DatEnd: string;
|
||||
PLZ: string;
|
||||
KF: string;
|
||||
}[] = await parser.fromString(await response.text());
|
||||
|
||||
const year = current.year();
|
||||
const month = current.month();
|
||||
|
||||
const json = JSON.parse(fs.readFileSync("./test.json", "utf-8"));
|
||||
|
||||
fs.writeFileSync(
|
||||
"./test.json",
|
||||
JSON.stringify(
|
||||
[
|
||||
...json,
|
||||
...data.map((row) => [
|
||||
year,
|
||||
month,
|
||||
parseFloat(row.KF),
|
||||
row.PLZ,
|
||||
]),
|
||||
],
|
||||
null,
|
||||
2
|
||||
)
|
||||
);
|
||||
|
||||
console.log(`Wrote ${year}-${month} to file.`);
|
||||
} while (current.add(1, "month").isBefore(end));
|
||||
@@ -28,6 +28,9 @@
|
||||
ausweisart: Enums.Ausweisart.VerbrauchsausweisWohnen
|
||||
} as VerbrauchsausweisWohnen;
|
||||
|
||||
console.log(Enums);
|
||||
|
||||
|
||||
async function ausweisSpeichern() {
|
||||
// Um einen Ausweis zu speichern müssen wir eingeloggt sein, andernfalls wird die API den call ablehnen.
|
||||
// Wir prüfen also ob wir eingeloggt sind und leiten den Nutzer ggf. auf die Login Seite weiter.
|
||||
@@ -207,7 +210,7 @@
|
||||
<ZipSearch
|
||||
bind:zip={gebaeude.plz}
|
||||
bind:city={gebaeude.ort}
|
||||
name="zip"
|
||||
name="plz"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -251,14 +254,14 @@
|
||||
<Label>Keller *</Label>
|
||||
<div>
|
||||
<select
|
||||
name="keller_beheizt"
|
||||
name="keller"
|
||||
required
|
||||
bind:value={ausweis.keller_beheizt}
|
||||
bind:value={gebaeude.keller}
|
||||
>
|
||||
<option>Bitte auswählen</option>
|
||||
<option value={false}>nicht vorhanden</option>
|
||||
<option value={false}>unbeheizt</option>
|
||||
<option value={true}>beheizt</option>
|
||||
<option disabled>Bitte auswählen</option>
|
||||
<option value={Enums.Heizungsstatus.NICHT_VORHANDEN}>nicht vorhanden</option>
|
||||
<option value={Enums.Heizungsstatus.UNBEHEIZT}>unbeheizt</option>
|
||||
<option value={Enums.Heizungsstatus.BEHEIZT}>beheizt</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -267,11 +270,11 @@
|
||||
<div class="form-group col-md-4">
|
||||
<Label>Dachgeschoss *</Label>
|
||||
<div>
|
||||
<select name="dachgeschoss" required>
|
||||
<option>Bitte auswählen</option>
|
||||
<option value="dnein">nicht vorhanden</option>
|
||||
<option value="dub">unbeheizt</option>
|
||||
<option value="dbh">beheizt</option>
|
||||
<select name="dachgeschoss" bind:value={gebaeude.dachgeschoss} required>
|
||||
<option disabled>Bitte auswählen</option>
|
||||
<option value={Enums.Heizungsstatus.NICHT_VORHANDEN}>nicht vorhanden</option>
|
||||
<option value={Enums.Heizungsstatus.UNBEHEIZT}>unbeheizt</option>
|
||||
<option value={Enums.Heizungsstatus.BEHEIZT}>beheizt</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
|
||||
export let redirect: string | null = null;
|
||||
|
||||
async function login() {
|
||||
async function login(e: SubmitEvent) {
|
||||
e.preventDefault()
|
||||
const response = await loginClient(email, passwort)
|
||||
|
||||
if (response === null) {
|
||||
@@ -31,7 +32,7 @@
|
||||
|
||||
<div style="width:50%;margin: 0 auto">
|
||||
<h1>Login</h1>
|
||||
<div class="flex flex-col gap-4">
|
||||
<form class="flex flex-col gap-4" on:submit={login}>
|
||||
<div>
|
||||
<h4>Email</h4>
|
||||
<input
|
||||
@@ -49,15 +50,15 @@
|
||||
class="px-2.5 py-1.5 rounded-lg border bg-gray-50"
|
||||
type="password"
|
||||
placeholder="********"
|
||||
name="password"
|
||||
name="passwort"
|
||||
bind:value={passwort}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<button class="button" on:click={login}>Einloggen</button>
|
||||
<button type="submit" >Einloggen</button>
|
||||
<div class="flex-row justify-between" style="margin-top: 10px">
|
||||
<a href="/signup?redirect={redirect}">Registrieren</a>
|
||||
<a href="/auth/signup?redirect={redirect}">Registrieren</a>
|
||||
<a href="/user/passwort_vergessen?redirect={redirect}">Passwort Vergessen?</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
|
||||
export let redirect: string | null = null;
|
||||
|
||||
async function login() {
|
||||
async function login(e: SubmitEvent) {
|
||||
e.preventDefault()
|
||||
try {
|
||||
const response = await client.v1.benutzer.erstellen.mutate({
|
||||
email,
|
||||
@@ -23,7 +24,7 @@
|
||||
return
|
||||
}
|
||||
|
||||
window.location.href = "/login";
|
||||
window.location.href = "/auth/login";
|
||||
} catch (e) {
|
||||
addNotification({
|
||||
message: "Ups...",
|
||||
@@ -38,13 +39,14 @@
|
||||
|
||||
<div style="width:50%;margin: 0 auto">
|
||||
<h1>Registrieren:</h1>
|
||||
<div class="flex flex-col gap-4">
|
||||
<form class="flex flex-col gap-4" on:submit={login}>
|
||||
<div class="flex flex-row gap-4 w-full">
|
||||
<div class="w-1/2">
|
||||
<h4>Vorname</h4>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Vorname"
|
||||
name="vorname"
|
||||
class="px-2.5 py-1.5 rounded-lg border bg-gray-50"
|
||||
bind:value={vorname}
|
||||
required
|
||||
@@ -55,6 +57,7 @@
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Nachname"
|
||||
name="name"
|
||||
class="px-2.5 py-1.5 rounded-lg border bg-gray-50"
|
||||
bind:value={name}
|
||||
required
|
||||
@@ -66,6 +69,7 @@
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Email"
|
||||
name="email"
|
||||
class="px-2.5 py-1.5 rounded-lg border bg-gray-50"
|
||||
bind:value={email}
|
||||
required
|
||||
@@ -76,19 +80,20 @@
|
||||
<input
|
||||
type="password"
|
||||
placeholder="********"
|
||||
name="passwort"
|
||||
class="px-2.5 py-1.5 rounded-lg border bg-gray-50"
|
||||
bind:value={passwort}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<button class="button" on:click={login}
|
||||
<button type="submit" class="button"
|
||||
>Registrieren</button
|
||||
>
|
||||
<div class="flex-row justify-between" style="margin-top: 10px">
|
||||
<a
|
||||
href="/login?redirect={redirect}">Einloggen</a
|
||||
href="/auth/login?redirect={redirect}">Einloggen</a
|
||||
>
|
||||
<a href="/user/passwort_vergessen?redirect={redirect}">Passwort Vergessen?</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -156,8 +156,7 @@
|
||||
</HelpLabel>
|
||||
<div>
|
||||
<input
|
||||
name="IGort"
|
||||
|
||||
name="ort"
|
||||
readonly={true}
|
||||
bind:value={gebaeude.ort}
|
||||
type="text"
|
||||
@@ -174,7 +173,7 @@
|
||||
</HelpLabel>
|
||||
<div>
|
||||
<input
|
||||
name="IGflaeche"
|
||||
name="flaeche"
|
||||
maxlength="4"
|
||||
type="number"
|
||||
required
|
||||
@@ -191,14 +190,14 @@
|
||||
<Label>Keller *</Label>
|
||||
<div>
|
||||
<select
|
||||
name="IGkeller"
|
||||
name="keller"
|
||||
required
|
||||
bind:value={gebaeude.keller}
|
||||
>
|
||||
<option>Bitte auswählen</option>
|
||||
<option value={false}>nicht vorhanden</option>
|
||||
<option value={false}>unbeheizt</option>
|
||||
<option value={true}>beheizt</option>
|
||||
<option value={Enums.Heizungsstatus.NICHT_VORHANDEN}>nicht vorhanden</option>
|
||||
<option value={Enums.Heizungsstatus.UNBEHEIZT}>unbeheizt</option>
|
||||
<option value={Enums.Heizungsstatus.BEHEIZT}>beheizt</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -207,11 +206,11 @@
|
||||
<div class="form-group col-md-4">
|
||||
<Label>Dachgeschoss *</Label>
|
||||
<div>
|
||||
<select name="IGdach" class="" required>
|
||||
<select name="dachgeschoss" required>
|
||||
<option>Bitte auswählen</option>
|
||||
<option value="dnein">nicht vorhanden</option>
|
||||
<option value="dub">unbeheizt</option>
|
||||
<option value="dbh">beheizt</option>
|
||||
<option value={Enums.Heizungsstatus.NICHT_VORHANDEN}>nicht vorhanden</option>
|
||||
<option value={Enums.Heizungsstatus.UNBEHEIZT}>unbeheizt</option>
|
||||
<option value={Enums.Heizungsstatus.BEHEIZT}>beheizt</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import LoginModule from "../modules/LoginModule.svelte";
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
import LoginModule from "../../modules/LoginModule.svelte";
|
||||
import Layout from "../../layouts/Layout.astro";
|
||||
import { validateAccessTokenServer } from "src/server/lib/validateAccessToken";
|
||||
|
||||
const valid = await validateAccessTokenServer(Astro)
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import RegisterModule from "../modules/RegisterModule.svelte";
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
import RegisterModule from "../../modules/RegisterModule.svelte";
|
||||
import Layout from "../../layouts/Layout.astro";
|
||||
|
||||
const redirect = Astro.url.searchParams.get("redirect");
|
||||
---
|
||||
Reference in New Issue
Block a user