Owadokun Tosin Tobi commited on
Commit
f7fce54
·
unverified ·
1 Parent(s): 17b209e

A critical fix to prevent page reload

Files changed (1) hide show
  1. app/components.py +72 -39
app/components.py CHANGED
@@ -1,73 +1,106 @@
1
  from fasthtml.common import *
2
 
3
- def Layout(title, content):
4
- """Global Page Layout with PicoCSS"""
 
 
 
5
  return Html(
6
  Head(
7
  Title(title),
8
- # PicoCSS: Minimalist Semantic CSS
9
  Link(rel="stylesheet", href="https://cdn.jsdelivr.net/npm/@picocss/pico@latest/css/pico.min.css"),
10
- # PrismJS: For beautiful JSON Syntax Highlighting
 
 
 
 
11
  Link(rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css"),
12
  Script(src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js"),
13
  Script(src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-json.min.js"),
14
- Style("body { max-width: 800px; margin: 0 auto; padding: 20px; }")
 
 
 
 
 
 
 
 
15
  ),
16
  Body(
17
  Header(
18
- H1("🛡️ Structura", style="color: #00E5FF; margin-bottom: 0;"),
19
  P("The Unbreakable Data Architect", style="opacity: 0.7;"),
20
  style="border-bottom: 1px solid #333; padding-bottom: 20px; margin-bottom: 40px;"
21
  ),
22
- Main(content),
23
  Footer(
24
- P("Powered by PydanticAI & Gemini 2.5", style="text-align: center; opacity: 0.5; font-size: 0.8rem;")
25
  )
26
  )
27
  )
28
 
29
- def InputForm():
30
- """The HTMX-powered Input Form"""
 
 
 
 
 
 
 
 
 
 
 
31
  return Form(
32
- Label("Raw Input Data", cls="label"),
33
  Textarea(
34
  name="text_input",
35
- placeholder="Paste messy text here (Email, Invoice, Job Post)...",
36
  rows=8,
37
- style="font-family: monospace;"
38
  ),
39
 
40
- Label("Target Schema", cls="label"),
41
- Select(
42
- Option("Invoice Extraction", value="invoice"),
43
- Option("Resume Parsing", value="resume"),
44
- Option("Email Summary", value="email"),
45
- name="schema_type"
 
 
 
 
 
46
  ),
47
 
48
  Button("Extract Structure ⚡", cls="contrast", type="submit"),
49
 
50
- # HTMX Magic: Swaps the result div without reloading page
51
  hx_post="/extract",
52
  hx_target="#result-area",
53
- hx_swap="innerHTML"
 
54
  )
55
 
56
- def ResultDisplay(json_data=None, error=None):
57
- """Renders the output or error state"""
58
- if error:
59
- return Div(
60
- H4("❌ Extraction Failed"),
61
- P(error),
62
- style="background: #3d1a1a; color: #ff8080; padding: 15px; border-radius: 8px; border: 1px solid #ff4d4d;"
63
- )
64
-
65
- if json_data:
66
- return Div(
67
- H4("✅ Validated JSON Output"),
68
- # Pre/Code blocks triggered PrismJS highlighting
69
- Pre(Code(json_data, cls="language-json")),
70
- P("Schema validation passed.", style="color: #00E5FF; font-size: 0.8rem; margin-top: 10px;")
71
- )
72
-
73
- return Div(id="result-area") # Empty placeholder
 
 
1
  from fasthtml.common import *
2
 
3
+ def PageLayout(title: str, content: list):
4
+ """
5
+ The Base Layout.
6
+ Injects PicoCSS (Styling), PrismJS (Syntax Highlight), and HTMX (Interactivity).
7
+ """
8
  return Html(
9
  Head(
10
  Title(title),
11
+ # 1. PicoCSS: Semantic minimalist framework
12
  Link(rel="stylesheet", href="https://cdn.jsdelivr.net/npm/@picocss/pico@latest/css/pico.min.css"),
13
+
14
+ # 2. HTMX (CRITICAL FIX: Prevents page reloads)
15
+ Script(src="https://unpkg.com/htmx.org@1.9.10"),
16
+
17
+ # 3. PrismJS: For beautiful JSON highlighting
18
  Link(rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css"),
19
  Script(src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js"),
20
  Script(src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-json.min.js"),
21
+
22
+ # Custom Styles
23
+ Style("""
24
+ body { max-width: 900px; margin: 0 auto; padding: 20px; background-color: #11191f; }
25
+ .json-box { border-radius: 8px; overflow: hidden; margin-top: 20px; }
26
+ h1 { color: #00E5FF; }
27
+ button.contrast { background-color: #00E5FF; border-color: #00E5FF; color: black; font-weight: bold; }
28
+ .error-box { background: #3d1a1a; color: #ff8080; padding: 15px; border-radius: 8px; border: 1px solid #ff4d4d; }
29
+ """)
30
  ),
31
  Body(
32
  Header(
33
+ H1("🛡️ Structura"),
34
  P("The Unbreakable Data Architect", style="opacity: 0.7;"),
35
  style="border-bottom: 1px solid #333; padding-bottom: 20px; margin-bottom: 40px;"
36
  ),
37
+ Main(*content),
38
  Footer(
39
+ P("Powered by PydanticAI & Gemini 2.5", style="text-align: center; opacity: 0.5; font-size: 0.8rem; margin-top: 50px;")
40
  )
41
  )
42
  )
43
 
44
+ # ... (Rest of components.py remains the same)
45
+ def HeroSection():
46
+ return Div(
47
+ H2("Turn Chaos into Structure"),
48
+ P("Paste messy emails, invoices, or resumes below. Get guaranteed, type-safe JSON back."),
49
+ style="margin-bottom: 30px;"
50
+ )
51
+
52
+ def ExtractionForm():
53
+ """
54
+ The Interactive Form.
55
+ Uses HTMX (hx-post) to swap the result area without a page reload.
56
+ """
57
  return Form(
58
+ Label("Raw Input Data"),
59
  Textarea(
60
  name="text_input",
61
+ placeholder="e.g. Invoice #909 from CloudFix for $500...",
62
  rows=8,
63
+ style="font-family: monospace; background: #0b0f13; color: white; border: 1px solid #333;"
64
  ),
65
 
66
+ Grid(
67
+ Label("Target Schema",
68
+ Select(
69
+ Option("Invoice Extraction", value="invoice"),
70
+ Option("Resume Parsing", value="resume"),
71
+ Option("Generic Data", value="generic"),
72
+ name="schema_type"
73
+ )
74
+ ),
75
+ # Empty div for grid balance or future features
76
+ Div()
77
  ),
78
 
79
  Button("Extract Structure ⚡", cls="contrast", type="submit"),
80
 
81
+ # HTMX Configuration
82
  hx_post="/extract",
83
  hx_target="#result-area",
84
+ hx_swap="innerHTML",
85
+ hx_indicator="#loading"
86
  )
87
 
88
+ def LoadingIndicator():
89
+ return Div("⚙️ AI is processing...", id="loading", cls="htmx-indicator", style="color: #00E5FF; margin-top: 10px;")
90
+
91
+ def SuccessDisplay(json_str: str):
92
+ return Div(
93
+ H4("✅ Validated Output", style="color: #4ade80; margin-bottom: 10px;"),
94
+ Div(
95
+ Pre(Code(json_str, cls="language-json")),
96
+ cls="json-box"
97
+ ),
98
+ P("Schema Verified by PydanticAI", style="color: grey; font-size: 0.8rem; margin-top: 10px; text-align: right;")
99
+ )
100
+
101
+ def ErrorDisplay(error_msg: str):
102
+ return Div(
103
+ H4("❌ Extraction Failed"),
104
+ P(error_msg),
105
+ cls="error-box"
106
+ )