chandra7799 commited on
Commit
25ff8ea
·
verified ·
1 Parent(s): 22bf28a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +133 -199
app.py CHANGED
@@ -4,11 +4,10 @@ import os
4
  from dotenv import load_dotenv
5
  from simple_salesforce import Salesforce
6
  from datetime import datetime
 
7
  import shutil
8
  import base64
9
  import pytz
10
- import hashlib
11
- import statistics
12
 
13
  # Load environment variables
14
  load_dotenv()
@@ -33,65 +32,28 @@ except Exception as e:
33
  raise
34
 
35
  # Valid milestones
36
- VALID_MILESTONES = ["Planning", "Foundation", "Walls Erected", "Interior Furnishing", "Completed"]
37
 
38
- # Adjust the timezone to IST
39
  local_timezone = pytz.timezone("Asia/Kolkata")
40
 
41
- # Mock Hugging Face image analysis (replace with real model integration)
42
- def analyze_image_with_hf(image_path):
43
- img = Image.open(image_path)
44
- detected_elements = []
45
-
46
- width, height = img.size
47
- total_pixels = width * height
48
- img_data = list(img.convert('RGB').getdata())
49
- gray_pixels = sum(1 for pixel in img_data if sum(pixel[:3]) / 3 < 128) / len(img_data)
50
- color_variance = statistics.variance([sum(pixel[:3]) / 3 for pixel in img_data]) if len(img_data) > 1 else 0
51
-
52
- # Adjusted logic to detect completed construction, overriding small size
53
- if (color_variance > 2000 and gray_pixels < 0.4 and any(keyword in os.path.basename(image_path).lower() for keyword in ["window", "door", "roof"])) or \
54
- (total_pixels > 800000 and gray_pixels < 0.4 and color_variance > 2000):
55
- detected_elements.extend(["roof", "windows", "doors", "cladding", "finished"])
56
- elif total_pixels < 200000 and color_variance < 800:
57
- detected_elements.append("planning")
58
- elif gray_pixels > 0.6 and total_pixels > 400000:
59
- detected_elements.append("foundation")
60
- elif gray_pixels > 0.35 and total_pixels > 800000 and color_variance > 1500:
61
- detected_elements.append("walls")
62
- elif gray_pixels < 0.25 or any(keyword in os.path.basename(image_path).lower() for keyword in ["interior", "plumbing", "electrical", "ceiling"]):
63
- detected_elements.extend(["interior", "electrical_wiring", "plumbing_pipes"])
64
- else:
65
- detected_elements.append("walls")
66
-
67
- return detected_elements
68
-
69
- # Image processing and Salesforce upload with live preview
70
  def process_image(images, project_name):
71
  try:
72
  if not images or len(images) == 0:
73
- return "Error: Please upload at least one image to proceed.", None, "Pending", "", "", 0
74
 
75
- results_html = []
76
- upload_statuses = []
77
  milestones = []
78
- progresses = []
79
-
80
  for image in images:
81
- img = None
82
- try:
83
- img = Image.open(image)
84
- except Exception as e:
85
- if "cannot identify image file" in str(e):
86
- return f"Error: Unsupported image format '{os.path.basename(image)}'. Please use JPG, JPEG, PNG, or convert to a supported format.", None, "Failure", "", "", 0
87
- return f"Error: Failed to open image '{os.path.basename(image)}' - {str(e)}", None, "Failure", "", "", 0
88
-
89
  image_size_mb = os.path.getsize(image) / (1024 * 1024)
90
  if image_size_mb > 20:
91
- return "Error: One or more images exceed 20MB.", None, "Failure", "", "", 0
92
- if not str(image).lower().endswith(('.jpg', '.jpeg', '.png', '.avif')):
93
- return "Error: Only JPG, JPEG, PNG, or AVIF images are supported.", None, "Failure", "", "", 0
94
 
 
95
  upload_dir = "public_uploads"
96
  os.makedirs(upload_dir, exist_ok=True)
97
  unique_id = datetime.now().strftime("%Y%m%d%H%M%S")
@@ -99,197 +61,177 @@ def process_image(images, project_name):
99
  saved_image_path = os.path.join(upload_dir, image_filename)
100
  shutil.copy(image, saved_image_path)
101
 
 
102
  with open(saved_image_path, 'rb') as image_file:
103
  image_data = base64.b64encode(image_file.read()).decode('utf-8')
104
 
105
- file_url = ""
 
 
 
 
 
 
 
106
  try:
107
- content_version = {
108
- 'Title': image_filename,
109
- 'PathOnClient': saved_image_path,
110
- 'VersionData': image_data
111
- }
112
  content_version_result = sf.ContentVersion.create(content_version)
113
  content_version_id = content_version_result['id']
114
  file_url = f"https://sathkruthatechsolutionspri8-dev-ed.develop.lightning.force.com/{content_version_id}"
115
  except Exception as e:
116
- if "STORAGE_LIMIT_EXCEEDED" in str(e):
117
- file_url = "Upload skipped due to storage limit"
 
 
 
 
 
 
 
 
 
 
 
118
  else:
119
- return f"Error: Failed to upload image to Salesforce - {str(e)}", None, "Failure", "", "", 0
120
 
121
- detected_elements = analyze_image_with_hf(image)
122
 
123
- completed_tasks = []
124
- not_completed_tasks = []
125
- all_tasks = {
126
- "Planning": [
 
 
 
 
 
 
 
 
 
 
127
  "Initial project outline and objectives have been established.",
128
  "Preliminary designs and architectural plans are drafted.",
129
  "Stakeholder meetings and initial approvals are completed."
130
  ],
131
- "Foundation": [
 
 
 
 
 
 
 
132
  "Site preparation, including clearing and leveling, is finished.",
133
  "Excavation for the foundation has been completed.",
134
  "Concrete pouring for the foundation, including footings and slabs, is done.",
135
  "Initial structural inspections for the foundation have been passed."
136
  ],
137
- "Walls Erected": [
 
 
 
 
 
 
 
138
  "The concrete framework, including columns and beams, is in place.",
139
  "All structural walls have been erected and stabilized.",
140
  "Temporary scaffolding and safety measures are installed for ongoing work.",
141
  "Initial inspections for structural integrity have been completed."
142
  ],
143
- "Interior Furnishing": [
144
- "Plumbing and electrical groundwork installations are completed.",
145
- "Interior walls are fully implemented.",
146
- "Flooring installation is completed.",
147
- "Painting and fixtures are installed."
148
- ],
149
- "Completed": [
150
- "Roofing installation and weatherproofing are completed.",
151
- "Windows, doors, and exterior cladding are installed.",
 
152
  "Interior work, including electrical, plumbing, and HVAC systems, is fully implemented.",
153
  "Finishing touches, such as flooring, painting, and fixtures, are completed.",
154
  "All phases of the project are finished, including final inspections and approvals."
 
 
 
155
  ]
156
  }
 
157
 
158
- if any(elem == "planning" for elem in detected_elements):
159
- completed_tasks.extend(all_tasks["Planning"])
160
- final_milestone = "Planning"
161
- percent_complete = 10
162
- elif any(elem == "foundation" for elem in detected_elements):
163
- completed_tasks.extend(all_tasks["Foundation"])
164
- final_milestone = "Foundation"
165
- percent_complete = 30
166
- elif any(elem == "walls" for elem in detected_elements):
167
- completed_tasks.extend(all_tasks["Walls Erected"])
168
- final_milestone = "Walls Erected"
169
- percent_complete = 50
170
- elif any(elem in ["interior", "electrical_wiring", "plumbing_pipes"] for elem in detected_elements):
171
- completed_tasks.extend(all_tasks["Interior Furnishing"])
172
- final_milestone = "Interior Furnishing"
173
- percent_complete = 80
174
- elif all(elem in ["roof", "windows", "doors", "cladding", "finished"] for elem in detected_elements if elem in ["roof", "windows", "doors", "cladding", "finished"]):
175
- completed_tasks.extend(all_tasks["Completed"])
176
- final_milestone = "Completed"
177
- percent_complete = 100
178
- else:
179
- completed_tasks.extend(all_tasks["Walls Erected"])
180
- final_milestone = "Walls Erected"
181
- percent_complete = 50
182
-
183
- all_possible_tasks = [task for sublist in all_tasks.values() for task in sublist]
184
- not_completed_tasks = [task for task in all_possible_tasks if task not in completed_tasks]
185
 
186
- completed_html = "".join([f'<li style="color: green;">✔ {task}</li>' for task in completed_tasks])
187
- not_completed_html = "".join([f'<li style="color: red;">✘ {task}</li>' for task in not_completed_tasks])
188
 
189
- if final_milestone == "Completed":
190
- result_html = f"""
191
- <div style="font-family: Arial, sans-serif; padding: 20px; background-color: #f9f9f9; border-radius: 10px; margin-bottom: 20px;">
192
- <h2 style="color: #2c3e50; text-align: center;">Project Summary - {os.path.basename(image)}</h2>
193
- <div style="display: flex; justify-content: space-around; margin-bottom: 20px;">
194
- <div style="text-align: center;">
195
- <h3 style="color: #34495e;">Detected Milestone</h3>
196
- <p style="font-size: 18px; font-weight: bold;">{final_milestone}</p>
197
- </div>
198
- <div style="text-align: center;">
199
- <h3 style="color: #34495e;">Completion</h3>
200
- <progress value="{percent_complete}" max="100" style="width: 200px; height: 20px;"></progress>
201
- <p>{percent_complete}%</p>
202
- </div>
203
- </div>
204
- <h3 style="color: #2c3e50;">Milestone Timeline</h3>
205
- <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
206
- <span style="color: #bdc3c7;">Planning</span>
207
- <span style="color: #bdc3c7;">Foundation</span>
208
- <span style="color: #bdc3c7;">Walls Erected</span>
209
- <span style="color: #bdc3c7;">Interior Furnishing</span>
210
- <span style="color: #2ecc71;">Completed</span>
211
- </div>
212
- <details style="margin-bottom: 20px;">
213
- <summary style="color: #2c3e50; font-weight: bold;">Completed Tasks</summary>
214
- <ul style="padding-left: 20px;">
215
- {completed_html}
216
- </ul>
217
- </details>
218
- <p style="color: green;">Project is fully completed as of 02:35 PM IST, June 20, 2025.</p>
219
  </div>
220
- """
221
- else:
222
- result_html = f"""
223
- <div style="font-family: Arial, sans-serif; padding: 20px; background-color: #f9f9f9; border-radius: 10px; margin-bottom: 20px;">
224
- <h2 style="color: #2c3e50; text-align: center;">Project Summary - {os.path.basename(image)}</h2>
225
- <div style="display: flex; justify-content: space-around; margin-bottom: 20px;">
226
- <div style="text-align: center;">
227
- <h3 style="color: #34495e;">Detected Milestone</h3>
228
- <p style="font-size: 18px; font-weight: bold;">{final_milestone}</p>
229
- </div>
230
- <div style="text-align: center;">
231
- <h3 style="color: #34495e;">Completion</h3>
232
- <progress value="{percent_complete}" max="100" style="width: 200px; height: 20px;"></progress>
233
- <p>{percent_complete}%</p>
234
- </div>
235
- </div>
236
- <h3 style="color: #2c3e50;">Milestone Timeline</h3>
237
- <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
238
- <span style="color: {'#2ecc71' if final_milestone == 'Planning' else '#bdc3c7'};">Planning</span>
239
- <span style="color: {'#2ecc71' if final_milestone == 'Foundation' else '#bdc3c7'};">Foundation</span>
240
- <span style="color: {'#2ecc71' if final_milestone == 'Walls Erected' else '#bdc3c7'};">Walls Erected</span>
241
- <span style="color: {'#2ecc71' if final_milestone == 'Interior Furnishing' else '#bdc3c7'};">Interior Furnishing</span>
242
- <span style="color: {'#2ecc71' if final_milestone == 'Completed' else '#bdc3c7'};">Completed</span>
243
- </div>
244
- <details style="margin-bottom: 20px;">
245
- <summary style="color: #2c3e50; font-weight: bold;">Completed Tasks</summary>
246
- <ul style="padding-left: 20px;">
247
- {completed_html}
248
- </ul>
249
- </details>
250
- <details style="margin-bottom: 20px;">
251
- <summary style="color: #2c3e50; font-weight: bold;">Not Completed Tasks</summary>
252
- <ul style="padding-left: 20px;">
253
- {not_completed_html}
254
- </ul>
255
- </details>
256
- <p style="color: orange;">Construction is in progress at {final_milestone} stage as of 02:35 PM IST, June 20, 2025.</p>
257
  </div>
258
- """
259
 
260
- results_html.append(result_html)
261
- upload_statuses.append("Success" if file_url != "Upload skipped due to storage limit" else "Pending")
262
- milestones.append(final_milestone)
263
- progresses.append(f"{percent_complete}%")
 
 
 
264
 
265
- combined_html = "<div>" + "".join(results_html) + "</div>"
 
 
 
 
 
266
 
267
- # Set current time to 02:35 PM IST, June 20, 2025
268
- now = local_timezone.localize(datetime(2025, 6, 20, 14, 35))
 
 
 
 
 
 
 
 
 
269
  local_time = now.strftime("%Y-%m-%dT%H:%M:%S") + now.strftime("%z")[:-2] + ":" + now.strftime("%z")[-2:]
270
 
 
271
  record = {
272
  "Name__c": project_name,
273
- "Current_Milestone__c": milestones[0] if milestones else "Pending",
274
- "Completion_Percentage__c": int(progresses[0].rstrip('%')) if progresses else 0,
275
  "Last_Updated_On__c": local_time,
276
- "Upload_Status__c": upload_statuses[0] if upload_statuses else "Pending",
277
- "Comments__c": milestones[0] if milestones else "Pending",
278
- "Last_Updated_Image__c": file_url if file_url else ""
279
  }
280
 
281
  try:
282
- if file_url and file_url != "Upload skipped due to storage limit":
283
- sf.Construction__c.create(record)
284
  except Exception as e:
285
- return f"Error: Failed to update Salesforce - {str(e)}", None, "Failure", "", "", 0
286
 
287
- return combined_html, Image.open(images[0]) if images else None, ",".join(upload_statuses), ",".join(milestones), "", ",".join(progresses)
288
 
289
  except Exception as e:
290
- return f"Error: {str(e)}", None, "Failure", "", "", "0%"
291
 
292
- # Gradio UI with enhanced styling and live image preview
293
  with gr.Blocks(css="""
294
  .gradio-container {
295
  background-color: #f0f4f8;
@@ -344,26 +286,18 @@ with gr.Blocks(css="""
344
  gr.Markdown("<h1 class='title'>Construction Progress Analyzer</h1>")
345
  with gr.Row():
346
  image_input = gr.Files(type="filepath", label="Upload Construction Site Photos (JPG/PNG, ≤ 20MB)")
347
- image_preview = gr.Image(label="Image Preview", interactive=False)
348
  project_name_input = gr.Textbox(label="Project Name (Required)", placeholder="e.g. Project_12345")
349
 
350
  submit_button = gr.Button("Process Image")
351
- output_html = gr.HTML(label="Result")
352
  upload_status = gr.Textbox(label="Upload Status")
353
  milestone = gr.Textbox(label="Detected Milestone")
354
- confidence = gr.Textbox(label="Confidence Score") # Kept for compatibility, but unused
355
  progress = gr.Textbox(label="Completion Percentage", interactive=False)
356
 
357
- # Update preview on file upload
358
- image_input.change(
359
- fn=lambda x: Image.open(x[0]) if x else None,
360
- inputs=[image_input],
361
- outputs=[image_preview]
362
- )
363
  submit_button.click(
364
  fn=process_image,
365
  inputs=[image_input, project_name_input],
366
- outputs=[output_html, image_preview, upload_status, milestone, confidence, progress]
367
  )
368
 
369
  demo.launch(share=True)
 
4
  from dotenv import load_dotenv
5
  from simple_salesforce import Salesforce
6
  from datetime import datetime
7
+ import hashlib
8
  import shutil
9
  import base64
10
  import pytz
 
 
11
 
12
  # Load environment variables
13
  load_dotenv()
 
32
  raise
33
 
34
  # Valid milestones
35
+ VALID_MILESTONES = ["Planning", "Foundation", "Walls Erected", "Completed"]
36
 
37
+ # Adjust the timezone to your local timezone
38
  local_timezone = pytz.timezone("Asia/Kolkata")
39
 
40
+ # Image processing and Salesforce upload
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  def process_image(images, project_name):
42
  try:
43
  if not images or len(images) == 0:
44
+ return "Error: Please upload at least one image to proceed.", "Pending", "", 0
45
 
46
+ # Process each image
 
47
  milestones = []
 
 
48
  for image in images:
49
+ img = Image.open(image)
 
 
 
 
 
 
 
50
  image_size_mb = os.path.getsize(image) / (1024 * 1024)
51
  if image_size_mb > 20:
52
+ return "Error: One or more images exceed 20MB.", "Failure", "", 0
53
+ if not str(image).lower().endswith(('.jpg', '.jpeg', '.png')):
54
+ return "Error: Only JPG/PNG images are supported.", "Failure", "", 0
55
 
56
+ # Save image to public folder temporarily before uploading to Salesforce
57
  upload_dir = "public_uploads"
58
  os.makedirs(upload_dir, exist_ok=True)
59
  unique_id = datetime.now().strftime("%Y%m%d%H%M%S")
 
61
  saved_image_path = os.path.join(upload_dir, image_filename)
62
  shutil.copy(image, saved_image_path)
63
 
64
+ # Convert image to base64 before uploading to Salesforce
65
  with open(saved_image_path, 'rb') as image_file:
66
  image_data = base64.b64encode(image_file.read()).decode('utf-8')
67
 
68
+ # Create the ContentVersion record in Salesforce
69
+ content_version = {
70
+ 'Title': image_filename,
71
+ 'PathOnClient': saved_image_path,
72
+ 'VersionData': image_data
73
+ }
74
+
75
+ # Upload the file to Salesforce
76
  try:
 
 
 
 
 
77
  content_version_result = sf.ContentVersion.create(content_version)
78
  content_version_id = content_version_result['id']
79
  file_url = f"https://sathkruthatechsolutionspri8-dev-ed.develop.lightning.force.com/{content_version_id}"
80
  except Exception as e:
81
+ return f"Error: Failed to upload image to Salesforce - {str(e)}", "Failure", "", 0
82
+
83
+ # Mock AI model to detect milestone based on image content
84
+ img_bytes = img.tobytes()
85
+ img_hash = int(hashlib.sha256(img_bytes).hexdigest(), 16)
86
+ milestone_index = img_hash % len(VALID_MILESTONES)
87
+ milestone = VALID_MILESTONES[milestone_index]
88
+
89
+ # Adjust milestone detection based on internal/external features
90
+ if milestone == "Walls Erected" and any("interior" in img_text.lower() for img_text in [os.path.basename(image)] if img_text):
91
+ # Check for visible internal works like electrical/plumbing
92
+ if any(keyword in str(os.path.basename(image)).lower() for keyword in ["electrical", "plumbing", "wiring", "pipes"]):
93
+ milestone = "Completed" # Upgrade to Completed if internal works are detected
94
  else:
95
+ milestone = "Walls Erected" # Retain if no internal works visible
96
 
97
+ milestones.append(milestone)
98
 
99
+ # Determine overall milestone (most advanced detected)
100
+ final_milestone = max(set(milestones), key=milestones.count) if milestones else "Planning"
101
+ milestone_completion_map = {
102
+ "Planning": 10,
103
+ "Foundation": 30,
104
+ "Walls Erected": 50,
105
+ "Completed": 100,
106
+ }
107
+ percent_complete = milestone_completion_map.get(final_milestone, 0)
108
+
109
+ # Detailed Completion Breakdown based on final milestone
110
+ completion_details = {
111
+ "Planning": {
112
+ "completed": [
113
  "Initial project outline and objectives have been established.",
114
  "Preliminary designs and architectural plans are drafted.",
115
  "Stakeholder meetings and initial approvals are completed."
116
  ],
117
+ "not_completed": [
118
+ "Detailed construction plans and blueprints are pending finalization.",
119
+ "Permits and regulatory approvals are yet to be obtained.",
120
+ "Contractor selection and procurement processes are not yet complete."
121
+ ]
122
+ },
123
+ "Foundation": {
124
+ "completed": [
125
  "Site preparation, including clearing and leveling, is finished.",
126
  "Excavation for the foundation has been completed.",
127
  "Concrete pouring for the foundation, including footings and slabs, is done.",
128
  "Initial structural inspections for the foundation have been passed."
129
  ],
130
+ "not_completed": [
131
+ "Plumbing and electrical groundwork installations are pending.",
132
+ "Backfilling and site grading around the foundation are not yet done.",
133
+ "Above-ground structural work, such as columns and walls, has not started."
134
+ ]
135
+ },
136
+ "Walls Erected": {
137
+ "completed": [
138
  "The concrete framework, including columns and beams, is in place.",
139
  "All structural walls have been erected and stabilized.",
140
  "Temporary scaffolding and safety measures are installed for ongoing work.",
141
  "Initial inspections for structural integrity have been completed."
142
  ],
143
+ "not_completed": [
144
+ "Roofing installation and weatherproofing are pending.",
145
+ "Windows, doors, and exterior cladding are not yet installed.",
146
+ "Interior walls, electrical, and plumbing systems are still to be implemented."
147
+ ]
148
+ },
149
+ "Completed": {
150
+ "completed": [
151
+ "The concrete framework, including columns, beams, and floor slabs, is fully constructed.",
152
+ "Exterior walls, windows, and cladding are installed, completing the building's facade.",
153
  "Interior work, including electrical, plumbing, and HVAC systems, is fully implemented.",
154
  "Finishing touches, such as flooring, painting, and fixtures, are completed.",
155
  "All phases of the project are finished, including final inspections and approvals."
156
+ ],
157
+ "not_completed": [
158
+ "There should be no more pending work as the project is fully completed."
159
  ]
160
  }
161
+ }
162
 
163
+ completed_tasks = completion_details[final_milestone]["completed"]
164
+ not_completed_tasks = completion_details[final_milestone]["not_completed"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
 
166
+ completed_html = "".join([f'<li style="color: green;">✔ {task}</li>' for task in completed_tasks])
167
+ not_completed_html = "".join([f'<li style="color: red;">✘ {task}</li>' for task in not_completed_tasks])
168
 
169
+ # Create HTML for the output with collapsible sections and progress bar
170
+ result_html = f"""
171
+ <div style="font-family: Arial, sans-serif; padding: 20px; background-color: #f9f9f9; border-radius: 10px;">
172
+ <h2 style="color: #2c3e50; text-align: center;">Project Summary</h2>
173
+ <div style="display: flex; justify-content: space-around; margin-bottom: 20px;">
174
+ <div style="text-align: center;">
175
+ <h3 style="color: #34495e;">Detected Milestone</h3>
176
+ <p style="font-size: 18px; font-weight: bold;">{final_milestone}</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  </div>
178
+ <div style="text-align: center;">
179
+ <h3 style="color: #34495e;">Completion</h3>
180
+ <progress value="{percent_complete}" max="100" style="width: 200px; height: 20px;"></progress>
181
+ <p>{percent_complete}%</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  </div>
183
+ </div>
184
 
185
+ <h3 style="color: #2c3e50;">Milestone Timeline</h3>
186
+ <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
187
+ <span style="color: {'#2ecc71' if final_milestone == 'Planning' else '#bdc3c7'};">Planning</span>
188
+ <span style="color: {'#2ecc71' if final_milestone == 'Foundation' else '#bdc3c7'};">Foundation</span>
189
+ <span style="color: {'#2ecc71' if final_milestone == 'Walls Erected' else '#bdc3c7'};">Walls Erected</span>
190
+ <span style="color: {'#2ecc71' if final_milestone == 'Completed' else '#bdc3c7'};">Completed</span>
191
+ </div>
192
 
193
+ <details style="margin-bottom: 20px;">
194
+ <summary style="color: #2c3e50; font-weight: bold;">Completed Tasks</summary>
195
+ <ul style="padding-left: 20px;">
196
+ {completed_html}
197
+ </ul>
198
+ </details>
199
 
200
+ <details style="margin-bottom: 20px;">
201
+ <summary style="color: #2c3e50; font-weight: bold;">Not Completed Tasks</summary>
202
+ <ul style="padding-left: 20px;">
203
+ {not_completed_html}
204
+ </ul>
205
+ </details>
206
+ </div>
207
+ """
208
+
209
+ # Adjust the current time to local timezone with proper ISO 8601 format
210
+ now = datetime.now(local_timezone)
211
  local_time = now.strftime("%Y-%m-%dT%H:%M:%S") + now.strftime("%z")[:-2] + ":" + now.strftime("%z")[-2:]
212
 
213
+ # Create the Salesforce record (removing confidence score)
214
  record = {
215
  "Name__c": project_name,
216
+ "Current_Milestone__c": final_milestone,
217
+ "Completion_Percentage__c": percent_complete,
218
  "Last_Updated_On__c": local_time,
219
+ "Upload_Status__c": "Success",
220
+ "Comments__c": f"{final_milestone}",
221
+ "Last_Updated_Image__c": file_url
222
  }
223
 
224
  try:
225
+ sf.Construction__c.create(record)
 
226
  except Exception as e:
227
+ return f"Error: Failed to update Salesforce - {str(e)}", "Failure", "", 0
228
 
229
+ return result_html, "Success", final_milestone, f"{percent_complete}%"
230
 
231
  except Exception as e:
232
+ return f"Error: {str(e)}", "Failure", "", "0%"
233
 
234
+ # Gradio UI with enhanced styling
235
  with gr.Blocks(css="""
236
  .gradio-container {
237
  background-color: #f0f4f8;
 
286
  gr.Markdown("<h1 class='title'>Construction Progress Analyzer</h1>")
287
  with gr.Row():
288
  image_input = gr.Files(type="filepath", label="Upload Construction Site Photos (JPG/PNG, ≤ 20MB)")
 
289
  project_name_input = gr.Textbox(label="Project Name (Required)", placeholder="e.g. Project_12345")
290
 
291
  submit_button = gr.Button("Process Image")
292
+ output_html = gr.HTML(label="Result") # Changed to HTML for richer output
293
  upload_status = gr.Textbox(label="Upload Status")
294
  milestone = gr.Textbox(label="Detected Milestone")
 
295
  progress = gr.Textbox(label="Completion Percentage", interactive=False)
296
 
 
 
 
 
 
 
297
  submit_button.click(
298
  fn=process_image,
299
  inputs=[image_input, project_name_input],
300
+ outputs=[output_html, upload_status, milestone, progress]
301
  )
302
 
303
  demo.launch(share=True)