first commit
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
node_modules
|
||||||
|
.env
|
||||||
|
.vscode/*
|
||||||
49
Dockerfile
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# Stage 1: Build (Erstellung des Produktionsbundles)
|
||||||
|
FROM node:20-alpine AS build
|
||||||
|
|
||||||
|
# Setze das Arbeitsverzeichnis
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
# Kopiere package.json und package-lock.json und installiere die Abhängigkeiten
|
||||||
|
COPY package.json ./
|
||||||
|
RUN npm install --force && npm cache clean --force
|
||||||
|
|
||||||
|
# Kopiere die weiteren wichtigen Projektdateien
|
||||||
|
|
||||||
|
COPY components.json .
|
||||||
|
COPY eslint.config.js .
|
||||||
|
COPY index.html .
|
||||||
|
COPY postcss.config.js .
|
||||||
|
COPY tailwind.config.ts .
|
||||||
|
COPY tsconfig.app.json .
|
||||||
|
COPY tsconfig.json .
|
||||||
|
COPY tsconfig.node.json .
|
||||||
|
COPY vite.config.ts .
|
||||||
|
COPY src ./src
|
||||||
|
COPY public ./public
|
||||||
|
COPY .env .
|
||||||
|
# Baue das Projekt für die Produktion
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Stage 2: Production (Einfacher Webserver für die bereitgestellten Dateien)
|
||||||
|
FROM node:20-alpine AS production
|
||||||
|
|
||||||
|
# Setze das Arbeitsverzeichnis
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
# Installiere ein einfaches Static File Hosting Tool (wie serve)
|
||||||
|
RUN npm install -g serve
|
||||||
|
|
||||||
|
# Kopiere die gebauten Dateien aus der Build-Phase
|
||||||
|
COPY --from=build /usr/src/app/dist ./dist
|
||||||
|
|
||||||
|
# Kopiere die generierte index.html aus dem Build-Ordner (aus der Build-Phase)
|
||||||
|
COPY --from=build /usr/src/app/index.html ./index.html
|
||||||
|
# Baue die TypeScript API
|
||||||
|
#RUN npm install && npx tsc api.ts
|
||||||
|
|
||||||
|
# Exponiere den Port, auf dem der Server läuft
|
||||||
|
EXPOSE 5030
|
||||||
|
|
||||||
|
# Starte den Server auf Port 5000 (dieser wird dann über den Nginx-Reverse-Proxy weitergeleitet)
|
||||||
|
CMD ["serve", "-s", "dist", "-l", "5030"]
|
||||||
218
api_doku.md
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
# REST API Übersicht (aus Client-Calls im Projekt abgeleitet)
|
||||||
|
|
||||||
|
- **Base URL**: `VITE_WEBHOOK_URL` (siehe `src/lib/config.ts -> getWebhookUrl()`)
|
||||||
|
- **Auth**:
|
||||||
|
- Cookies werden standardmäßig mitgesendet (`credentials: 'include'`)
|
||||||
|
- Falls vorhanden wird `Authorization: Bearer <token>` gesetzt (siehe `apiFetch`)
|
||||||
|
- Bei `401` wird automatisch Refresh versucht über `/auth/rnjwt`
|
||||||
|
|
||||||
|
## Auth
|
||||||
|
|
||||||
|
- **POST /auth_login**
|
||||||
|
- Headers: `Content-Type: application/json`
|
||||||
|
- Body:
|
||||||
|
```json
|
||||||
|
{ "email": "string", "password": "string" }
|
||||||
|
```
|
||||||
|
- Response:
|
||||||
|
```json
|
||||||
|
{ "token": "string", "user": { ... } }
|
||||||
|
```
|
||||||
|
|
||||||
|
- **GET /auth/rnjwt**
|
||||||
|
- Zweck: JWT Refresh
|
||||||
|
- Response:
|
||||||
|
```json
|
||||||
|
{ "token": "string" }
|
||||||
|
```
|
||||||
|
|
||||||
|
## Events
|
||||||
|
|
||||||
|
- **POST /event/new_manual**
|
||||||
|
- Headers: `Content-Type: application/json`
|
||||||
|
- Body:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "string",
|
||||||
|
"description": "string?",
|
||||||
|
"location": "string?",
|
||||||
|
"url": "string?",
|
||||||
|
"image": "string?",
|
||||||
|
"manager_name": "string?",
|
||||||
|
"manager_email": "string?",
|
||||||
|
"begin_date": "YYYY-MM-DD?",
|
||||||
|
"end_date": "YYYY-MM-DD?"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- Response: beliebiges Event-Objekt
|
||||||
|
|
||||||
|
- **GET /events/get_current**
|
||||||
|
- Response: `Event[]` oder ein einzelnes Event-Objekt
|
||||||
|
|
||||||
|
- **GET /events**
|
||||||
|
- Response: `Event[]` oder ein einzelnes Event-Objekt
|
||||||
|
|
||||||
|
- **POST /event/new_fromurl**
|
||||||
|
- Headers: `Content-Type: application/json`
|
||||||
|
- Body:
|
||||||
|
```json
|
||||||
|
{ "url": "string", "command": "eventmodus_extract_from_url" }
|
||||||
|
```
|
||||||
|
- Response: `data.message_from_ai` oder Roh-Response
|
||||||
|
|
||||||
|
## Blog
|
||||||
|
|
||||||
|
- **GET /blog/new_blog**
|
||||||
|
- Response:
|
||||||
|
```json
|
||||||
|
{ "id": "string" } // oder { "blog_id": "string" }
|
||||||
|
```
|
||||||
|
|
||||||
|
- **POST /blog/publish**
|
||||||
|
- Headers: `Content-Type: application/json`
|
||||||
|
- Body:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"blog_id": "string",
|
||||||
|
"publish_date": "YYYY-MM-DD",
|
||||||
|
"publish_socialmedia": true,
|
||||||
|
"socialmedia_channels": ["string"],
|
||||||
|
"socialmedia_languages": ["string"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- Response: beliebige Publikations-Infos
|
||||||
|
|
||||||
|
- **POST /blog/update**
|
||||||
|
- Headers: `Content-Type: application/json`
|
||||||
|
- Body:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"blog_id": "string",
|
||||||
|
"content": { ... }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- Response: Update-Ergebnis
|
||||||
|
|
||||||
|
- **POST /blog/generate**
|
||||||
|
- Headers: `Content-Type: application/json`
|
||||||
|
- Body:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"blog_Id": "string",
|
||||||
|
"topic": "string",
|
||||||
|
"tonality": "string",
|
||||||
|
"languages": ["string"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- Response: generierter Blog-Content
|
||||||
|
|
||||||
|
- **GET /blog/topic_suggestion**
|
||||||
|
- Response:
|
||||||
|
```json
|
||||||
|
{ "topics": ["string", ...] } | ["string", ...]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dateien & Medien
|
||||||
|
|
||||||
|
- **POST /file_upload_blog**
|
||||||
|
- Body (FormData):
|
||||||
|
- `file`: File
|
||||||
|
- `blog_id`: string
|
||||||
|
- Response:
|
||||||
|
```json
|
||||||
|
{ "url": "string", ... }
|
||||||
|
```
|
||||||
|
|
||||||
|
- **POST /file_upload_event**
|
||||||
|
- Body (FormData):
|
||||||
|
- `file`: File
|
||||||
|
- `event_id`: string
|
||||||
|
- Response:
|
||||||
|
```json
|
||||||
|
{ "url": "string", ... }
|
||||||
|
```
|
||||||
|
|
||||||
|
- **POST /upload_tmp**
|
||||||
|
- Body (FormData):
|
||||||
|
- `file`: File
|
||||||
|
- Response:
|
||||||
|
```json
|
||||||
|
{ "url": "string", ... }
|
||||||
|
```
|
||||||
|
|
||||||
|
- **POST /media/image_generator**
|
||||||
|
- Headers: `Content-Type: application/json`
|
||||||
|
- Body:
|
||||||
|
```json
|
||||||
|
{ "blog_id": "string", "title": "string" }
|
||||||
|
```
|
||||||
|
- Response:
|
||||||
|
```json
|
||||||
|
{ "url": "string" } // oder { "imageUrl": "string" }
|
||||||
|
```
|
||||||
|
|
||||||
|
- Hinweis: `generateAIImage` ruft aktuell
|
||||||
|
- **POST /file_upload**
|
||||||
|
- Headers: `Content-Type: application/json`
|
||||||
|
- Body:
|
||||||
|
```json
|
||||||
|
{ "prompt": "string" }
|
||||||
|
```
|
||||||
|
- Response:
|
||||||
|
```json
|
||||||
|
{ "imageUrl": "string", ... }
|
||||||
|
```
|
||||||
|
- Anmerkung: Endpoint-Name wirkt untypisch für Image-Generation.
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
|
||||||
|
- **POST /tools/speech2text**
|
||||||
|
- Body (FormData):
|
||||||
|
- `file`: Audio-Datei
|
||||||
|
- Response:
|
||||||
|
```json
|
||||||
|
{ "transcription": "string" } // oder "text", "result"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Social Media
|
||||||
|
|
||||||
|
- **POST /socialmedia/post2event**
|
||||||
|
- Headers: `Content-Type: application/json`
|
||||||
|
- Body: frei, je nach Nutzungsfall (Payload für Generierung)
|
||||||
|
- Response: generierte Posts
|
||||||
|
|
||||||
|
- **POST /socialmedia/publish_post**
|
||||||
|
- Headers: `Content-Type: application/json`
|
||||||
|
- Body:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"postId": "string",
|
||||||
|
"posts": { ... },
|
||||||
|
"images": { ... },
|
||||||
|
"scheduledTime": "string"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- Response: Veröffentlichungs-Ergebnis
|
||||||
|
|
||||||
|
## Gemeinsame Aspekte
|
||||||
|
|
||||||
|
- **Headers**
|
||||||
|
- `Content-Type: application/json` bei JSON-Requests
|
||||||
|
- FormData-Uploads ohne explizites `Content-Type` (Browser setzt Multi‑Part)
|
||||||
|
- **Auth**
|
||||||
|
- Cookies via `credentials: 'include'`
|
||||||
|
- Optionaler Bearer-Token via `Authorization`
|
||||||
|
- Auto-Refresh bei 401 über `/auth/rnjwt`, danach Retry
|
||||||
|
- **Statuscodes**
|
||||||
|
- Client erwartet `response.ok === true` bei Erfolg, sonst Fehlerwurf
|
||||||
|
- **Variabilität**
|
||||||
|
- Einige Responses sind polymorph (Array oder Objekt). Umgang entsprechend im Client.
|
||||||
|
|
||||||
|
# Beispiel: apiFetch Verhalten
|
||||||
|
|
||||||
|
- Sendet automatisch Cookies
|
||||||
|
- Fügt `Authorization: Bearer <token>` hinzu, wenn verfügbar
|
||||||
|
- Bei 401:
|
||||||
|
- versucht `GET /auth/rnjwt`
|
||||||
|
- wiederholt Request mit neuem Token
|
||||||
|
- bei erneutem 401: Logout und Fehlermeldung
|
||||||
20
components.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema.json",
|
||||||
|
"style": "default",
|
||||||
|
"rsc": false,
|
||||||
|
"tsx": true,
|
||||||
|
"tailwind": {
|
||||||
|
"config": "tailwind.config.ts",
|
||||||
|
"css": "src/index.css",
|
||||||
|
"baseColor": "slate",
|
||||||
|
"cssVariables": true,
|
||||||
|
"prefix": ""
|
||||||
|
},
|
||||||
|
"aliases": {
|
||||||
|
"components": "@/components",
|
||||||
|
"utils": "@/lib/utils",
|
||||||
|
"ui": "@/components/ui",
|
||||||
|
"lib": "@/lib",
|
||||||
|
"hooks": "@/hooks"
|
||||||
|
}
|
||||||
|
}
|
||||||
23
deploy.sh
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Setze die Docker-Compose-Datei
|
||||||
|
COMPOSE_FILE="/home/martin/docker/apps/kimaschine.assistent/docker-compose.yml"
|
||||||
|
|
||||||
|
|
||||||
|
# Docker-Container herunterfahren
|
||||||
|
echo "🛑 Stopping Docker containers..."
|
||||||
|
docker-compose -f $COMPOSE_FILE down --remove-orphans
|
||||||
|
|
||||||
|
# Git-Pull mit Benutzername und Passwort
|
||||||
|
echo "📂 Pulling latest changes from Git..."
|
||||||
|
git pull
|
||||||
|
|
||||||
|
# Docker-Image neu bauen
|
||||||
|
echo "🔨 Rebuilding Docker image without cache..."
|
||||||
|
docker-compose -f $COMPOSE_FILE build --no-cache
|
||||||
|
|
||||||
|
# Docker-Container wieder hochfahren
|
||||||
|
echo "🚀 Starting Docker containers..."
|
||||||
|
docker-compose -f $COMPOSE_FILE up -d
|
||||||
|
|
||||||
|
echo "✅ Workflow completed!"
|
||||||
BIN
dist/Logo.png
vendored
Normal file
|
After Width: | Height: | Size: 68 KiB |
191
dist/assets/index-CzGVSrN-.js
vendored
Normal file
1
dist/assets/index-DHgMgX29.css
vendored
Normal file
BIN
dist/default_event.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
dist/favicon/android-icon-144x144.png
vendored
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
dist/favicon/android-icon-192x192.png
vendored
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
dist/favicon/android-icon-36x36.png
vendored
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
dist/favicon/android-icon-48x48.png
vendored
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
dist/favicon/android-icon-72x72.png
vendored
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
dist/favicon/android-icon-96x96.png
vendored
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
dist/favicon/apple-icon-114x114.png
vendored
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
dist/favicon/apple-icon-120x120.png
vendored
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
dist/favicon/apple-icon-144x144.png
vendored
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
dist/favicon/apple-icon-152x152.png
vendored
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
dist/favicon/apple-icon-180x180.png
vendored
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
dist/favicon/apple-icon-57x57.png
vendored
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
dist/favicon/apple-icon-60x60.png
vendored
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
dist/favicon/apple-icon-72x72.png
vendored
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
dist/favicon/apple-icon-76x76.png
vendored
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
dist/favicon/apple-icon-precomposed.png
vendored
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
dist/favicon/apple-icon.png
vendored
Normal file
|
After Width: | Height: | Size: 34 KiB |
2
dist/favicon/browserconfig.xml
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>
|
||||||
BIN
dist/favicon/favicon-16x16.png
vendored
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
dist/favicon/favicon-32x32.png
vendored
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
dist/favicon/favicon-96x96.png
vendored
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
dist/favicon/favicon.ico
vendored
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
41
dist/favicon/manifest.json
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"name": "App",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "\/android-icon-36x36.png",
|
||||||
|
"sizes": "36x36",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "0.75"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "\/android-icon-48x48.png",
|
||||||
|
"sizes": "48x48",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "1.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "\/android-icon-72x72.png",
|
||||||
|
"sizes": "72x72",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "1.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "\/android-icon-96x96.png",
|
||||||
|
"sizes": "96x96",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "2.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "\/android-icon-144x144.png",
|
||||||
|
"sizes": "144x144",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "3.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "\/android-icon-192x192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "4.0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
dist/favicon/ms-icon-144x144.png
vendored
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
dist/favicon/ms-icon-150x150.png
vendored
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
dist/favicon/ms-icon-310x310.png
vendored
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
dist/favicon/ms-icon-70x70.png
vendored
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
dist/images/ITTools.jpeg
vendored
Normal file
|
After Width: | Height: | Size: 157 KiB |
BIN
dist/images/robo/robo_blogauthor.png
vendored
Normal file
|
After Width: | Height: | Size: 130 KiB |
BIN
dist/images/robo/robo_event.png
vendored
Normal file
|
After Width: | Height: | Size: 186 KiB |
BIN
dist/images/sales.jpeg
vendored
Normal file
|
After Width: | Height: | Size: 107 KiB |
BIN
dist/images/webhero.jpeg
vendored
Normal file
|
After Width: | Height: | Size: 177 KiB |
93
dist/index.html
vendored
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>K.I. Maschine</title>
|
||||||
|
<meta name="description" content="KIMaschine.de" />
|
||||||
|
<meta name="author" content="KIMaschine.de" />
|
||||||
|
|
||||||
|
<meta property="og:title" content="K.I. Maschine.de" />
|
||||||
|
<meta property="og:description" content="KImaschine automates your website, blog, and social media content using advanced AI. Save time, boost efficiency, and stay ahead in the digital competition." />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:image" content="https://kimaschine.de/logo.png" />
|
||||||
|
|
||||||
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
|
<meta name="twitter:site" content="@KIMaschine_de" />
|
||||||
|
<meta name="twitter:image" content="https://kimaschine.de/logo.png" />
|
||||||
|
|
||||||
|
<!-- Favicon links -->
|
||||||
|
<link rel="apple-touch-icon" sizes="57x57" href="/favicon/apple-icon-57x57.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="60x60" href="/favicon/apple-icon-60x60.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="72x72" href="/favicon/apple-icon-72x72.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="76x76" href="/favicon/apple-icon-76x76.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="114x114" href="/favicon/apple-icon-114x114.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="120x120" href="/favicon/apple-icon-120x120.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="144x144" href="/favicon/apple-icon-144x144.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="152x152" href="/favicon/apple-icon-152x152.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-icon-180x180.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="36x36" href="/favicon/android-icon-36x36.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="48x48" href="/favicon/android-icon-48x48.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="72x72" href="/favicon/android-icon-72x72.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="96x96" href="/favicon/android-icon-96x96.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="144x144" href="/favicon/android-icon-144x144.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="192x192" href="/favicon/android-icon-192x192.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="96x96" href="/favicon/favicon-96x96.png">
|
||||||
|
<link rel="shortcut icon" href="/favicon/favicon.ico">
|
||||||
|
<link rel="manifest" href="/favicon/manifest.json">
|
||||||
|
<meta name="msapplication-TileColor" content="#ffffff">
|
||||||
|
<meta name="msapplication-TileImage" content="/favicon/ms-icon-144x144.png">
|
||||||
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
<script type="module" crossorigin src="/assets/index-CzGVSrN-.js"></script>
|
||||||
|
<link rel="stylesheet" crossorigin href="/assets/index-DHgMgX29.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<!-- IMPORTANT: DO NOT REMOVE THIS SCRIPT TAG OR THIS VERY COMMENT! -->
|
||||||
|
<!-- <script src="https://cdn.gpteng.co/gptengineer.js" type="module"></script> -->
|
||||||
|
<!-- Metricool Tracking -->
|
||||||
|
<!-- <script>
|
||||||
|
function loadScript(a){
|
||||||
|
var b=document.getElementsByTagName("head")[0],
|
||||||
|
c=document.createElement("script");
|
||||||
|
c.type="text/javascript",
|
||||||
|
c.src="https://tracker.metricool.com/resources/be.js",
|
||||||
|
c.onreadystatechange=a,
|
||||||
|
c.onload=a,
|
||||||
|
b.appendChild(c)
|
||||||
|
}
|
||||||
|
loadScript(function(){
|
||||||
|
beTracker.t({hash:"9496eca8438c4d21471232f7b1bf962f"})
|
||||||
|
});
|
||||||
|
</script> -->
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
<meta property="og:title" content="KIMaschine.de" />
|
||||||
|
<meta property="og:description" content="KIMaschine.de" />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:image" content="https://kimaschinede.vercel.app/logo.png" />
|
||||||
|
|
||||||
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
|
<meta name="twitter:site" content="@KIMaschine_de" />
|
||||||
|
<meta name="twitter:image" content="https://kimaschinede.vercel.app/logo.png" />
|
||||||
|
|
||||||
|
<link rel="apple-touch-icon" sizes="57x57" href="favicon/apple-icon-57x57.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="60x60" href="favicon/apple-icon-60x60.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="72x72" href="favicon/apple-icon-72x72.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="76x76" href="favicon/apple-icon-76x76.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="114x114" href="favicon/apple-icon-114x114.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="120x120" href="favicon/apple-icon-120x120.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="144x144" href="favicon/apple-icon-144x144.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="152x152" href="favicon/apple-icon-152x152.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="favicon/apple-icon-180x180.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="192x192" href="favicon/android-icon-192x192.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="favicon/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="96x96" href="favicon/favicon-96x96.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="favicon/favicon-16x16.png">
|
||||||
|
<link rel="manifest" href="/favicon/manifest.json">
|
||||||
|
<meta name="msapplication-TileColor" content="#ffffff">
|
||||||
|
<meta name="msapplication-TileImage" content="favicon/ms-icon-144x144.png">
|
||||||
|
<meta name="theme-color" content="#ffffff">
|
||||||
BIN
dist/lovable-uploads/1396093b-9357-4118-8305-776ac2bf90b8.png
vendored
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
dist/lovable-uploads/2acd3368-2b93-4913-8041-5151b626a0cd.png
vendored
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
dist/martin.jpeg
vendored
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
dist/miguel.jpeg
vendored
Normal file
|
After Width: | Height: | Size: 40 KiB |
1
dist/placeholder.svg
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="1200" fill="none"><rect width="1200" height="1200" fill="#EAEAEA" rx="3"/><g opacity=".5"><g opacity=".5"><path fill="#FAFAFA" d="M600.709 736.5c-75.454 0-136.621-61.167-136.621-136.62 0-75.454 61.167-136.621 136.621-136.621 75.453 0 136.62 61.167 136.62 136.621 0 75.453-61.167 136.62-136.62 136.62Z"/><path stroke="#C9C9C9" stroke-width="2.418" d="M600.709 736.5c-75.454 0-136.621-61.167-136.621-136.62 0-75.454 61.167-136.621 136.621-136.621 75.453 0 136.62 61.167 136.62 136.621 0 75.453-61.167 136.62-136.62 136.62Z"/></g><path stroke="url(#a)" stroke-width="2.418" d="M0-1.209h553.581" transform="scale(1 -1) rotate(45 1163.11 91.165)"/><path stroke="url(#b)" stroke-width="2.418" d="M404.846 598.671h391.726"/><path stroke="url(#c)" stroke-width="2.418" d="M599.5 795.742V404.017"/><path stroke="url(#d)" stroke-width="2.418" d="m795.717 796.597-391.441-391.44"/><path fill="#fff" d="M600.709 656.704c-31.384 0-56.825-25.441-56.825-56.824 0-31.384 25.441-56.825 56.825-56.825 31.383 0 56.824 25.441 56.824 56.825 0 31.383-25.441 56.824-56.824 56.824Z"/><g clip-path="url(#e)"><path fill="#666" fill-rule="evenodd" d="M616.426 586.58h-31.434v16.176l3.553-3.554.531-.531h9.068l.074-.074 8.463-8.463h2.565l7.18 7.181V586.58Zm-15.715 14.654 3.698 3.699 1.283 1.282-2.565 2.565-1.282-1.283-5.2-5.199h-6.066l-5.514 5.514-.073.073v2.876a2.418 2.418 0 0 0 2.418 2.418h26.598a2.418 2.418 0 0 0 2.418-2.418v-8.317l-8.463-8.463-7.181 7.181-.071.072Zm-19.347 5.442v4.085a6.045 6.045 0 0 0 6.046 6.045h26.598a6.044 6.044 0 0 0 6.045-6.045v-7.108l1.356-1.355-1.282-1.283-.074-.073v-17.989h-38.689v23.43l-.146.146.146.147Z" clip-rule="evenodd"/></g><path stroke="#C9C9C9" stroke-width="2.418" d="M600.709 656.704c-31.384 0-56.825-25.441-56.825-56.824 0-31.384 25.441-56.825 56.825-56.825 31.383 0 56.824 25.441 56.824 56.825 0 31.383-25.441 56.824-56.824 56.824Z"/></g><defs><linearGradient id="a" x1="554.061" x2="-.48" y1=".083" y2=".087" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="b" x1="796.912" x2="404.507" y1="599.963" y2="599.965" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="c" x1="600.792" x2="600.794" y1="403.677" y2="796.082" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="d" x1="404.85" x2="796.972" y1="403.903" y2="796.02" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><clipPath id="e"><path fill="#fff" d="M581.364 580.535h38.689v38.689h-38.689z"/></clipPath></defs></svg>
|
||||||
|
After Width: | Height: | Size: 3.2 KiB |
14
dist/robots.txt
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
User-agent: Googlebot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: Bingbot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: Twitterbot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: facebookexternalhit
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: *
|
||||||
|
Allow: /
|
||||||
0
dist/test.svg
vendored
Normal file
29
eslint.config.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import js from "@eslint/js";
|
||||||
|
import globals from "globals";
|
||||||
|
import reactHooks from "eslint-plugin-react-hooks";
|
||||||
|
import reactRefresh from "eslint-plugin-react-refresh";
|
||||||
|
import tseslint from "typescript-eslint";
|
||||||
|
|
||||||
|
export default tseslint.config(
|
||||||
|
{ ignores: ["dist"] },
|
||||||
|
{
|
||||||
|
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
||||||
|
files: ["**/*.{ts,tsx}"],
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 2020,
|
||||||
|
globals: globals.browser,
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
"react-hooks": reactHooks,
|
||||||
|
"react-refresh": reactRefresh,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
...reactHooks.configs.recommended.rules,
|
||||||
|
"react-refresh/only-export-components": [
|
||||||
|
"warn",
|
||||||
|
{ allowConstantExport: true },
|
||||||
|
],
|
||||||
|
"@typescript-eslint/no-unused-vars": "off",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
1
google0a5a3eb63f61c0ea.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
google-site-verification: google0a5a3eb63f61c0ea.html
|
||||||
92
index.html
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>K.I. Maschine</title>
|
||||||
|
<meta name="description" content="KIMaschine.de" />
|
||||||
|
<meta name="author" content="KIMaschine.de" />
|
||||||
|
|
||||||
|
<meta property="og:title" content="K.I. Maschine.de" />
|
||||||
|
<meta property="og:description" content="KImaschine automates your website, blog, and social media content using advanced AI. Save time, boost efficiency, and stay ahead in the digital competition." />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:image" content="https://kimaschine.de/logo.png" />
|
||||||
|
|
||||||
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
|
<meta name="twitter:site" content="@KIMaschine_de" />
|
||||||
|
<meta name="twitter:image" content="https://kimaschine.de/logo.png" />
|
||||||
|
|
||||||
|
<!-- Favicon links -->
|
||||||
|
<link rel="apple-touch-icon" sizes="57x57" href="/favicon/apple-icon-57x57.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="60x60" href="/favicon/apple-icon-60x60.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="72x72" href="/favicon/apple-icon-72x72.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="76x76" href="/favicon/apple-icon-76x76.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="114x114" href="/favicon/apple-icon-114x114.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="120x120" href="/favicon/apple-icon-120x120.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="144x144" href="/favicon/apple-icon-144x144.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="152x152" href="/favicon/apple-icon-152x152.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-icon-180x180.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="36x36" href="/favicon/android-icon-36x36.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="48x48" href="/favicon/android-icon-48x48.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="72x72" href="/favicon/android-icon-72x72.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="96x96" href="/favicon/android-icon-96x96.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="144x144" href="/favicon/android-icon-144x144.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="192x192" href="/favicon/android-icon-192x192.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="96x96" href="/favicon/favicon-96x96.png">
|
||||||
|
<link rel="shortcut icon" href="/favicon/favicon.ico">
|
||||||
|
<link rel="manifest" href="/favicon/manifest.json">
|
||||||
|
<meta name="msapplication-TileColor" content="#ffffff">
|
||||||
|
<meta name="msapplication-TileImage" content="/favicon/ms-icon-144x144.png">
|
||||||
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<!-- IMPORTANT: DO NOT REMOVE THIS SCRIPT TAG OR THIS VERY COMMENT! -->
|
||||||
|
<!-- <script src="https://cdn.gpteng.co/gptengineer.js" type="module"></script> -->
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
<!-- Metricool Tracking -->
|
||||||
|
<!-- <script>
|
||||||
|
function loadScript(a){
|
||||||
|
var b=document.getElementsByTagName("head")[0],
|
||||||
|
c=document.createElement("script");
|
||||||
|
c.type="text/javascript",
|
||||||
|
c.src="https://tracker.metricool.com/resources/be.js",
|
||||||
|
c.onreadystatechange=a,
|
||||||
|
c.onload=a,
|
||||||
|
b.appendChild(c)
|
||||||
|
}
|
||||||
|
loadScript(function(){
|
||||||
|
beTracker.t({hash:"9496eca8438c4d21471232f7b1bf962f"})
|
||||||
|
});
|
||||||
|
</script> -->
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
<meta property="og:title" content="KIMaschine.de" />
|
||||||
|
<meta property="og:description" content="KIMaschine.de" />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:image" content="https://kimaschinede.vercel.app/logo.png" />
|
||||||
|
|
||||||
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
|
<meta name="twitter:site" content="@KIMaschine_de" />
|
||||||
|
<meta name="twitter:image" content="https://kimaschinede.vercel.app/logo.png" />
|
||||||
|
|
||||||
|
<link rel="apple-touch-icon" sizes="57x57" href="favicon/apple-icon-57x57.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="60x60" href="favicon/apple-icon-60x60.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="72x72" href="favicon/apple-icon-72x72.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="76x76" href="favicon/apple-icon-76x76.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="114x114" href="favicon/apple-icon-114x114.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="120x120" href="favicon/apple-icon-120x120.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="144x144" href="favicon/apple-icon-144x144.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="152x152" href="favicon/apple-icon-152x152.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="favicon/apple-icon-180x180.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="192x192" href="favicon/android-icon-192x192.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="favicon/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="96x96" href="favicon/favicon-96x96.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="favicon/favicon-16x16.png">
|
||||||
|
<link rel="manifest" href="/favicon/manifest.json">
|
||||||
|
<meta name="msapplication-TileColor" content="#ffffff">
|
||||||
|
<meta name="msapplication-TileImage" content="favicon/ms-icon-144x144.png">
|
||||||
|
<meta name="theme-color" content="#ffffff">
|
||||||
10453
package-lock.json
generated
Normal file
101
package.json
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
{
|
||||||
|
"name": "vite_react_shadcn_ts",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"build:dev": "vite build --mode development",
|
||||||
|
"lint": "eslint .",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"test": "vitest",
|
||||||
|
"test:watch": "vitest --watch",
|
||||||
|
"coverage": "vitest run --coverage"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@hookform/resolvers": "^3.9.0",
|
||||||
|
"@radix-ui/react-accordion": "^1.2.0",
|
||||||
|
"@radix-ui/react-alert-dialog": "^1.1.1",
|
||||||
|
"@radix-ui/react-aspect-ratio": "^1.1.0",
|
||||||
|
"@radix-ui/react-avatar": "^1.1.0",
|
||||||
|
"@radix-ui/react-checkbox": "^1.1.1",
|
||||||
|
"@radix-ui/react-collapsible": "^1.1.0",
|
||||||
|
"@radix-ui/react-context-menu": "^2.2.1",
|
||||||
|
"@radix-ui/react-dialog": "^1.1.2",
|
||||||
|
"@radix-ui/react-dropdown-menu": "^2.1.1",
|
||||||
|
"@radix-ui/react-hover-card": "^1.1.1",
|
||||||
|
"@radix-ui/react-icons": "^1.3.2",
|
||||||
|
"@radix-ui/react-label": "^2.1.0",
|
||||||
|
"@radix-ui/react-menubar": "^1.1.1",
|
||||||
|
"@radix-ui/react-navigation-menu": "^1.2.0",
|
||||||
|
"@radix-ui/react-popover": "^1.1.1",
|
||||||
|
"@radix-ui/react-progress": "^1.1.0",
|
||||||
|
"@radix-ui/react-radio-group": "^1.2.0",
|
||||||
|
"@radix-ui/react-scroll-area": "^1.1.0",
|
||||||
|
"@radix-ui/react-select": "^2.1.1",
|
||||||
|
"@radix-ui/react-separator": "^1.1.0",
|
||||||
|
"@radix-ui/react-slider": "^1.2.0",
|
||||||
|
"@radix-ui/react-slot": "^1.1.0",
|
||||||
|
"@radix-ui/react-switch": "^1.1.0",
|
||||||
|
"@radix-ui/react-tabs": "^1.1.12",
|
||||||
|
"@radix-ui/react-toast": "^1.2.1",
|
||||||
|
"@radix-ui/react-toggle": "^1.1.0",
|
||||||
|
"@radix-ui/react-toggle-group": "^1.1.0",
|
||||||
|
"@radix-ui/react-tooltip": "^1.1.4",
|
||||||
|
"@tanstack/react-query": "^5.56.2",
|
||||||
|
"@types/react-dropzone": "^4.2.2",
|
||||||
|
"class-variance-authority": "^0.7.1",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"cmdk": "^1.0.0",
|
||||||
|
"date-fns": "^3.6.0",
|
||||||
|
"embla-carousel-react": "^8.3.0",
|
||||||
|
"input-otp": "^1.2.4",
|
||||||
|
"lucide-react": "^0.462.0",
|
||||||
|
"next-themes": "^0.3.0",
|
||||||
|
"react": "^18.3.1",
|
||||||
|
"react-day-picker": "^9.7.0",
|
||||||
|
"react-dom": "^18.3.1",
|
||||||
|
"react-dropzone": "^14.3.8",
|
||||||
|
"react-easy-crop": "^5.5.6",
|
||||||
|
"react-helmet-async": "^2.0.5",
|
||||||
|
"react-hook-form": "^7.53.0",
|
||||||
|
"react-markdown": "^10.1.0",
|
||||||
|
"react-quill": "^2.0.0",
|
||||||
|
"react-resizable-panels": "^2.1.3",
|
||||||
|
"react-router-dom": "^6.26.2",
|
||||||
|
"react-swipeable": "^7.0.2",
|
||||||
|
"recharts": "^2.12.7",
|
||||||
|
"sonner": "^1.5.0",
|
||||||
|
"tailwind-merge": "^2.5.2",
|
||||||
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
"vaul": "^0.9.3",
|
||||||
|
"zod": "^3.23.8"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@eslint/js": "^9.9.0",
|
||||||
|
"@tailwindcss/typography": "^0.5.15",
|
||||||
|
"@testing-library/jest-dom": "^6.6.3",
|
||||||
|
"@testing-library/react": "^16.0.1",
|
||||||
|
"@testing-library/user-event": "^14.5.2",
|
||||||
|
"@types/node": "^22.5.5",
|
||||||
|
"@types/react": "^18.3.23",
|
||||||
|
"@types/react-dom": "^18.3.7",
|
||||||
|
"@vitejs/plugin-react": "^4.5.0",
|
||||||
|
"@vitejs/plugin-react-swc": "^3.5.0",
|
||||||
|
"@vitest/coverage-v8": "^2.1.9",
|
||||||
|
"autoprefixer": "^10.4.20",
|
||||||
|
"eslint": "^9.9.0",
|
||||||
|
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
|
||||||
|
"eslint-plugin-react-refresh": "^0.4.9",
|
||||||
|
"globals": "^15.9.0",
|
||||||
|
"jsdom": "^25.0.1",
|
||||||
|
"lovable-tagger": "^1.1.7",
|
||||||
|
"postcss": "^8.4.47",
|
||||||
|
"tailwindcss": "^3.4.11",
|
||||||
|
"typescript": "^5.5.3",
|
||||||
|
"typescript-eslint": "^8.0.1",
|
||||||
|
"vite": "^5.4.1",
|
||||||
|
"vitest": "^2.1.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
6
postcss.config.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export default {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
BIN
public/Logo.png
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
public/default_event.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
public/favicon/android-icon-144x144.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
public/favicon/android-icon-192x192.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
public/favicon/android-icon-36x36.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
public/favicon/android-icon-48x48.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
public/favicon/android-icon-72x72.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
public/favicon/android-icon-96x96.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
public/favicon/apple-icon-114x114.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/favicon/apple-icon-120x120.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/favicon/apple-icon-144x144.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
public/favicon/apple-icon-152x152.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
public/favicon/apple-icon-180x180.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
public/favicon/apple-icon-57x57.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
public/favicon/apple-icon-60x60.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
public/favicon/apple-icon-72x72.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
public/favicon/apple-icon-76x76.png
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
public/favicon/apple-icon-precomposed.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
public/favicon/apple-icon.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
2
public/favicon/browserconfig.xml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>
|
||||||
BIN
public/favicon/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
public/favicon/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
public/favicon/favicon-96x96.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
public/favicon/favicon.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
41
public/favicon/manifest.json
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"name": "App",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "\/android-icon-36x36.png",
|
||||||
|
"sizes": "36x36",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "0.75"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "\/android-icon-48x48.png",
|
||||||
|
"sizes": "48x48",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "1.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "\/android-icon-72x72.png",
|
||||||
|
"sizes": "72x72",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "1.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "\/android-icon-96x96.png",
|
||||||
|
"sizes": "96x96",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "2.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "\/android-icon-144x144.png",
|
||||||
|
"sizes": "144x144",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "3.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "\/android-icon-192x192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "4.0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
public/favicon/ms-icon-144x144.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
public/favicon/ms-icon-150x150.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
public/favicon/ms-icon-310x310.png
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
public/favicon/ms-icon-70x70.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
public/images/ITTools.jpeg
Normal file
|
After Width: | Height: | Size: 157 KiB |
BIN
public/images/robo/robo_blogauthor.png
Normal file
|
After Width: | Height: | Size: 130 KiB |
BIN
public/images/robo/robo_event.png
Normal file
|
After Width: | Height: | Size: 186 KiB |
BIN
public/images/sales.jpeg
Normal file
|
After Width: | Height: | Size: 107 KiB |
BIN
public/images/webhero.jpeg
Normal file
|
After Width: | Height: | Size: 177 KiB |
BIN
public/kgblogo.png
Normal file
|
After Width: | Height: | Size: 107 KiB |
BIN
public/lovable-uploads/1396093b-9357-4118-8305-776ac2bf90b8.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
public/lovable-uploads/2acd3368-2b93-4913-8041-5151b626a0cd.png
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
public/martin.jpeg
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
public/miguel.jpeg
Normal file
|
After Width: | Height: | Size: 40 KiB |
1
public/placeholder.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="1200" fill="none"><rect width="1200" height="1200" fill="#EAEAEA" rx="3"/><g opacity=".5"><g opacity=".5"><path fill="#FAFAFA" d="M600.709 736.5c-75.454 0-136.621-61.167-136.621-136.62 0-75.454 61.167-136.621 136.621-136.621 75.453 0 136.62 61.167 136.62 136.621 0 75.453-61.167 136.62-136.62 136.62Z"/><path stroke="#C9C9C9" stroke-width="2.418" d="M600.709 736.5c-75.454 0-136.621-61.167-136.621-136.62 0-75.454 61.167-136.621 136.621-136.621 75.453 0 136.62 61.167 136.62 136.621 0 75.453-61.167 136.62-136.62 136.62Z"/></g><path stroke="url(#a)" stroke-width="2.418" d="M0-1.209h553.581" transform="scale(1 -1) rotate(45 1163.11 91.165)"/><path stroke="url(#b)" stroke-width="2.418" d="M404.846 598.671h391.726"/><path stroke="url(#c)" stroke-width="2.418" d="M599.5 795.742V404.017"/><path stroke="url(#d)" stroke-width="2.418" d="m795.717 796.597-391.441-391.44"/><path fill="#fff" d="M600.709 656.704c-31.384 0-56.825-25.441-56.825-56.824 0-31.384 25.441-56.825 56.825-56.825 31.383 0 56.824 25.441 56.824 56.825 0 31.383-25.441 56.824-56.824 56.824Z"/><g clip-path="url(#e)"><path fill="#666" fill-rule="evenodd" d="M616.426 586.58h-31.434v16.176l3.553-3.554.531-.531h9.068l.074-.074 8.463-8.463h2.565l7.18 7.181V586.58Zm-15.715 14.654 3.698 3.699 1.283 1.282-2.565 2.565-1.282-1.283-5.2-5.199h-6.066l-5.514 5.514-.073.073v2.876a2.418 2.418 0 0 0 2.418 2.418h26.598a2.418 2.418 0 0 0 2.418-2.418v-8.317l-8.463-8.463-7.181 7.181-.071.072Zm-19.347 5.442v4.085a6.045 6.045 0 0 0 6.046 6.045h26.598a6.044 6.044 0 0 0 6.045-6.045v-7.108l1.356-1.355-1.282-1.283-.074-.073v-17.989h-38.689v23.43l-.146.146.146.147Z" clip-rule="evenodd"/></g><path stroke="#C9C9C9" stroke-width="2.418" d="M600.709 656.704c-31.384 0-56.825-25.441-56.825-56.824 0-31.384 25.441-56.825 56.825-56.825 31.383 0 56.824 25.441 56.824 56.825 0 31.383-25.441 56.824-56.824 56.824Z"/></g><defs><linearGradient id="a" x1="554.061" x2="-.48" y1=".083" y2=".087" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="b" x1="796.912" x2="404.507" y1="599.963" y2="599.965" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="c" x1="600.792" x2="600.794" y1="403.677" y2="796.082" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="d" x1="404.85" x2="796.972" y1="403.903" y2="796.02" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><clipPath id="e"><path fill="#fff" d="M581.364 580.535h38.689v38.689h-38.689z"/></clipPath></defs></svg>
|
||||||
|
After Width: | Height: | Size: 3.2 KiB |
14
public/robots.txt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
User-agent: Googlebot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: Bingbot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: Twitterbot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: facebookexternalhit
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: *
|
||||||
|
Allow: /
|
||||||
0
public/test.svg
Normal file
42
src/App.css
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#root {
|
||||||
|
max-width: 1280px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
height: 6em;
|
||||||
|
padding: 1.5em;
|
||||||
|
will-change: filter;
|
||||||
|
transition: filter 300ms;
|
||||||
|
}
|
||||||
|
.logo:hover {
|
||||||
|
filter: drop-shadow(0 0 2em #646cffaa);
|
||||||
|
}
|
||||||
|
.logo.react:hover {
|
||||||
|
filter: drop-shadow(0 0 2em #61dafbaa);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes logo-spin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
a:nth-of-type(2) .logo {
|
||||||
|
animation: logo-spin infinite 20s linear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
padding: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.read-the-docs {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
48
src/App.tsx
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
import { Toaster } from "@/components/ui/toaster";
|
||||||
|
import { Toaster as Sonner } from "@/components/ui/sonner";
|
||||||
|
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||||
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||||
|
import { BrowserRouter, Routes, Route } from "react-router-dom";
|
||||||
|
import { HelmetProvider } from "react-helmet-async";
|
||||||
|
import { LanguageProvider } from "@/contexts/LanguageContext";
|
||||||
|
import { AuthProvider, useAuth } from "@/contexts/AuthContext";
|
||||||
|
import Main from "./components/app/Main";
|
||||||
|
import LoginContainer from "./components/auth/LoginContainer";
|
||||||
|
import ArtistCollabForm from "@/features/event/components/ArtistCollabForm";
|
||||||
|
|
||||||
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
|
const AppContent = () => {
|
||||||
|
const { user } = useAuth();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Routes>
|
||||||
|
<Route path="/collab/:token" element={<ArtistCollabForm />} />
|
||||||
|
<Route
|
||||||
|
path="/*"
|
||||||
|
element={user ? <Main /> : <LoginContainer />}
|
||||||
|
/>
|
||||||
|
</Routes>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const App = () => (
|
||||||
|
<HelmetProvider>
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
|
<TooltipProvider>
|
||||||
|
<LanguageProvider>
|
||||||
|
<AuthProvider>
|
||||||
|
<Toaster />
|
||||||
|
<Sonner />
|
||||||
|
<BrowserRouter>
|
||||||
|
<AppContent />
|
||||||
|
</BrowserRouter>
|
||||||
|
</AuthProvider>
|
||||||
|
</LanguageProvider>
|
||||||
|
</TooltipProvider>
|
||||||
|
</QueryClientProvider>
|
||||||
|
</HelmetProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default App;
|
||||||
108
src/components/app/Main.tsx
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { LogOut, Menu } from 'lucide-react';
|
||||||
|
import { useAuth } from '@/contexts/AuthContext';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import DashboardContainer from '../dashboard/DashboardContainer';
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
|
const Main: React.FC = () => {
|
||||||
|
const { user, logout } = useAuth();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [hasActiveEvent, setHasActiveEvent] = useState(false);
|
||||||
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
||||||
|
|
||||||
|
// Check for active events - This will be replaced with actual API call
|
||||||
|
useEffect(() => {
|
||||||
|
// TODO: Replace with actual API call to check for active events
|
||||||
|
const checkActiveEvents = async () => {
|
||||||
|
try {
|
||||||
|
// const response = await fetch('/api/events/active');
|
||||||
|
// const data = await response.json();
|
||||||
|
// setHasActiveEvent(data.hasActiveEvent);
|
||||||
|
|
||||||
|
// For now, we'll set it to false
|
||||||
|
setHasActiveEvent(false);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error checking active events:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
checkActiveEvents();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleAction = (action: string) => {
|
||||||
|
console.log('Selected action:', action);
|
||||||
|
// Handle navigation or other actions based on the selected card
|
||||||
|
switch (action) {
|
||||||
|
case 'event':
|
||||||
|
// Navigate to events page or open event form
|
||||||
|
break;
|
||||||
|
case 'blog':
|
||||||
|
// Navigate to blog page or open blog form
|
||||||
|
break;
|
||||||
|
case 'quick-post':
|
||||||
|
// Open quick post dialog
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-background">
|
||||||
|
{/* Header */}
|
||||||
|
<header className="sticky top-0 z-40 border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
||||||
|
<div className="container flex h-16 items-center justify-between px-4">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className="md:hidden"
|
||||||
|
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
||||||
|
>
|
||||||
|
<Menu className="h-5 w-5" />
|
||||||
|
<span className="sr-only">Toggle menu</span>
|
||||||
|
</Button>
|
||||||
|
<div
|
||||||
|
className="flex items-center gap-2 cursor-pointer"
|
||||||
|
onClick={() => navigate('/')}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src="/Logo.png"
|
||||||
|
alt="Logo"
|
||||||
|
className="h-10 w-auto object-contain"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div className="hidden md:block text-sm text-muted-foreground">
|
||||||
|
Hallo, {user?.name?.split(' ')[0] || 'Benutzer'}
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
className="gap-1.5 text-sm"
|
||||||
|
onClick={logout}
|
||||||
|
>
|
||||||
|
<LogOut className="h-4 w-4" />
|
||||||
|
<span className="hidden sm:inline">Abmelden</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{/* Main Content */}
|
||||||
|
<main className="container py-6 px-0 md:px-4">
|
||||||
|
<div className="mx-auto md:max-w-5xl">
|
||||||
|
<DashboardContainer
|
||||||
|
onActionClick={handleAction}
|
||||||
|
hasActiveEvent={hasActiveEvent}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Main;
|
||||||