first praktikum variant

This commit is contained in:
titver968
2025-04-16 08:47:54 +02:00
parent d2857684fe
commit 10c443285d
58 changed files with 16193 additions and 0 deletions

23
.gitignore vendored Normal file
View File

@@ -0,0 +1,23 @@
node_modules
# Output
.output
.vercel
.netlify
.wrangler
/.svelte-kit
/build
# OS
.DS_Store
Thumbs.db
# Env
.env
.env.*
!.env.example
!.env.test
# Vite
vite.config.js.timestamp-*
vite.config.ts.timestamp-*

1
.npmrc Normal file
View File

@@ -0,0 +1 @@
engine-strict=true

6
.prettierignore Normal file
View File

@@ -0,0 +1,6 @@
# Package Managers
package-lock.json
pnpm-lock.yaml
yarn.lock
bun.lock
bun.lockb

15
.prettierrc Normal file
View File

@@ -0,0 +1,15 @@
{
"useTabs": true,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100,
"plugins": ["prettier-plugin-svelte"],
"overrides": [
{
"files": "*.svelte",
"options": {
"parser": "svelte"
}
}
]
}

View File

@@ -0,0 +1,38 @@
# sv
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
## Creating a project
If you're seeing this, you've probably already done this step. Congrats!
```bash
# create a new project in the current directory
npx sv create
# create a new project in my-app
npx sv create my-app
```
## Developing
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
```bash
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
```
## Building
To create a production version of your app:
```bash
npm run build
```
You can preview the production build with `npm run preview`.
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.

38
data/anmeldungen.json Normal file
View File

@@ -0,0 +1,38 @@
[
{
"anrede": "Herr",
"vorname": "Max",
"nachname": "Mustermann",
"geburtsdatum": "2005-03-15",
"strasse": "Tannenbergallee",
"hausnummer": "11",
"ort": "Hannover",
"plz": "30163",
"telefon": "0511 9695 1234",
"schulart": "Gymnasium",
"zeitraum": "sofort",
"motivation": "Ich will umbedingt",
"wunsch1": "Bauhof",
"wunsch2": "Rathaus",
"wunsch3": "Bibliothek",
"timestamp": "2025-04-15T12:01:23.224Z"
},
{
"anrede": "Frau",
"vorname": "Maria",
"nachname": "Mann",
"geburtsdatum": "2020-11-22",
"strasse": "Distelkamp",
"hausnummer": "6",
"ort": "Hannover",
"plz": "30459",
"telefon": "0511 2151505",
"schulart": "Berufschule",
"zeitraum": "ab september",
"motivation": "gar keine, meine Eltern zwingen mich das zu tun",
"wunsch1": "Kindergarten",
"wunsch2": "Bauhof",
"wunsch3": "Schule",
"timestamp": "2025-04-15T12:03:41.691Z"
}
]

36
eslint.config.js Normal file
View File

@@ -0,0 +1,36 @@
import prettier from 'eslint-config-prettier';
import js from '@eslint/js';
import { includeIgnoreFile } from '@eslint/compat';
import svelte from 'eslint-plugin-svelte';
import globals from 'globals';
import { fileURLToPath } from 'node:url';
import ts from 'typescript-eslint';
import svelteConfig from './svelte.config.js';
const gitignorePath = fileURLToPath(new URL('./.gitignore', import.meta.url));
export default ts.config(
includeIgnoreFile(gitignorePath),
js.configs.recommended,
...ts.configs.recommended,
...svelte.configs.recommended,
prettier,
...svelte.configs.prettier,
{
languageOptions: {
globals: { ...globals.browser, ...globals.node }
},
rules: { 'no-undef': 'off' }
},
{
files: ['**/*.svelte', '**/*.svelte.ts', '**/*.svelte.js'],
languageOptions: {
parserOptions: {
projectService: true,
extraFileExtensions: ['.svelte'],
parser: ts.parser,
svelteConfig
}
}
}
);

5203
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

43
package.json Normal file
View File

@@ -0,0 +1,43 @@
{
"name": "praktikum",
"private": true,
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"prepare": "svelte-kit sync || echo ''",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"format": "prettier --write .",
"lint": "prettier --check . && eslint ."
},
"devDependencies": {
"@eslint/compat": "^1.2.5",
"@eslint/js": "^9.18.0",
"@sveltejs/adapter-auto": "^4.0.0",
"@sveltejs/kit": "^2.16.0",
"@sveltejs/vite-plugin-svelte": "^5.0.0",
"@tailwindcss/postcss": "^4.1.4",
"autoprefixer": "^10.4.21",
"eslint": "^9.18.0",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-svelte": "^3.0.0",
"globals": "^16.0.0",
"postcss": "^8.5.3",
"prettier": "^3.4.2",
"prettier-plugin-svelte": "^3.3.3",
"prisma": "^6.6.0",
"svelte": "^5.0.0",
"svelte-check": "^4.0.0",
"tailwindcss": "^3.4.17",
"typescript": "^5.0.0",
"typescript-eslint": "^8.20.0",
"vite": "^6.2.6",
"vite-plugin": "^0.0.0"
},
"dependencies": {
"@prisma/client": "^6.6.0"
}
}

6
postcss.config.cjs Normal file
View File

@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {}
}
};

6
postcss.config.js Normal file
View File

@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
}
}

BIN
prisma/dev.db Normal file

Binary file not shown.

BIN
prisma/dev.db-journal Normal file

Binary file not shown.

View File

@@ -0,0 +1,21 @@
-- CreateTable
CREATE TABLE "Anmeldung" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"anrede" TEXT NOT NULL,
"vorname" TEXT NOT NULL,
"nachname" TEXT NOT NULL,
"geburtsdatum" TEXT NOT NULL,
"strasse" TEXT NOT NULL,
"hausnummer" TEXT NOT NULL,
"ort" TEXT NOT NULL,
"plz" TEXT NOT NULL,
"telefon" TEXT NOT NULL,
"email" TEXT NOT NULL,
"schulart" TEXT NOT NULL,
"zeitraum" TEXT NOT NULL,
"motivation" TEXT NOT NULL,
"wunsch1" TEXT NOT NULL,
"wunsch2" TEXT NOT NULL,
"wunsch3" TEXT NOT NULL,
"timestamp" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);

View File

@@ -0,0 +1,8 @@
/*
Warnings:
- A unique constraint covering the columns `[email]` on the table `Anmeldung` will be added. If there are existing duplicate values, this will fail.
*/
-- CreateIndex
CREATE UNIQUE INDEX "Anmeldung_email_key" ON "Anmeldung"("email");

View File

@@ -0,0 +1,52 @@
/*
Warnings:
- You are about to drop the column `wunsch1` on the `Anmeldung` table. All the data in the column will be lost.
- You are about to drop the column `wunsch2` on the `Anmeldung` table. All the data in the column will be lost.
- You are about to drop the column `wunsch3` on the `Anmeldung` table. All the data in the column will be lost.
- Added the required column `wunsch1Id` to the `Anmeldung` table without a default value. This is not possible if the table is not empty.
- Added the required column `wunsch2Id` to the `Anmeldung` table without a default value. This is not possible if the table is not empty.
- Added the required column `wunsch3Id` to the `Anmeldung` table without a default value. This is not possible if the table is not empty.
*/
-- CreateTable
CREATE TABLE "Dienststelle" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" TEXT NOT NULL
);
-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_Anmeldung" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"anrede" TEXT NOT NULL,
"vorname" TEXT NOT NULL,
"nachname" TEXT NOT NULL,
"geburtsdatum" TEXT NOT NULL,
"strasse" TEXT NOT NULL,
"hausnummer" TEXT NOT NULL,
"ort" TEXT NOT NULL,
"plz" TEXT NOT NULL,
"telefon" TEXT NOT NULL,
"email" TEXT NOT NULL,
"schulart" TEXT NOT NULL,
"zeitraum" TEXT NOT NULL,
"motivation" TEXT NOT NULL,
"wunsch1Id" INTEGER NOT NULL,
"wunsch2Id" INTEGER NOT NULL,
"wunsch3Id" INTEGER NOT NULL,
"timestamp" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "Anmeldung_wunsch1Id_fkey" FOREIGN KEY ("wunsch1Id") REFERENCES "Dienststelle" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "Anmeldung_wunsch2Id_fkey" FOREIGN KEY ("wunsch2Id") REFERENCES "Dienststelle" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "Anmeldung_wunsch3Id_fkey" FOREIGN KEY ("wunsch3Id") REFERENCES "Dienststelle" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_Anmeldung" ("anrede", "email", "geburtsdatum", "hausnummer", "id", "motivation", "nachname", "ort", "plz", "schulart", "strasse", "telefon", "timestamp", "vorname", "zeitraum") SELECT "anrede", "email", "geburtsdatum", "hausnummer", "id", "motivation", "nachname", "ort", "plz", "schulart", "strasse", "telefon", "timestamp", "vorname", "zeitraum" FROM "Anmeldung";
DROP TABLE "Anmeldung";
ALTER TABLE "new_Anmeldung" RENAME TO "Anmeldung";
CREATE UNIQUE INDEX "Anmeldung_email_key" ON "Anmeldung"("email");
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;
-- CreateIndex
CREATE UNIQUE INDEX "Dienststelle_name_key" ON "Dienststelle"("name");

View File

@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (e.g., Git)
provider = "sqlite"

BIN
prisma/praktika.db Normal file

Binary file not shown.

44
prisma/schema.prisma Normal file
View File

@@ -0,0 +1,44 @@
generator client {
provider = "prisma-client-js"
output = "../src/generated/client"
}
datasource db {
provider = "sqlite"
url = "file:./praktika.db"
}
model Dienststelle {
id Int @id @default(autoincrement())
name String @unique
anmeldungenWunsch1 Anmeldung[] @relation("Wunsch1")
anmeldungenWunsch2 Anmeldung[] @relation("Wunsch2")
anmeldungenWunsch3 Anmeldung[] @relation("Wunsch3")
}
model Anmeldung {
id Int @id @default(autoincrement())
anrede String
vorname String
nachname String
geburtsdatum String
strasse String
hausnummer String
ort String
plz String
telefon String
email String @unique
schulart String
zeitraum String
motivation String
wunsch1Id Int
wunsch2Id Int
wunsch3Id Int
wunsch1 Dienststelle @relation("Wunsch1", fields: [wunsch1Id], references: [id])
wunsch2 Dienststelle @relation("Wunsch2", fields: [wunsch2Id], references: [id])
wunsch3 Dienststelle @relation("Wunsch3", fields: [wunsch3Id], references: [id])
timestamp DateTime @default(now())
}

4
src/app.css Normal file
View File

@@ -0,0 +1,4 @@
/* src/app.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

13
src/app.d.ts vendored Normal file
View File

@@ -0,0 +1,13 @@
// See https://svelte.dev/docs/kit/types#app.d.ts
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface PageState {}
// interface Platform {}
}
}
export {};

12
src/app.html Normal file
View File

@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>

1
src/generated/client/client.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
export * from "./index"

View File

@@ -0,0 +1 @@
module.exports = { ...require('.') }

1
src/generated/client/default.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
export * from "./index"

View File

@@ -0,0 +1 @@
module.exports = { ...require('.') }

1
src/generated/client/edge.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
export * from "./default"

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,183 @@
Object.defineProperty(exports, "__esModule", { value: true });
const {
Decimal,
objectEnumValues,
makeStrictEnum,
Public,
getRuntime,
skip
} = require('./runtime/index-browser.js')
const Prisma = {}
exports.Prisma = Prisma
exports.$Enums = {}
/**
* Prisma Client JS version: 6.6.0
* Query Engine version: f676762280b54cd07c770017ed3711ddde35f37a
*/
Prisma.prismaVersion = {
client: "6.6.0",
engine: "f676762280b54cd07c770017ed3711ddde35f37a"
}
Prisma.PrismaClientKnownRequestError = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`PrismaClientKnownRequestError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)};
Prisma.PrismaClientUnknownRequestError = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`PrismaClientUnknownRequestError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.PrismaClientRustPanicError = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`PrismaClientRustPanicError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.PrismaClientInitializationError = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`PrismaClientInitializationError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.PrismaClientValidationError = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`PrismaClientValidationError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.Decimal = Decimal
/**
* Re-export of sql-template-tag
*/
Prisma.sql = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`sqltag is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.empty = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`empty is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.join = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`join is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.raw = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`raw is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.validator = Public.validator
/**
* Extensions
*/
Prisma.getExtensionContext = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`Extensions.getExtensionContext is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.defineExtension = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`Extensions.defineExtension is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
/**
* Shorthand utilities for JSON filtering
*/
Prisma.DbNull = objectEnumValues.instances.DbNull
Prisma.JsonNull = objectEnumValues.instances.JsonNull
Prisma.AnyNull = objectEnumValues.instances.AnyNull
Prisma.NullTypes = {
DbNull: objectEnumValues.classes.DbNull,
JsonNull: objectEnumValues.classes.JsonNull,
AnyNull: objectEnumValues.classes.AnyNull
}
/**
* Enums
*/
exports.Prisma.TransactionIsolationLevel = makeStrictEnum({
Serializable: 'Serializable'
});
exports.Prisma.DienststelleScalarFieldEnum = {
id: 'id',
name: 'name'
};
exports.Prisma.AnmeldungScalarFieldEnum = {
id: 'id',
anrede: 'anrede',
vorname: 'vorname',
nachname: 'nachname',
geburtsdatum: 'geburtsdatum',
strasse: 'strasse',
hausnummer: 'hausnummer',
ort: 'ort',
plz: 'plz',
telefon: 'telefon',
email: 'email',
schulart: 'schulart',
zeitraum: 'zeitraum',
motivation: 'motivation',
wunsch1Id: 'wunsch1Id',
wunsch2Id: 'wunsch2Id',
wunsch3Id: 'wunsch3Id',
timestamp: 'timestamp'
};
exports.Prisma.SortOrder = {
asc: 'asc',
desc: 'desc'
};
exports.Prisma.ModelName = {
Dienststelle: 'Dienststelle',
Anmeldung: 'Anmeldung'
};
/**
* This is a stub Prisma Client that will error at runtime if called.
*/
class PrismaClient {
constructor() {
return new Proxy(this, {
get(target, prop) {
let message
const runtime = getRuntime()
if (runtime.isEdge) {
message = `PrismaClient is not configured to run in ${runtime.prettyName}. In order to run Prisma Client on edge runtime, either:
- Use Prisma Accelerate: https://pris.ly/d/accelerate
- Use Driver Adapters: https://pris.ly/d/driver-adapters
`;
} else {
message = 'PrismaClient is unable to run in this browser environment, or has been bundled for the browser (running in `' + runtime.prettyName + '`).'
}
message += `
If this is unexpected, please open an issue: https://pris.ly/prisma-prisma-bug-report`
throw new Error(message)
}
})
}
}
exports.PrismaClient = PrismaClient
Object.assign(exports, Prisma)

4934
src/generated/client/index.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -0,0 +1,140 @@
{
"name": "prisma-client-adf7b99ed2cd8cd2cee0d44889b4e30f60c1f125fa75af990eead4656fa74274",
"main": "index.js",
"types": "index.d.ts",
"browser": "index-browser.js",
"exports": {
"./client": {
"require": {
"node": "./index.js",
"edge-light": "./wasm.js",
"workerd": "./wasm.js",
"worker": "./wasm.js",
"browser": "./index-browser.js",
"default": "./index.js"
},
"import": {
"node": "./index.js",
"edge-light": "./wasm.js",
"workerd": "./wasm.js",
"worker": "./wasm.js",
"browser": "./index-browser.js",
"default": "./index.js"
},
"default": "./index.js"
},
"./package.json": "./package.json",
".": {
"require": {
"node": "./index.js",
"edge-light": "./wasm.js",
"workerd": "./wasm.js",
"worker": "./wasm.js",
"browser": "./index-browser.js",
"default": "./index.js"
},
"import": {
"node": "./index.js",
"edge-light": "./wasm.js",
"workerd": "./wasm.js",
"worker": "./wasm.js",
"browser": "./index-browser.js",
"default": "./index.js"
},
"default": "./index.js"
},
"./edge": {
"types": "./edge.d.ts",
"require": "./edge.js",
"import": "./edge.js",
"default": "./edge.js"
},
"./react-native": {
"types": "./react-native.d.ts",
"require": "./react-native.js",
"import": "./react-native.js",
"default": "./react-native.js"
},
"./extension": {
"types": "./extension.d.ts",
"require": "./extension.js",
"import": "./extension.js",
"default": "./extension.js"
},
"./index-browser": {
"types": "./index.d.ts",
"require": "./index-browser.js",
"import": "./index-browser.js",
"default": "./index-browser.js"
},
"./index": {
"types": "./index.d.ts",
"require": "./index.js",
"import": "./index.js",
"default": "./index.js"
},
"./wasm": {
"types": "./wasm.d.ts",
"require": "./wasm.js",
"import": "./wasm.mjs",
"default": "./wasm.mjs"
},
"./runtime/client": {
"types": "./runtime/client.d.ts",
"require": "./runtime/client.js",
"import": "./runtime/client.mjs",
"default": "./runtime/client.mjs"
},
"./runtime/library": {
"types": "./runtime/library.d.ts",
"require": "./runtime/library.js",
"import": "./runtime/library.mjs",
"default": "./runtime/library.mjs"
},
"./runtime/binary": {
"types": "./runtime/binary.d.ts",
"require": "./runtime/binary.js",
"import": "./runtime/binary.mjs",
"default": "./runtime/binary.mjs"
},
"./runtime/wasm": {
"types": "./runtime/wasm.d.ts",
"require": "./runtime/wasm.js",
"import": "./runtime/wasm.mjs",
"default": "./runtime/wasm.mjs"
},
"./runtime/edge": {
"types": "./runtime/edge.d.ts",
"require": "./runtime/edge.js",
"import": "./runtime/edge-esm.js",
"default": "./runtime/edge-esm.js"
},
"./runtime/react-native": {
"types": "./runtime/react-native.d.ts",
"require": "./runtime/react-native.js",
"import": "./runtime/react-native.js",
"default": "./runtime/react-native.js"
},
"./generator-build": {
"require": "./generator-build/index.js",
"import": "./generator-build/index.js",
"default": "./generator-build/index.js"
},
"./sql": {
"require": {
"types": "./sql.d.ts",
"node": "./sql.js",
"default": "./sql.js"
},
"import": {
"types": "./sql.d.ts",
"node": "./sql.mjs",
"default": "./sql.mjs"
},
"default": "./sql.js"
},
"./*": "./*"
},
"version": "6.6.0",
"sideEffects": false
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,370 @@
declare class AnyNull extends NullTypesEnumValue {
private readonly _brand_AnyNull;
}
declare type Args<T, F extends Operation> = T extends {
[K: symbol]: {
types: {
operations: {
[K in F]: {
args: any;
};
};
};
};
} ? T[symbol]['types']['operations'][F]['args'] : any;
declare class DbNull extends NullTypesEnumValue {
private readonly _brand_DbNull;
}
export declare function Decimal(n: Decimal.Value): Decimal;
export declare namespace Decimal {
export type Constructor = typeof Decimal;
export type Instance = Decimal;
export type Rounding = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
export type Modulo = Rounding | 9;
export type Value = string | number | Decimal;
// http://mikemcl.github.io/decimal.js/#constructor-properties
export interface Config {
precision?: number;
rounding?: Rounding;
toExpNeg?: number;
toExpPos?: number;
minE?: number;
maxE?: number;
crypto?: boolean;
modulo?: Modulo;
defaults?: boolean;
}
}
export declare class Decimal {
readonly d: number[];
readonly e: number;
readonly s: number;
constructor(n: Decimal.Value);
absoluteValue(): Decimal;
abs(): Decimal;
ceil(): Decimal;
clampedTo(min: Decimal.Value, max: Decimal.Value): Decimal;
clamp(min: Decimal.Value, max: Decimal.Value): Decimal;
comparedTo(n: Decimal.Value): number;
cmp(n: Decimal.Value): number;
cosine(): Decimal;
cos(): Decimal;
cubeRoot(): Decimal;
cbrt(): Decimal;
decimalPlaces(): number;
dp(): number;
dividedBy(n: Decimal.Value): Decimal;
div(n: Decimal.Value): Decimal;
dividedToIntegerBy(n: Decimal.Value): Decimal;
divToInt(n: Decimal.Value): Decimal;
equals(n: Decimal.Value): boolean;
eq(n: Decimal.Value): boolean;
floor(): Decimal;
greaterThan(n: Decimal.Value): boolean;
gt(n: Decimal.Value): boolean;
greaterThanOrEqualTo(n: Decimal.Value): boolean;
gte(n: Decimal.Value): boolean;
hyperbolicCosine(): Decimal;
cosh(): Decimal;
hyperbolicSine(): Decimal;
sinh(): Decimal;
hyperbolicTangent(): Decimal;
tanh(): Decimal;
inverseCosine(): Decimal;
acos(): Decimal;
inverseHyperbolicCosine(): Decimal;
acosh(): Decimal;
inverseHyperbolicSine(): Decimal;
asinh(): Decimal;
inverseHyperbolicTangent(): Decimal;
atanh(): Decimal;
inverseSine(): Decimal;
asin(): Decimal;
inverseTangent(): Decimal;
atan(): Decimal;
isFinite(): boolean;
isInteger(): boolean;
isInt(): boolean;
isNaN(): boolean;
isNegative(): boolean;
isNeg(): boolean;
isPositive(): boolean;
isPos(): boolean;
isZero(): boolean;
lessThan(n: Decimal.Value): boolean;
lt(n: Decimal.Value): boolean;
lessThanOrEqualTo(n: Decimal.Value): boolean;
lte(n: Decimal.Value): boolean;
logarithm(n?: Decimal.Value): Decimal;
log(n?: Decimal.Value): Decimal;
minus(n: Decimal.Value): Decimal;
sub(n: Decimal.Value): Decimal;
modulo(n: Decimal.Value): Decimal;
mod(n: Decimal.Value): Decimal;
naturalExponential(): Decimal;
exp(): Decimal;
naturalLogarithm(): Decimal;
ln(): Decimal;
negated(): Decimal;
neg(): Decimal;
plus(n: Decimal.Value): Decimal;
add(n: Decimal.Value): Decimal;
precision(includeZeros?: boolean): number;
sd(includeZeros?: boolean): number;
round(): Decimal;
sine() : Decimal;
sin() : Decimal;
squareRoot(): Decimal;
sqrt(): Decimal;
tangent() : Decimal;
tan() : Decimal;
times(n: Decimal.Value): Decimal;
mul(n: Decimal.Value) : Decimal;
toBinary(significantDigits?: number): string;
toBinary(significantDigits: number, rounding: Decimal.Rounding): string;
toDecimalPlaces(decimalPlaces?: number): Decimal;
toDecimalPlaces(decimalPlaces: number, rounding: Decimal.Rounding): Decimal;
toDP(decimalPlaces?: number): Decimal;
toDP(decimalPlaces: number, rounding: Decimal.Rounding): Decimal;
toExponential(decimalPlaces?: number): string;
toExponential(decimalPlaces: number, rounding: Decimal.Rounding): string;
toFixed(decimalPlaces?: number): string;
toFixed(decimalPlaces: number, rounding: Decimal.Rounding): string;
toFraction(max_denominator?: Decimal.Value): Decimal[];
toHexadecimal(significantDigits?: number): string;
toHexadecimal(significantDigits: number, rounding: Decimal.Rounding): string;
toHex(significantDigits?: number): string;
toHex(significantDigits: number, rounding?: Decimal.Rounding): string;
toJSON(): string;
toNearest(n: Decimal.Value, rounding?: Decimal.Rounding): Decimal;
toNumber(): number;
toOctal(significantDigits?: number): string;
toOctal(significantDigits: number, rounding: Decimal.Rounding): string;
toPower(n: Decimal.Value): Decimal;
pow(n: Decimal.Value): Decimal;
toPrecision(significantDigits?: number): string;
toPrecision(significantDigits: number, rounding: Decimal.Rounding): string;
toSignificantDigits(significantDigits?: number): Decimal;
toSignificantDigits(significantDigits: number, rounding: Decimal.Rounding): Decimal;
toSD(significantDigits?: number): Decimal;
toSD(significantDigits: number, rounding: Decimal.Rounding): Decimal;
toString(): string;
truncated(): Decimal;
trunc(): Decimal;
valueOf(): string;
static abs(n: Decimal.Value): Decimal;
static acos(n: Decimal.Value): Decimal;
static acosh(n: Decimal.Value): Decimal;
static add(x: Decimal.Value, y: Decimal.Value): Decimal;
static asin(n: Decimal.Value): Decimal;
static asinh(n: Decimal.Value): Decimal;
static atan(n: Decimal.Value): Decimal;
static atanh(n: Decimal.Value): Decimal;
static atan2(y: Decimal.Value, x: Decimal.Value): Decimal;
static cbrt(n: Decimal.Value): Decimal;
static ceil(n: Decimal.Value): Decimal;
static clamp(n: Decimal.Value, min: Decimal.Value, max: Decimal.Value): Decimal;
static clone(object?: Decimal.Config): Decimal.Constructor;
static config(object: Decimal.Config): Decimal.Constructor;
static cos(n: Decimal.Value): Decimal;
static cosh(n: Decimal.Value): Decimal;
static div(x: Decimal.Value, y: Decimal.Value): Decimal;
static exp(n: Decimal.Value): Decimal;
static floor(n: Decimal.Value): Decimal;
static hypot(...n: Decimal.Value[]): Decimal;
static isDecimal(object: any): object is Decimal;
static ln(n: Decimal.Value): Decimal;
static log(n: Decimal.Value, base?: Decimal.Value): Decimal;
static log2(n: Decimal.Value): Decimal;
static log10(n: Decimal.Value): Decimal;
static max(...n: Decimal.Value[]): Decimal;
static min(...n: Decimal.Value[]): Decimal;
static mod(x: Decimal.Value, y: Decimal.Value): Decimal;
static mul(x: Decimal.Value, y: Decimal.Value): Decimal;
static noConflict(): Decimal.Constructor; // Browser only
static pow(base: Decimal.Value, exponent: Decimal.Value): Decimal;
static random(significantDigits?: number): Decimal;
static round(n: Decimal.Value): Decimal;
static set(object: Decimal.Config): Decimal.Constructor;
static sign(n: Decimal.Value): number;
static sin(n: Decimal.Value): Decimal;
static sinh(n: Decimal.Value): Decimal;
static sqrt(n: Decimal.Value): Decimal;
static sub(x: Decimal.Value, y: Decimal.Value): Decimal;
static sum(...n: Decimal.Value[]): Decimal;
static tan(n: Decimal.Value): Decimal;
static tanh(n: Decimal.Value): Decimal;
static trunc(n: Decimal.Value): Decimal;
static readonly default?: Decimal.Constructor;
static readonly Decimal?: Decimal.Constructor;
static readonly precision: number;
static readonly rounding: Decimal.Rounding;
static readonly toExpNeg: number;
static readonly toExpPos: number;
static readonly minE: number;
static readonly maxE: number;
static readonly crypto: boolean;
static readonly modulo: Decimal.Modulo;
static readonly ROUND_UP: 0;
static readonly ROUND_DOWN: 1;
static readonly ROUND_CEIL: 2;
static readonly ROUND_FLOOR: 3;
static readonly ROUND_HALF_UP: 4;
static readonly ROUND_HALF_DOWN: 5;
static readonly ROUND_HALF_EVEN: 6;
static readonly ROUND_HALF_CEIL: 7;
static readonly ROUND_HALF_FLOOR: 8;
static readonly EUCLID: 9;
}
declare type Exact<A, W> = (A extends unknown ? (W extends A ? {
[K in keyof A]: Exact<A[K], W[K]>;
} : W) : never) | (A extends Narrowable ? A : never);
export declare function getRuntime(): GetRuntimeOutput;
declare type GetRuntimeOutput = {
id: RuntimeName;
prettyName: string;
isEdge: boolean;
};
declare class JsonNull extends NullTypesEnumValue {
private readonly _brand_JsonNull;
}
/**
* Generates more strict variant of an enum which, unlike regular enum,
* throws on non-existing property access. This can be useful in following situations:
* - we have an API, that accepts both `undefined` and `SomeEnumType` as an input
* - enum values are generated dynamically from DMMF.
*
* In that case, if using normal enums and no compile-time typechecking, using non-existing property
* will result in `undefined` value being used, which will be accepted. Using strict enum
* in this case will help to have a runtime exception, telling you that you are probably doing something wrong.
*
* Note: if you need to check for existence of a value in the enum you can still use either
* `in` operator or `hasOwnProperty` function.
*
* @param definition
* @returns
*/
export declare function makeStrictEnum<T extends Record<PropertyKey, string | number>>(definition: T): T;
declare type Narrowable = string | number | bigint | boolean | [];
declare class NullTypesEnumValue extends ObjectEnumValue {
_getNamespace(): string;
}
/**
* Base class for unique values of object-valued enums.
*/
declare abstract class ObjectEnumValue {
constructor(arg?: symbol);
abstract _getNamespace(): string;
_getName(): string;
toString(): string;
}
export declare const objectEnumValues: {
classes: {
DbNull: typeof DbNull;
JsonNull: typeof JsonNull;
AnyNull: typeof AnyNull;
};
instances: {
DbNull: DbNull;
JsonNull: JsonNull;
AnyNull: AnyNull;
};
};
declare type Operation = 'findFirst' | 'findFirstOrThrow' | 'findUnique' | 'findUniqueOrThrow' | 'findMany' | 'create' | 'createMany' | 'createManyAndReturn' | 'update' | 'updateMany' | 'updateManyAndReturn' | 'upsert' | 'delete' | 'deleteMany' | 'aggregate' | 'count' | 'groupBy' | '$queryRaw' | '$executeRaw' | '$queryRawUnsafe' | '$executeRawUnsafe' | 'findRaw' | 'aggregateRaw' | '$runCommandRaw';
declare namespace Public {
export {
validator
}
}
export { Public }
declare type RuntimeName = 'workerd' | 'deno' | 'netlify' | 'node' | 'bun' | 'edge-light' | '';
declare function validator<V>(): <S>(select: Exact<S, V>) => S;
declare function validator<C, M extends Exclude<keyof C, `$${string}`>, O extends keyof C[M] & Operation>(client: C, model: M, operation: O): <S>(select: Exact<S, Args<C[M], O>>) => S;
declare function validator<C, M extends Exclude<keyof C, `$${string}`>, O extends keyof C[M] & Operation, P extends keyof Args<C[M], O>>(client: C, model: M, operation: O, prop: P): <S>(select: Exact<S, Args<C[M], O>[P]>) => S;
export { }

File diff suppressed because one or more lines are too long

3604
src/generated/client/runtime/library.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,44 @@
generator client {
provider = "prisma-client-js"
output = "../src/generated/client"
}
datasource db {
provider = "sqlite"
url = "file:./praktika.db"
}
model Dienststelle {
id Int @id @default(autoincrement())
name String @unique
anmeldungenWunsch1 Anmeldung[] @relation("Wunsch1")
anmeldungenWunsch2 Anmeldung[] @relation("Wunsch2")
anmeldungenWunsch3 Anmeldung[] @relation("Wunsch3")
}
model Anmeldung {
id Int @id @default(autoincrement())
anrede String
vorname String
nachname String
geburtsdatum String
strasse String
hausnummer String
ort String
plz String
telefon String
email String @unique
schulart String
zeitraum String
motivation String
wunsch1Id Int
wunsch2Id Int
wunsch3Id Int
wunsch1 Dienststelle @relation("Wunsch1", fields: [wunsch1Id], references: [id])
wunsch2 Dienststelle @relation("Wunsch2", fields: [wunsch2Id], references: [id])
wunsch3 Dienststelle @relation("Wunsch3", fields: [wunsch3Id], references: [id])
timestamp DateTime @default(now())
}

1
src/generated/client/wasm.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
export * from "./index"

View File

@@ -0,0 +1,183 @@
Object.defineProperty(exports, "__esModule", { value: true });
const {
Decimal,
objectEnumValues,
makeStrictEnum,
Public,
getRuntime,
skip
} = require('./runtime/index-browser.js')
const Prisma = {}
exports.Prisma = Prisma
exports.$Enums = {}
/**
* Prisma Client JS version: 6.6.0
* Query Engine version: f676762280b54cd07c770017ed3711ddde35f37a
*/
Prisma.prismaVersion = {
client: "6.6.0",
engine: "f676762280b54cd07c770017ed3711ddde35f37a"
}
Prisma.PrismaClientKnownRequestError = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`PrismaClientKnownRequestError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)};
Prisma.PrismaClientUnknownRequestError = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`PrismaClientUnknownRequestError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.PrismaClientRustPanicError = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`PrismaClientRustPanicError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.PrismaClientInitializationError = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`PrismaClientInitializationError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.PrismaClientValidationError = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`PrismaClientValidationError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.Decimal = Decimal
/**
* Re-export of sql-template-tag
*/
Prisma.sql = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`sqltag is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.empty = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`empty is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.join = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`join is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.raw = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`raw is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.validator = Public.validator
/**
* Extensions
*/
Prisma.getExtensionContext = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`Extensions.getExtensionContext is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
Prisma.defineExtension = () => {
const runtimeName = getRuntime().prettyName;
throw new Error(`Extensions.defineExtension is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
)}
/**
* Shorthand utilities for JSON filtering
*/
Prisma.DbNull = objectEnumValues.instances.DbNull
Prisma.JsonNull = objectEnumValues.instances.JsonNull
Prisma.AnyNull = objectEnumValues.instances.AnyNull
Prisma.NullTypes = {
DbNull: objectEnumValues.classes.DbNull,
JsonNull: objectEnumValues.classes.JsonNull,
AnyNull: objectEnumValues.classes.AnyNull
}
/**
* Enums
*/
exports.Prisma.TransactionIsolationLevel = makeStrictEnum({
Serializable: 'Serializable'
});
exports.Prisma.DienststelleScalarFieldEnum = {
id: 'id',
name: 'name'
};
exports.Prisma.AnmeldungScalarFieldEnum = {
id: 'id',
anrede: 'anrede',
vorname: 'vorname',
nachname: 'nachname',
geburtsdatum: 'geburtsdatum',
strasse: 'strasse',
hausnummer: 'hausnummer',
ort: 'ort',
plz: 'plz',
telefon: 'telefon',
email: 'email',
schulart: 'schulart',
zeitraum: 'zeitraum',
motivation: 'motivation',
wunsch1Id: 'wunsch1Id',
wunsch2Id: 'wunsch2Id',
wunsch3Id: 'wunsch3Id',
timestamp: 'timestamp'
};
exports.Prisma.SortOrder = {
asc: 'asc',
desc: 'desc'
};
exports.Prisma.ModelName = {
Dienststelle: 'Dienststelle',
Anmeldung: 'Anmeldung'
};
/**
* This is a stub Prisma Client that will error at runtime if called.
*/
class PrismaClient {
constructor() {
return new Proxy(this, {
get(target, prop) {
let message
const runtime = getRuntime()
if (runtime.isEdge) {
message = `PrismaClient is not configured to run in ${runtime.prettyName}. In order to run Prisma Client on edge runtime, either:
- Use Prisma Accelerate: https://pris.ly/d/accelerate
- Use Driver Adapters: https://pris.ly/d/driver-adapters
`;
} else {
message = 'PrismaClient is unable to run in this browser environment, or has been bundled for the browser (running in `' + runtime.prettyName + '`).'
}
message += `
If this is unexpected, please open an issue: https://pris.ly/prisma-prisma-bug-report`
throw new Error(message)
}
})
}
}
exports.PrismaClient = PrismaClient
Object.assign(exports, Prisma)

1
src/lib/index.ts Normal file
View File

@@ -0,0 +1 @@
// place files you want to import through the `$lib` alias in this folder.

View File

@@ -0,0 +1,4 @@
<script lang="ts">
import '../app.css';
</script>
<slot />

120
src/routes/+page.svelte Normal file
View File

@@ -0,0 +1,120 @@
<script lang="ts">
import { onMount } from 'svelte';
let anrede = '';
let vorname = '';
let nachname = '';
let geburtsdatum = '';
let strasse = '';
let hausnummer = '';
let ort = '';
let plz = '';
let telefon = '';
let email = '';
let schulart = '';
let zeitraum = '';
let motivation = '';
let wunsch1Id = '';
let wunsch2Id = '';
let wunsch3Id = '';
let success = false;
let dienststellen = [];
onMount(async () => {
const res = await fetch('/api/admin/dienststellen');
dienststellen = await res.json();
});
async function anmelden() {
const res = await fetch('/api/anmelden', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
anrede, vorname, nachname, geburtsdatum,
strasse, hausnummer, ort, plz,
telefon, email, schulart, zeitraum, motivation,
wunsch1Id, wunsch2Id, wunsch3Id
})
});
const result = await res.json();
success = result.success;
}
</script>
<div class="min-h-screen bg-gray-100 flex items-center justify-center p-6">
<form on:submit|preventDefault={anmelden}
class="bg-white shadow-md rounded-2xl p-8 max-w-2xl w-full space-y-4">
<h1 class="text-2xl font-bold text-gray-800 mb-4 text-center">Praktikumsanmeldung</h1>
<!-- Anrede -->
<select bind:value={anrede} required class="input">
<option value="" disabled selected hidden>Anrede wählen</option>
<option value="Herr">Herr</option>
<option value="Frau">Frau</option>
<option value="Divers">Divers</option>
</select>
<!-- Persönliche Daten -->
<div class="grid grid-cols-2 gap-4">
<input bind:value={vorname} placeholder="Vorname" required class="input" />
<input bind:value={nachname} placeholder="Nachname" required class="input" />
<input bind:value={geburtsdatum} type="date" placeholder="Geburtsdatum" required class="input col-span-2" />
<input bind:value={strasse} placeholder="Straße" required class="input" />
<input bind:value={hausnummer} placeholder="Hausnummer" required class="input" />
<input bind:value={plz} placeholder="Postleitzahl" required class="input" />
<input bind:value={ort} placeholder="Ort" required class="input" />
<input bind:value={telefon} placeholder="Telefonnummer" required class="input col-span-2" />
<input bind:value={email} type="email" placeholder="E-Mail-Adresse" required class="input col-span-2" />
<input bind:value={schulart} placeholder="Schulart" required class="input col-span-2" />
<input bind:value={zeitraum} placeholder="Wunschzeitraum fürs Praktikum" required class="input col-span-2" />
</div>
<!-- Wunschdienststellen -->
<div class="grid grid-cols-1 gap-4">
<select bind:value={wunsch1Id} required>
<option value="" disabled selected>1. Wunschdienststelle</option>
{#each dienststellen as d}
<option value={d.id}>{d.name}</option>
{/each}
</select>
<select bind:value={wunsch2Id} required>
<option value="" disabled selected>2. Wunschdienststelle</option>
{#each dienststellen as d}
<option value={d.id}>{d.name}</option>
{/each}
</select>
<select bind:value={wunsch3Id} required>
<option value="" disabled selected>3. Wunschdienststelle</option>
{#each dienststellen as d}
<option value={d.id}>{d.name}</option>
{/each}
</select>
</div>
<!-- Motivation -->
<textarea bind:value={motivation} placeholder="Motivation (optional)"
class="w-full border border-gray-300 rounded-xl p-3 focus:outline-none focus:ring-2 focus:ring-blue-500 h-32 resize-none" >
</textarea>
<!-- Button -->
<button type="submit"
class="w-full bg-blue-600 text-white py-3 rounded-xl hover:bg-blue-700 transition-all">
Jetzt anmelden
</button>
{#if success}
<p class="text-green-600 font-semibold text-center">Anmeldung erfolgreich gesendet!</p>
{/if}
</form>
</div>
<style>
.input {
@apply w-full border border-gray-300 rounded-xl p-3 focus:outline-none focus:ring-2 focus:ring-blue-500;
}
</style>

View File

@@ -0,0 +1,65 @@
<script lang="ts">
let passwort = '';
let eingeloggt = false;
let fehler = false;
let anmeldungen = [];
async function login() {
const res = await fetch('/api/admin/login', {
method: 'POST',
body: JSON.stringify({ passwort }),
headers: { 'Content-Type': 'application/json' }
});
if (res.ok) {
eingeloggt = true;
fehler = false;
const result = await fetch('/api/admin/anmeldungen');
anmeldungen = await result.json();
} else {
fehler = true;
}
}
</script>
<div class="p-6 max-w-4xl mx-auto">
{#if !eingeloggt}
<div class="space-y-4">
<h1 class="text-2xl font-bold">Admin Login</h1>
<input type="password" bind:value={passwort} placeholder="Passwort" class="input w-full" />
<button on:click={login} class="bg-blue-600 text-white px-4 py-2 rounded">Login</button>
{#if fehler}
<p class="text-red-600">Falsches Passwort</p>
{/if}
</div>
{:else}
<p><a href="/admin/dienststellen" class="text-blue-600 underline">Dienststellen verwalten</a></p>
<h1 class="text-2xl font-bold mb-4">Alle Anmeldungen</h1>
<table class="w-full border text-sm">
<thead>
<tr class="bg-gray-200">
<th class="p-2 text-left">Name</th>
<th class="p-2 text-left">E-Mail</th>
<th class="p-2 text-left">Wunsch 13</th>
<th class="p-2 text-left">Datum</th>
</tr>
</thead>
<tbody>
{#each anmeldungen as a}
<tr class="border-t">
<td class="p-2">{a.anrede} {a.vorname} {a.nachname}</td>
<td class="p-2">{a.email}</td>
<td class="p-2">{a.wunsch1}, {a.wunsch2}, {a.wunsch3}</td>
<td class="p-2">{new Date(a.timestamp).toLocaleDateString()}</td>
</tr>
{/each}
</tbody>
</table>
{/if}
</div>
<style>
.input {
@apply border rounded px-3 py-2 w-full;
}

View File

@@ -0,0 +1,65 @@
<script lang="ts">
import { onMount } from 'svelte';
let dienststellen: { id: number; name: string }[] = [];
let neuerName = '';
let fehlermeldung = '';
async function ladeDienststellen() {
const res = await fetch('/api/admin/dienststellen');
dienststellen = await res.json();
}
async function hinzufuegen() {
fehlermeldung = '';
if (!neuerName.trim()) return;
const res = await fetch('/api/admin/dienststellen', {
method: 'POST',
body: JSON.stringify({ name: neuerName }),
headers: { 'Content-Type': 'application/json' }
});
if (res.ok) {
neuerName = '';
await ladeDienststellen();
} else {
const err = await res.json();
fehlermeldung = err.error || 'Fehler beim Hinzufügen';
}
}
async function loeschen(id: number) {
if (!confirm('Diese Dienststelle wirklich löschen?')) return;
await fetch(`/api/admin/dienststellen?id=${id}`, { method: 'DELETE' });
await ladeDienststellen();
}
onMount(ladeDienststellen);
</script>
<div class="p-6 max-w-xl mx-auto space-y-6">
<h1 class="text-2xl font-bold">Dienststellen verwalten</h1>
<div class="flex gap-2">
<input bind:value={neuerName} placeholder="Neue Dienststelle" class="input w-full" />
<button on:click={hinzufuegen} class="bg-blue-600 text-white px-4 py-2 rounded">Hinzufügen</button>
</div>
{#if fehlermeldung}
<p class="text-red-600">{fehlermeldung}</p>
{/if}
<ul class="divide-y border rounded">
{#each dienststellen as d}
<li class="flex justify-between items-center p-2">
<span>{d.name}</span>
<button on:click={() => loeschen(d.id)} class="text-sm text-red-600 hover:underline">Löschen</button>
</li>
{/each}
</ul>
</div>
<style>
.input {
@apply border rounded px-3 py-2;
}

View File

@@ -0,0 +1,19 @@
import { PrismaClient } from '@prisma/client';
import type { RequestHandler } from '@sveltejs/kit';
const prisma = new PrismaClient();
export const GET: RequestHandler = async () => {
const anmeldungen = await prisma.anmeldung.findMany({
//include: {
// wunsch1: true,
// wunsch2: true,
// wunsch3: true
//};
orderBy: { timestamp: 'desc' }
});
return new Response(JSON.stringify(anmeldungen), {
headers: { 'Content-Type': 'application/json' }
});
};

View File

@@ -0,0 +1,25 @@
import { PrismaClient } from '@prisma/client';
import type { RequestHandler } from '@sveltejs/kit';
const prisma = new PrismaClient();
export const GET: RequestHandler = async () => {
const dienststellen = await prisma.dienststelle.findMany({ orderBy: { name: 'asc' } });
return new Response(JSON.stringify(dienststellen));
};
export const POST: RequestHandler = async ({ request }) => {
const { name } = await request.json();
try {
const created = await prisma.dienststelle.create({ data: { name } });
return new Response(JSON.stringify(created));
} catch (e) {
return new Response(JSON.stringify({ error: 'Dienststelle existiert bereits' }), { status: 400 });
}
};
export const DELETE: RequestHandler = async ({ url }) => {
const id = Number(url.searchParams.get('id'));
await prisma.dienststelle.delete({ where: { id } });
return new Response(JSON.stringify({ success: true }));
};

View File

@@ -0,0 +1,13 @@
import type { RequestHandler } from '@sveltejs/kit';
const ADMIN_PASS = 'supergeheim'; // Passwort hier festlegen
export const POST: RequestHandler = async ({ request }) => {
const { passwort } = await request.json();
if (passwort === ADMIN_PASS) {
return new Response(JSON.stringify({ success: true }));
}
return new Response('Unauthorized', { status: 401 });
};

View File

@@ -0,0 +1,52 @@
import { PrismaClient } from '@prisma/client';
import type { RequestHandler } from '@sveltejs/kit';
const prisma = new PrismaClient();
export const POST: RequestHandler = async ({ request }) => {
const data = await request.json();
try {
await prisma.anmeldung.create({
data: {
anrede: data.anrede,
vorname: data.vorname,
nachname: data.nachname,
geburtsdatum: data.geburtsdatum,
strasse: data.strasse,
hausnummer: data.hausnummer,
ort: data.ort,
plz: data.plz,
telefon: data.telefon,
email: data.email,
schulart: data.schulart,
zeitraum: data.zeitraum,
motivation: data.motivation,
wunsch1Id: data.wunsch1Id,
wunsch2Id: data.wunsch2Id,
wunsch3Id: data.wunsch3Id
}
});
const exists = await prisma.anmeldung.findUnique({
where: { email: data.email }
});
if (exists) {
return new Response(JSON.stringify({ success: false, error: 'Diese E-Mail wurde bereits verwendet.' }), {
status: 400,
headers: { 'Content-Type': 'application/json' }
});
} else {
return new Response(JSON.stringify({ success: true }), {
headers: { 'Content-Type': 'application/json' }
});
}
} catch (error) {
console.error(error);
return new Response(JSON.stringify({ success: false, error: 'Fehler bei Speicherung' }), {
status: 500,
headers: { 'Content-Type': 'application/json' }
});
}
};

BIN
static/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

18
svelte.config.js Normal file
View File

@@ -0,0 +1,18 @@
import adapter from '@sveltejs/adapter-auto';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://svelte.dev/docs/kit/integrations
// for more information about preprocessors
preprocess: vitePreprocess(),
kit: {
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
adapter: adapter()
}
};
export default config;

9
tailwind.config.cjs Normal file
View File

@@ -0,0 +1,9 @@
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{html,js,svelte,ts}'],
theme: {
extend: {},
},
plugins: [],
}

19
tsconfig.json Normal file
View File

@@ -0,0 +1,19 @@
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler"
}
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
//
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
// from the referenced tsconfig.json - TypeScript does not merge them in
}

6
vite.config.ts Normal file
View File

@@ -0,0 +1,6 @@
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [sveltekit()]
});