File size: 19,779 Bytes
a0a0034
 
 
 
 
771f178
a0a0034
 
 
 
 
 
 
 
 
 
 
 
 
771f178
a0a0034
771f178
a0a0034
 
 
 
 
 
771f178
a0a0034
 
 
 
 
 
 
771f178
 
 
 
 
 
 
 
a0a0034
 
771f178
 
 
 
 
 
 
 
 
a0a0034
 
771f178
a0a0034
771f178
 
 
 
 
 
 
 
a0a0034
771f178
 
 
 
 
a0a0034
771f178
 
 
a0a0034
771f178
 
a0a0034
771f178
 
 
 
 
a0a0034
771f178
 
a0a0034
771f178
 
 
 
 
 
 
 
 
 
a0a0034
771f178
 
 
 
 
 
 
 
 
 
a0a0034
771f178
 
 
 
 
 
 
 
 
 
 
 
a0a0034
771f178
 
 
 
 
 
 
 
a0a0034
771f178
 
a0a0034
 
771f178
 
a0a0034
 
771f178
a0a0034
771f178
 
 
 
 
 
 
 
 
 
 
 
a0a0034
 
771f178
 
 
 
 
a0a0034
 
 
 
771f178
 
 
 
 
 
 
a0a0034
771f178
 
a0a0034
 
771f178
a0a0034
771f178
a0a0034
 
 
 
 
771f178
 
 
 
 
 
3f5ff7f
771f178
 
 
 
 
 
 
 
a0a0034
 
 
 
 
771f178
a0a0034
 
 
771f178
 
a0a0034
 
771f178
a0a0034
771f178
 
a0a0034
771f178
 
a0a0034
 
 
 
 
 
 
 
 
771f178
 
a0a0034
 
 
 
 
771f178
a0a0034
 
 
771f178
a0a0034
 
 
 
771f178
 
a0a0034
 
 
771f178
 
3f5ff7f
771f178
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a0a0034
 
 
 
 
 
771f178
 
 
a0a0034
 
 
771f178
a0a0034
 
 
771f178
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3f5ff7f
771f178
 
 
 
 
 
 
 
 
 
 
 
a0a0034
 
771f178
a0a0034
771f178
 
 
 
 
 
a0a0034
 
 
 
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
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dark Real Estate - 3D Showroom</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Cairo:wght@300;400;700;900&display=swap" rel="stylesheet">
    
    <!-- Leaflet Map -->
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"/>
    <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>

    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        dark: { bg: '#0B0F19', surface: '#161D2B', accent: '#F59E0B' }
                    },
                    fontFamily: { sans: ['Cairo', 'sans-serif'] }
                }
            }
        }
    </script>
    
    <style>
        body { margin: 0; padding: 0; overflow: hidden; font-family: 'Cairo', sans-serif; background: #000; color: #fff; }
        
        .ai-gradient-text {
            background: linear-gradient(135deg, #FCD34D, #F59E0B);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }

        /* Showroom Drawer */
        .showroom-drawer {
            background: rgba(11, 15, 25, 0.85);
            backdrop-filter: blur(40px);
            -webkit-backdrop-filter: blur(40px);
            border-top: 1px solid rgba(255, 255, 255, 0.1);
            box-shadow: 0 -20px 60px rgba(0,0,0,0.6);
            transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
        }

        /* Scrollbars */
        .drawer-scroll::-webkit-scrollbar { width: 4px; height: 4px; }
        .drawer-scroll::-webkit-scrollbar-track { background: transparent; }
        .drawer-scroll::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.2); border-radius: 10px; }
        .drawer-scroll::-webkit-scrollbar-thumb:hover { background: #F59E0B; }

        /* Map Tweaks */
        #map { width: 100%; height: 100px; border-radius: 1rem; border: 1px solid rgba(255,255,255,0.1); }
        .leaflet-control-zoom { display: none; }
    </style>
</head>
<body class="w-screen h-screen relative">

    <!-- TOP: THE SHOWROOM (Visuals) -->
    <div class="absolute top-0 left-0 right-0 h-[75vh] bg-black z-0 overflow-hidden group">
        
        <!-- Navbar Overlay -->
        <nav class="absolute top-6 left-8 right-8 z-50 flex justify-between items-center pointer-events-none">
            <div class="flex items-center gap-3 cursor-pointer pointer-events-auto hover:scale-105 transition bg-black/40 backdrop-blur border border-white/10 px-4 py-2 rounded-full" onclick="window.location.href='explore.html'">
                <i class="fa-solid fa-arrow-right text-white"></i>
                <span class="text-sm font-bold text-white uppercase">العودة للبحث</span>
            </div>
            <div class="pointer-events-auto flex gap-3">
                <span class="bg-dark-accent text-black font-black px-4 py-2 rounded-full shadow-[0_0_20px_rgba(245,158,11,0.5)]" id="propStatus">للبيع</span>
                <span class="bg-black/60 backdrop-blur border border-white/20 text-white font-bold px-4 py-2 rounded-full" id="propType">عقار</span>
            </div>
        </nav>

        <!-- Hero Image -->
        <img id="fgImage" src="" class="absolute inset-0 w-full h-full object-cover transition duration-[3s] ease-out group-hover:scale-105 opacity-90">
        <div id="imgOverlay" class="absolute inset-0 bg-gradient-to-t from-[#0B0F19] via-transparent to-black/30 pointer-events-none z-10"></div>

        <!-- 3D Iframe (Hidden initially) -->
        <iframe id="matterportFrame" class="hidden absolute inset-0 w-full h-full z-20 border-0" allowfullscreen allow="xr-spatial-tracking"></iframe>

        <!-- 3D Toggle Button -->
        <button id="start3DTourBtn" onclick="start3DTour()" class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 z-30 group-hover:scale-110 transition duration-300">
            <div class="w-32 h-32 bg-black/50 backdrop-blur-xl border border-white/30 rounded-full flex flex-col items-center justify-center text-white shadow-[0_0_50px_rgba(0,0,0,0.6)] cursor-pointer hover:bg-dark-accent hover:text-black hover:border-dark-accent transition-colors duration-300 group/btn">
                <i class="fa-solid fa-vr-cardboard text-5xl mb-2 group-hover/btn:scale-110 transition"></i>
                <span class="font-black text-xs uppercase tracking-widest">بدء الجولة</span>
            </div>
        </button>
    </div>

    <!-- BOTTOM: THE DASHBOARD DRAWER -->
    <div class="showroom-drawer absolute bottom-0 left-0 right-0 h-[35vh] rounded-t-[3rem] z-40 p-8 pt-10 flex flex-row gap-8 overflow-x-auto drawer-scroll items-stretch">
        
        <!-- SECTION 1: Property Info (Fixed Width) -->
        <div class="w-[400px] shrink-0 flex flex-col justify-between border-l border-white/10 pl-8">
            <div>
                <h1 class="text-3xl font-black leading-tight text-white mb-2 line-clamp-2" id="propTitle">جاري التحميل...</h1>
                <div class="text-sm text-gray-400 flex items-center gap-1 mb-4"><i class="fa-solid fa-location-dot text-dark-accent"></i> <span id="propLocation">...</span></div>
                <div class="text-4xl font-black text-dark-accent tracking-wide" id="propPrice">... <span class="text-lg text-gray-400 font-normal">ج.م</span></div>
            </div>

            <!-- Specs Grid -->
            <div class="grid grid-cols-4 gap-2 mt-4">
                <div class="bg-white/5 border border-white/10 rounded-xl p-2 flex flex-col items-center justify-center text-center">
                    <i class="fa-solid fa-bed text-dark-accent text-lg mb-1"></i><span id="specBeds" class="font-bold text-sm">-</span>
                </div>
                <div class="bg-white/5 border border-white/10 rounded-xl p-2 flex flex-col items-center justify-center text-center">
                    <i class="fa-solid fa-bath text-dark-accent text-lg mb-1"></i><span id="specBaths" class="font-bold text-sm">-</span>
                </div>
                <div class="bg-white/5 border border-white/10 rounded-xl p-2 flex flex-col items-center justify-center text-center">
                    <i class="fa-solid fa-ruler-combined text-dark-accent text-lg mb-1"></i><span id="specArea" class="font-bold text-sm">-</span>
                </div>
                <div class="bg-white/5 border border-white/10 rounded-xl p-2 flex flex-col items-center justify-center text-center">
                    <i class="fa-solid fa-car text-dark-accent text-lg mb-1"></i><span id="specParking" class="font-bold text-sm">-</span>
                </div>
            </div>
        </div>

        <!-- SECTION 2: AI Analysis (Fixed Width) -->
        <div class="w-[350px] shrink-0 flex flex-col gap-4 border-l border-white/10 pl-8">
            <div class="flex items-center gap-2 mb-2">
                <div class="w-8 h-8 rounded-full bg-dark-accent flex items-center justify-center text-black shadow-[0_0_10px_rgba(245,158,11,0.5)]"><i class="fa-solid fa-robot"></i></div>
                <span class="text-xl font-black ai-gradient-text">التحليل الذكي</span>
            </div>

            <!-- AI Valuation Mini -->
            <div class="bg-dark-surface/50 rounded-xl p-4 border border-white/5">
                <div class="text-[10px] font-bold uppercase text-gray-400 mb-1"><i class="fa-solid fa-scale-balanced text-dark-accent"></i> تقييم السعر</div>
                <div id="valTitleContainer" class="text-lg font-black text-white"><i class="fa-solid fa-spinner fa-spin"></i> جاري...</div>
            </div>

            <!-- Investment Scores -->
            <div class="bg-dark-surface/50 rounded-xl p-4 border border-white/5 flex-1 flex flex-col justify-center space-y-4">
                <div>
                    <div class="flex justify-between text-xs font-bold mb-1"><span class="text-gray-300">عائد الاستثمار (ROI)</span><span class="text-white" id="roiText">...</span></div>
                    <div class="w-full bg-black/50 rounded-full h-1.5"><div class="bg-blue-400 h-full rounded-full transition-all duration-1000 w-0" id="roiBar"></div></div>
                </div>
                <div>
                    <div class="flex justify-between text-xs font-bold mb-1"><span class="text-gray-300">النمو الرأسمالي</span><span class="text-white" id="growthText">...</span></div>
                    <div class="w-full bg-black/50 rounded-full h-1.5"><div class="bg-green-400 h-full rounded-full transition-all duration-1000 w-0" id="growthBar"></div></div>
                </div>
            </div>
        </div>

        <!-- SECTION 3: Communication & Map (Flexible Width) -->
        <div class="flex-1 min-w-[400px] flex gap-6">
            
            <!-- AI Chat -->
            <div class="flex-1 flex flex-col bg-white/5 border border-white/10 rounded-2xl overflow-hidden h-full">
                <div class="bg-white/5 p-3 border-b border-white/5 flex items-center gap-2">
                    <i class="fa-regular fa-comment-dots text-dark-accent"></i> <span class="text-sm font-bold">اسأل الذكاء الاصطناعي</span>
                </div>
                <div class="flex-1 overflow-y-auto drawer-scroll p-4 space-y-3" id="chatArea">
                    <div class="flex gap-2">
                        <div class="bg-white/10 p-2 rounded-xl rounded-tr-none text-xs text-gray-200 border border-white/5 shadow-sm max-w-[90%]">
                            أنا هنا للإجابة على أي أسئلة حول العقار.
                        </div>
                    </div>
                </div>
                <div class="p-2 border-t border-white/5 bg-black/20">
                    <div class="flex bg-black/50 rounded-lg overflow-hidden border border-white/10 focus-within:border-dark-accent transition">
                        <input type="text" id="chatInput" placeholder="اكتب سؤالك..." class="w-full bg-transparent text-xs text-white px-3 py-2 outline-none">
                        <button onclick="sendChatMessage()" class="text-dark-accent px-3 hover:text-white transition"><i class="fa-solid fa-paper-plane"></i></button>
                    </div>
                </div>
            </div>

            <!-- Mini Map & Desc -->
            <div class="w-[250px] shrink-0 flex flex-col gap-4 h-full">
                <div id="map" class="shadow-inner flex-1 max-h-[120px]"></div>
                <div class="flex-1 overflow-y-auto drawer-scroll text-xs text-gray-400 leading-relaxed pr-2" id="propDesc">
                    ...
                </div>
            </div>
        </div>

    </div>

    <script>
        document.addEventListener('DOMContentLoaded', async () => {
            const params = new URLSearchParams(window.location.search);
            const propIndex = params.get('index') || 0;
            
            let propData = null;
            const storedAiData = sessionStorage.getItem('aiRecommendations');
            if(storedAiData) {
                const db = JSON.parse(storedAiData);
                propData = db[propIndex]; 
            }

            // Fallback: If no data in session storage (e.g. direct link), fetch from backend
            if(!propData) {
                try {
                    const res = await fetch('/api/properties');
                    const json = await res.json();
                    if(json.properties && json.properties.length > 0) {
                        const db = json.properties;
                        propData = db[propIndex] || db[0]; // fallback to first if index invalid
                    }
                } catch (e) {
                    console.error("Failed to fetch fallback properties", e);
                }
            }

            if(propData) {
                document.getElementById('propTitle').innerText = propData.title;
                document.getElementById('propLocation').innerText = propData.location;
                document.getElementById('propPrice').innerText = propData.price;
                document.getElementById('propDesc').innerText = propData.description;
                document.getElementById('propType').innerText = propData.type;
                document.getElementById('propStatus').innerText = propData.status;
                
                if(propData.image) document.getElementById('fgImage').src = propData.image;

                if(propData.lat && propData.lng) {
                    const map = L.map('map', { zoomControl: false, attributionControl: false }).setView([propData.lat, propData.lng], 14);
                    L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png').addTo(map);
                    const icon = L.divIcon({ className: 'custom-div-icon', html: "<div style='width:12px;height:12px;background:#F59E0B;border-radius:50%;border:2px solid #000;'></div>", iconSize: [12, 12], iconAnchor: [6, 6] });
                    L.marker([propData.lat, propData.lng], {icon: icon}).addTo(map);
                }
                
                fetchInsights(propData);
            }

            document.getElementById('chatInput').addEventListener('keypress', function (e) {
                if (e.key === 'Enter') sendChatMessage();
            });
        });

        function start3DTour() {
            const iframe = document.getElementById('matterportFrame');
            const img = document.getElementById('fgImage');
            const overlay = document.getElementById('imgOverlay');
            const btn = document.getElementById('start3DTourBtn');
            
            const storedAiData = sessionStorage.getItem('aiRecommendations');
            const params = new URLSearchParams(window.location.search);
            const propIndex = params.get('index') || 0;
            let matterportId = "SxQL3iGyoDo"; 
            
            if(storedAiData) {
                const db = JSON.parse(storedAiData);
                if(db[propIndex] && db[propIndex].matterport_id) matterportId = db[propIndex].matterport_id;
            }
            
            iframe.src = `https://my.matterport.com/show/?m=${matterportId}&play=1`;
            iframe.classList.remove('hidden');
            img.style.opacity = '0';
            overlay.style.opacity = '0';
            btn.classList.add('hidden');
        }

        async function fetchInsights(prop) {
            try {
                const response = await fetch('/api/property/insight', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify({ title: prop.title, price: prop.price, location: prop.location, type: prop.type, description: prop.description })
                });
                const result = await response.json();
                if(result.success) {
                    const data = result.data;
                    document.getElementById('valTitleContainer').innerHTML = `<span class="text-green-400">${data.valuation_title}</span>`;
                    
                    document.getElementById('roiText').innerText = data.roi_percentage;
                    document.getElementById('roiBar').style.width = data.roi_progress + '%';
                    
                    document.getElementById('growthText').innerText = data.growth_percentage;
                    document.getElementById('growthBar').style.width = data.growth_progress + '%';
                    
                    if(data.specs) {
                        document.getElementById('specBeds').innerText = data.specs.beds || '-';
                        document.getElementById('specBaths').innerText = data.specs.baths || '-';
                        document.getElementById('specArea').innerText = data.specs.area ? data.specs.area + 'm' : '-';
                        document.getElementById('specParking').innerText = data.specs.parking || '-';
                    }
                }
            } catch (error) {
                document.getElementById('valTitleContainer').innerHTML = `<span class="text-red-400">فشل التحليل</span>`;
            }
        }

        let chatContext = [];

        async function sendChatMessage() {
            const input = document.getElementById('chatInput');
            const message = input.value.trim();
            if(!message) return;

            const chatArea = document.getElementById('chatArea');
            
            chatArea.insertAdjacentHTML('beforeend', `
                <div class="flex gap-2 flex-row-reverse">
                    <div class="bg-dark-accent p-2 rounded-xl rounded-tl-none text-xs text-black border border-transparent max-w-[85%] font-bold shadow-sm">
                        ${message}
                    </div>
                </div>
            `);
            input.value = '';
            chatArea.scrollTop = chatArea.scrollHeight;

            const typingId = 'typing-' + Date.now();
            chatArea.insertAdjacentHTML('beforeend', `<div id="${typingId}" class="flex gap-2">
                <div class="bg-white/10 p-2 rounded-xl rounded-tr-none text-xs text-gray-400 shadow-sm border border-white/5"><i class="fa-solid fa-ellipsis fa-fade"></i></div>
            </div>`);
            chatArea.scrollTop = chatArea.scrollHeight;

            if (chatContext.length === 0) {
                const title = document.getElementById('propTitle').innerText;
                const price = document.getElementById('propPrice').innerText;
                const loc = document.getElementById('propLocation').innerText;
                const desc = document.getElementById('propDesc').innerText;
                chatContext.push({ "role": "system", "content": `أنت مساعد عقاري ذكي. المستخدم يسأل عن العقار التالي: 
العنوان: ${title}
السعر: ${price}
المنطقة: ${loc}
الوصف: ${desc}
أجب باختصار وبشكل مباشر ومفيد بناءً على هذه المعلومات فقط.` });
            }

            try {
                const response = await fetch('/api/chat', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify({ message: message, history: chatContext })
                });
                const data = await response.json();
                document.getElementById(typingId).remove();
                
                const reply = data.reply || "عذراً، حدث خطأ.";
                chatArea.insertAdjacentHTML('beforeend', `
                    <div class="flex gap-2">
                        <div class="bg-white/10 p-2 rounded-xl rounded-tr-none text-xs text-white border border-white/5 max-w-[85%] shadow-sm leading-relaxed">
                            ${reply.replace(/\n/g, '<br>')}
                        </div>
                    </div>
                `);
                chatArea.scrollTop = chatArea.scrollHeight;

                chatContext.push({"role": "user", "content": message}, {"role": "assistant", "content": reply});
            } catch (e) {
                document.getElementById(typingId).remove();
                chatArea.insertAdjacentHTML('beforeend', `<div class="text-red-400 text-[10px]">فشل الاتصال.</div>`);
            }
        }
    </script>
</body>
</html>