Kushal commited on
Commit
7922299
·
1 Parent(s): 1064345

Update: Backend PDF engine and report templates (cleaned environment)

Browse files
.gitignore ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ .venv/
5
+ venv/
6
+ ENV/
7
+ .env
8
+ .pytest_cache/
9
+ *.pdf
10
+ data/generated_reports/
app/templates/investor-pitch-deck.html ADDED
@@ -0,0 +1,248 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Investor Pitch Deck</title>
6
+ <style>
7
+ @page {
8
+ size: A4;
9
+ margin: 1in;
10
+ @bottom-center {
11
+ content: "Generated by Builders.ai • Page " counter(page);
12
+ font-style: italic;
13
+ font-size: 0.95em;
14
+ color: #888;
15
+ }
16
+ }
17
+ html, body {
18
+ height: 100%;
19
+ font-family: 'Segoe UI', 'DejaVu Sans', Arial, sans-serif;
20
+ background: #f6f8fa;
21
+ }
22
+ body {
23
+ margin: 0;
24
+ padding: 0;
25
+ background: #f6f8fa;
26
+ }
27
+ .report-wrapper {
28
+ max-width: 900px;
29
+ margin: 0 auto;
30
+ background: #fff;
31
+ border-radius: 8px;
32
+ box-shadow: 0 1px 4px rgba(50,80,150,0.1);
33
+ padding: 40px 60px 30px 60px;
34
+ }
35
+ .header {
36
+ border-bottom: 2px solid #2C4694;
37
+ padding-bottom: 18px;
38
+ margin-bottom: 30px;
39
+ text-align: center;
40
+ }
41
+ .main-title {
42
+ font-size: 2.2em;
43
+ color: #2C4694;
44
+ font-weight: bold;
45
+ margin-bottom: 4px;
46
+ }
47
+ .subtitle {
48
+ color: #7087B1;
49
+ font-size: 1.08em;
50
+ font-weight: 500;
51
+ }
52
+ .report-date {
53
+ color: #434343;
54
+ font-size: 1em;
55
+ margin-top: 10px;
56
+ font-style: italic;
57
+ }
58
+ h2 {
59
+ color: #2C4694;
60
+ font-size: 1.22em;
61
+ margin-top: 2.3em;
62
+ text-transform: uppercase;
63
+ border-bottom: 1.5px solid #DCE3F2;
64
+ padding-bottom: 1.5px;
65
+ letter-spacing: 0.04em;
66
+ }
67
+ .detail-table {
68
+ margin: 1.5em 0 2em 0;
69
+ width: 100%;
70
+ border-collapse: collapse;
71
+ }
72
+ .detail-table th, .detail-table td {
73
+ padding: 10px 16px 10px 0;
74
+ vertical-align: top;
75
+ }
76
+ .detail-table th {
77
+ text-align: left;
78
+ color: #32345a;
79
+ background: #fafbff;
80
+ font-weight: 600;
81
+ border-right: 2px solid #f2f3f7;
82
+ min-width: 160px;
83
+ }
84
+ .detail-table td {
85
+ color: #25334d;
86
+ }
87
+ .content-box {
88
+ padding: 18px 22px;
89
+ margin-top: 0.7em;
90
+ border-radius: 6px;
91
+ border: 1.5px solid #e1e9f7;
92
+ background: #f7fafd;
93
+ font-size: 1.06em;
94
+ color: #283D51;
95
+ line-height: 1.55;
96
+ }
97
+ .finproj-list, .risk-list {
98
+ margin: 1.5em 0;
99
+ padding-left: 0;
100
+ list-style: none;
101
+ }
102
+ .finproj-list li, .risk-list li {
103
+ margin-bottom: 0.8em;
104
+ padding: 12px 18px;
105
+ background: #f7fafd;
106
+ border-left: 3px solid #2C4694;
107
+ border-radius: 4px;
108
+ }
109
+ .signoff {
110
+ margin-top: 3.7em;
111
+ text-align: right;
112
+ color: #6e8db2;
113
+ }
114
+
115
+ /* Editable styles */
116
+ .editable {
117
+ border: 2px dashed transparent;
118
+ padding: 2px 4px;
119
+ border-radius: 4px;
120
+ cursor: text;
121
+ transition: all 0.2s;
122
+ min-height: 1.2em;
123
+ display: inline-block;
124
+ min-width: 50px;
125
+ }
126
+ .editable:hover {
127
+ border-color: #2C4694;
128
+ background-color: rgba(44, 70, 148, 0.05);
129
+ }
130
+ .editable:focus {
131
+ outline: none;
132
+ border-color: #2C4694;
133
+ background-color: rgba(44, 70, 148, 0.1);
134
+ }
135
+ .editable-content {
136
+ border: 2px dashed transparent;
137
+ padding: 4px;
138
+ border-radius: 4px;
139
+ cursor: text;
140
+ transition: all 0.2s;
141
+ min-height: 2em;
142
+ }
143
+ .editable-content:hover {
144
+ border-color: #2C4694;
145
+ background-color: rgba(44, 70, 148, 0.05);
146
+ }
147
+ .editable-content:focus {
148
+ outline: none;
149
+ border-color: #2C4694;
150
+ background-color: rgba(44, 70, 148, 0.1);
151
+ }
152
+ .ai-button {
153
+ background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);
154
+ color: white;
155
+ border: none;
156
+ padding: 4px 8px;
157
+ border-radius: 4px;
158
+ font-size: 10px;
159
+ cursor: pointer;
160
+ margin-left: 8px;
161
+ font-weight: bold;
162
+ }
163
+ .ai-button:hover {
164
+ transform: scale(1.05);
165
+ }
166
+ </style>
167
+ </head>
168
+ <body>
169
+ <div class="report-wrapper">
170
+ <div class="header">
171
+ <div class="main-title">Investor Pitch Deck</div>
172
+ <div class="subtitle">Generated by Builders.ai</div>
173
+ <div class="report-date">{{DATE}}</div>
174
+ </div>
175
+
176
+ <h2>Project Overview</h2>
177
+ <table class="detail-table">
178
+ <tr><th>Project Name</th><td><span class="editable" contenteditable="true" data-field="project_name">{{PROJECT_NAME}}</span></td></tr>
179
+ <tr><th>Location</th><td><span class="editable" contenteditable="true" data-field="location">{{LOCATION}}</span></td></tr>
180
+ <tr><th>Project Type</th><td><span class="editable" contenteditable="true" data-field="project_type">{{PROJECT_TYPE}}</span></td></tr>
181
+ <tr><th>Investment Required</th><td><span class="editable" contenteditable="true" data-field="investment_required">{{INVESTMENT_REQUIRED}}</span></td></tr>
182
+ <tr><th>Expected Completion</th><td><span class="editable" contenteditable="true" data-field="expected_completion">{{EXPECTED_COMPLETION}}</span></td></tr>
183
+ <tr><th>Developer</th><td><span class="editable" contenteditable="true" data-field="developer_name">{{DEVELOPER_NAME}}</span></td></tr>
184
+ </table>
185
+
186
+ <h2>Market Opportunity <button class="ai-button" onclick="generateAI('market_opportunity')">✨ AI</button></h2>
187
+ <div class="content-box">
188
+ <div class="editable-content" contenteditable="true" data-field="market_opportunity">{{MARKET_OPPORTUNITY}}</div>
189
+ </div>
190
+
191
+ <h2>Financial Projections</h2>
192
+ <ul class="finproj-list">
193
+ <li><b>Projected ROI:</b> <span class="editable" contenteditable="true" data-field="roi_projection">{{ROI_PROJECTION}}</span></li>
194
+ <li><b>Financial Summary:</b> <span class="editable" contenteditable="true" data-field="financial_summary">{{FINANCIAL_SUMMARY}}</span></li>
195
+ </ul>
196
+
197
+ <h2>Risk and Mitigation</h2>
198
+ <ul class="risk-list">
199
+ <li><b>Key Risks:</b> <span class="editable" contenteditable="true" data-field="risk_factors">{{RISK_FACTORS}}</span></li>
200
+ <li><b>Mitigation Strategies:</b> <span class="editable" contenteditable="true" data-field="risk_mitigation">{{RISK_MITIGATION}}</span></li>
201
+ </ul>
202
+
203
+ <h2>Opportunity Summary <button class="ai-button" onclick="generateAI('summary')">✨ AI</button></h2>
204
+ <div class="content-box">
205
+ <div class="editable-content" contenteditable="true" data-field="summary">{{SUMMARY}}</div>
206
+ </div>
207
+
208
+ <div class="signoff">
209
+ <br/><br/>
210
+ <div>— End of Pitch Deck —</div>
211
+ </div>
212
+ </div>
213
+
214
+ <script>
215
+ // Enable design mode for rich text editing
216
+ document.addEventListener('DOMContentLoaded', function() {
217
+ document.designMode = 'on';
218
+
219
+ const editableElements = document.querySelectorAll('.editable, .editable-content');
220
+
221
+ editableElements.forEach(element => {
222
+ element.addEventListener('blur', function() {
223
+ const field = this.getAttribute('data-field');
224
+ const value = this.innerHTML || this.textContent;
225
+ if (field) {
226
+ window.parent.postMessage({
227
+ type: 'updateField',
228
+ field: field,
229
+ value: value
230
+ }, '*');
231
+ }
232
+ });
233
+
234
+ element.addEventListener('keydown', function(e) {
235
+ if (e.key === 'Enter' && !e.shiftKey && !this.classList.contains('editable-content')) {
236
+ e.preventDefault();
237
+ this.blur();
238
+ }
239
+ });
240
+ });
241
+ });
242
+
243
+ function generateAI(field) {
244
+ window.parent.postMessage({type: 'generateAI', field: field}, '*');
245
+ }
246
+ </script>
247
+ </body>
248
+ </html>
app/templates/legal-compliance.html ADDED
@@ -0,0 +1,233 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Legal Compliance Report</title>
6
+ <style>
7
+ @page {
8
+ size: A4;
9
+ margin: 1in;
10
+ @bottom-center {
11
+ content: "Generated by Builders.ai • Page " counter(page);
12
+ font-style: italic;
13
+ font-size: 0.95em;
14
+ color: #888;
15
+ }
16
+ }
17
+ html, body {
18
+ height: 100%;
19
+ font-family: 'Segoe UI', 'DejaVu Sans', Arial, sans-serif;
20
+ background: #f6f8fa;
21
+ }
22
+ body {
23
+ margin: 0;
24
+ padding: 0;
25
+ background: #f6f8fa;
26
+ }
27
+ .report-wrapper {
28
+ max-width: 900px;
29
+ margin: 0 auto;
30
+ background: #fff;
31
+ border-radius: 8px;
32
+ box-shadow: 0 1px 4px rgba(50,80,150,0.1);
33
+ padding: 40px 60px 30px 60px;
34
+ }
35
+ .header {
36
+ border-bottom: 2px solid #2C4694;
37
+ padding-bottom: 18px;
38
+ margin-bottom: 30px;
39
+ text-align: center;
40
+ }
41
+ .logo-title {
42
+ font-size: 2.2em;
43
+ color: #2C4694;
44
+ font-weight: bold;
45
+ margin-bottom: 4px;
46
+ }
47
+ .subtitle {
48
+ color: #7087B1;
49
+ font-size: 1.08em;
50
+ font-weight: 500;
51
+ }
52
+ .report-date {
53
+ color: #434343;
54
+ font-size: 1em;
55
+ margin-top: 10px;
56
+ font-style: italic;
57
+ }
58
+ h2 {
59
+ color: #2C4694;
60
+ font-size: 1.22em;
61
+ margin-top: 2.3em;
62
+ text-transform: uppercase;
63
+ border-bottom: 1.5px solid #DCE3F2;
64
+ padding-bottom: 1.5px;
65
+ letter-spacing: 0.04em;
66
+ }
67
+ .fact-table {
68
+ margin: 1.5em 0 2em 0;
69
+ width: 100%;
70
+ border-collapse: collapse;
71
+ }
72
+ .fact-table th, .fact-table td {
73
+ padding: 10px 16px 10px 0;
74
+ vertical-align: top;
75
+ }
76
+ .fact-table th {
77
+ text-align: left;
78
+ color: #32345a;
79
+ background: #fafbff;
80
+ font-weight: 600;
81
+ border-right: 2px solid #f2f3f7;
82
+ min-width: 160px;
83
+ }
84
+ .fact-table td {
85
+ color: #25334d;
86
+ }
87
+ .content-box {
88
+ padding: 18px 22px;
89
+ margin-top: 0.7em;
90
+ border-radius: 6px;
91
+ border: 1.5px solid #e1e9f7;
92
+ background: #f7fafd;
93
+ font-size: 1.06em;
94
+ color: #283D51;
95
+ line-height: 1.55;
96
+ }
97
+ .signoff {
98
+ margin-top: 3.5em;
99
+ text-align: right;
100
+ color: #7087B1;
101
+ }
102
+
103
+ /* Editable styles */
104
+ .editable {
105
+ border: 2px dashed transparent;
106
+ padding: 2px 4px;
107
+ border-radius: 4px;
108
+ cursor: text;
109
+ transition: all 0.2s;
110
+ min-height: 1.2em;
111
+ display: inline-block;
112
+ min-width: 50px;
113
+ }
114
+ .editable:hover {
115
+ border-color: #2C4694;
116
+ background-color: rgba(44, 70, 148, 0.05);
117
+ }
118
+ .editable:focus {
119
+ outline: none;
120
+ border-color: #2C4694;
121
+ background-color: rgba(44, 70, 148, 0.1);
122
+ }
123
+ .editable-content {
124
+ border: 2px dashed transparent;
125
+ padding: 4px;
126
+ border-radius: 4px;
127
+ cursor: text;
128
+ transition: all 0.2s;
129
+ min-height: 2em;
130
+ }
131
+ .editable-content:hover {
132
+ border-color: #2C4694;
133
+ background-color: rgba(44, 70, 148, 0.05);
134
+ }
135
+ .editable-content:focus {
136
+ outline: none;
137
+ border-color: #2C4694;
138
+ background-color: rgba(44, 70, 148, 0.1);
139
+ }
140
+ .ai-button {
141
+ background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);
142
+ color: white;
143
+ border: none;
144
+ padding: 4px 8px;
145
+ border-radius: 4px;
146
+ font-size: 10px;
147
+ cursor: pointer;
148
+ margin-left: 8px;
149
+ font-weight: bold;
150
+ }
151
+ .ai-button:hover {
152
+ transform: scale(1.05);
153
+ }
154
+ </style>
155
+ </head>
156
+ <body>
157
+ <div class="report-wrapper">
158
+ <div class="header">
159
+ <div class="logo-title">Legal Compliance Report</div>
160
+ <div class="subtitle">Generated by Builders.ai</div>
161
+ <div class="report-date">{{DATE}}</div>
162
+ </div>
163
+
164
+ <h2>Project Information</h2>
165
+ <table class="fact-table">
166
+ <tr><th>Property Name</th><td><span class="editable" contenteditable="true" data-field="property_name">{{PROPERTY_NAME}}</span></td></tr>
167
+ <tr><th>Location</th><td><span class="editable" contenteditable="true" data-field="location">{{LOCATION}}</span></td></tr>
168
+ <tr><th>Construction Type</th><td><span class="editable" contenteditable="true" data-field="construction_type">{{CONSTRUCTION_TYPE}}</span></td></tr>
169
+ <tr><th>Developer</th><td><span class="editable" contenteditable="true" data-field="developer_name">{{DEVELOPER_NAME}}</span></td></tr>
170
+ <tr><th>Legal Clearance Status</th><td><span class="editable" contenteditable="true" data-field="legal_clearance">{{LEGAL_CLEARANCE}}</span></td></tr>
171
+ </table>
172
+
173
+ <h2>Legal Compliance Analysis <button class="ai-button" onclick="generateAI('legal_notes')">✨ AI</button></h2>
174
+ <div class="content-box">
175
+ <div class="editable-content" contenteditable="true" data-field="legal_notes">{{LEGAL_NOTES}}</div>
176
+ </div>
177
+
178
+ <h2>Regulatory Requirements <button class="ai-button" onclick="generateAI('regulatory_requirements')">✨ AI</button></h2>
179
+ <div class="content-box">
180
+ <div class="editable-content" contenteditable="true" data-field="regulatory_requirements">{{REGULATORY_REQUIREMENTS}}</div>
181
+ </div>
182
+
183
+ <h2>Risk Assessment <button class="ai-button" onclick="generateAI('risk_assessment')">✨ AI</button></h2>
184
+ <div class="content-box">
185
+ <div class="editable-content" contenteditable="true" data-field="risk_assessment">{{RISK_ASSESSMENT}}</div>
186
+ </div>
187
+
188
+ <h2>Recommendations <button class="ai-button" onclick="generateAI('recommendations')">✨ AI</button></h2>
189
+ <div class="content-box">
190
+ <div class="editable-content" contenteditable="true" data-field="recommendations">{{RECOMMENDATIONS}}</div>
191
+ </div>
192
+
193
+ <div class="signoff">
194
+ <br/><br/>
195
+ <div>— End of Legal Report —</div>
196
+ </div>
197
+ </div>
198
+
199
+ <script>
200
+ // Enable design mode for rich text editing
201
+ document.addEventListener('DOMContentLoaded', function() {
202
+ document.designMode = 'on';
203
+
204
+ const editableElements = document.querySelectorAll('.editable, .editable-content');
205
+
206
+ editableElements.forEach(element => {
207
+ element.addEventListener('blur', function() {
208
+ const field = this.getAttribute('data-field');
209
+ const value = this.innerHTML || this.textContent;
210
+ if (field) {
211
+ window.parent.postMessage({
212
+ type: 'updateField',
213
+ field: field,
214
+ value: value
215
+ }, '*');
216
+ }
217
+ });
218
+
219
+ element.addEventListener('keydown', function(e) {
220
+ if (e.key === 'Enter' && !e.shiftKey && !this.classList.contains('editable-content')) {
221
+ e.preventDefault();
222
+ this.blur();
223
+ }
224
+ });
225
+ });
226
+ });
227
+
228
+ function generateAI(field) {
229
+ window.parent.postMessage({type: 'generateAI', field: field}, '*');
230
+ }
231
+ </script>
232
+ </body>
233
+ </html>
app/templates/property-evaluation.html ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Property Evaluation Report</title>
6
+ <style>
7
+ @page {
8
+ size: A4;
9
+ margin: 1in;
10
+ @bottom-center {
11
+ content: "Generated by Builders.ai • Page " counter(page);
12
+ font-style: italic;
13
+ font-size: 0.95em;
14
+ color: #888;
15
+ }
16
+ }
17
+ html, body {
18
+ height: 100%;
19
+ font-family: 'Segoe UI', 'DejaVu Sans', Arial, sans-serif;
20
+ background: #f6f8fa;
21
+ }
22
+ body {
23
+ margin: 0;
24
+ padding: 0;
25
+ background: #f6f8fa;
26
+ }
27
+ .report-wrapper {
28
+ max-width: 900px;
29
+ margin: 0 auto;
30
+ background: #fff;
31
+ border-radius: 8px;
32
+ box-shadow: 0 1px 4px rgba(50,80,150,0.1);
33
+ padding: 40px 60px 30px 60px;
34
+ }
35
+ .header {
36
+ border-bottom: 2px solid #2C4694;
37
+ padding-bottom: 18px;
38
+ margin-bottom: 30px;
39
+ text-align: center;
40
+ }
41
+ .header .logo-title {
42
+ font-size: 2.2em;
43
+ color: #2C4694;
44
+ font-weight: bold;
45
+ margin-bottom: 4px;
46
+ }
47
+ .header .subtitle {
48
+ color: #7087B1;
49
+ font-size: 1.08em;
50
+ font-weight: 500;
51
+ }
52
+ .header .report-date {
53
+ color: #434343;
54
+ font-size: 1em;
55
+ margin-top: 10px;
56
+ font-style: italic;
57
+ }
58
+ h2 {
59
+ color: #2C4694;
60
+ font-size: 1.22em;
61
+ margin-top: 2.3em;
62
+ text-transform: uppercase;
63
+ border-bottom: 1.5px solid #DCE3F2;
64
+ padding-bottom: 1.5px;
65
+ letter-spacing: 0.04em;
66
+ }
67
+ .fact-table {
68
+ margin: 1.5em 0 2em 0;
69
+ width: 100%;
70
+ border-collapse: collapse;
71
+ }
72
+ .fact-table th, .fact-table td {
73
+ padding: 10px 16px 10px 0;
74
+ vertical-align: top;
75
+ }
76
+ .fact-table th {
77
+ text-align: left;
78
+ color: #32345a;
79
+ background: #fafbff;
80
+ font-weight: 600;
81
+ border-right: 2px solid #f2f3f7;
82
+ min-width: 160px;
83
+ }
84
+ .fact-table td {
85
+ color: #25334d;
86
+ }
87
+ .content-box {
88
+ padding: 18px 22px;
89
+ margin-top: 0.7em;
90
+ border-radius: 6px;
91
+ border: 1.5px solid #e1e9f7;
92
+ background: #f7fafd;
93
+ font-size: 1.06em;
94
+ color: #283D51;
95
+ line-height: 1.55;
96
+ }
97
+ .signoff {
98
+ margin-top: 3.5em;
99
+ text-align: right;
100
+ color: #7087B1;
101
+ }
102
+
103
+ /* Editable styles */
104
+ .editable {
105
+ border: 2px dashed transparent;
106
+ padding: 2px 4px;
107
+ border-radius: 4px;
108
+ cursor: text;
109
+ transition: all 0.2s;
110
+ min-height: 1.2em;
111
+ display: inline-block;
112
+ min-width: 50px;
113
+ }
114
+ .editable:hover {
115
+ border-color: #2C4694;
116
+ background-color: rgba(44, 70, 148, 0.05);
117
+ }
118
+ .editable:focus {
119
+ outline: none;
120
+ border-color: #2C4694;
121
+ background-color: rgba(44, 70, 148, 0.1);
122
+ }
123
+ .editable-content {
124
+ border: 2px dashed transparent;
125
+ padding: 4px;
126
+ border-radius: 4px;
127
+ cursor: text;
128
+ transition: all 0.2s;
129
+ min-height: 2em;
130
+ }
131
+ .editable-content:hover {
132
+ border-color: #2C4694;
133
+ background-color: rgba(44, 70, 148, 0.05);
134
+ }
135
+ .editable-content:focus {
136
+ outline: none;
137
+ border-color: #2C4694;
138
+ background-color: rgba(44, 70, 148, 0.1);
139
+ }
140
+ .ai-button {
141
+ background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);
142
+ color: white;
143
+ border: none;
144
+ padding: 4px 8px;
145
+ border-radius: 4px;
146
+ font-size: 10px;
147
+ cursor: pointer;
148
+ margin-left: 8px;
149
+ font-weight: bold;
150
+ }
151
+ .ai-button:hover {
152
+ transform: scale(1.05);
153
+ }
154
+ </style>
155
+ </head>
156
+ <body>
157
+ <div class="report-wrapper">
158
+ <div class="header">
159
+ <div class="logo-title">Property Evaluation Report</div>
160
+ <div class="subtitle">Generated by Builders.ai</div>
161
+ <div class="report-date">{{DATE}}</div>
162
+ </div>
163
+
164
+ <h2>Basic Property Information</h2>
165
+ <table class="fact-table">
166
+ <tr><th>Property Name</th><td><span class="editable" contenteditable="true" data-field="property_name">{{PROPERTY_NAME}}</span></td></tr>
167
+ <tr><th>Location</th><td><span class="editable" contenteditable="true" data-field="location">{{LOCATION}}</span></td></tr>
168
+ <tr><th>Area (sqft)</th><td><span class="editable" contenteditable="true" data-field="area_sqft">{{AREA_SQFT}}</span></td></tr>
169
+ <tr><th>Floors</th><td><span class="editable" contenteditable="true" data-field="floors">{{FLOORS}}</span></td></tr>
170
+ <tr><th>Estimated Cost</th><td><span class="editable" contenteditable="true" data-field="estimated_cost">{{ESTIMATED_COST}}</span></td></tr>
171
+ <tr><th>Construction Type</th><td><span class="editable" contenteditable="true" data-field="construction_type">{{CONSTRUCTION_TYPE}}</span></td></tr>
172
+ <tr><th>Expected Completion</th><td><span class="editable" contenteditable="true" data-field="expected_completion">{{EXPECTED_COMPLETION}}</span></td></tr>
173
+ <tr><th>Developer</th><td><span class="editable" contenteditable="true" data-field="developer_name">{{DEVELOPER_NAME}}</span></td></tr>
174
+ <tr><th>Legal Clearance Status</th><td><span class="editable" contenteditable="true" data-field="legal_clearance">{{LEGAL_CLEARANCE}}</span></td></tr>
175
+ <tr><th>Target Buyer Segment</th><td><span class="editable" contenteditable="true" data-field="target_buyer_segment">{{TARGET_BUYER_SEGMENT}}</span></td></tr>
176
+ <tr><th>Nearby Facilities</th><td><span class="editable" contenteditable="true" data-field="nearby_facilities">{{NEARBY_FACILITIES}}</span></td></tr>
177
+ </table>
178
+
179
+ <h2>Project Summary <button class="ai-button" onclick="generateAI('summary')">✨ AI</button></h2>
180
+ <div class="content-box">
181
+ <div class="editable-content" contenteditable="true" data-field="summary">{{SUMMARY}}</div>
182
+ </div>
183
+
184
+ <h2>AI Recommendations <button class="ai-button" onclick="generateAI('recommendations')">✨ AI</button></h2>
185
+ <div class="content-box">
186
+ <div class="editable-content" contenteditable="true" data-field="recommendations">{{RECOMMENDATIONS}}</div>
187
+ </div>
188
+
189
+ <h2>Legal / Policy Notes <button class="ai-button" onclick="generateAI('legal_notes')">✨ AI</button></h2>
190
+ <div class="content-box">
191
+ <div class="editable-content" contenteditable="true" data-field="legal_notes">{{LEGAL_NOTES}}</div>
192
+ </div>
193
+
194
+ <h2>Final Observations <button class="ai-button" onclick="generateAI('additional_notes')">✨ AI</button></h2>
195
+ <div class="content-box">
196
+ <div class="editable-content" contenteditable="true" data-field="additional_notes">{{ADDITIONAL_NOTES}}</div>
197
+ </div>
198
+
199
+ <div class="signoff">
200
+ <br/><br/>
201
+ <div>— End of Report —</div>
202
+ </div>
203
+ </div>
204
+
205
+ <script>
206
+ // Enable design mode for rich text editing
207
+ document.addEventListener('DOMContentLoaded', function() {
208
+ document.designMode = 'on';
209
+
210
+ const editableElements = document.querySelectorAll('.editable, .editable-content');
211
+
212
+ editableElements.forEach(element => {
213
+ element.addEventListener('blur', function() {
214
+ const field = this.getAttribute('data-field');
215
+ const value = this.innerHTML || this.textContent;
216
+ if (field) {
217
+ window.parent.postMessage({
218
+ type: 'updateField',
219
+ field: field,
220
+ value: value
221
+ }, '*');
222
+ }
223
+ });
224
+
225
+ element.addEventListener('keydown', function(e) {
226
+ if (e.key === 'Enter' && !e.shiftKey && !this.classList.contains('editable-content')) {
227
+ e.preventDefault();
228
+ this.blur();
229
+ }
230
+ });
231
+ });
232
+ });
233
+
234
+ function generateAI(field) {
235
+ window.parent.postMessage({type: 'generateAI', field: field}, '*');
236
+ }
237
+ </script>
238
+ </body>
239
+ </html>
requirements.txt CHANGED
@@ -28,3 +28,4 @@ google-api-python-client==2.108.0
28
  google-auth-httplib2==0.1.1
29
  google-auth-oauthlib==1.1.0
30
  psycopg2-binary==2.9.9
 
 
28
  google-auth-httplib2==0.1.1
29
  google-auth-oauthlib==1.1.0
30
  psycopg2-binary==2.9.9
31
+ xhtml2pdf==0.2.15