nniehaus commited on
Commit
9540a98
Β·
verified Β·
1 Parent(s): 79acb06

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +635 -0
app.py ADDED
@@ -0,0 +1,635 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+
3
+ # Set page config to minimize default margins and padding - MUST BE FIRST STREAMLIT COMMAND
4
+ st.set_page_config(
5
+ page_title="Home Value Maximizer",
6
+ page_icon="🏑",
7
+ layout="wide",
8
+ initial_sidebar_state="collapsed"
9
+ )
10
+
11
+ import requests
12
+ from PIL import Image
13
+ import base64
14
+ from io import BytesIO
15
+ import time
16
+ from datetime import datetime, timedelta
17
+ import re
18
+
19
+ # Configure OpenAI API settings
20
+ API_URL = "https://api.openai.com/v1/chat/completions"
21
+ MODEL_NAME = "gpt-4o" # Updated to use GPT-4o which includes vision capabilities
22
+
23
+ # Get current date
24
+ current_date = datetime.now().strftime("%B %d, %Y")
25
+
26
+ # Set API key from Hugging Face secrets
27
+ try:
28
+ OPENAI_API_KEY = st.secrets["OPENAI_API_KEY"]
29
+ except:
30
+ OPENAI_API_KEY = "" # Will be prompted to enter API key if not in secrets
31
+
32
+ # Session state initialization
33
+ if "uploaded_images" not in st.session_state:
34
+ st.session_state["uploaded_images"] = []
35
+ if "api_key" not in st.session_state:
36
+ st.session_state["api_key"] = OPENAI_API_KEY
37
+ if "token_usage" not in st.session_state:
38
+ st.session_state["token_usage"] = {}
39
+
40
+ # Function to encode image to base64
41
+ def encode_image(image):
42
+ # Convert RGBA to RGB if needed
43
+ if image.mode == 'RGBA':
44
+ background = Image.new('RGB', image.size, (255, 255, 255))
45
+ background.paste(image, (0, 0), image)
46
+ image = background
47
+
48
+ # Resize large images to reduce token usage
49
+ max_size = (1024, 1024)
50
+ if image.width > max_size[0] or image.height > max_size[1]:
51
+ image.thumbnail(max_size, Image.LANCZOS)
52
+
53
+ buffered = BytesIO()
54
+ image.save(buffered, format="JPEG", quality=85)
55
+ return base64.b64encode(buffered.getvalue()).decode('utf-8')
56
+
57
+ # Function to fix formatting issues in text
58
+ def fix_formatting(text):
59
+ # Fix issues with numbers and text run together
60
+ text = re.sub(r'(\d+)([a-zA-Z])', r'\1 \2', text)
61
+
62
+ # Fix issues with missing spaces after commas and periods
63
+ text = re.sub(r'([.,])([a-zA-Z0-9])', r'\1 \2', text)
64
+
65
+ # Fix issues with missing spaces after colons
66
+ text = re.sub(r':([a-zA-Z0-9])', r': \1', text)
67
+
68
+ return text
69
+
70
+ # Function to analyze home photos with OpenAI's API
71
+ def analyze_home_photos(images, timeframe, additional_details, api_key):
72
+ if not api_key:
73
+ return "Error: API Key is required for analysis."
74
+
75
+ headers = {
76
+ "Content-Type": "application/json",
77
+ "Authorization": f"Bearer {api_key}"
78
+ }
79
+
80
+ # Construct the message content
81
+ content = [
82
+ {"type": "text", "text": f"""Analyze these home photos and provide EXTREMELY SPECIFIC strategies to maximize the selling price.
83
+ The owner plans to sell within {timeframe}. Today's date is {current_date}. {additional_details}
84
+
85
+ Be incredibly detailed and specific about what you see in each image. Reference exact features, colors, materials, and conditions.
86
+ Provide precise recommendations with specific products, materials, colors, and techniques.
87
+
88
+ IMPORTANT: Ensure all your text is properly formatted with spaces between numbers and words, and proper spacing after punctuation.
89
+ """}
90
+ ]
91
+
92
+ # Add images to the message with proper format for vision API
93
+ for img in images:
94
+ base64_img = encode_image(img)
95
+ content.append({
96
+ "type": "image_url",
97
+ "image_url": {
98
+ "url": f"data:image/jpeg;base64,{base64_img}",
99
+ "detail": "low" # Use low detail to reduce token usage
100
+ }
101
+ })
102
+
103
+ # Enhanced system prompt for more specific and actionable recommendations
104
+ system_prompt = """You are an expert real estate advisor with deep knowledge of home selling strategies. You analyze home photos to provide EXTREMELY SPECIFIC, actionable recommendations that will maximize the property's selling price.
105
+
106
+ ## FORMAT YOUR RESPONSE LIKE THIS:
107
+
108
+ ### πŸ“‹ KEY RECOMMENDATIONS SUMMARY
109
+ Begin with this exact text: "**HOME VALUE MAXIMIZER SUMMARY**"
110
+
111
+ Then add this line: "Below are the top improvements to maximize your home's value. See detailed sections for specific costs, instructions, and timeline."
112
+
113
+ Then, list 5 bullet points of the MOST IMPACTFUL improvements that will increase the property's value. For each bullet:
114
+ - Make the first sentence **bold**
115
+ - Include the specific issue identified
116
+ - Include the recommended solution
117
+ - Include the estimated value increase or ROI
118
+
119
+ ### 🌟 TOP PRICE-MAXIMIZING PRIORITIES
120
+ Present the 3-4 MOST IMPACTFUL improvements first, formatted as a clear list. Each item MUST include:
121
+ - **Exact issue you see**: Be incredibly specific about what you observe in the photo (e.g., "The beige laminate countertops in the kitchen are visibly worn with scratches near the sink area")
122
+ - **Precise recommendation**: Specify EXACT materials, colors, products, or contractors (e.g., "Replace with Calacatta Quartz countertops in white with subtle gray veining")
123
+ - **Specific cost estimate**: Give narrow ranges (e.g., "$2,800-$3,200")
124
+ - **Precise value impact**: Quantify the increase (e.g., "Estimated to add $8,000-$10,000 to home value")
125
+ - **Timeline**: Exact number of days needed and mention if permits are required
126
+
127
+ ### πŸ”¨ QUICK WINS (1-3 days)
128
+ List 5-6 fast, high-ROI improvements with EXACT details:
129
+ - **Kitchen**: Name specific issues, specific solutions, specific products/colors/materials
130
+ - **Bathroom**: Name specific issues, specific solutions, specific products/colors/materials
131
+ - **Living Spaces**: Name specific issues, specific solutions, specific products/colors/materials
132
+ - **Exterior**: Name specific issues, specific solutions, specific products/colors/materials
133
+ Include PRECISE cost estimates, DIY or contractor recommendations, and EXACT product suggestions.
134
+
135
+ ### πŸ“Š SPECIFIC PRICING STRATEGY
136
+ Provide EXACT details on:
137
+ - **Precise price point**: Suggest a specific price point or narrow range based on visible features (e.g., "$399,900" not "$399,900toappealpsychologically")
138
+ - **Specific pricing psychology**: e.g., "$399,900 rather than $400,000" - MAKE SURE TO INCLUDE SPACES BETWEEN NUMBERS AND TEXT
139
+ - **Exact timing**: Specific days of week and dates based on current date and selling timeframe
140
+ - **Market-specific advice**: Relate to current market conditions with specific details
141
+
142
+ IMPORTANT: ALWAYS use proper spacing in your text. For example:
143
+ - CORRECT: "List at $399,900 to appeal psychologically to buyers under $400k."
144
+ - INCORRECT: "List at $399,900toappealpsychologicallytobuyers."
145
+
146
+ ### πŸ“Έ DETAILED MARKETING PLAN
147
+ Provide SPECIFIC advice on:
148
+ - **Exactly which room features**: Name specific architectural elements or features to highlight
149
+ - **Specific photography angles**: Exact camera positions and times of day for optimal lighting
150
+ - **Specific staging items**: Name exact furniture pieces, decor items, or color accents to add/remove
151
+ - **Exact virtual tools**: Name specific apps or services for virtual tours/staging
152
+
153
+ ### πŸ“ SPECIFIC NEGOTIATION TACTICS
154
+ Recommend PRECISE approaches:
155
+ - **Exact language**: Provide specific scripts for countering common objections
156
+ - **Specific inspection strategy**: Name exact items to fix pre-inspection
157
+ - **Precise contingency planning**: Specific strategies for common issues based on the home's visible condition
158
+
159
+ ### ⚠️ CRITICAL ISSUES TO ADDRESS
160
+ List 3 SPECIFIC problems visible in the photos that must be fixed, with EXACT solutions.
161
+
162
+ ### πŸ“… DETAILED TIMELINE WITH DATES
163
+ Create a PRECISE calendar using EXACT DATES starting from TODAY (${current_date}). Factor in the user's stated selling timeframe of ${timeframe}.
164
+
165
+ For example, if selling within 1-3 months:
166
+ - By [EXACT DATE]: Complete specific kitchen updates (list precisely what)
167
+ - By [EXACT DATE]: Finish specific bathroom improvements (list precisely what)
168
+ - By [EXACT DATE]: Address specific exterior issues (list precisely what)
169
+ - [EXACT DATE]: Schedule professional photography
170
+ - [EXACT DATE]: List the home on the market
171
+
172
+ ## IMPORTANT GUIDELINES:
173
+ 1. Be EXTREMELY SPECIFIC about what you see in each photo - reference exact details, colors, materials
174
+ 2. Give PRECISE product recommendations when possible - name brands, models, colors
175
+ 3. Provide EXACT cost estimates in narrow ranges
176
+ 4. Specify CLEAR timelines with CALENDAR DATES based on today's date (${current_date})
177
+ 5. Make all advice HYPER-SPECIFIC to the actual property in the photos
178
+ 6. NEVER give generic advice - every recommendation should directly reference visible elements
179
+ 7. ALWAYS use proper spacing in text - add spaces between numbers and words, after punctuation, etc.
180
+ """
181
+
182
+ # Replace placeholders in the system prompt
183
+ formatted_system_prompt = system_prompt.replace("${current_date}", current_date).replace("${timeframe}", timeframe)
184
+
185
+ # Create the API payload with enhanced system prompt
186
+ payload = {
187
+ "model": MODEL_NAME,
188
+ "messages": [
189
+ {
190
+ "role": "system",
191
+ "content": formatted_system_prompt
192
+ },
193
+ {
194
+ "role": "user",
195
+ "content": content
196
+ }
197
+ ],
198
+ "max_tokens": 2500
199
+ }
200
+
201
+ try:
202
+ response = requests.post(API_URL, headers=headers, json=payload, timeout=90)
203
+
204
+ if response.status_code == 200:
205
+ response_data = response.json()
206
+
207
+ # Store token usage data
208
+ if "usage" in response_data:
209
+ st.session_state["token_usage"] = response_data["usage"]
210
+
211
+ # Get the content and fix any formatting issues
212
+ content = response_data["choices"][0]["message"]["content"]
213
+ content = fix_formatting(content)
214
+
215
+ return content
216
+ else:
217
+ error_text = f"API Error: {response.status_code}"
218
+ if response.text:
219
+ try:
220
+ error_json = response.json()
221
+ if "error" in error_json:
222
+ error_text += f" - {error_json['error']['message']}"
223
+ except:
224
+ error_text += f" - {response.text[:200]}"
225
+ return f"Error: {error_text}. Please check your API key and try again."
226
+ except Exception as e:
227
+ return f"Error: {str(e)}"
228
+
229
+ # Calculate estimated cost
230
+ def calculate_cost(token_usage):
231
+ if not token_usage:
232
+ return {"total": "Unknown"}
233
+
234
+ # Latest pricing as of April 2024 for GPT-4o
235
+ input_cost_per_1M = 3 # $3 per 1M input tokens for GPT-4o
236
+ output_cost_per_1M = 10 # $10 per 1M output tokens for GPT-4o
237
+
238
+ prompt_tokens = token_usage.get("prompt_tokens", 0)
239
+ completion_tokens = token_usage.get("completion_tokens", 0)
240
+
241
+ input_cost = (prompt_tokens / 1000000) * input_cost_per_1M
242
+ output_cost = (completion_tokens / 1000000) * output_cost_per_1M
243
+ total_cost = input_cost + output_cost
244
+
245
+ return {
246
+ "input_tokens": prompt_tokens,
247
+ "output_tokens": completion_tokens,
248
+ "input_cost": input_cost,
249
+ "output_cost": output_cost,
250
+ "total_cost": total_cost
251
+ }
252
+
253
+ # Custom CSS to fix all styling issues including text visibility and header spacing
254
+ st.markdown("""
255
+ <style>
256
+ /* Override streamlit's default padding to prevent header cutoff */
257
+ .main .block-container {
258
+ padding-top: 2rem !important; /* Increased from 1rem to give more space */
259
+ padding-bottom: 1rem !important;
260
+ max-width: 100% !important;
261
+ }
262
+
263
+ /* Fix for the header area to ensure it's fully visible in Hugging Face Spaces */
264
+ .stApp {
265
+ margin-top: 0.5rem !important;
266
+ }
267
+
268
+ /* Fix text visibility issues - ensure good contrast */
269
+ .upload-text {
270
+ color: #262730 !important;
271
+ background-color: transparent !important;
272
+ font-weight: 500 !important;
273
+ }
274
+
275
+ /* Make the title and header area more compact but visible */
276
+ .title-area {
277
+ margin: 0 !important;
278
+ padding: 0.5rem 0 !important; /* Added top/bottom padding */
279
+ margin-bottom: 0.5rem !important;
280
+ }
281
+
282
+ /* Make header more compact but ensure visibility */
283
+ .stMarkdown h1 {
284
+ margin-top: 0.5rem !important; /* Added margin to prevent cutoff */
285
+ margin-bottom: 0.5rem !important;
286
+ font-size: 1.8rem !important;
287
+ padding: 0 !important;
288
+ line-height: 1.3 !important; /* Improved line height */
289
+ }
290
+
291
+ /* Ensure the logo and title are visible */
292
+ .title-section {
293
+ display: block !important;
294
+ padding-top: 0.5rem !important;
295
+ margin-bottom: 0.75rem !important;
296
+ }
297
+
298
+ /* Steps styling - improved visibility and spacing */
299
+ .steps-container {
300
+ display: flex;
301
+ justify-content: space-between;
302
+ margin: 0.75rem 0 1rem 0 !important; /* Added top margin */
303
+ padding: 0 !important;
304
+ }
305
+
306
+ .step-item {
307
+ flex: 1;
308
+ padding: 0.5rem !important; /* Increased padding */
309
+ font-size: 0.85rem;
310
+ color: #262730;
311
+ background-color: #f0f2f6;
312
+ border-radius: 4px;
313
+ margin-right: 0.5rem;
314
+ text-align: center;
315
+ }
316
+
317
+ /* Enhanced section styling */
318
+ .stMarkdown h3 {
319
+ margin-top: 1.5rem;
320
+ padding: 0.5rem;
321
+ border-radius: 0.5rem;
322
+ font-weight: 600;
323
+ color: white;
324
+ }
325
+
326
+ /* Style for summary section */
327
+ .stMarkdown h3:contains("KEY RECOMMENDATIONS SUMMARY") {
328
+ background-color: #2196f3;
329
+ }
330
+
331
+ /* Summary content styling */
332
+ .summary-title {
333
+ font-size: 1.2rem;
334
+ font-weight: bold;
335
+ margin-bottom: 0.5rem;
336
+ color: #2196f3;
337
+ }
338
+
339
+ .summary-subtitle {
340
+ font-size: 0.9rem;
341
+ font-weight: 500;
342
+ margin-bottom: 1rem;
343
+ color: #424242;
344
+ }
345
+
346
+ /* Priority recommendations */
347
+ .stMarkdown h3:contains("TOP PRICE") {
348
+ background-color: #1e88e5;
349
+ }
350
+
351
+ /* Quick improvements section */
352
+ .stMarkdown h3:contains("QUICK WINS") {
353
+ background-color: #43a047;
354
+ }
355
+
356
+ /* Strategic pricing section */
357
+ .stMarkdown h3:contains("SPECIFIC PRICING") {
358
+ background-color: #5e35b1;
359
+ }
360
+
361
+ /* Marketing section */
362
+ .stMarkdown h3:contains("DETAILED MARKETING") {
363
+ background-color: #fb8c00;
364
+ }
365
+
366
+ /* Negotiation section */
367
+ .stMarkdown h3:contains("SPECIFIC NEGOTIATION") {
368
+ background-color: #00897b;
369
+ }
370
+
371
+ /* Critical issues section */
372
+ .stMarkdown h3:contains("CRITICAL ISSUES") {
373
+ background-color: #e53935;
374
+ }
375
+
376
+ /* Timeline section */
377
+ .stMarkdown h3:contains("DETAILED TIMELINE") {
378
+ background-color: #8e24aa;
379
+ }
380
+
381
+ /* Style for bullet points in summary */
382
+ .stMarkdown ul li {
383
+ margin-bottom: 0.75rem;
384
+ line-height: 1.6;
385
+ }
386
+
387
+ /* Bold text */
388
+ .stMarkdown strong {
389
+ color: #262730;
390
+ font-weight: 700;
391
+ }
392
+
393
+ /* Results container */
394
+ .results-container {
395
+ padding: 1.5rem;
396
+ background-color: white;
397
+ border-radius: 0.5rem;
398
+ box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
399
+ margin-bottom: 1.5rem;
400
+ }
401
+
402
+ /* Cost information */
403
+ .cost-info {
404
+ background-color: #f8f9fa;
405
+ padding: 0.75rem;
406
+ border-radius: 0.5rem;
407
+ font-size: 0.85rem;
408
+ margin-top: 1rem;
409
+ }
410
+
411
+ /* Blue background for summary section */
412
+ .summary-section {
413
+ background-color: #e3f2fd;
414
+ border-radius: 8px;
415
+ padding: 1rem;
416
+ margin-bottom: 1.5rem;
417
+ border-left: 4px solid #2196f3;
418
+ }
419
+
420
+ /* Custom header style for subheaders */
421
+ .custom-subheader {
422
+ background-color: #f5f5f5;
423
+ padding: 10px;
424
+ border-radius: 5px;
425
+ margin-bottom: 10px;
426
+ color: #262730;
427
+ font-weight: 600;
428
+ }
429
+
430
+ /* Fix for code blocks and pre-formatted text */
431
+ pre, code {
432
+ white-space: pre-wrap !important;
433
+ word-break: break-word !important;
434
+ }
435
+
436
+ /* Fix for Hugging Face Spaces iframe header issues */
437
+ @media screen and (max-width: 1200px) {
438
+ .main .block-container {
439
+ padding-top: 3rem !important; /* Even more padding for smaller screens */
440
+ }
441
+ }
442
+ </style>
443
+ """, unsafe_allow_html=True)
444
+
445
+ # Page config was moved to the top of the file as the first Streamlit command
446
+
447
+ # Custom compact header - modified for better visibility
448
+ st.markdown("""
449
+ <div class="title-section">
450
+ <h1>Home Value Maximizer 🏑</h1>
451
+ <div class="upload-text">πŸ“Έ Upload photos β†’ πŸ’° Get specific improvements β†’ 🏑 Maximize selling price</div>
452
+ </div>
453
+
454
+ <div class="steps-container">
455
+ <div class="step-item">1. Upload multiple photos of your home</div>
456
+ <div class="step-item">2. Enter your selling timeline & preferences</div>
457
+ <div class="step-item">3. Click 'Analyze My Home' for detailed strategies</div>
458
+ </div>
459
+ """, unsafe_allow_html=True)
460
+
461
+ # API Key input if not in secrets
462
+ if not st.session_state["api_key"]:
463
+ st.session_state["api_key"] = st.text_input("Enter your OpenAI API Key", type="password")
464
+ st.info("Your API key is required to analyze the images. It will not be stored permanently.")
465
+
466
+ # Main content columns
467
+ col1, col2 = st.columns(2)
468
+
469
+ with col1:
470
+ # Custom subheader with background
471
+ st.markdown('<div class="custom-subheader">πŸ“Έ Upload Home Photos</div>', unsafe_allow_html=True)
472
+ uploaded_files = st.file_uploader("Upload photos of different areas of your home",
473
+ accept_multiple_files=True,
474
+ type=["jpg", "jpeg", "png"])
475
+
476
+ # Process uploaded images
477
+ if uploaded_files:
478
+ images = []
479
+ for file in uploaded_files:
480
+ try:
481
+ image = Image.open(file)
482
+ # Resize large images to reduce token usage
483
+ max_size = (1024, 1024)
484
+ if image.width > max_size[0] or image.height > max_size[1]:
485
+ image.thumbnail(max_size, Image.LANCZOS)
486
+ images.append(image)
487
+ except Exception as e:
488
+ st.error(f"Error opening image {file.name}: {e}")
489
+
490
+ st.session_state["uploaded_images"] = images
491
+
492
+ # Display uploaded images
493
+ if images:
494
+ st.write(f"**{len(images)} images uploaded**")
495
+ image_cols = st.columns(min(3, len(images)))
496
+ for i, img in enumerate(images):
497
+ with image_cols[i % min(3, len(images))]:
498
+ st.image(img, width=150, caption=f"Image {i+1}")
499
+
500
+ # Custom subheader with background
501
+ st.markdown('<div class="custom-subheader">🏠 Selling Timeline & Details</div>', unsafe_allow_html=True)
502
+
503
+ # Expanded selling timeline options
504
+ timeframe = st.radio("When do you plan to sell your home?",
505
+ ["Within 1 month", "1-3 months", "3-6 months", "6-12 months", "More than 12 months"])
506
+
507
+ additional_details = st.text_area("Additional Details",
508
+ placeholder="Describe your home, local market conditions, target buyers, or any specific concerns you have about the selling process.",
509
+ height=100)
510
+
511
+ # Additional preferences with custom subheader
512
+ st.markdown('<div class="custom-subheader">πŸ’° Budget & Preferences</div>', unsafe_allow_html=True)
513
+
514
+ max_budget = st.slider("Maximum budget for improvements ($)",
515
+ min_value=1000,
516
+ max_value=50000,
517
+ value=10000,
518
+ step=1000)
519
+
520
+ improvement_focus = st.multiselect(
521
+ "Areas to focus on (optional)",
522
+ ["Curb appeal", "Kitchen", "Bathroom", "Living spaces", "Outdoor areas", "Storage solutions", "Energy efficiency", "Marketing", "Pricing strategy", "Negotiation", "Staging"],
523
+ default=["Curb appeal", "Kitchen", "Bathroom", "Pricing strategy"]
524
+ )
525
+
526
+ diy_preference = st.select_slider(
527
+ "DIY Preference",
528
+ options=["Professional work only", "Mix of DIY and professional", "Mostly DIY if possible"],
529
+ value="Mix of DIY and professional"
530
+ )
531
+
532
+ # Analysis button
533
+ analyze_button = st.button('πŸ” Analyze My Home',
534
+ use_container_width=True,
535
+ disabled=len(st.session_state["uploaded_images"]) == 0 or not st.session_state["api_key"])
536
+
537
+ if len(st.session_state["uploaded_images"]) == 0:
538
+ st.warning("Please upload at least one photo of your home to receive recommendations.")
539
+
540
+ if not st.session_state["api_key"]:
541
+ st.warning("Please enter your OpenAI API key to enable analysis.")
542
+
543
+ with col2:
544
+ # Custom subheader with background
545
+ st.markdown('<div class="custom-subheader">πŸ’‘ Comprehensive Selling Strategies</div>', unsafe_allow_html=True)
546
+
547
+ # Process and display analysis results
548
+ if analyze_button or "analysis_result" in st.session_state:
549
+ # Process analysis if button pressed
550
+ if analyze_button:
551
+ # Simple loading indicator using pure Streamlit - no HTML, JS or CSS
552
+ with st.spinner("🏑 Analyzing your home photos..."):
553
+ # Show a progress bar
554
+ progress_bar = st.progress(0)
555
+
556
+ # Show the analysis steps with native Streamlit components
557
+ steps_placeholder = st.empty()
558
+ steps_placeholder.info("Step 1: Identifying property features and conditions...")
559
+ progress_bar.progress(25)
560
+ time.sleep(1) # Small delay for visual effect
561
+
562
+ steps_placeholder.info("Step 2: Evaluating improvement opportunities and researching specific recommendations...")
563
+ progress_bar.progress(50)
564
+ time.sleep(1) # Small delay for visual effect
565
+
566
+ steps_placeholder.info("Step 3: Calculating ROI potential and precise cost estimates...")
567
+ progress_bar.progress(75)
568
+ time.sleep(1) # Small delay for visual effect
569
+
570
+ steps_placeholder.info("Step 4: Creating detailed timeline and finalizing recommendations...")
571
+
572
+ # Make the actual API call
573
+ analysis_text = analyze_home_photos(
574
+ st.session_state["uploaded_images"],
575
+ timeframe,
576
+ f"Budget: ${max_budget}. Focus areas: {', '.join(improvement_focus)}. DIY preference: {diy_preference}. {additional_details}",
577
+ st.session_state["api_key"]
578
+ )
579
+
580
+ # Complete the progress bar
581
+ progress_bar.progress(100)
582
+
583
+ # Store the result and clear the loading indicators
584
+ st.session_state["analysis_result"] = analysis_text
585
+ steps_placeholder.empty()
586
+ progress_bar.empty()
587
+
588
+ # Display results
589
+ if "analysis_result" in st.session_state:
590
+ # Process the output to enhance summary formatting
591
+ result = st.session_state["analysis_result"]
592
+
593
+ # Check if we need to style the summary section
594
+ if "**HOME VALUE MAXIMIZER SUMMARY**" in result:
595
+ # Split the result to find the summary section
596
+ parts = result.split("### πŸ“‹ KEY RECOMMENDATIONS SUMMARY", 1)
597
+ if len(parts) > 1:
598
+ before_summary = parts[0]
599
+ rest_parts = parts[1].split("### 🌟", 1)
600
+ if len(rest_parts) > 1:
601
+ summary_content = rest_parts[0]
602
+ after_summary = "### 🌟" + rest_parts[1]
603
+
604
+ # Apply custom formatting to the summary
605
+ result = before_summary + '<div class="summary-section">' + summary_content + '</div>' + after_summary
606
+
607
+ # Display the enhanced result
608
+ st.markdown(f'<div class="results-container">{result}</div>', unsafe_allow_html=True)
609
+
610
+ # Add a download button for the report
611
+ st.download_button(
612
+ label="Download Selling Strategies as Text",
613
+ data=st.session_state["analysis_result"],
614
+ file_name="home_selling_strategies.txt",
615
+ mime="text/plain",
616
+ use_container_width=True
617
+ )
618
+ else:
619
+ st.markdown('<div class="results-container">**Personalized selling strategies will appear here after you submit your home photos and details**</div>', unsafe_allow_html=True)
620
+
621
+ # Disclaimer section
622
+ st.markdown("---")
623
+ with st.expander("πŸ“œ **Disclaimer**"):
624
+ st.markdown("""
625
+ **Disclaimer:**
626
+ This Home Value Maximizer tool provides recommendations based on AI analysis of your home photos.
627
+ Results are for **informational purposes only** and may not be accurate for your specific market or situation.
628
+
629
+ - **Price impact estimates** are approximate and depend on local market conditions
630
+ - **Pricing strategies** should be verified with a local real estate professional familiar with your specific market
631
+ - **Improvement recommendations** and costs may vary based on your location and local labor costs
632
+ - **Product recommendations** are suggestions only; please research compatibility with your home
633
+
634
+ For the best results, consult with experienced real estate professionals in your area before making significant decisions.
635
+ """)