diff --git a/.phase39-state.json b/.phase39-state.json index 58afdbd..4e4a8ca 100644 --- a/.phase39-state.json +++ b/.phase39-state.json @@ -5,6 +5,7 @@ "attempted_features": [ "file-upload-component", "image-gallery-component", - "key-value-list-component" + "key-value-list-component", + "code-block-component" ] } \ No newline at end of file diff --git a/.phase40-state.json b/.phase40-state.json new file mode 100644 index 0000000..65dc5b9 --- /dev/null +++ b/.phase40-state.json @@ -0,0 +1,5 @@ +{ + "completed_features": [], + "current_feature": "sidebar-component", + "started_at": "2026-05-23T10:18:26.780535" +} \ No newline at end of file diff --git a/GENERATION_LOG.md b/GENERATION_LOG.md index 2cd0280..fd00316 100644 --- a/GENERATION_LOG.md +++ b/GENERATION_LOG.md @@ -4186,3 +4186,28 @@ src/index.ts(27,25): error TS2769: No overload matches this call. Overload 1 of 3, '(plugin: FastifyPluginCallback<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error. Argument of type 'Promise' is not assignable to parameter of type 'FastifyPluginCallback<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'. Type 'Promise' provides no match for the signature '(instance: FastifyInstance, +- `10:14:59` **INFO** Committed feature code-block-component +- `10:14:59` **INFO** Pushed: rc=0 + +## Phase-39 Run beendet (2026-05-23 10:14:59) + +- `10:14:59` **INFO** OK: 0, Attempted: 4, Total: 4 + +## 🚀 Phase-40 Codegen-Run gestartet (2026-05-23 10:18:26) + + +## Phase-3 Feature: sidebar-component (2026-05-23 10:18:26) + +- `10:18:26` **INFO** Description: Sidebar mit collapse-Logik +- `10:18:26` **INFO** Generating apps/web/src/components/Sidebar.tsx (Sidebar-Component. Props: items (array {to, label, icon?}), collapsed?…) +- `10:18:49` **INFO** wrote 2628 chars in 22.4s (attempt 1) +- `10:18:49` **INFO** Running tsc --noEmit on api… +- `10:18:50` **WARN** tsc errors: +src/db/schema.ts(37,14): error TS7022: 'customers' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. +src/db/schema.ts(45,59): error TS7024: Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions. +src/db/schema.ts(49,14): error TS7022: 'projects' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. +src/db/schema.ts(53,56): error TS7024: Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions. +src/index.ts(27,25): error TS2769: No overload matches this call. + Overload 1 of 3, '(plugin: FastifyPluginCallback<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error. + Argument of type 'Promise' is not assignable to parameter of type 'FastifyPluginCallback<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'. + Type 'Promise' provides no match for the signature '(instance: FastifyInstance, diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx new file mode 100644 index 0000000..4c1a8bc --- /dev/null +++ b/apps/web/src/components/Sidebar.tsx @@ -0,0 +1,77 @@ +import React from 'react'; +import { Link } from '@tanstack/react-router'; +import { ChevronLeft, ChevronRight } from 'lucide-react'; +import { cn } from '@emberclone/shared/utils'; + +interface SidebarItem { + to: string; + label: string; + icon?: React.ElementType; +} + +interface SidebarProps { + items: SidebarItem[]; + collapsed?: boolean; + onToggle?: () => void; +} + +export default function Sidebar({ items, collapsed = false, onToggle }: SidebarProps) { + return ( + + ); +} \ No newline at end of file diff --git a/scripts/phase40_features.py b/scripts/phase40_features.py new file mode 100644 index 0000000..452c681 --- /dev/null +++ b/scripts/phase40_features.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +"""Phase-40: standalone components — Sidebar, Logo, FormGroup, Banner.""" + +from __future__ import annotations + +import asyncio, datetime, json, sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).resolve().parent)) +from phase2_features import Feature, FileGen, ROOT, log, log_section +from phase3_features import run_feature_v2 + +PHASE_STATE = ROOT / ".phase40-state.json" + +FEATURES: list[Feature] = [ + Feature( + name="sidebar-component", + description="Sidebar mit collapse-Logik", + files=[FileGen( + path="apps/web/src/components/Sidebar.tsx", + purpose=( + "Sidebar-Component. Props: items (array {to, label, icon?}), collapsed?: boolean, onToggle?(). " + "Vertikale Navigation. Wenn collapsed: nur Icons (width w-16), sonst w-64 mit Labels. " + "ChevronLeft/Right Toggle button. Tailwind. Export default." + ), + )], + ), + Feature( + name="logo-component", + description="Logo SVG + Text", + files=[FileGen( + path="apps/web/src/components/Logo.tsx", + purpose=( + "Logo-Component. Props: size?: 'sm'|'md'|'lg', showText?: boolean. " + "Inline-SVG eines Flammen-Symbols (Ember) in orange + Text 'EmberClone' (text-zinc-900 dark:text-zinc-100 font-bold). " + "Tailwind. Export default." + ), + )], + ), + Feature( + name="form-group-component", + description="FormGroup wrapper für Label/Input/Error", + files=[FileGen( + path="apps/web/src/components/FormGroup.tsx", + purpose=( + "FormGroup-Component. Props: label, htmlFor?, error?, helpText?, required?, children. " + "Wrapper-div. Label oben (text-sm font-medium) + optional red asterisk wenn required. " + "Children (Input slot). Error rot drunter ODER helpText grau drunter. Tailwind. Export default." + ), + )], + ), + Feature( + name="banner-component", + description="Banner für Top-Bar (e.g. Trial-Hinweis)", + files=[FileGen( + path="apps/web/src/components/Banner.tsx", + purpose=( + "Banner-Component. Props: message, variant?: 'info'|'warning'|'success', actionLabel?, onAction?, dismissible?. " + "Volle-Breite Top-Bar mit Tailwind bg per variant. Center content + optional CTA-Button + optional X. " + "Export default." + ), + )], + ), +] + + +def load_state(): + if PHASE_STATE.exists(): + return json.loads(PHASE_STATE.read_text()) + return {"completed_features": [], "current_feature": None, "started_at": datetime.datetime.now().isoformat()} + + +def save_state(state): + PHASE_STATE.write_text(json.dumps(state, indent=2)) + + +async def main(): + log_section("🚀 Phase-40 Codegen-Run gestartet") + state = load_state() + for feature in FEATURES: + if feature.name in state.get("completed_features", []): + continue + state["current_feature"] = feature.name; save_state(state) + try: + success = await run_feature_v2(feature) + state.setdefault("completed_features" if success else "attempted_features", []).append(feature.name) + save_state(state) + except Exception as e: + log(f"❌ {feature.name} crashed: {e}", level="ERROR") + state.setdefault("attempted_features", []).append(feature.name); save_state(state) + log_section("Phase-40 Run beendet") + log(f"OK: {len(state.get('completed_features', []))}, Attempted: {len(state.get('attempted_features', []))}, Total: {len(FEATURES)}") + return 0 + + +if __name__ == "__main__": + sys.exit(asyncio.run(main()))