diff --git a/packages/reservation-platform/docker/compose.yml b/packages/reservation-platform/docker/compose.yml index 538564f..0c79dff 100644 --- a/packages/reservation-platform/docker/compose.yml +++ b/packages/reservation-platform/docker/compose.yml @@ -13,7 +13,18 @@ services: myp-rp: image: myp-rp:latest container_name: myp-rp + environment: + - NEXT_PUBLIC_API_URL=http://192.168.0.105:5000 + - OAUTH_CLIENT_ID=client_id + - OAUTH_CLIENT_SECRET=client_secret env_file: "/srv/myp-env/github.env" volumes: - /srv/MYP-DB:/usr/src/app/db restart: unless-stopped + # Füge Healthcheck hinzu für besseres Monitoring + healthcheck: + test: ["CMD", "wget", "--spider", "http://localhost:3000"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s diff --git a/packages/reservation-platform/setup-backend-url.sh b/packages/reservation-platform/setup-backend-url.sh new file mode 100755 index 0000000..d7c982c --- /dev/null +++ b/packages/reservation-platform/setup-backend-url.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +# Skript zum Setzen der Backend-URL in der Frontend-Konfiguration +# Verwendet für die Verbindung zum Backend-Server unter 192.168.0.105:5000 + +# Farbcodes für Ausgabe +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Funktion zur Ausgabe mit Zeitstempel +log() { + echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1" +} + +error_log() { + echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')] FEHLER:${NC} $1" >&2 +} + +# Definiere Variablen +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +ENV_FILE="$SCRIPT_DIR/.env.local" +DEFAULT_BACKEND_URL="http://192.168.0.105:5000" + +# Falls übergebene Parameter vorhanden sind, Backend-URL anpassen +if [ -n "$1" ]; then + BACKEND_URL="$1" + log "Verwende übergebene Backend-URL: ${BACKEND_URL}" +else + BACKEND_URL="$DEFAULT_BACKEND_URL" + log "Verwende Standard-Backend-URL: ${BACKEND_URL}" +fi + +# Erstelle .env.local Datei mit Backend-URL +log "${YELLOW}Erstelle .env.local Datei...${NC}" +cat > "$ENV_FILE" << EOL +# Backend API Konfiguration +NEXT_PUBLIC_API_URL=${BACKEND_URL} + +# OAuth Konfiguration (falls nötig) +OAUTH_CLIENT_ID=client_id +OAUTH_CLIENT_SECRET=client_secret +EOL + +# Überprüfe, ob die Datei erstellt wurde +if [ -f "$ENV_FILE" ]; then + log "${GREEN}Erfolgreich .env.local Datei mit Backend-URL erstellt: ${BACKEND_URL}${NC}" +else + error_log "Konnte .env.local Datei nicht erstellen." + exit 1 +fi + +# Hinweis für Docker-Installation +log "${YELLOW}WICHTIG: Wenn Sie Docker verwenden, stellen Sie sicher, dass Sie die Umgebungsvariable setzen:${NC}" +log "NEXT_PUBLIC_API_URL=${BACKEND_URL}" +log "" +log "${GREEN}Backend-URL wurde erfolgreich konfiguriert. Nach einem Neustart der Anwendung sollte die Verbindung hergestellt werden.${NC}" + +# Berechtigungen setzen +chmod 600 "$ENV_FILE" + +exit 0 \ No newline at end of file diff --git a/packages/reservation-platform/src/app/api/jobs/[id]/route.ts b/packages/reservation-platform/src/app/api/jobs/[id]/route.ts new file mode 100644 index 0000000..0124e10 --- /dev/null +++ b/packages/reservation-platform/src/app/api/jobs/[id]/route.ts @@ -0,0 +1,99 @@ +import { API_ENDPOINTS } from "@/utils/api-config"; + +export const dynamic = "force-dynamic"; + +export async function GET( + request: Request, + { params }: { params: { id: string } } +) { + try { + const id = params.id; + + // Rufe einzelnen Job vom externen Backend ab + const response = await fetch(`${API_ENDPOINTS.JOBS}/${id}`); + + if (!response.ok) { + console.error(`Backend-Fehler: ${response.status} ${response.statusText}`); + return new Response(JSON.stringify({ error: 'Backend nicht erreichbar' }), { + status: 502, + headers: { 'Content-Type': 'application/json' } + }); + } + + const job = await response.json(); + return Response.json(job); + } catch (error) { + console.error('Fehler beim Abrufen des Jobs vom Backend:', error); + return new Response(JSON.stringify({ error: 'Backend nicht erreichbar' }), { + status: 500, + headers: { 'Content-Type': 'application/json' } + }); + } +} + +export async function PUT( + request: Request, + { params }: { params: { id: string } } +) { + try { + const id = params.id; + const body = await request.json(); + + // Sende Job-Aktualisierung an das externe Backend + const response = await fetch(`${API_ENDPOINTS.JOBS}/${id}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(body) + }); + + if (!response.ok) { + console.error(`Backend-Fehler: ${response.status} ${response.statusText}`); + return new Response(JSON.stringify({ error: 'Backend nicht erreichbar' }), { + status: 502, + headers: { 'Content-Type': 'application/json' } + }); + } + + const result = await response.json(); + return Response.json(result); + } catch (error) { + console.error('Fehler beim Aktualisieren des Jobs:', error); + return new Response(JSON.stringify({ error: 'Fehler beim Aktualisieren des Jobs' }), { + status: 500, + headers: { 'Content-Type': 'application/json' } + }); + } +} + +export async function DELETE( + request: Request, + { params }: { params: { id: string } } +) { + try { + const id = params.id; + + // Sende Job-Löschung an das externe Backend + const response = await fetch(`${API_ENDPOINTS.JOBS}/${id}`, { + method: 'DELETE' + }); + + if (!response.ok) { + console.error(`Backend-Fehler: ${response.status} ${response.statusText}`); + return new Response(JSON.stringify({ error: 'Backend nicht erreichbar' }), { + status: 502, + headers: { 'Content-Type': 'application/json' } + }); + } + + const result = await response.json(); + return Response.json(result); + } catch (error) { + console.error('Fehler beim Löschen des Jobs:', error); + return new Response(JSON.stringify({ error: 'Fehler beim Löschen des Jobs' }), { + status: 500, + headers: { 'Content-Type': 'application/json' } + }); + } +} \ No newline at end of file diff --git a/packages/reservation-platform/src/app/api/jobs/route.ts b/packages/reservation-platform/src/app/api/jobs/route.ts new file mode 100644 index 0000000..be13688 --- /dev/null +++ b/packages/reservation-platform/src/app/api/jobs/route.ts @@ -0,0 +1,59 @@ +import { API_ENDPOINTS } from "@/utils/api-config"; + +export const dynamic = "force-dynamic"; + +export async function GET() { + try { + // Rufe Jobs vom externen Backend ab + const response = await fetch(API_ENDPOINTS.JOBS); + + if (!response.ok) { + console.error(`Backend-Fehler: ${response.status} ${response.statusText}`); + return new Response(JSON.stringify({ error: 'Backend nicht erreichbar' }), { + status: 502, + headers: { 'Content-Type': 'application/json' } + }); + } + + const jobs = await response.json(); + return Response.json(jobs); + } catch (error) { + console.error('Fehler beim Abrufen der Jobs vom Backend:', error); + return new Response(JSON.stringify({ error: 'Backend nicht erreichbar' }), { + status: 500, + headers: { 'Content-Type': 'application/json' } + }); + } +} + +export async function POST(request: Request) { + try { + const body = await request.json(); + + // Sende Job-Erstellung an das externe Backend + const response = await fetch(API_ENDPOINTS.JOBS, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(body) + }); + + if (!response.ok) { + console.error(`Backend-Fehler: ${response.status} ${response.statusText}`); + return new Response(JSON.stringify({ error: 'Backend nicht erreichbar' }), { + status: 502, + headers: { 'Content-Type': 'application/json' } + }); + } + + const result = await response.json(); + return Response.json(result); + } catch (error) { + console.error('Fehler beim Erstellen des Jobs:', error); + return new Response(JSON.stringify({ error: 'Fehler beim Erstellen des Jobs' }), { + status: 500, + headers: { 'Content-Type': 'application/json' } + }); + } +} \ No newline at end of file diff --git a/packages/reservation-platform/src/app/api/printers/route.ts b/packages/reservation-platform/src/app/api/printers/route.ts index d9e06fb..6f641ae 100644 --- a/packages/reservation-platform/src/app/api/printers/route.ts +++ b/packages/reservation-platform/src/app/api/printers/route.ts @@ -1,9 +1,27 @@ -import { getPrinters } from "@/server/actions/printers"; +import { API_ENDPOINTS } from "@/utils/api-config"; export const dynamic = "force-dynamic"; export async function GET() { - const printers = await getPrinters(); - - return Response.json(printers); + try { + // Rufe Drucker vom externen Backend ab statt von der lokalen Datenbank + const response = await fetch(API_ENDPOINTS.PRINTERS); + + if (!response.ok) { + console.error(`Backend-Fehler: ${response.status} ${response.statusText}`); + return new Response(JSON.stringify({ error: 'Backend nicht erreichbar' }), { + status: 502, + headers: { 'Content-Type': 'application/json' } + }); + } + + const printers = await response.json(); + return Response.json(printers); + } catch (error) { + console.error('Fehler beim Abrufen der Drucker vom Backend:', error); + return new Response(JSON.stringify({ error: 'Backend nicht erreichbar' }), { + status: 500, + headers: { 'Content-Type': 'application/json' } + }); + } } diff --git a/packages/reservation-platform/src/utils/api-config.ts b/packages/reservation-platform/src/utils/api-config.ts new file mode 100644 index 0000000..528b003 --- /dev/null +++ b/packages/reservation-platform/src/utils/api-config.ts @@ -0,0 +1,9 @@ +// Basis-URL für Backend-API +export const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://192.168.0.105:5000"; + +// Endpunkte für die verschiedenen Ressourcen +export const API_ENDPOINTS = { + PRINTERS: `${API_BASE_URL}/api/printers`, + JOBS: `${API_BASE_URL}/api/jobs`, + USERS: `${API_BASE_URL}/api/users`, +}; \ No newline at end of file diff --git a/packages/reservation-platform/src/utils/external-api.ts b/packages/reservation-platform/src/utils/external-api.ts new file mode 100644 index 0000000..5ed9ff2 --- /dev/null +++ b/packages/reservation-platform/src/utils/external-api.ts @@ -0,0 +1,78 @@ +import { API_ENDPOINTS } from './api-config'; + +// Typdefinitionen für API-Responses +export interface Printer { + id: string; + name: string; + ip: string; + status: string; + is_enabled: boolean; +} + +export interface Job { + id: string; + printer_id: string; + user_id: string; + start_time: string; + end_time: string; + status: string; +} + +// Fetcher für SWR mit Fehlerbehandlung +const fetchWithErrorHandling = async (url: string) => { + const response = await fetch(url); + + if (!response.ok) { + const error = new Error('Ein Fehler ist bei der API-Anfrage aufgetreten'); + throw error; + } + + return response.json(); +}; + +// API-Funktionen +export const api = { + // Drucker-Endpunkte + printers: { + getAll: () => fetchWithErrorHandling(API_ENDPOINTS.PRINTERS), + getById: (id: string) => fetchWithErrorHandling(`${API_ENDPOINTS.PRINTERS}/${id}`), + create: (data: Partial) => + fetch(API_ENDPOINTS.PRINTERS, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(data), + }).then(res => res.json()), + update: (id: string, data: Partial) => + fetch(`${API_ENDPOINTS.PRINTERS}/${id}`, { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(data), + }).then(res => res.json()), + delete: (id: string) => + fetch(`${API_ENDPOINTS.PRINTERS}/${id}`, { + method: 'DELETE', + }).then(res => res.json()), + }, + + // Jobs-Endpunkte + jobs: { + getAll: () => fetchWithErrorHandling(API_ENDPOINTS.JOBS), + getById: (id: string) => fetchWithErrorHandling(`${API_ENDPOINTS.JOBS}/${id}`), + create: (data: Partial) => + fetch(API_ENDPOINTS.JOBS, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(data), + }).then(res => res.json()), + update: (id: string, data: Partial) => + fetch(`${API_ENDPOINTS.JOBS}/${id}`, { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(data), + }).then(res => res.json()), + delete: (id: string) => + fetch(`${API_ENDPOINTS.JOBS}/${id}`, { + method: 'DELETE', + }).then(res => res.json()), + }, +}; \ No newline at end of file