File size: 11,985 Bytes
3c184b3
 
 
025f2ca
3c184b3
025f2ca
3c184b3
 
 
 
 
 
 
 
 
 
 
fc91734
3c184b3
 
fc91734
 
 
3c184b3
 
 
 
 
 
 
 
 
 
 
 
 
fc91734
3c184b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a3892df
3c184b3
 
 
 
 
 
 
 
 
 
 
 
 
 
037d8ad
3c184b3
 
 
 
 
 
 
fc91734
3c184b3
 
fc91734
037d8ad
 
3c184b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3dad338
3c184b3
 
 
 
 
 
 
 
3dad338
3c184b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3dad338
 
3c184b3
 
fc91734
3c184b3
 
 
 
 
 
 
 
 
 
3dad338
3c184b3
 
 
 
 
 
 
 
 
 
 
 
fc91734
3c184b3
fc91734
3c184b3
 
 
 
fc91734
3c184b3
fc91734
3c184b3
3dad338
 
3c184b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3dad338
3c184b3
 
 
 
 
 
3dad338
3c184b3
 
 
 
 
 
 
 
3dad338
3c184b3
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
import json
import os

from utils.utils import get_aversion_color, get_qualitative_aversion

RESOURCE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "resources")
with open(os.path.join(RESOURCE_DIR, "aversions.json"), "r") as f:
    aversions_data = json.load(f)
AVERSIONS = {item["Name"]: item for item in aversions_data}


def create_poi_html(poi: dict, user_id: str) -> str:
    """Create HTML representation of a POI with sensory features"""
    html = f"""
    <div style="border: 1px solid #ddd; padding: 15px; border-radius: 10px; margin-bottom: 20px;">
        <div style="display: flex; flex-direction: row; gap: 20px;">
            <div style="flex: 0 0 300px;">
                <img src="{poi["image_url:token_seq"]}" style="width: 100%; height: auto; border-radius: 8px; object-fit: cover;" alt="{poi["name:token_seq"]}">
            </div>
            <div style="flex: 1;">
                <h3 style="margin-top: 0;">{poi["name:token_seq"]}</h3>
                <p><strong>Descrizione:</strong> {poi["description:token_seq"]}</p>
                <p><strong>Luogo:</strong> {poi["address:token_seq"]}</p>
                
                <div style="margin: 15px 0;">
                    <h4>Caratteristiche Sensoriali:</h4>
                    <table style="width: 100%; border-collapse: collapse;">
                        <thead>
                            <tr style="background-color: #4a4a4a; color: white;">
                                <th style="text-align: left; padding: 8px; border: 1px solid #ddd; width: 35%;">Caratteristica</th>
                                <th style="text-align: center; padding: 8px; border: 1px solid #ddd; width: 65%;">Livello (1-5)</th>
                            </tr>
                        </thead>
                        <tbody>
    """

    for feature, level in poi["sensory_features:token"].items():
        icon = AVERSIONS[feature]["Icon"]
        bar_color = get_aversion_color(level, AVERSIONS[feature]["Type"])
        html += f"""
                            <tr>
                                <td style="text-align: left; padding: 8px; border: 1px solid #ddd;">
                                    <div style="display: flex; align-items: center;">
                                        <span style="font-size: 18px; margin-right: 8px;">{icon}</span>
                                        {feature}
                                    </div>
                                </td>
                                <td style="text-align: left; padding: 8px; border: 1px solid #ddd;">
                                    <div style="position: relative; background-color: #f0f0f0; width: 100%; height: 24px; border-radius: 12px;">
                                        <div style="position: absolute; background-color: {bar_color}; width: {level * 20}%; height: 100%; border-radius: 12px; display: flex; align-items: center;">
                                            <span style="position: absolute; left: 50%; color: 'black'; font-weight: bold; text-shadow: 0px 0px 2px black;">{level}</span>
                                        </div>
                                        <div style="position: absolute; width: 100%; height: 100%; display: flex; justify-content: space-between; align-items: center; padding: 0 10px; box-sizing: border-box; pointer-events: none;">
                                            <span style="font-size: 10px; opacity: 0.9; color: black">Basso</span>
                                            <span style="font-size: 10px; opacity: 0.9; color: black">Alto</span>
                                        </div>
                                    </div>
                                </td>
                            </tr>
    """
    html += f"""        </tbody>
                    </table>
                    <div style="margin: 15px 0; padding: 10px; background-color: #3a3a3a; color: white; border-left: 5px solid #7FB77E; border-radius: 5px;" --explanation_type="{poi.get("explanation_type", -1)}">
                        <h3>Spiegazione della raccomandazione: ti suggeriamo questo luogo perché ...</h3>
                        <p>{poi["explanation"]}</p>
                    </div>
                </div>  
            </div>
        </div>
    </div>
    """

    return html


def create_recommendation_item(rec, index, selected=False) -> str:
    """Create HTML for a single recommendation item"""
    poi_category = ' - '.join(rec["category:token_seq"]).replace('_', ' ')
    return f"""
    <div onclick="document.getElementById('select-button-{index}').click();" 
         style="display: flex; align-items: center; padding: 10px; margin-bottom: 10px; border: 1px solid #ddd; 
                border-radius: 10px; cursor: pointer; transition: background-color 0.3s; background-color: {'#888888' if selected else 'transparent'};"
         onmouseover="this.style.backgroundColor='{'#888888' if selected else '#393939'}';" 
         onmouseout="this.style.backgroundColor='{'#888888' if selected else 'transparent'}';">
        <div style="width: 80px; height: 80px; overflow: hidden; border-radius: 8px; margin-right: 15px;">
            <img src="{rec["image_url:token_seq"]}" style="width: 100%; height: 100%; object-fit: cover;" alt="{rec["name:token_seq"]}">
        </div>
        <div>
            <h3 style="margin: 0 0 5px 0;">{rec["name:token_seq"]}</h3>
            <p style="margin: 0 0 5px 0; font-size: 0.9em;">{rec["description:token_seq"] or ''}</p>
            <p style="margin: 0 0 5px 0; font-size: 0.93m; line-height: 1.4;">{'🏷️ ' + poi_category if poi_category else ''}</p>
        </div>
        <div style="margin-left: 50px; font-size: 40px; color: white; font-weight: bold; z-index: 10; text-shadow: 0 0 4px white;">
            {"✓" if selected else ""}
        </div>
    </div>
    """


def create_poi_card_selectable(poi: dict, is_selected: bool = False) -> str:
    """Create HTML representation of a selectable POI card for search interface"""

    # Enhanced visual feedback based on selection state
    if is_selected:
        border_color = "#30892F"
        background_color = "#f0f8f0"  # Slightly darker green tint
        tick_icon = "✓"
        # Dark overlay for selected state
        overlay_style = "background-color: rgba(0, 0, 0, 0.15);"
        # Darker content background
        content_bg = "#e8f5e8"
        # Darker text colors for selected state
        title_color = "#2c5530"
        location_color = "#4a5c4d"
        category_color = "#5a6b5d"
    else:
        border_color = "#ddd"
        background_color = "white"
        tick_icon = ""
        overlay_style = ""
        content_bg = "white"
        title_color = "#333"
        location_color = "#666"
        category_color = "#777"

    # Create compact sensory features display
    sensory_html = ""
    if poi.get("sensory_features"):
        sensory_items = []
        for feature, level in poi["sensory_features"].items():
            icon = AVERSIONS[feature]["Icon"]
            color = get_aversion_color(level, AVERSIONS[feature]["Type"])
            qualitative_level = get_qualitative_aversion(
                level, AVERSIONS[feature]["Type"]
            )
            qualitative_level = {"GOOD": "Basso", "ACCEPTABLE": "Medio", "BAD": "Alto"}[
                qualitative_level
            ]

            sensory_items.append(
                f'<span style="color: {color}; margin-right: 8px;" title="{feature}: {level}/5">{icon} {feature}: {qualitative_level}</span>'
            )

        sensory_html = f"""
        <div style="margin: 8px 0; padding: 8px; background: white; border-radius: 6px; border-left: 3px solid #7FB77E;">
            <div style="font-size: 12px; color: #666; margin-bottom: 4px;">Caratteristiche Sensoriali:</div>
            <div style="font-size: 14px;"><ul><li>{"</li><li>".join(sensory_items)}</li></ul></div>
        </div>
        """

    # Escape single quotes in POI name for JavaScript
    poi_id_escaped = poi["poi_id:token"].replace(" ", "-").replace("'", "").replace('"', "")
    poi_category = ' - '.join(poi["category:token_seq"]).replace('_', ' ')
    
    html = f"""
    <div class="poi-card" data-poi-name="{poi["name:token_seq"]}" 
         style="border: 2px solid {border_color}; 
                background-color: {background_color};
                padding: 0; 
                border-radius: 12px; 
                margin-bottom: 20px; 
                cursor: pointer;
                transition: all 0.3s ease;
                position: relative;
                overflow: hidden;
                box-shadow: 0 2px 8px rgba(0,0,0,0.1);"
         onclick="document.getElementById('poi-btn-{poi_id_escaped}').click();"
         onmouseover="this.style.transform='scale(1.02)'; this.style.boxShadow='0 4px 12px rgba(0,0,0,0.15)';" 
         onmouseout="this.style.transform='scale(1)'; this.style.boxShadow='0 2px 8px rgba(0,0,0,0.1)';">
        
        <!-- Dark overlay for selected state -->
        <div style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; z-index: 1; {overlay_style} pointer-events: none;"></div>
        
        <div style="position: absolute; top: 15px; right: 15px; font-size: 28px; color: #7FB77E; font-weight: bold; z-index: 10; text-shadow: 0 0 4px white;">
            {tick_icon}
        </div>
        
        <!-- Image filling horizontally -->
        <div style="width: 100%; height: 200px; overflow: hidden; position: relative;">
            <img src="{poi["image_url:token_seq"]}" 
                 style="width: 100%; height: 100%; object-fit: cover;" 
                 alt="{poi["name:token_seq"]}">
        </div>
        
        <!-- Content below image -->
        <div style="padding: 15px; background-color: {content_bg}; position: relative; z-index: 2;">
            <h3 style="margin: 0 0 8px 0; color: {title_color}; font-size: 18px;">{poi["name:token_seq"]}</h3>
            <p style="margin: 0 0 8px 0; color: {location_color}; font-size: 14px; font-weight: 500;">
                📍 {poi["address:token_seq"]}
            </p>
            <p style="margin: 0 0 12px 0; color: {category_color}; font-size: 14px; line-height: 1.4;">
                {'🏷️ ' + poi_category if poi_category else ''}
            </p>
            
            {sensory_html}
            
            <div style="display: flex; justify-content: space-between; align-items: center; margin-top: 12px;">
                <span style="display: inline-block; padding: 6px 12px; background-color: {"#d4edda" if is_selected else "#e8f4e8"}; color: {title_color}; border-radius: 20px; font-size: 12px; font-weight: bold;">
                    {("✓ Selezionato" if is_selected else "Clicca per selezionare")}
                </span>
            </div>
        </div>
    </div>
    """

    return html


def create_poi_cards_list(pois: list, selected_pois: set) -> str:
    if not pois:
        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>"

    # Genera HTML per i POI filtrati
    poi_cards_html = []
    for poi in pois:
        is_selected = (poi.get("poi_id:token"), poi.get("name:token_seq")) in selected_pois
        card_html = create_poi_card_selectable(poi, is_selected)
        poi_cards_html.append(card_html)

    html = f"""
    <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 20px; margin: 20px 0;">
        {"".join(poi_cards_html)}
    </div>
    <div style='text-align: center; color: black; margin-top: 20px; padding: 15px; background: #f0f0f0; border-radius: 8px;'>
        <strong style='color: black;'>Trovati {len(pois)} punti di interesse</strong> • <span style='color: #7FB77E;'>{len(selected_pois)} selezionati</span>
    </div>
    """

    return html