#!/bin/bash # ============================================================== # BAN YARO — Neues Feature anlegen # Erstellt alle nötigen Dateien für eine neue Seite/Feature. # Verwendung: bash scripts/new-feature.sh # Beispiel: bash scripts/new-feature.sh poison # ============================================================== set -e FEATURE="$1" if [ -z "$FEATURE" ]; then echo "Verwendung: bash scripts/new-feature.sh " echo "Beispiel: bash scripts/new-feature.sh poison" exit 1 fi # Snake_case für JS-Modul-Name (bindestriche → unterstriche) JS_NAME=$(echo "$FEATURE" | tr '-' '_') # Titel (erstes Buchstabe groß) TITLE=$(echo "$FEATURE" | sed 's/-/ /g' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) substr($i,2); print}') ROOT="$(cd "$(dirname "$0")/.." && pwd)" echo "=== Neues Feature: $FEATURE ===" # ---------------------------------------------------------- # 1. Frontend: JS-Seiten-Modul # ---------------------------------------------------------- JS_FILE="$ROOT/backend/static/js/pages/${FEATURE}.js" if [ -f "$JS_FILE" ]; then echo " ⚠️ $JS_FILE existiert bereits, übersprungen." else cat > "$JS_FILE" << EOF /* ============================================================ BAN YARO — ${TITLE} Seiten-Modul. Wird von App.js lazy geladen. ============================================================ */ window.Page_${JS_NAME} = (() => { let _container = null; let _state = null; // ---------------------------------------------------------- async function init(container, appState) { _container = container; _state = appState; await render(); } // ---------------------------------------------------------- async function render() { _container.innerHTML = UI.skeleton(3); try { // TODO: Daten laden // const data = await API.${JS_NAME}.list(...); _container.innerHTML = \`

${TITLE}

Noch in Entwicklung.

\`; } catch (err) { _container.innerHTML = UI.emptyState({ icon: '⚠️', title: 'Fehler beim Laden', text: err.message, }); } } // Vom + Button aufgerufen function openNew() { // TODO: Neuer Eintrag Modal } // Wenn User Hund wechselt function onDogChange(dog) { if (_container) render(); } // Bei erneutem Seitenaufruf function refresh() { if (_container) render(); } return { init, refresh, openNew, onDogChange }; })(); EOF echo " ✓ Frontend: backend/static/js/pages/${FEATURE}.js" fi # ---------------------------------------------------------- # 2. Backend: Route # ---------------------------------------------------------- ROUTE_FILE="$ROOT/backend/routes/${FEATURE}.py" if [ -f "$ROUTE_FILE" ]; then echo " ⚠️ $ROUTE_FILE existiert bereits, übersprungen." else cat > "$ROUTE_FILE" << EOF """BAN YARO — ${TITLE} Routes""" from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel from typing import Optional from database import db from auth import get_current_user router = APIRouter() # TODO: Pydantic-Modelle definieren # class ${TITLE}Create(BaseModel): # ... # TODO: Endpoints implementieren # @router.get("") # async def list_${JS_NAME}(user=Depends(get_current_user)): # ... EOF echo " ✓ Backend: backend/routes/${FEATURE}.py" fi # ---------------------------------------------------------- # 3. Hinweis: Router in main.py registrieren # ---------------------------------------------------------- echo "" echo " Noch manuell in backend/main.py eintragen:" echo " from routes.${FEATURE} import router as ${JS_NAME}_router" echo " app.include_router(${JS_NAME}_router, prefix='/api/${FEATURE}', tags=['${TITLE}'])" echo "" echo "=== Fertig. Viel Spaß beim Bauen! ==="