jackmedda commited on
Commit
3dad338
·
1 Parent(s): fc91734

Handled duplicates, replaced description with category

Browse files
Files changed (3) hide show
  1. html_items.py +10 -9
  2. main.py +20 -19
  3. utils/poi_search_utils.py +20 -18
html_items.py CHANGED
@@ -110,7 +110,7 @@ def create_poi_card_selectable(poi: dict, is_selected: bool = False) -> str:
110
  # Darker text colors for selected state
111
  title_color = "#2c5530"
112
  location_color = "#4a5c4d"
113
- description_color = "#5a6b5d"
114
  else:
115
  border_color = "#ddd"
116
  background_color = "white"
@@ -119,7 +119,7 @@ def create_poi_card_selectable(poi: dict, is_selected: bool = False) -> str:
119
  content_bg = "white"
120
  title_color = "#333"
121
  location_color = "#666"
122
- description_color = "#777"
123
 
124
  # Create compact sensory features display
125
  sensory_html = ""
@@ -147,7 +147,8 @@ def create_poi_card_selectable(poi: dict, is_selected: bool = False) -> str:
147
  """
148
 
149
  # Escape single quotes in POI name for JavaScript
150
- poi_name_escaped = poi["name:token_seq"].replace("'", "\\'")
 
151
 
152
  html = f"""
153
  <div class="poi-card" data-poi-name="{poi["name:token_seq"]}"
@@ -161,7 +162,7 @@ def create_poi_card_selectable(poi: dict, is_selected: bool = False) -> str:
161
  position: relative;
162
  overflow: hidden;
163
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);"
164
- onclick="document.getElementById('poi-btn-{poi_name_escaped.replace(" ", "-")}').click();"
165
  onmouseover="this.style.transform='scale(1.02)'; this.style.boxShadow='0 4px 12px rgba(0,0,0,0.15)';"
166
  onmouseout="this.style.transform='scale(1)'; this.style.boxShadow='0 2px 8px rgba(0,0,0,0.1)';">
167
 
@@ -185,8 +186,8 @@ def create_poi_card_selectable(poi: dict, is_selected: bool = False) -> str:
185
  <p style="margin: 0 0 8px 0; color: {location_color}; font-size: 14px; font-weight: 500;">
186
  📍 {poi["address:token_seq"]}
187
  </p>
188
- <p style="margin: 0 0 12px 0; color: {description_color}; font-size: 14px; line-height: 1.4;">
189
- {poi["description:token_seq"][:120]}{"..." if len(poi["description:token_seq"]) > 120 else ""}
190
  </p>
191
 
192
  {sensory_html}
@@ -203,14 +204,14 @@ def create_poi_card_selectable(poi: dict, is_selected: bool = False) -> str:
203
  return html
204
 
205
 
206
- def create_poi_cards_list(pois: list, selected_names: set) -> str:
207
  if not pois:
208
  return "<div style='text-align:center; color:#666; margin: 40px; padding: 40px; background: #f8f9fa; border-radius: 12px;'><h3>🔍 Nessun punto di interesse trovato</h3><p>Prova con termini di ricerca diversi</p></div>"
209
 
210
  # Genera HTML per i POI filtrati
211
  poi_cards_html = []
212
  for poi in pois:
213
- is_selected = poi.get("name:token_seq") in selected_names
214
  card_html = create_poi_card_selectable(poi, is_selected)
215
  poi_cards_html.append(card_html)
216
 
@@ -219,7 +220,7 @@ def create_poi_cards_list(pois: list, selected_names: set) -> str:
219
  {"".join(poi_cards_html)}
220
  </div>
221
  <div style='text-align: center; color: black; margin-top: 20px; padding: 15px; background: #f0f0f0; border-radius: 8px;'>
222
- <strong style='color: black;'>Trovati {len(pois)} punti di interesse</strong> • <span style='color: #7FB77E;'>{len(selected_names)} selezionati</span>
223
  </div>
224
  """
225
 
 
110
  # Darker text colors for selected state
111
  title_color = "#2c5530"
112
  location_color = "#4a5c4d"
113
+ category_color = "#5a6b5d"
114
  else:
115
  border_color = "#ddd"
116
  background_color = "white"
 
119
  content_bg = "white"
120
  title_color = "#333"
121
  location_color = "#666"
122
+ category_color = "#777"
123
 
124
  # Create compact sensory features display
125
  sensory_html = ""
 
147
  """
148
 
149
  # Escape single quotes in POI name for JavaScript
150
+ poi_id_escaped = poi["poi_id:token"].replace(" ", "-").replace("'", "").replace('"', "")
151
+ poi_category = ' - '.join(poi["category:token_seq"]).replace('_', ' ')
152
 
153
  html = f"""
154
  <div class="poi-card" data-poi-name="{poi["name:token_seq"]}"
 
162
  position: relative;
163
  overflow: hidden;
164
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);"
165
+ onclick="document.getElementById('poi-btn-{poi_id_escaped}').click();"
166
  onmouseover="this.style.transform='scale(1.02)'; this.style.boxShadow='0 4px 12px rgba(0,0,0,0.15)';"
167
  onmouseout="this.style.transform='scale(1)'; this.style.boxShadow='0 2px 8px rgba(0,0,0,0.1)';">
168
 
 
186
  <p style="margin: 0 0 8px 0; color: {location_color}; font-size: 14px; font-weight: 500;">
187
  📍 {poi["address:token_seq"]}
188
  </p>
189
+ <p style="margin: 0 0 12px 0; color: {category_color}; font-size: 14px; line-height: 1.4;">
190
+ {'🏷️ ' + poi_category if poi_category else ''}
191
  </p>
192
 
193
  {sensory_html}
 
204
  return html
205
 
206
 
207
+ def create_poi_cards_list(pois: list, selected_pois: set) -> str:
208
  if not pois:
209
  return "<div style='text-align:center; color:#666; margin: 40px; padding: 40px; background: #f8f9fa; border-radius: 12px;'><h3>🔍 Nessun punto di interesse trovato</h3><p>Prova con termini di ricerca diversi</p></div>"
210
 
211
  # Genera HTML per i POI filtrati
212
  poi_cards_html = []
213
  for poi in pois:
214
+ is_selected = (poi.get("poi_id:token"), poi.get("name:token_seq")) in selected_pois
215
  card_html = create_poi_card_selectable(poi, is_selected)
216
  poi_cards_html.append(card_html)
217
 
 
220
  {"".join(poi_cards_html)}
221
  </div>
222
  <div style='text-align: center; color: black; margin-top: 20px; padding: 15px; background: #f0f0f0; border-radius: 8px;'>
223
+ <strong style='color: black;'>Trovati {len(pois)} punti di interesse</strong> • <span style='color: #7FB77E;'>{len(selected_pois)} selezionati</span>
224
  </div>
225
  """
226
 
main.py CHANGED
@@ -169,7 +169,7 @@ def create_main_app(self):
169
  # Stati globali dell'applicazione
170
  app_user_id = gr.State("")
171
  current_page = gr.State("login") # "login", "poi_selection", "sensory_config", "recommendations"
172
- selected_poi_names = gr.State(set())
173
  recommendations_state = gr.State([])
174
  selected_poi_index = gr.State(-1)
175
  completed_survey_pois = gr.State(set())
@@ -250,14 +250,15 @@ def create_main_app(self):
250
  # Create hidden buttons for each POI
251
  poi_buttons = {}
252
  for poi in pois_list:
 
253
  poi_name = poi["name:token_seq"]
254
- safe_name = (
255
- poi_name.replace(" ", "-").replace("'", "").replace('"', "")
256
  )
257
  button = gr.Button(
258
- poi_name, visible=False, elem_id=f"poi-btn-{safe_name}"
259
  )
260
- poi_buttons[poi_name] = button
261
 
262
  with gr.Column(
263
  visible=False, elem_classes="sensory-config-main-container"
@@ -442,19 +443,19 @@ def create_main_app(self):
442
  login_status, # login_status
443
  )
444
 
445
- def handle_poi_click(poi_name, selected_names, query):
446
  """Handle POI click - toggle selection"""
447
  print(f"🔥 POI Button clicked: {poi_name}")
448
- return toggle_poi_selection(poi_name, selected_names, query)
449
-
450
- def handle_proceed_to_sensory_config(user_id, selected_names):
451
  """Handle proceeding to next step"""
452
- if not selected_names:
453
  gr.Warning("⚠️ Seleziona la card di almeno un Punto di Interesse per continuare!")
454
  return
455
 
456
- update_user_selected_pois(user_id, selected_names)
457
- gr.Info(f"✅ Procedendo con {len(selected_names)} Punti di Interesse selezionati")
458
  return navigate_to_sensory_config()
459
 
460
  def navigate_to_poi_selection():
@@ -537,28 +538,28 @@ def create_main_app(self):
537
  # Dynamic search - triggers on every keystroke
538
  search_input.change(
539
  fn=search_pois,
540
- inputs=[search_input, selected_poi_names],
541
  outputs=[poi_display],
542
  )
543
 
544
  # Set up click handlers for each POI button
545
- for poi_name, button in poi_buttons.items():
546
  button.click(
547
- fn=partial(handle_poi_click, poi_name),
548
- inputs=[selected_poi_names, search_input],
549
- outputs=[selected_poi_names, poi_display, selection_summary],
550
  )
551
 
552
  # Clear all selections
553
  clear_button.click(
554
  fn=clear_all_selections,
555
  inputs=[search_input],
556
- outputs=[selected_poi_names, poi_display, selection_summary],
557
  )
558
 
559
  continue_to_sensory_btn.click(
560
  fn=handle_proceed_to_sensory_config,
561
- inputs=[app_user_id, selected_poi_names],
562
  outputs=[
563
  login_page,
564
  poi_selection_page,
 
169
  # Stati globali dell'applicazione
170
  app_user_id = gr.State("")
171
  current_page = gr.State("login") # "login", "poi_selection", "sensory_config", "recommendations"
172
+ current_selected_pois = gr.State(set())
173
  recommendations_state = gr.State([])
174
  selected_poi_index = gr.State(-1)
175
  completed_survey_pois = gr.State(set())
 
250
  # Create hidden buttons for each POI
251
  poi_buttons = {}
252
  for poi in pois_list:
253
+ poi_id = poi["poi_id:token"]
254
  poi_name = poi["name:token_seq"]
255
+ safe_id = (
256
+ poi_id.replace(" ", "-").replace("'", "").replace('"', "")
257
  )
258
  button = gr.Button(
259
+ poi_name, visible=False, elem_id=f"poi-btn-{safe_id}"
260
  )
261
+ poi_buttons[(poi_id, poi_name)] = button
262
 
263
  with gr.Column(
264
  visible=False, elem_classes="sensory-config-main-container"
 
443
  login_status, # login_status
444
  )
445
 
446
+ def handle_poi_click(poi_id, poi_name, selected_pois, query):
447
  """Handle POI click - toggle selection"""
448
  print(f"🔥 POI Button clicked: {poi_name}")
449
+ return toggle_poi_selection(poi_id, poi_name, selected_pois, query)
450
+
451
+ def handle_proceed_to_sensory_config(user_id, selected_pois):
452
  """Handle proceeding to next step"""
453
+ if not selected_pois:
454
  gr.Warning("⚠️ Seleziona la card di almeno un Punto di Interesse per continuare!")
455
  return
456
 
457
+ update_user_selected_pois(user_id, selected_pois)
458
+ gr.Info(f"✅ Procedendo con {len(selected_pois)} Punti di Interesse selezionati")
459
  return navigate_to_sensory_config()
460
 
461
  def navigate_to_poi_selection():
 
538
  # Dynamic search - triggers on every keystroke
539
  search_input.change(
540
  fn=search_pois,
541
+ inputs=[search_input, current_selected_pois],
542
  outputs=[poi_display],
543
  )
544
 
545
  # Set up click handlers for each POI button
546
+ for (poi_id, poi_name), button in poi_buttons.items():
547
  button.click(
548
+ fn=partial(handle_poi_click, poi_id, poi_name),
549
+ inputs=[current_selected_pois, search_input],
550
+ outputs=[current_selected_pois, poi_display, selection_summary],
551
  )
552
 
553
  # Clear all selections
554
  clear_button.click(
555
  fn=clear_all_selections,
556
  inputs=[search_input],
557
+ outputs=[current_selected_pois, poi_display, selection_summary],
558
  )
559
 
560
  continue_to_sensory_btn.click(
561
  fn=handle_proceed_to_sensory_config,
562
+ inputs=[app_user_id, current_selected_pois],
563
  outputs=[
564
  login_page,
565
  poi_selection_page,
utils/poi_search_utils.py CHANGED
@@ -10,9 +10,11 @@ try:
10
  with open(os.path.join(RESOURCE_DIR, "turin_autism.item.json"), "r") as f:
11
  pois_list = json.load(f)
12
  for poi in pois_list:
13
- poi["description:token_seq"] = poi.get("description", "")
14
- poi["address:token_seq"] = poi.get("address", "")
15
- poi["coordinates:float_seq"] = poi.get("coordinates", [])
 
 
16
  except FileNotFoundError:
17
  with open(os.path.join(RESOURCE_DIR, "mock_data.json"), "r") as f:
18
  LOADED_MOCK_POIS = json.load(f)
@@ -20,7 +22,7 @@ except FileNotFoundError:
20
  check_image_url(pois_list)
21
 
22
 
23
- def search_pois(search_query: str, selected_names: set) -> str:
24
  """Cerca POI basandosi sulla query di ricerca e restituisce HTML"""
25
 
26
  # Filtra i POI basandosi sulla query
@@ -40,26 +42,26 @@ def search_pois(search_query: str, selected_names: set) -> str:
40
  ):
41
  filtered_pois.append(poi)
42
 
43
- return create_poi_cards_list(filtered_pois, selected_names)
44
 
45
 
46
  def toggle_poi_selection(
47
- poi_name: str, selected_names: set, current_query: str
48
  ) -> tuple[set, str, str]:
49
  """Alterna la selezione di un POI e aggiorna il display"""
50
 
51
  # Copia il set per evitare modifiche dirette
52
- new_selected = selected_names.copy()
53
 
54
- print(f"DEBUG: Toggling POI '{poi_name}'")
55
- print(f"DEBUG: Current selected: {selected_names}")
56
 
57
- if poi_name in new_selected:
58
- new_selected.remove(poi_name)
59
- print(f"DEBUG: Removed '{poi_name}' from selection")
60
  else:
61
- new_selected.add(poi_name)
62
- print(f"DEBUG: Added '{poi_name}' to selection")
63
 
64
  print(f"DEBUG: New selected: {new_selected}")
65
 
@@ -73,13 +75,13 @@ def toggle_poi_selection(
73
  return new_selected, updated_html, summary
74
 
75
 
76
- def get_selection_summary(selected_names: set) -> str:
77
  """Restituisce un riassunto dei POI selezionati"""
78
- if not selected_names:
79
  return "**Punti di Interesse selezionati: 0** - Seleziona i luoghi di tuo interesse cliccando sulle card"
80
 
81
- names_list = list(selected_names)
82
- return f"**Punti di Interesse selezionati: {len(selected_names)}** => {' - '.join(names_list[:3])}{' e altri...' if len(selected_names) > 3 else ''}"
83
 
84
 
85
  def clear_all_selections(current_query: str) -> tuple[set, str, str]:
 
10
  with open(os.path.join(RESOURCE_DIR, "turin_autism.item.json"), "r") as f:
11
  pois_list = json.load(f)
12
  for poi in pois_list:
13
+ for col in ["description:token_seq", "address:token_seq", "coordinates:float_seq"]:
14
+ if poi[col] is None:
15
+ poi[col] = ""
16
+ if poi["category:token_seq"] is None:
17
+ poi["category:token_seq"] = [""]
18
  except FileNotFoundError:
19
  with open(os.path.join(RESOURCE_DIR, "mock_data.json"), "r") as f:
20
  LOADED_MOCK_POIS = json.load(f)
 
22
  check_image_url(pois_list)
23
 
24
 
25
+ def search_pois(search_query: str, selected_pois: set) -> str:
26
  """Cerca POI basandosi sulla query di ricerca e restituisce HTML"""
27
 
28
  # Filtra i POI basandosi sulla query
 
42
  ):
43
  filtered_pois.append(poi)
44
 
45
+ return create_poi_cards_list(filtered_pois, selected_pois)
46
 
47
 
48
  def toggle_poi_selection(
49
+ poi_id, poi_name: str, selected_pois: set, current_query: str
50
  ) -> tuple[set, str, str]:
51
  """Alterna la selezione di un POI e aggiorna il display"""
52
 
53
  # Copia il set per evitare modifiche dirette
54
+ new_selected = selected_pois.copy()
55
 
56
+ print(f"DEBUG: Toggling POI '{poi_name} ({poi_id})' selection")
57
+ print(f"DEBUG: Current selected: {selected_pois}")
58
 
59
+ if (poi_id, poi_name) in new_selected:
60
+ new_selected.remove((poi_id, poi_name))
61
+ print(f"DEBUG: Removed '{poi_name} ({poi_id})' from selection")
62
  else:
63
+ new_selected.add((poi_id, poi_name))
64
+ print(f"DEBUG: Added '{poi_name} ({poi_id})' to selection")
65
 
66
  print(f"DEBUG: New selected: {new_selected}")
67
 
 
75
  return new_selected, updated_html, summary
76
 
77
 
78
+ def get_selection_summary(selected_pois: set) -> str:
79
  """Restituisce un riassunto dei POI selezionati"""
80
+ if not selected_pois:
81
  return "**Punti di Interesse selezionati: 0** - Seleziona i luoghi di tuo interesse cliccando sulle card"
82
 
83
+ names_list = [name for _, name in selected_pois]
84
+ return f"**Punti di Interesse selezionati: {len(names_list)}** => {' - '.join(names_list[:3])}{' e altri...' if len(names_list) > 3 else ''}"
85
 
86
 
87
  def clear_all_selections(current_query: str) -> tuple[set, str, str]: