This commit is contained in:
simonaltschaffl@gmail.com 2025-11-11 17:40:02 +01:00
parent 2bbc73375d
commit 7b0be73de9
3 changed files with 85 additions and 52 deletions

View File

@ -3,11 +3,11 @@ import { Container, Row, Col, Card, Badge, Table, Button, Form, Nav } from "reac
import mermaid from "mermaid"; import mermaid from "mermaid";
const Wireframe = ({ title, children }) => ( const Wireframe = ({ title, children }) => (
<Col md={6} lg={4} className="mb-4"> <Col md={6} lg={4} className="mb-4" style={{ minWidth: 0 }}>
<Card className="h-100 shadow-sm"> <Card className="h-100 shadow-sm" style={{ overflow: 'hidden' }}>
<Card.Header as="h5" className="text-center bg-light">{title}</Card.Header> <Card.Header as="h5" className="text-center bg-light">{title}</Card.Header>
<Card.Body className="d-flex justify-content-center align-items-center p-2"> <Card.Body className="d-flex justify-content-center align-items-center p-2" style={{ overflow: 'hidden' }}>
<div className="bg-white w-100 h-100 border rounded-3 shadow-inner p-3 d-flex flex-column" style={{ aspectRatio: '9 / 19.5' }}> <div className="bg-white w-100 h-100 border rounded-3 shadow-inner p-3 d-flex flex-column" style={{ aspectRatio: '9 / 19.5', overflow: 'hidden' }}>
{children} {children}
</div> </div>
</Card.Body> </Card.Body>
@ -18,17 +18,33 @@ const Wireframe = ({ title, children }) => (
function KrimiDinner() { function KrimiDinner() {
useEffect(() => { useEffect(() => {
mermaid.initialize({ startOnLoad: false, theme: 'neutral' }); // Initialize mermaid and only run if there are mermaid diagrams on the page
try { try {
mermaid.run(); mermaid.initialize({ startOnLoad: false, theme: 'neutral' });
} catch (e) { const mermaidEls = typeof document !== 'undefined' ? document.querySelectorAll('.mermaid') : [];
console.error("Mermaid run error:", e); if (mermaid && typeof mermaid.run === 'function' && mermaidEls.length > 0) {
try {
mermaid.run();
} catch (e) {
if (e && e.message) {
console.error("Mermaid run error:", e.message, e);
} else {
try {
console.error("Mermaid run error (stringified):", JSON.stringify(e));
} catch (stringifyErr) {
console.error("Mermaid run error (object):", e);
}
}
}
}
} catch (initErr) {
console.error('Mermaid init error:', initErr);
} }
}, []); }, []);
return ( return (
<div className="project-page"> <div className="project-page">
<Container> <Container className="mt-4">
<header className="text-center border-bottom pb-4 mb-5"> <header className="text-center border-bottom pb-4 mb-5">
<h1 className="project-title">Projekt-Blaupause: KI-Krimi-Dinner "Projekt Chimera"</h1> <h1 className="project-title">Projekt-Blaupause: KI-Krimi-Dinner "Projekt Chimera"</h1>
<div className="mt-4 d-flex justify-content-center flex-wrap"> <div className="mt-4 d-flex justify-content-center flex-wrap">
@ -114,40 +130,36 @@ function KrimiDinner() {
<p> <p>
Die Architektur ist auf maximale Kontrolle und Skalierbarkeit ausgelegt. Die React Native-Clients kommunizieren ausschließlich mit dem FastAPI-Backend. Echtzeit-Updates werden über eine WebSocket-Verbindung gepusht. Die Architektur ist auf maximale Kontrolle und Skalierbarkeit ausgelegt. Die React Native-Clients kommunizieren ausschließlich mit dem FastAPI-Backend. Echtzeit-Updates werden über eine WebSocket-Verbindung gepusht.
</p> </p>
<div className="text-center bg-light p-3 rounded"> <div className="text-center bg-light p-3 rounded mermaid">
<pre className="mermaid"> {`graph TD
{` subgraph "Spieler-Geräte"
graph TD P1["React Native Apps"]
subgraph "Spieler-Geräte" end
P1["React Native Apps"]
end
subgraph "Authentifizierung" subgraph "Authentifizierung"
Auth["Supabase Auth"] Auth["Supabase Auth"]
end end
subgraph "Sicheres Backend" subgraph "Sicheres Backend"
FastAPI["FastAPI Server <br> REST & WebSockets"] FastAPI["FastAPI Server <br> REST & WebSockets"]
end end
subgraph "Spieldaten-Bank" subgraph "Spieldaten-Bank"
PG_DB["PostgreSQL DB"] PG_DB["PostgreSQL DB"]
end end
subgraph "Externe Dienste" subgraph "Externe Dienste"
OAI["OpenAI API"] OAI["OpenAI API"]
end end
%% Verbindungen %% Verbindungen
P1 -- "1. Login" --> Auth P1 -- "1. Login" --> Auth
P1 -- "2. API Calls (mit Token)" --> FastAPI P1 -- "2. API Calls (mit Token)" --> FastAPI
FastAPI -- "3. KI Call" --> OAI FastAPI -- "3. KI Call" --> OAI
FastAPI -- "4. DB-Zugriff" --> PG_DB FastAPI -- "4. DB-Zugriff" --> PG_DB
FastAPI -- "5. WebSocket Updates" --> P1 FastAPI -- "5. WebSocket Updates" --> P1`}
`}
</pre>
</div> </div>
<h3 className="mt-4">Datenfluss-Beschreibung:</h3> <h3 className="mt-4">Datenfluss-Beschreibung:</h3>
<ol> <ol>
@ -162,6 +174,7 @@ function KrimiDinner() {
<section className="mb-5"> <section className="mb-5">
<h2>4. User Interface (UI) Konzept</h2> <h2>4. User Interface (UI) Konzept</h2>
<p>Die UI-Konzepte werden als klare, moderne Wireframes visualisiert, um den gesamten App-Flow darzustellen.</p> <p>Die UI-Konzepte werden als klare, moderne Wireframes visualisiert, um den gesamten App-Flow darzustellen.</p>
<Container fluid className="px-0">
<Row> <Row>
<Wireframe title="1. Login"> <Wireframe title="1. Login">
<div className="text-center pt-4 pb-3"> <div className="text-center pt-4 pb-3">
@ -439,6 +452,7 @@ function KrimiDinner() {
</div> </div>
</Wireframe> </Wireframe>
</Row> </Row>
</Container>
</section> </section>
<section className="mb-5"> <section className="mb-5">

View File

@ -5,6 +5,14 @@ import './styles/styles.css';
import App from "./components/app"; import App from "./components/app";
const root = ReactDOM.createRoot(document.getElementById("root")); const root = ReactDOM.createRoot(document.getElementById("root"));
// Global error handlers to surface full error objects for debugging in the browser console
window.addEventListener('error', (event) => {
// event.error may be an Error instance or any thrown value
console.error('Global error event:', event.error ?? event.message ?? event);
});
window.addEventListener('unhandledrejection', (event) => {
console.error('Unhandled promise rejection:', event.reason);
});
root.render( root.render(
<React.StrictMode> <React.StrictMode>
<div className="app-container"> <div className="app-container">

View File

@ -6,6 +6,9 @@ body {
margin: 0; margin: 0;
padding: 0; padding: 0;
overflow-x: hidden; overflow-x: hidden;
width: 100%;
max-width: 100vw;
box-sizing: border-box;
} }
.app-container { .app-container {
@ -57,9 +60,17 @@ a {
text-decoration: none; text-decoration: none;
} }
a:hover { code {
color: #0056b3; overflow-x: auto;
text-decoration: underline; word-break: break-all;
max-width: 100%;
}
pre {
overflow-x: auto;
max-width: 100%;
word-wrap: break-word;
white-space: pre-wrap;
} }
.navigation { .navigation {
@ -78,7 +89,7 @@ a:hover {
padding-top: 0.8rem; padding-top: 0.8rem;
padding-bottom: 0.8rem; padding-bottom: 0.8rem;
width: 100%; width: 100%;
max-width: 1100px; max-width: 1000px;
} }
.my-name { .my-name {
@ -194,9 +205,9 @@ section {
.project-page { .project-page {
overflow-x: hidden; overflow-x: hidden;
width: 100%;
box-sizing: border-box;
} }
@ -206,15 +217,15 @@ section {
.mermaid { .mermaid {
overflow: hidden !important;
overflow-x: auto;
text-align: center; text-align: center;
max-width: 100%;
width: 100%;
box-sizing: border-box;
display: block;
}
.mermaid svg {
max-width: 100% !important;
height: auto !important;
} }