sksameermujahid commited on
Commit
935bbdf
·
verified ·
1 Parent(s): 4d2d12d

Delete templates/newindex.html

Browse files
Files changed (1) hide show
  1. templates/newindex.html +0 -1916
templates/newindex.html DELETED
@@ -1,1916 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>AI Property Verifier</title>
7
- <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet">
8
- <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
9
- <style>
10
- :root {
11
- --primary: #4361ee;
12
- --secondary: #3f37c9;
13
- --success: #4cc9f0;
14
- --danger: #f72585;
15
- --warning: #f8961e;
16
- --info: #4895ef;
17
- --light: #f8f9fa;
18
- --dark: #212529;
19
- --gray: #6c757d;
20
- --border-radius: 12px;
21
- --box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
22
- }
23
-
24
- * {
25
- margin: 0;
26
- padding: 0;
27
- box-sizing: border-box;
28
- }
29
-
30
- body {
31
- font-family: 'Poppins', sans-serif;
32
- background-color: #f5f7fa;
33
- color: #333;
34
- line-height: 1.6;
35
- padding: 20px;
36
- }
37
-
38
- .container {
39
- max-width: 1200px;
40
- margin: 0 auto;
41
- }
42
-
43
- header {
44
- text-align: center;
45
- margin-bottom: 30px;
46
- }
47
-
48
- h1 {
49
- font-size: 2.5rem;
50
- color: var(--primary);
51
- margin-bottom: 10px;
52
- }
53
-
54
- .subtitle {
55
- font-size: 1.1rem;
56
- color: var(--gray);
57
- }
58
-
59
- .card {
60
- background: white;
61
- border-radius: var(--border-radius);
62
- box-shadow: var(--box-shadow);
63
- padding: 25px;
64
- margin-bottom: 25px;
65
- }
66
-
67
- .card-header {
68
- border-bottom: 1px solid #eee;
69
- padding-bottom: 15px;
70
- margin-bottom: 20px;
71
- display: flex;
72
- justify-content: space-between;
73
- align-items: center;
74
- }
75
-
76
- .card-title {
77
- font-size: 1.5rem;
78
- color: var(--dark);
79
- font-weight: 600;
80
- }
81
-
82
- .form-grid {
83
- display: grid;
84
- grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
85
- gap: 20px;
86
- }
87
-
88
- .form-group {
89
- margin-bottom: 20px;
90
- }
91
-
92
- .form-label {
93
- display: block;
94
- margin-bottom: 8px;
95
- font-weight: 500;
96
- color: var(--dark);
97
- }
98
-
99
- .form-control {
100
- width: 100%;
101
- padding: 12px 15px;
102
- border: 1px solid #ddd;
103
- border-radius: var(--border-radius);
104
- font-size: 1rem;
105
- transition: border-color 0.3s;
106
- }
107
-
108
- .form-control:focus {
109
- border-color: var(--primary);
110
- outline: none;
111
- box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.1);
112
- }
113
-
114
- textarea.form-control {
115
- min-height: 100px;
116
- resize: vertical;
117
- }
118
-
119
- .btn {
120
- display: inline-block;
121
- padding: 12px 24px;
122
- background-color: var(--primary);
123
- color: white;
124
- border: none;
125
- border-radius: var(--border-radius);
126
- font-size: 1rem;
127
- font-weight: 500;
128
- cursor: pointer;
129
- transition: all 0.3s;
130
- }
131
-
132
- .btn:hover {
133
- background-color: var(--secondary);
134
- transform: translateY(-2px);
135
- }
136
-
137
- .btn-block {
138
- display: block;
139
- width: 100%;
140
- }
141
-
142
- .section-title {
143
- font-size: 1.2rem;
144
- color: var(--primary);
145
- margin-bottom: 15px;
146
- font-weight: 600;
147
- }
148
-
149
- .results-container {
150
- display: none;
151
- margin-top: 30px;
152
- }
153
-
154
- .results-grid {
155
- display: grid;
156
- grid-template-columns: repeat(auto-fill, minmax(450px, 1fr));
157
- gap: 25px;
158
- }
159
-
160
-
161
- .result-card {
162
- background: white;
163
- border-radius: var(--border-radius);
164
- box-shadow: var(--box-shadow);
165
- padding: 20px;
166
- height: 100%;
167
- }
168
-
169
- .result-header {
170
- display: flex;
171
- align-items: center;
172
- margin-bottom: 15px;
173
- }
174
-
175
- .result-icon {
176
- width: 40px;
177
- height: 40px;
178
- background-color: var(--light);
179
- border-radius: 50%;
180
- display: flex;
181
- align-items: center;
182
- justify-content: center;
183
- margin-right: 15px;
184
- }
185
-
186
- .result-title {
187
- font-size: 1.2rem;
188
- font-weight: 600;
189
- color: var(--dark);
190
- }
191
-
192
- .trust-score {
193
- text-align: center;
194
- padding: 20px;
195
- }
196
-
197
- .score-value {
198
- font-size: 3rem;
199
- font-weight: 700;
200
- color: var(--primary);
201
- }
202
-
203
- .score-label {
204
- font-size: 1rem;
205
- color: var(--gray);
206
- }
207
-
208
- .progress-container {
209
- margin: 15px 0;
210
- }
211
-
212
- .progress-bar {
213
- height: 10px;
214
- background-color: #eee;
215
- border-radius: 5px;
216
- overflow: hidden;
217
- }
218
-
219
- .progress-fill {
220
- height: 100%;
221
- background-color: var(--primary);
222
- border-radius: 5px;
223
- transition: width 0.5s ease-in-out;
224
- }
225
-
226
- .alert {
227
- padding: 15px;
228
- border-radius: var(--border-radius);
229
- margin-bottom: 20px;
230
- font-weight: 500;
231
- }
232
-
233
- .alert-danger {
234
- background-color: rgba(247, 37, 133, 0.1);
235
- color: var(--danger);
236
- border-left: 4px solid var(--danger);
237
- }
238
-
239
- .alert-warning {
240
- background-color: rgba(248, 150, 30, 0.1);
241
- color: var(--warning);
242
- border-left: 4px solid var(--warning);
243
- }
244
-
245
- .alert-success {
246
- background-color: rgba(76, 201, 240, 0.1);
247
- color: var(--success);
248
- border-left: 4px solid var(--success);
249
- }
250
-
251
- .suggestion-list {
252
- list-style-type: none;
253
- padding: 0;
254
- }
255
-
256
- .suggestion-item {
257
- padding: 10px 15px;
258
- background-color: rgba(67, 97, 238, 0.05);
259
- border-radius: var(--border-radius);
260
- margin-bottom: 10px;
261
- border-left: 3px solid var(--primary);
262
- }
263
-
264
- .image-preview {
265
- display: flex;
266
- flex-wrap: wrap;
267
- gap: 10px;
268
- margin-top: 10px;
269
- }
270
-
271
- .preview-item {
272
- width: 100px;
273
- height: 100px;
274
- border-radius: 8px;
275
- overflow: hidden;
276
- position: relative;
277
- }
278
-
279
- .preview-item img {
280
- width: 100%;
281
- height: 100%;
282
- object-fit: cover;
283
- }
284
-
285
- .preview-remove {
286
- position: absolute;
287
- top: 5px;
288
- right: 5px;
289
- background: rgba(0, 0, 0, 0.5);
290
- color: white;
291
- border: none;
292
- border-radius: 50%;
293
- width: 20px;
294
- height: 20px;
295
- display: flex;
296
- align-items: center;
297
- justify-content: center;
298
- cursor: pointer;
299
- }
300
-
301
- .loading {
302
- display: none;
303
- text-align: center;
304
- padding: 30px;
305
- }
306
-
307
- .spinner {
308
- width: 50px;
309
- height: 50px;
310
- border: 5px solid rgba(67, 97, 238, 0.1);
311
- border-radius: 50%;
312
- border-top-color: var(--primary);
313
- animation: spin 1s ease-in-out infinite;
314
- margin: 0 auto 20px;
315
- }
316
-
317
- @keyframes spin {
318
- to { transform: rotate(360deg); }
319
- }
320
-
321
- .chart-container {
322
- position: relative;
323
- height: 200px;
324
- margin-bottom: 20px;
325
- }
326
-
327
- .pdf-preview {
328
- background-color: #f8f9fa;
329
- padding: 15px;
330
- border-radius: var(--border-radius);
331
- margin-top: 10px;
332
- max-height: 200px;
333
- overflow-y: auto;
334
- }
335
-
336
- .pdf-filename {
337
- font-weight: 500;
338
- margin-bottom: 5px;
339
- }
340
-
341
- .image-gallery {
342
- display: grid;
343
- grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
344
- gap: 15px;
345
- margin-top: 20px;
346
- }
347
-
348
- .gallery-item {
349
- border-radius: var(--border-radius);
350
- overflow: hidden;
351
- box-shadow: var(--box-shadow);
352
- aspect-ratio: 1;
353
- }
354
-
355
- .gallery-item img {
356
- width: 100%;
357
- height: 100%;
358
- object-fit: cover;
359
- }
360
-
361
- .badge {
362
- display: inline-block;
363
- padding: 5px 10px;
364
- border-radius: 20px;
365
- font-size: 0.8rem;
366
- font-weight: 500;
367
- margin-right: 5px;
368
- margin-bottom: 5px;
369
- }
370
-
371
- .badge-primary { background-color: rgba(67, 97, 238, 0.1); color: var(--primary); }
372
- .badge-success { background-color: rgba(76, 201, 240, 0.1); color: var(--success); }
373
- .badge-warning { background-color: rgba(248, 150, 30, 0.1); color: var(--warning); }
374
- .badge-danger { background-color: rgba(247, 37, 133, 0.1); color: var(--danger); }
375
-
376
- .explanation-box {
377
- background-color: #f8f9fa;
378
- border-radius: var(--border-radius);
379
- padding: 15px;
380
- margin-top: 15px;
381
- border-left: 4px solid var(--info);
382
- }
383
-
384
- .explanation-title {
385
- font-weight: 600;
386
- color: var(--info);
387
- margin-bottom: 10px;
388
- }
389
-
390
- @media (max-width: 768px) {
391
- .form-grid, .results-grid {
392
- grid-template-columns: 1fr;
393
- }
394
-
395
- .card {
396
- padding: 15px;
397
- }
398
- }
399
-
400
- .property-summary {
401
- padding: 15px;
402
- }
403
-
404
- .property-details p {
405
- margin-bottom: 8px;
406
- }
407
-
408
- .final-verdict {
409
- padding: 15px;
410
- }
411
-
412
- .verdict-box {
413
- display: flex;
414
- align-items: center;
415
- padding: 15px;
416
- border-radius: var(--border-radius);
417
- margin-bottom: 15px;
418
- background-color: #f8f9fa;
419
- }
420
-
421
- .verdict-icon {
422
- font-size: 2rem;
423
- margin-right: 15px;
424
- }
425
-
426
- .verdict-text {
427
- font-size: 1.2rem;
428
- font-weight: 600;
429
- }
430
-
431
- .verdict-legitimate {
432
- background-color: rgba(76, 201, 240, 0.1);
433
- border-left: 4px solid var(--success);
434
- }
435
-
436
- .verdict-suspicious {
437
- background-color: rgba(248, 150, 30, 0.1);
438
- border-left: 4px solid var(--warning);
439
- }
440
-
441
- .verdict-fraudulent {
442
- background-color: rgba(247, 37, 133, 0.1);
443
- border-left: 4px solid var(--danger);
444
- }
445
-
446
- .verification-scores {
447
- padding: 15px;
448
- }
449
-
450
- .score-item {
451
- margin-bottom: 15px;
452
- }
453
-
454
- .score-label {
455
- font-weight: 500;
456
- margin-bottom: 5px;
457
- }
458
-
459
- .score-bar-container {
460
- display: flex;
461
- align-items: center;
462
- }
463
-
464
- .score-bar {
465
- height: 10px;
466
- background-color: #e9ecef;
467
- border-radius: 5px;
468
- flex-grow: 1;
469
- margin-right: 10px;
470
- position: relative;
471
- overflow: hidden;
472
- }
473
-
474
- .score-bar::before {
475
- content: '';
476
- position: absolute;
477
- top: 0;
478
- left: 0;
479
- height: 100%;
480
- background-color: var(--primary);
481
- border-radius: 5px;
482
- width: 0%;
483
- transition: width 0.5s ease;
484
- }
485
-
486
- .score-value {
487
- font-weight: 600;
488
- min-width: 40px;
489
- text-align: right;
490
- }
491
-
492
- .red-flags {
493
- padding: 15px;
494
- }
495
- </style>
496
- </head>
497
- <body>
498
- <div class="container">
499
- <header>
500
- <h1>AI Property Verifier & Fraud Detection</h1>
501
- <p class="subtitle">Powered by advanced AI models to verify property listings and detect potential fraud</p>
502
- </header>
503
-
504
- <div class="card">
505
- <div class="card-header">
506
- <h2 class="card-title">Property Details</h2>
507
- </div>
508
-
509
- <form id="propertyForm">
510
- <div class="section-title">Basic Information</div>
511
- <div class="form-grid">
512
- <div class="form-group">
513
- <label class="form-label" for="propertyName">Property Name</label>
514
- <input type="text" class="form-control" id="propertyName" name="property_name" required>
515
- </div>
516
-
517
- <div class="form-group">
518
- <label class="form-label" for="propertyType">Property Type</label>
519
- <select class="form-control" id="propertyType" name="property_type" required>
520
- <option value="">Select Type</option>
521
- <option value="Apartment">Apartment</option>
522
- <option value="House">House</option>
523
- <option value="Condo">Condo</option>
524
- <option value="Townhouse">Townhouse</option>
525
- <option value="Villa">Villa</option>
526
- <option value="Land">Land</option>
527
- <option value="Commercial">Commercial</option>
528
- <option value="Other">Other</option>
529
- </select>
530
- </div>
531
-
532
- <div class="form-group">
533
- <label class="form-label" for="status">Status</label>
534
- <select class="form-control" id="status" name="status" required>
535
- <option value="">Select Status</option>
536
- <option value="For Sale">For Sale</option>
537
- <option value="For Rent">For Rent</option>
538
- <option value="Sold">Sold</option>
539
- <option value="Under Contract">Under Contract</option>
540
- <option value="Pending">Pending</option>
541
- </select>
542
- </div>
543
- </div>
544
-
545
- <div class="form-group">
546
- <label class="form-label" for="description">Property Description</label>
547
- <textarea class="form-control" id="description" name="description" rows="4" required></textarea>
548
- </div>
549
-
550
- <div class="section-title">Location Details</div>
551
- <div class="form-grid">
552
- <div class="form-group">
553
- <label class="form-label" for="address">Address</label>
554
- <input type="text" class="form-control" id="address" name="address" required>
555
- </div>
556
-
557
- <div class="form-group">
558
- <label class="form-label" for="city">City</label>
559
- <input type="text" class="form-control" id="city" name="city" required>
560
- </div>
561
-
562
- <div class="form-group">
563
- <label class="form-label" for="state">State/Province</label>
564
- <input type="text" class="form-control" id="state" name="state" required>
565
- </div>
566
-
567
- <div class="form-group">
568
- <label class="form-label" for="country">Country</label>
569
- <input type="text" class="form-control" id="country" name="country" required>
570
- </div>
571
-
572
- <div class="form-group">
573
- <label class="form-label" for="zip">Zip/Postal Code</label>
574
- <input type="text" class="form-control" id="zip" name="zip" required>
575
- </div>
576
-
577
- <div class="form-group">
578
- <label class="form-label" for="latitude">Latitude</label>
579
- <input type="text" class="form-control" id="latitude" name="latitude" placeholder="e.g. 40.7128">
580
- </div>
581
-
582
- <div class="form-group">
583
- <label class="form-label" for="longitude">Longitude</label>
584
- <input type="text" class="form-control" id="longitude" name="longitude" placeholder="e.g. -74.0060">
585
- </div>
586
- </div>
587
-
588
- <div class="section-title">Property Specifications</div>
589
- <div class="form-grid">
590
- <div class="form-group">
591
- <label class="form-label" for="bedrooms">Bedrooms</label>
592
- <input type="number" class="form-control" id="bedrooms" name="bedrooms" min="0">
593
- </div>
594
-
595
- <div class="form-group">
596
- <label class="form-label" for="bathrooms">Bathrooms</label>
597
- <input type="number" class="form-control" id="bathrooms" name="bathrooms" min="0" step="0.5">
598
- </div>
599
-
600
- <div class="form-group">
601
- <label class="form-label" for="totalRooms">Total Rooms</label>
602
- <input type="number" class="form-control" id="totalRooms" name="total_rooms" min="0">
603
- </div>
604
-
605
- <div class="form-group">
606
- <label class="form-label" for="yearBuilt">Year Built</label>
607
- <input type="number" class="form-control" id="yearBuilt" name="year_built" min="1800" max="2100">
608
- </div>
609
-
610
- <div class="form-group">
611
- <label class="form-label" for="parking">Parking Spaces</label>
612
- <input type="number" class="form-control" id="parking" name="parking" min="0">
613
- </div>
614
-
615
- <div class="form-group">
616
- <label class="form-label" for="sqFt">Square Feet</label>
617
- <input type="text" class="form-control" id="sqFt" name="sq_ft" min="0">
618
- </div>
619
-
620
- <div class="form-group">
621
- <label class="form-label" for="marketValue">Market Value</label>
622
- <input type="text" class="form-control" id="marketValue" name="market_value" min="0">
623
- </div>
624
- </div>
625
-
626
- <div class="form-group">
627
- <label class="form-label" for="amenities">Amenities (comma separated)</label>
628
- <input type="text" class="form-control" id="amenities" name="amenities" placeholder="e.g. Pool, Gym, Garden, Garage">
629
- </div>
630
-
631
- <div class="form-group">
632
- <label class="form-label" for="nearbyLandmarks">Nearby Landmarks</label>
633
- <input type="text" class="form-control" id="nearbyLandmarks" name="nearby_landmarks" placeholder="e.g. School, Hospital, Park, Shopping Mall">
634
- </div>
635
-
636
- <div class="form-group">
637
- <label class="form-label" for="legalDetails">Legal & Infrastructure Details</label>
638
- <textarea class="form-control" id="legalDetails" name="legal_details" rows="3" placeholder="Include zoning, permits, utilities, etc."></textarea>
639
- </div>
640
-
641
- <div class="section-title">Documents & Images</div>
642
- <div class="form-group">
643
- <label class="form-label" for="images">Upload Images (JPG/PNG)</label>
644
- <input type="file" class="form-control" id="images" name="images" accept="image/jpeg, image/png" multiple>
645
- <div class="image-preview" id="imagePreview"></div>
646
- </div>
647
-
648
- <div class="form-group">
649
- <label class="form-label" for="documents">Upload Documents (PDF)</label>
650
- <input type="file" class="form-control" id="documents" name="documents" accept="application/pdf" multiple>
651
- <div id="pdfPreview"></div>
652
- </div>
653
-
654
- <div class="form-group">
655
- <button type="submit" class="btn btn-block" id="submitBtn">Verify Property with AI</button>
656
- </div>
657
- </form>
658
- </div>
659
-
660
- <div class="loading" id="loadingIndicator">
661
- <div class="spinner"></div>
662
- <p>AI models are analyzing your property data...</p>
663
- <p class="subtitle">This may take a moment as we're processing multiple AI models</p>
664
- </div>
665
-
666
- <div class="results-container" id="resultsContainer">
667
- <div class="card">
668
- <div class="card-header">
669
- <h2 class="card-title">AI Verification Results</h2>
670
- </div>
671
-
672
- <div class="results-grid">
673
- <div class="result-card">
674
- <div class="result-header">
675
- <div class="result-icon">🏠</div>
676
- <div class="result-title">Property Summary</div>
677
- </div>
678
- <div class="property-summary">
679
- <h3 id="propertyTitle">Property Details</h3>
680
- <div class="property-details">
681
- <p><strong>Name:</strong> <span id="summaryName"></span></p>
682
- <p><strong>Type:</strong> <span id="summaryType"></span></p>
683
- <p><strong>Status:</strong> <span id="summaryStatus"></span></p>
684
- <p><strong>Location:</strong> <span id="summaryLocation"></span></p>
685
- <p><strong>Price:</strong> <span id="summaryPrice"></span></p>
686
- <p><strong>Size:</strong> <span id="summarySize"></span></p>
687
- <p><strong>Bedrooms/Bathrooms:</strong> <span id="summaryRooms"></span></p>
688
- </div>
689
- </div>
690
- </div>
691
-
692
- <div class="result-card">
693
- <div class="result-header">
694
- <div class="result-icon">⚠️</div>
695
- <div class="result-title">Final Verdict</div>
696
- </div>
697
- <div class="final-verdict" id="finalVerdict">
698
- <div class="verdict-box" id="verdictBox">
699
- <div class="verdict-icon" id="verdictIcon">⏳</div>
700
- <div class="verdict-text" id="verdictText">Analysis in progress...</div>
701
- </div>
702
- <div class="verdict-reasons">
703
- <h4>Key Findings:</h4>
704
- <ul id="verdictReasons" class="suggestion-list">
705
- <!-- Will be populated by JavaScript -->
706
- </ul>
707
- </div>
708
- </div>
709
- </div>
710
-
711
- <div class="result-card">
712
- <div class="result-header">
713
- <div class="result-icon">🔍</div>
714
- <div class="result-title">Detailed Verification</div>
715
- </div>
716
- <div class="verification-scores">
717
- <div class="score-item">
718
- <div class="score-label">Trust Score</div>
719
- <div class="score-bar-container">
720
- <div class="score-bar" id="trustBar"></div>
721
- <div class="score-value" id="trustValue">--</div>
722
- </div>
723
- </div>
724
- <div class="score-item">
725
- <div class="score-label">Image Authenticity</div>
726
- <div class="score-bar-container">
727
- <div class="score-bar" id="imageBar"></div>
728
- <div class="score-value" id="imageValue">--</div>
729
- </div>
730
- </div>
731
- <div class="score-item">
732
- <div class="score-label">Document Verification</div>
733
- <div class="score-bar-container">
734
- <div class="score-bar" id="documentBar"></div>
735
- <div class="score-value" id="documentValue">--</div>
736
- </div>
737
- </div>
738
- <div class="score-item">
739
- <div class="score-label">Content Quality</div>
740
- <div class="score-bar-container">
741
- <div class="score-bar" id="contentBar"></div>
742
- <div class="score-value" id="contentValue">--</div>
743
- </div>
744
- </div>
745
- <div class="score-item">
746
- <div class="score-label">Location Accuracy</div>
747
- <div class="score-bar-container">
748
- <div class="score-bar" id="locationBar"></div>
749
- <div class="score-value" id="locationValue">--</div>
750
- </div>
751
- </div>
752
- </div>
753
- </div>
754
-
755
- <div class="result-card">
756
- <div class="result-header">
757
- <div class="result-icon">🚩</div>
758
- <div class="result-title">Red Flags</div>
759
- </div>
760
- <div class="red-flags">
761
- <ul id="redFlagsList" class="suggestion-list">
762
- <!-- Will be populated by JavaScript -->
763
- </ul>
764
- </div>
765
- </div>
766
-
767
- <div class="result-card">
768
- <div class="result-header">
769
- <div class="result-icon">📊</div>
770
- <div class="result-title">Trust Score</div>
771
- </div>
772
- <div class="trust-score">
773
- <div class="score-value" id="trustScoreValue">--</div>
774
- <div class="score-label">Trust Score</div>
775
- <div class="progress-container">
776
- <div class="progress-bar">
777
- <div class="progress-fill" id="trustScoreBar" style="width: 0%"></div>
778
- </div>
779
- </div>
780
- </div>
781
- <div class="chart-container">
782
- <canvas id="trustScoreChart"></canvas>
783
- </div>
784
- <div class="explanation-box">
785
- <div class="explanation-title">AI Reasoning</div>
786
- <div id="trustReasoning"></div>
787
- </div>
788
- </div>
789
-
790
- <div class="result-card">
791
- <div class="result-header">
792
- <div class="result-icon">🔍</div>
793
- <div class="result-title">Fraud Analysis</div>
794
- </div>
795
- <div id="fraudAlertContainer"></div>
796
- <div class="chart-container">
797
- <canvas id="fraudAnalysisChart"></canvas>
798
- </div>
799
- <div class="explanation-box">
800
- <div class="explanation-title">AI Reasoning</div>
801
- <div id="fraudReasoning"></div>
802
- </div>
803
- </div>
804
-
805
- <div class="result-card">
806
- <div class="result-header">
807
- <div class="result-icon">📝</div>
808
- <div class="result-title">AI Summary</div>
809
- </div>
810
- <div id="aiSummary"></div>
811
- </div>
812
-
813
- <div class="result-card">
814
- <div class="result-header">
815
- <div class="result-icon">💡</div>
816
- <div class="result-title">Improvement Suggestions</div>
817
- </div>
818
- <ul class="suggestion-list" id="suggestionsList"></ul>
819
- </div>
820
-
821
- <div class="result-card">
822
- <div class="result-header">
823
- <div class="result-icon">🏠</div>
824
- <div class="result-title">Property Quality Assessment</div>
825
- </div>
826
- <div id="qualityAssessment"></div>
827
- <div class="chart-container">
828
- <canvas id="qualityChart"></canvas>
829
- </div>
830
- </div>
831
-
832
- <div class="result-card">
833
- <div class="result-header">
834
- <div class="result-icon">📍</div>
835
- <div class="result-title">Location Analysis</div>
836
- </div>
837
- <div id="locationAnalysis"></div>
838
- <div class="chart-container">
839
- <canvas id="locationChart"></canvas>
840
- </div>
841
- </div>
842
-
843
- <div class="result-card">
844
- <div class="result-header">
845
- <div class="result-icon">💰</div>
846
- <div class="result-title">Price Analysis</div>
847
- </div>
848
- <div id="priceAnalysis"></div>
849
- <div class="chart-container">
850
- <canvas id="priceChart"></canvas>
851
- </div>
852
- </div>
853
-
854
- <div class="result-card">
855
- <div class="result-header">
856
- <div class="result-icon">⚖️</div>
857
- <div class="result-title">Legal Analysis</div>
858
- </div>
859
- <div id="legalAnalysis"></div>
860
- <div class="chart-container">
861
- <canvas id="legalChart"></canvas>
862
- </div>
863
- </div>
864
-
865
- <div class="result-card">
866
- <div class="result-header">
867
- <div class="result-icon">🔄</div>
868
- <div class="result-title">Cross-Validation Checks</div>
869
- </div>
870
- <div id="crossValidation"></div>
871
- </div>
872
-
873
- <div class="result-card">
874
- <div class="result-header">
875
- <div class="result-icon">📄</div>
876
- <div class="result-title">Document Analysis</div>
877
- </div>
878
- <div id="documentAnalysis"></div>
879
- <div class="chart-container">
880
- <canvas id="documentChart"></canvas>
881
- </div>
882
- </div>
883
-
884
- <div class="result-card">
885
- <div class="result-header">
886
- <div class="result-icon">🖼️</div>
887
- <div class="result-title">Image Analysis</div>
888
- </div>
889
- <div id="imageAnalysis"></div>
890
- <div class="image-gallery" id="imageGallery"></div>
891
- </div>
892
- </div>
893
- </div>
894
- </div>
895
- </div>
896
-
897
- <script>
898
- // Global variables to store form data
899
- let uploadedImages = [];
900
- let uploadedPDFs = [];
901
-
902
- // Initialize charts
903
- let trustScoreChart;
904
- let fraudAnalysisChart;
905
- let qualityChart;
906
- let locationChart;
907
- let priceChart;
908
- let legalChart;
909
- let documentChart;
910
-
911
- document.addEventListener('DOMContentLoaded', function() {
912
- // Request location access when page loads
913
- requestLocationAccess();
914
-
915
- const propertyForm = document.getElementById('propertyForm');
916
- const loadingIndicator = document.getElementById('loadingIndicator');
917
- const resultsContainer = document.getElementById('resultsContainer');
918
- const imageInput = document.getElementById('images');
919
- const imagePreview = document.getElementById('imagePreview');
920
- const pdfInput = document.getElementById('documents');
921
- const pdfPreview = document.getElementById('pdfPreview');
922
-
923
- // Handle image uploads
924
- imageInput.addEventListener('change', function(e) {
925
- handleImageUpload(e.target.files);
926
- });
927
-
928
- // Handle PDF uploads
929
- pdfInput.addEventListener('change', function(e) {
930
- handlePDFUpload(e.target.files);
931
- });
932
-
933
- // Form submission
934
- propertyForm.addEventListener('submit', function(e) {
935
- e.preventDefault();
936
- submitForm();
937
- });
938
-
939
- // Initialize charts
940
- initCharts();
941
- });
942
-
943
- function requestLocationAccess() {
944
- if (navigator.geolocation) {
945
- navigator.geolocation.getCurrentPosition(
946
- function(position) {
947
- const latitude = position.coords.latitude;
948
- const longitude = position.coords.longitude;
949
-
950
- // Update form fields with coordinates
951
- document.getElementById('latitude').value = latitude;
952
- document.getElementById('longitude').value = longitude;
953
-
954
- // Send to backend to get address details
955
- fetch('/get-location', {
956
- method: 'POST',
957
- headers: {
958
- 'Content-Type': 'application/json',
959
- },
960
- body: JSON.stringify({
961
- latitude: latitude,
962
- longitude: longitude
963
- }),
964
- })
965
- .then(response => response.json())
966
- .then(data => {
967
- if (data.status === 'success') {
968
- // Fill form fields with location data
969
- document.getElementById('address').value = data.address || '';
970
- document.getElementById('city').value = data.city || '';
971
- document.getElementById('state').value = data.state || '';
972
- document.getElementById('country').value = data.country || '';
973
- document.getElementById('zip').value = data.postal_code || '';
974
-
975
- console.log('Location data loaded successfully');
976
- } else {
977
- console.error('Error getting location details:', data.message);
978
- }
979
- })
980
- .catch(error => {
981
- console.error('Error getting location details:', error);
982
- });
983
- },
984
- function(error) {
985
- console.error('Error getting location:', error.message);
986
- // Show a message to the user about location access
987
- const locationMessage = document.createElement('div');
988
- locationMessage.className = 'alert alert-warning';
989
- locationMessage.innerHTML = 'Location access denied or unavailable. Please enter your location manually.';
990
- document.querySelector('.container').prepend(locationMessage);
991
-
992
- // Auto-remove the message after 5 seconds
993
- setTimeout(() => {
994
- locationMessage.remove();
995
- }, 5000);
996
- },
997
- {
998
- enableHighAccuracy: true,
999
- timeout: 5000,
1000
- maximumAge: 0
1001
- }
1002
- );
1003
- } else {
1004
- console.error('Geolocation is not supported by this browser');
1005
- }
1006
- }
1007
-
1008
- function handleImageUpload(files) {
1009
- const imagePreview = document.getElementById('imagePreview');
1010
-
1011
- for (let i = 0; i < files.length; i++) {
1012
- const file = files[i];
1013
- if (!file.type.match('image.*')) continue;
1014
-
1015
- const reader = new FileReader();
1016
- reader.onload = function(e) {
1017
- const imageData = e.target.result;
1018
- uploadedImages.push({
1019
- name: file.name,
1020
- data: imageData,
1021
- file: file
1022
- });
1023
-
1024
- // Create preview
1025
- const previewItem = document.createElement('div');
1026
- previewItem.className = 'preview-item';
1027
- previewItem.innerHTML = `
1028
- <img src="${imageData}" alt="${file.name}">
1029
- <button type="button" class="preview-remove" data-index="${uploadedImages.length - 1}">×</button>
1030
- `;
1031
- imagePreview.appendChild(previewItem);
1032
-
1033
- // Add remove functionality
1034
- previewItem.querySelector('.preview-remove').addEventListener('click', function() {
1035
- const index = parseInt(this.getAttribute('data-index'));
1036
- uploadedImages.splice(index, 1);
1037
- imagePreview.removeChild(previewItem);
1038
- updateImagePreviews();
1039
- });
1040
- };
1041
- reader.readAsDataURL(file);
1042
- }
1043
- }
1044
-
1045
- function updateImagePreviews() {
1046
- const imagePreview = document.getElementById('imagePreview');
1047
- imagePreview.innerHTML = '';
1048
-
1049
- uploadedImages.forEach((image, index) => {
1050
- const previewItem = document.createElement('div');
1051
- previewItem.className = 'preview-item';
1052
- previewItem.innerHTML = `
1053
- <img src="${image.data}" alt="${image.name}">
1054
- <button type="button" class="preview-remove" data-index="${index}">×</button>
1055
- `;
1056
- imagePreview.appendChild(previewItem);
1057
-
1058
- previewItem.querySelector('.preview-remove').addEventListener('click', function() {
1059
- uploadedImages.splice(index, 1);
1060
- updateImagePreviews();
1061
- });
1062
- });
1063
- }
1064
-
1065
- function handlePDFUpload(files) {
1066
- const pdfPreview = document.getElementById('pdfPreview');
1067
-
1068
- for (let i = 0; i < files.length; i++) {
1069
- const file = files[i];
1070
- if (file.type !== 'application/pdf') continue;
1071
-
1072
- uploadedPDFs.push({
1073
- name: file.name,
1074
- file: file
1075
- });
1076
-
1077
- // Create preview
1078
- const previewItem = document.createElement('div');
1079
- previewItem.className = 'pdf-preview';
1080
- previewItem.innerHTML = `
1081
- <div class="pdf-filename">${file.name}</div>
1082
- <button type="button" class="btn" data-index="${uploadedPDFs.length - 1}">Remove</button>
1083
- `;
1084
- pdfPreview.appendChild(previewItem);
1085
-
1086
- // Add remove functionality
1087
- previewItem.querySelector('.btn').addEventListener('click', function() {
1088
- const index = parseInt(this.getAttribute('data-index'));
1089
- uploadedPDFs.splice(index, 1);
1090
- pdfPreview.removeChild(previewItem);
1091
- updatePDFPreviews();
1092
- });
1093
- }
1094
- }
1095
-
1096
- function updatePDFPreviews() {
1097
- const pdfPreview = document.getElementById('pdfPreview');
1098
- pdfPreview.innerHTML = '';
1099
-
1100
- uploadedPDFs.forEach((pdf, index) => {
1101
- const previewItem = document.createElement('div');
1102
- previewItem.className = 'pdf-preview';
1103
- previewItem.innerHTML = `
1104
- <div class="pdf-filename">${pdf.name}</div>
1105
- <button type="button" class="btn" data-index="${index}">Remove</button>
1106
- `;
1107
- pdfPreview.appendChild(previewItem);
1108
-
1109
- previewItem.querySelector('.btn').addEventListener('click', function() {
1110
- uploadedPDFs.splice(index, 1);
1111
- updatePDFPreviews();
1112
- });
1113
- });
1114
- }
1115
-
1116
- function initCharts() {
1117
- try {
1118
- // Store all charts in an array for easier management
1119
- window.charts = [];
1120
-
1121
- // Trust Score Chart initialization
1122
- const trustCtx = document.getElementById('trustScoreChart').getContext('2d');
1123
- trustScoreChart = new Chart(trustCtx, {
1124
- type: 'doughnut',
1125
- data: {
1126
- datasets: [{
1127
- data: [0, 100],
1128
- backgroundColor: [
1129
- '#4361ee',
1130
- '#f1f1f1'
1131
- ],
1132
- borderWidth: 0
1133
- }]
1134
- },
1135
- options: {
1136
- cutout: '70%',
1137
- circumference: 180,
1138
- rotation: -90,
1139
- plugins: {
1140
- legend: {
1141
- display: false
1142
- },
1143
- tooltip: {
1144
- enabled: false
1145
- }
1146
- },
1147
- maintainAspectRatio: false
1148
- }
1149
- });
1150
- charts.push(trustScoreChart);
1151
-
1152
- // Fraud Analysis Chart (Bar)
1153
- const fraudAnalysisCtx = document.getElementById('fraudAnalysisChart').getContext('2d');
1154
- fraudAnalysisChart = new Chart(fraudAnalysisCtx, {
1155
- type: 'bar',
1156
- data: {
1157
- labels: ['Legitimate', 'Suspicious', 'Fraudulent'],
1158
- datasets: [{
1159
- label: 'Fraud Indicators',
1160
- data: [0, 0, 0],
1161
- backgroundColor: [
1162
- '#4cc9f0',
1163
- '#f8961e',
1164
- '#f72585'
1165
- ],
1166
- borderWidth: 0
1167
- }]
1168
- },
1169
- options: {
1170
- indexAxis: 'y',
1171
- plugins: {
1172
- legend: {
1173
- display: false
1174
- }
1175
- },
1176
- scales: {
1177
- x: {
1178
- beginAtZero: true,
1179
- max: 100
1180
- }
1181
- },
1182
- maintainAspectRatio: false
1183
- }
1184
- });
1185
-
1186
- // Quality Assessment Chart
1187
- const qualityCtx = document.getElementById('qualityChart').getContext('2d');
1188
- qualityChart = new Chart(qualityCtx, {
1189
- type: 'radar',
1190
- data: {
1191
- labels: ['Completeness', 'Accuracy', 'Clarity', 'Authenticity', 'Detail'],
1192
- datasets: [{
1193
- label: 'Quality Score',
1194
- data: [0, 0, 0, 0, 0],
1195
- backgroundColor: 'rgba(67, 97, 238, 0.2)',
1196
- borderColor: '#4361ee',
1197
- borderWidth: 2,
1198
- pointBackgroundColor: '#4361ee'
1199
- }]
1200
- },
1201
- options: {
1202
- scales: {
1203
- r: {
1204
- beginAtZero: true,
1205
- max: 100
1206
- }
1207
- },
1208
- maintainAspectRatio: false
1209
- }
1210
- });
1211
-
1212
- // Location Analysis Chart
1213
- const locationCtx = document.getElementById('locationChart').getContext('2d');
1214
- locationChart = new Chart(locationCtx, {
1215
- type: 'pie',
1216
- data: {
1217
- labels: ['Complete', 'Partial', 'Missing'],
1218
- datasets: [{
1219
- data: [0, 0, 0],
1220
- backgroundColor: [
1221
- '#4cc9f0',
1222
- '#f8961e',
1223
- '#f72585'
1224
- ],
1225
- borderWidth: 0
1226
- }]
1227
- },
1228
- options: {
1229
- plugins: {
1230
- legend: {
1231
- position: 'bottom'
1232
- }
1233
- },
1234
- maintainAspectRatio: false
1235
- }
1236
- });
1237
-
1238
- // Price Analysis Chart
1239
- const priceCtx = document.getElementById('priceChart').getContext('2d');
1240
- priceChart = new Chart(priceCtx, {
1241
- type: 'bar',
1242
- data: {
1243
- labels: ['Market Value', 'Price per Sq.Ft.'],
1244
- datasets: [{
1245
- label: 'Price Analysis',
1246
- data: [0, 0],
1247
- backgroundColor: [
1248
- '#4361ee',
1249
- '#4895ef'
1250
- ],
1251
- borderWidth: 0
1252
- }]
1253
- },
1254
- options: {
1255
- scales: {
1256
- y: {
1257
- beginAtZero: true
1258
- }
1259
- },
1260
- maintainAspectRatio: false
1261
- }
1262
- });
1263
-
1264
- // Legal Analysis Chart
1265
- const legalCtx = document.getElementById('legalChart').getContext('2d');
1266
- legalChart = new Chart(legalCtx, {
1267
- type: 'doughnut',
1268
- data: {
1269
- labels: ['Complete', 'Partial', 'Missing'],
1270
- datasets: [{
1271
- data: [0, 0, 0],
1272
- backgroundColor: [
1273
- '#4cc9f0',
1274
- '#f8961e',
1275
- '#f72585'
1276
- ],
1277
- borderWidth: 0
1278
- }]
1279
- },
1280
- options: {
1281
- plugins: {
1282
- legend: {
1283
- position: 'bottom'
1284
- }
1285
- },
1286
- maintainAspectRatio: false
1287
- }
1288
- });
1289
-
1290
- // Document Analysis Chart
1291
- const documentCtx = document.getElementById('documentChart').getContext('2d');
1292
- documentChart = new Chart(documentCtx, {
1293
- type: 'polarArea',
1294
- data: {
1295
- labels: ['Authentic', 'Suspicious', 'Incomplete'],
1296
- datasets: [{
1297
- data: [0, 0, 0],
1298
- backgroundColor: [
1299
- '#4cc9f0',
1300
- '#f8961e',
1301
- '#f72585'
1302
- ],
1303
- borderWidth: 0
1304
- }]
1305
- },
1306
- options: {
1307
- plugins: {
1308
- legend: {
1309
- position: 'bottom'
1310
- }
1311
- },
1312
- maintainAspectRatio: false
1313
- }
1314
- });
1315
-
1316
- // Add window resize handler for chart responsiveness
1317
- window.addEventListener('resize', debounce(() => {
1318
- charts.forEach(chart => {
1319
- if (chart && typeof chart.resize === 'function') {
1320
- chart.resize();
1321
- }
1322
- });
1323
- }, 250));
1324
-
1325
- } catch (error) {
1326
- console.error('Error initializing charts:', error);
1327
- document.getElementById('chartErrors').innerHTML =
1328
- '<div class="alert alert-danger">Error initializing charts. Please refresh the page.</div>';
1329
- }
1330
- }
1331
-
1332
- // Utility function for debouncing
1333
- function debounce(func, wait) {
1334
- let timeout;
1335
- return function executedFunction(...args) {
1336
- const later = () => {
1337
- clearTimeout(timeout);
1338
- func(...args);
1339
- };
1340
- clearTimeout(timeout);
1341
- timeout = setTimeout(later, wait);
1342
- };
1343
- }
1344
-
1345
- // Data validation function
1346
- function validateAnalysisData(data) {
1347
- return {
1348
- trustScore: {
1349
- score: data.trust_score?.score ?? 0,
1350
- reasoning: data.trust_score?.reasoning ?? 'No reasoning provided'
1351
- },
1352
- fraudClassification: {
1353
- alertLevel: data.fraud_classification?.alert_level ?? 'low',
1354
- classification: data.fraud_classification?.classification ?? 'Unknown',
1355
- confidence: data.fraud_classification?.confidence ?? 0,
1356
- indicators: data.fraud_classification?.fraud_indicators ?? [],
1357
- scores: data.fraud_classification?.indicator_scores ?? []
1358
- },
1359
- qualityAssessment: {
1360
- assessment: data.quality_assessment?.assessment ?? 'Unknown',
1361
- score: data.quality_assessment?.score ?? 0,
1362
- isAiGenerated: data.quality_assessment?.is_ai_generated ?? false,
1363
- reasoning: data.quality_assessment?.reasoning ?? 'No reasoning provided'
1364
- },
1365
- // ... other validations
1366
- };
1367
- }
1368
-
1369
- // Safe chart update function
1370
- function updateChart(chart, newData, options = {}) {
1371
- try {
1372
- if (chart && typeof chart.update === 'function') {
1373
- chart.data = newData;
1374
- chart.update(options);
1375
- return true;
1376
- }
1377
- return false;
1378
- } catch (error) {
1379
- console.error('Error updating chart:', error);
1380
- return false;
1381
- }
1382
- }
1383
-
1384
- function submitForm() {
1385
- // Show loading indicator
1386
- document.getElementById('loadingIndicator').style.display = 'block';
1387
- document.getElementById('resultsContainer').style.display = 'none';
1388
-
1389
- // Create form data
1390
- const formData = new FormData(document.getElementById('propertyForm'));
1391
-
1392
- // Add images
1393
- uploadedImages.forEach((image, index) => {
1394
- formData.append('images', image.file);
1395
- });
1396
-
1397
- // Add PDFs
1398
- uploadedPDFs.forEach((pdf, index) => {
1399
- formData.append('documents', pdf.file);
1400
- });
1401
-
1402
- // Send to backend
1403
- fetch('/verify', {
1404
- method: 'POST',
1405
- body: formData
1406
- })
1407
- .then(response => {
1408
- if (!response.ok) {
1409
- throw new Error('Network response was not ok');
1410
- }
1411
- return response.json();
1412
- })
1413
- .then(data => {
1414
- // Hide loading indicator
1415
- document.getElementById('loadingIndicator').style.display = 'none';
1416
-
1417
- // Display results
1418
- displayResults(data);
1419
-
1420
- // Show results container
1421
- document.getElementById('resultsContainer').style.display = 'block';
1422
-
1423
- // Scroll to results
1424
- document.getElementById('resultsContainer').scrollIntoView({ behavior: 'smooth' });
1425
- })
1426
- .catch(error => {
1427
- console.error('Error:', error);
1428
- document.getElementById('loadingIndicator').style.display = 'none';
1429
- alert('An error occurred while processing your request. Please try again.');
1430
- });
1431
- }
1432
- function displayResults(data) {
1433
- console.log("Received data:", JSON.stringify(data));
1434
-
1435
- // Validate and sanitize data
1436
- const validatedData = validateAnalysisData(data);
1437
-
1438
- try {
1439
- // Display Trust Score with validated data
1440
- const trustScore = validatedData.trustScore.score;
1441
- document.getElementById('trustScoreValue').textContent = trustScore;
1442
- document.getElementById('trustScoreBar').style.width = `${trustScore}%`;
1443
- document.getElementById('trustReasoning').textContent = validatedData.trustScore.reasoning;
1444
-
1445
- // Update Trust Score Chart safely
1446
- updateChart(trustScoreChart, {
1447
- datasets: [{
1448
- data: [trustScore, 100 - trustScore]
1449
- }]
1450
- });
1451
-
1452
- // Display Fraud Analysis
1453
- const fraudLevel = validatedData.fraudClassification.alertLevel;
1454
- const fraudContainer = document.getElementById('fraudAlertContainer');
1455
- fraudContainer.innerHTML = '';
1456
-
1457
- const alertClass = fraudLevel === 'high' ? 'alert-danger' :
1458
- fraudLevel === 'medium' ? 'alert-warning' : 'alert-success';
1459
-
1460
- const alertDiv = document.createElement('div');
1461
- alertDiv.className = `alert ${alertClass}`;
1462
- alertDiv.textContent = `Classification: ${validatedData.fraudClassification.classification} (Confidence: ${Math.round(validatedData.fraudClassification.confidence * 100)}%)`;
1463
- fraudContainer.appendChild(alertDiv);
1464
-
1465
- // Update Fraud Analysis Chart
1466
- const fraudIndicators = validatedData.fraudClassification.indicators || [];
1467
- const fraudScores = validatedData.fraudClassification.scores || [];
1468
- const formattedScores = fraudScores.map(score => score * 100);
1469
-
1470
- updateChart(fraudAnalysisChart, {
1471
- labels: fraudIndicators,
1472
- datasets: [{
1473
- data: formattedScores
1474
- }]
1475
- });
1476
-
1477
- document.getElementById('fraudReasoning').textContent = `This property was classified as ${validatedData.fraudClassification.classification} based on AI analysis of the listing details.`;
1478
-
1479
- // Display AI Summary
1480
- document.getElementById('aiSummary').textContent = data.summary || "No summary available";
1481
-
1482
- // Display Improvement Suggestions
1483
- const suggestionsList = document.getElementById('suggestionsList');
1484
- suggestionsList.innerHTML = '';
1485
-
1486
- if (data.suggestions && Array.isArray(data.suggestions) && data.suggestions.length > 0) {
1487
- data.suggestions.forEach(suggestion => {
1488
- if (suggestion && suggestion.trim()) {
1489
- const li = document.createElement('li');
1490
- li.className = 'suggestion-item';
1491
- li.textContent = suggestion;
1492
- suggestionsList.appendChild(li);
1493
- }
1494
- });
1495
- } else {
1496
- const li = document.createElement('li');
1497
- li.className = 'suggestion-item';
1498
- li.textContent = "No suggestions available";
1499
- suggestionsList.appendChild(li);
1500
- }
1501
-
1502
- // Display Quality Assessment
1503
- const qualityDiv = document.getElementById('qualityAssessment');
1504
- if (validatedData.qualityAssessment) {
1505
- qualityDiv.innerHTML = `
1506
- <p><strong>Assessment:</strong> ${validatedData.qualityAssessment.assessment}</p>
1507
- <p><strong>Quality Score:</strong> ${validatedData.qualityAssessment.score}%</p>
1508
- <p><strong>AI Generated:</strong> ${validatedData.qualityAssessment.isAiGenerated ? 'Likely' : 'Unlikely'}</p>
1509
- <p><strong>Reasoning:</strong> ${validatedData.qualityAssessment.reasoning}</p>
1510
- `;
1511
-
1512
- // Update Quality Chart
1513
- updateChart(qualityChart, {
1514
- datasets: [{
1515
- data: [
1516
- validatedData.qualityAssessment.score,
1517
- validatedData.qualityAssessment.isAiGenerated ? 30 : 80,
1518
- validatedData.qualityAssessment.score > 50 ? 70 : 40,
1519
- validatedData.qualityAssessment.isAiGenerated ? 40 : 75,
1520
- validatedData.qualityAssessment.score > 60 ? 80 : 50
1521
- ]
1522
- }]
1523
- });
1524
- } else {
1525
- qualityDiv.innerHTML = '<p>No quality assessment available</p>';
1526
- }
1527
-
1528
- // Display Location Analysis
1529
- const locationDiv = document.getElementById('locationAnalysis');
1530
- if (data.location_analysis) {
1531
- locationDiv.innerHTML = `
1532
- <p><strong>Assessment:</strong> ${data.location_analysis.assessment || "Unknown"}</p>
1533
- <p><strong>Completeness:</strong> ${data.location_analysis.completeness_score || 0}%</p>
1534
- <p><strong>Coordinates:</strong> ${data.location_analysis.coordinates_check || "Unknown"}</p>
1535
- <p><strong>Landmarks:</strong> ${data.location_analysis.landmarks_provided ? 'Provided' : 'Not provided'}</p>
1536
- `;
1537
-
1538
- // Update Location Chart
1539
- updateChart(locationChart, {
1540
- datasets: [{
1541
- data: [
1542
- data.location_analysis.completeness_score || 0,
1543
- 100 - (data.location_analysis.completeness_score || 0),
1544
- data.location_analysis.coordinates_check === 'coordinates_missing' ? 30 : 0
1545
- ]
1546
- }]
1547
- });
1548
- } else {
1549
- locationDiv.innerHTML = '<p>No location analysis available</p>';
1550
- }
1551
-
1552
- // Display Price Analysis
1553
- const priceDiv = document.getElementById('priceAnalysis');
1554
- if (data.price_analysis && data.price_analysis.has_price) {
1555
- priceDiv.innerHTML = `
1556
- <p><strong>Assessment:</strong> ${data.price_analysis.assessment || "Unknown"}</p>
1557
- <p><strong>Price:</strong> ₹${(data.price_analysis.price || 0).toLocaleString()}</p>
1558
- ${data.price_analysis.has_sqft ? `<p><strong>Price per Sq.Ft.:</strong> ₹${(data.price_analysis.price_per_sqft || 0).toLocaleString(undefined, {maximumFractionDigits: 2})}</p>` : ''}
1559
- <p><strong>Confidence:</strong> ${Math.round((data.price_analysis.confidence || 0) * 100)}%</p>
1560
- `;
1561
-
1562
- // Update Price Chart
1563
- updateChart(priceChart, {
1564
- labels: ['Market Value (thousands)', 'Price per Sq.Ft.'],
1565
- datasets: [{
1566
- data: [
1567
- (data.price_analysis.price || 0) / 1000, // Scale down for better visualization
1568
- data.price_analysis.price_per_sqft || 0
1569
- ]
1570
- }]
1571
- });
1572
- } else {
1573
- priceDiv.innerHTML = `<p>No price information provided for analysis.</p>`;
1574
- }
1575
-
1576
- // Display Legal Analysis
1577
- const legalDiv = document.getElementById('legalAnalysis');
1578
- if (data.legal_analysis) {
1579
- legalDiv.innerHTML = `
1580
- <p><strong>Assessment:</strong> ${data.legal_analysis.assessment || "Unknown"}</p>
1581
- <p><strong>Completeness:</strong> ${data.legal_analysis.completeness_score || 0}%</p>
1582
- <p><strong>Summary:</strong> ${data.legal_analysis.summary || "No summary available"}</p>
1583
- ${data.legal_analysis.terms_found && data.legal_analysis.terms_found.length > 0 ? `<p><strong>Legal Terms Found:</strong> ${data.legal_analysis.terms_found.join(', ')}</p>` : ''}
1584
- ${data.legal_analysis.potential_issues ? '<p class="alert alert-warning">Potential legal issues detected</p>' : ''}
1585
- `;
1586
-
1587
- // Update Legal Chart
1588
- updateChart(legalChart, {
1589
- datasets: [{
1590
- data: [
1591
- data.legal_analysis.completeness_score || 0,
1592
- 100 - (data.legal_analysis.completeness_score || 0),
1593
- data.legal_analysis.potential_issues ? 30 : 0
1594
- ]
1595
- }]
1596
- });
1597
- } else {
1598
- legalDiv.innerHTML = '<p>No legal analysis available</p>';
1599
- }
1600
-
1601
- // Display Cross-Validation Checks
1602
- const crossValidationDiv = document.getElementById('crossValidation');
1603
- crossValidationDiv.innerHTML = '<ul class="suggestion-list">';
1604
-
1605
- try {
1606
- // Safely check if cross_validation exists and is an array
1607
- if (data && data.cross_validation && Array.isArray(data.cross_validation)) {
1608
- // Only proceed if the array has items
1609
- if (data.cross_validation.length > 0) {
1610
- data.cross_validation.forEach(check => {
1611
- if (check && typeof check === 'object') {
1612
- const status = check.status || 'unknown';
1613
- const checkName = check.check || 'Check';
1614
- const message = check.message || 'No details available';
1615
-
1616
- // Determine status class
1617
- let statusClass = 'badge-warning'; // Default
1618
- if (['consistent', 'valid', 'reasonable', 'match', 'likely_valid'].includes(status)) {
1619
- statusClass = 'badge-success';
1620
- } else if (['suspicious', 'inconsistent', 'invalid', 'no_match'].includes(status)) {
1621
- statusClass = 'badge-danger';
1622
- }
1623
-
1624
- crossValidationDiv.innerHTML += `
1625
- <li class="suggestion-item">
1626
- <span class="badge ${statusClass}">${status}</span>
1627
- <strong>${checkName}:</strong> ${message}
1628
- </li>
1629
- `;
1630
- }
1631
- });
1632
- } else {
1633
- crossValidationDiv.innerHTML += '<li class="suggestion-item">No cross-validation checks performed</li>';
1634
- }
1635
- } else {
1636
- crossValidationDiv.innerHTML += '<li class="suggestion-item">No cross-validation data available</li>';
1637
- }
1638
- } catch (error) {
1639
- console.error("Error displaying cross-validation:", error);
1640
- crossValidationDiv.innerHTML += '<li class="suggestion-item">Error displaying cross-validation results</li>';
1641
- }
1642
-
1643
- crossValidationDiv.innerHTML += '</ul>';
1644
-
1645
- // Display Document Analysis
1646
- const documentDiv = document.getElementById('documentAnalysis');
1647
- documentDiv.innerHTML = '';
1648
-
1649
- if (data.document_analysis && data.document_analysis.pdf_count > 0) {
1650
- documentDiv.innerHTML = `<p><strong>Documents Analyzed:</strong> ${data.document_analysis.pdf_count}</p>`;
1651
-
1652
- data.document_analysis.pdf_analysis.forEach((pdf, index) => {
1653
- documentDiv.innerHTML += `
1654
- <div class="pdf-preview">
1655
- <p><strong>Document ${index + 1}</strong></p>
1656
- <p><strong>Type:</strong> ${pdf.document_type.classification} (${Math.round(pdf.document_type.confidence * 100)}% confidence)</p>
1657
- <p><strong>Authenticity:</strong> ${pdf.authenticity.assessment} (${Math.round(pdf.authenticity.confidence * 100)}% confidence)</p>
1658
- <p><strong>Summary:</strong> ${pdf.summary}</p>
1659
- <p><strong>Contains Signatures:</strong> ${pdf.contains_signatures ? 'Yes' : 'No'}</p>
1660
- <p><strong>Contains Dates:</strong> ${pdf.contains_dates ? 'Yes' : 'No'}</p>
1661
- </div>
1662
- `;
1663
- });
1664
-
1665
- // Update Document Chart
1666
- let authenticCount = 0;
1667
- let suspiciousCount = 0;
1668
- let incompleteCount = 0;
1669
-
1670
- data.document_analysis.pdf_analysis.forEach(pdf => {
1671
- if (pdf.authenticity.assessment.includes('authentic')) {
1672
- authenticCount++;
1673
- } else if (pdf.authenticity.assessment.includes('fraudulent')) {
1674
- suspiciousCount++;
1675
- } else {
1676
- incompleteCount++;
1677
- }
1678
- });
1679
-
1680
- updateChart(documentChart, {
1681
- datasets: [{
1682
- data: [
1683
- authenticCount,
1684
- suspiciousCount,
1685
- incompleteCount
1686
- ]
1687
- }]
1688
- });
1689
- } else {
1690
- documentDiv.innerHTML = '<p>No documents were uploaded for analysis.</p>';
1691
- }
1692
-
1693
- // Display Image Analysis
1694
- const imageAnalysisDiv = document.getElementById('imageAnalysis');
1695
- const imageGallery = document.getElementById('imageGallery');
1696
-
1697
- imageAnalysisDiv.innerHTML = '';
1698
- imageGallery.innerHTML = '';
1699
-
1700
- if (data.image_analysis && data.images && data.images.length > 0) {
1701
- imageAnalysisDiv.innerHTML = `<p><strong>Images Analyzed:</strong> ${data.image_analysis.image_count}</p>`;
1702
-
1703
- let propertyRelatedCount = 0;
1704
- data.image_analysis.image_analysis.forEach(img => {
1705
- if (img && img.is_property_related) {
1706
- propertyRelatedCount++;
1707
- }
1708
- });
1709
-
1710
- imageAnalysisDiv.innerHTML += `<p><strong>Property-Related Images:</strong> ${propertyRelatedCount} of ${data.image_analysis.image_count}</p>`;
1711
-
1712
- // Display images in gallery
1713
- data.images.forEach((imgData, index) => {
1714
- const imgAnalysis = data.image_analysis.image_analysis[index];
1715
- const galleryItem = document.createElement('div');
1716
- galleryItem.className = 'gallery-item';
1717
-
1718
- galleryItem.innerHTML = `
1719
- <img src="data:image/jpeg;base64,${imgData}" alt="Property Image ${index + 1}">
1720
- <div class="badge ${imgAnalysis && imgAnalysis.is_property_related ? 'badge-success' : 'badge-warning'}"
1721
- style="position: absolute; top: 5px; right: 5px;">
1722
- ${imgAnalysis && imgAnalysis.is_property_related ? 'Property' : 'Not Property'}
1723
- </div>
1724
- `;
1725
-
1726
- imageGallery.appendChild(galleryItem);
1727
- });
1728
- } else {
1729
- imageAnalysisDiv.innerHTML = '<p>No images were uploaded for analysis.</p>';
1730
- }
1731
-
1732
- // Update Property Summary
1733
- document.getElementById('summaryName').textContent = document.getElementById('propertyName').value || 'Not provided';
1734
- document.getElementById('summaryType').textContent = document.getElementById('propertyType').value || 'Not provided';
1735
- document.getElementById('summaryStatus').textContent = document.getElementById('status').value || 'Not provided';
1736
- document.getElementById('summaryLocation').textContent =
1737
- `${document.getElementById('address').value || ''}, ${document.getElementById('city').value || ''}, ${document.getElementById('state').value || ''}, India`;
1738
- document.getElementById('summaryPrice').textContent = document.getElementById('marketValue').value ? `₹${document.getElementById('marketValue').value}` : 'Not provided';
1739
- document.getElementById('summarySize').textContent = document.getElementById('sqFt').value ? `${document.getElementById('sqFt').value} sq. ft.` : 'Not provided';
1740
- document.getElementById('summaryRooms').textContent =
1741
- `${document.getElementById('bedrooms').value || '0'} BHK`; // BHK is common in Indian real estate
1742
-
1743
- // Update Final Verdict
1744
- const verdictBox = document.getElementById('verdictBox');
1745
- const verdictIcon = document.getElementById('verdictIcon');
1746
- const verdictText = document.getElementById('verdictText');
1747
-
1748
- if (fraudLevel === 'high' || trustScore < 40) {
1749
- verdictBox.className = 'verdict-box verdict-fraudulent';
1750
- verdictIcon.textContent = '❌';
1751
- verdictText.textContent = 'HIGH RISK - LIKELY FRAUDULENT';
1752
- } else if (fraudLevel === 'medium' || trustScore < 70) {
1753
- verdictBox.className = 'verdict-box verdict-suspicious';
1754
- verdictIcon.textContent = '⚠️';
1755
- verdictText.textContent = 'CAUTION - SUSPICIOUS ELEMENTS';
1756
- } else {
1757
- verdictBox.className = 'verdict-box verdict-legitimate';
1758
- verdictIcon.textContent = '✅';
1759
- verdictText.textContent = 'VERIFIED REAL ESTATE LISTING';
1760
- }
1761
-
1762
- // Update Verdict Reasons
1763
- const verdictReasons = document.getElementById('verdictReasons');
1764
- verdictReasons.innerHTML = '';
1765
-
1766
- // Add key findings based on analysis
1767
- const findings = [];
1768
-
1769
- if (validatedData.qualityAssessment && validatedData.qualityAssessment.isAiGenerated) {
1770
- findings.push('Description appears to be AI-generated');
1771
- }
1772
-
1773
- if (data.cross_validation) {
1774
- data.cross_validation.forEach(check => {
1775
- if (check.status === 'inconsistent' || check.status === 'invalid' ||
1776
- check.status === 'suspicious' || check.status === 'no_match') {
1777
- findings.push(check.message);
1778
- }
1779
- });
1780
- }
1781
-
1782
- if (data.price_analysis && data.price_analysis.assessment === 'suspicious pricing') {
1783
- findings.push('Price appears suspicious for this type of property');
1784
- }
1785
-
1786
- if (data.legal_analysis && data.legal_analysis.potential_issues) {
1787
- findings.push('Potential legal issues detected');
1788
- }
1789
-
1790
- // Add at least one positive finding if the verdict is good
1791
- if (findings.length === 0 && trustScore > 70) {
1792
- findings.push('Property details appear consistent and legitimate');
1793
- findings.push('No suspicious elements detected in the listing');
1794
- }
1795
-
1796
- // If we still have no findings, add a generic one
1797
- if (findings.length === 0) {
1798
- findings.push('Analysis inconclusive - insufficient information provided');
1799
- }
1800
-
1801
- findings.forEach(finding => {
1802
- const li = document.createElement('li');
1803
- li.className = 'suggestion-item';
1804
- li.textContent = finding;
1805
- verdictReasons.appendChild(li);
1806
- });
1807
-
1808
- // Update Verification Scores
1809
- updateScoreBar('trustBar', 'trustValue', trustScore);
1810
-
1811
- // Image authenticity score
1812
- let imageScore = 0;
1813
- if (data.image_analysis && data.image_analysis.image_analysis) {
1814
- const propertyImages = data.image_analysis.image_analysis.filter(img => img && img.is_property_related);
1815
- imageScore = data.image_analysis.image_count > 0 ?
1816
- Math.round((propertyImages.length / data.image_analysis.image_count) * 100) : 0;
1817
- }
1818
- updateScoreBar('imageBar', 'imageValue', imageScore);
1819
-
1820
- // Document verification score
1821
- let docScore = 0;
1822
- if (data.document_analysis && data.document_analysis.pdf_analysis) {
1823
- const authenticDocs = data.document_analysis.pdf_analysis.filter(
1824
- pdf => pdf.authenticity && pdf.authenticity.assessment.includes('authentic')
1825
- );
1826
- docScore = data.document_analysis.pdf_count > 0 ?
1827
- Math.round((authenticDocs.length / data.document_analysis.pdf_count) * 100) : 0;
1828
- }
1829
- updateScoreBar('documentBar', 'documentValue', docScore);
1830
-
1831
- // Content quality score
1832
- const contentScore = validatedData.qualityAssessment ? validatedData.qualityAssessment.score : 0;
1833
- updateScoreBar('contentBar', 'contentValue', contentScore);
1834
-
1835
- // Location accuracy score
1836
- const locationScore = data.location_analysis ? data.location_analysis.completeness_score || 0 : 0;
1837
- updateScoreBar('locationBar', 'locationValue', locationScore);
1838
-
1839
- // Update Red Flags
1840
- const redFlagsList = document.getElementById('redFlagsList');
1841
- redFlagsList.innerHTML = '';
1842
-
1843
- const redFlags = [];
1844
-
1845
- // Check for inconsistencies and issues
1846
- if (data.cross_validation) {
1847
- data.cross_validation.forEach(check => {
1848
- if (check.status === 'inconsistent' || check.status === 'invalid' ||
1849
- check.status === 'suspicious' || check.status === 'no_match') {
1850
- redFlags.push(`${check.check}: ${check.message}`);
1851
- }
1852
- });
1853
- }
1854
-
1855
- if (validatedData.qualityAssessment && validatedData.qualityAssessment.isAiGenerated) {
1856
- redFlags.push('Description appears to be AI-generated, which may indicate a fake listing');
1857
- }
1858
-
1859
- if (data.price_analysis &&
1860
- (data.price_analysis.assessment === 'suspicious pricing' ||
1861
- data.price_analysis.assessment === 'overpriced' ||
1862
- data.price_analysis.assessment === 'underpriced')) {
1863
- redFlags.push(`Price is ${data.price_analysis.assessment} for this type of property`);
1864
- }
1865
-
1866
- if (data.legal_analysis && data.legal_analysis.potential_issues) {
1867
- redFlags.push('Potential legal issues detected in the property documentation');
1868
- }
1869
-
1870
- if (data.image_analysis && data.image_analysis.image_count > 0) {
1871
- const propertyImages = data.image_analysis.image_analysis.filter(img => img && img.is_property_related);
1872
- if (propertyImages.length === 0) {
1873
- redFlags.push('None of the uploaded images appear to be related to real estate');
1874
- }
1875
- }
1876
-
1877
- // If no red flags, add a positive message
1878
- if (redFlags.length === 0) {
1879
- redFlags.push('No significant red flags detected in this listing');
1880
- }
1881
-
1882
- redFlags.forEach(flag => {
1883
- const li = document.createElement('li');
1884
- li.className = 'suggestion-item';
1885
- li.textContent = flag;
1886
- redFlagsList.appendChild(li);
1887
- });
1888
-
1889
- } catch (error) {
1890
- console.error('Error displaying results:', error);
1891
- document.getElementById('resultsContainer').innerHTML =
1892
- '<div class="alert alert-danger">Error displaying results. Please try again.</div>';
1893
- }
1894
- }
1895
-
1896
- function updateScoreBar(barId, valueId, score) {
1897
- const bar = document.getElementById(barId);
1898
- const value = document.getElementById(valueId);
1899
-
1900
- if (bar && value) {
1901
- bar.style.setProperty('--score-width', `${score}%`);
1902
- bar.style.background = `linear-gradient(to right,
1903
- ${getScoreColor(score)} ${score}%,
1904
- #e9ecef ${score}%)`;
1905
- value.textContent = `${score}%`;
1906
- }
1907
- }
1908
-
1909
- function getScoreColor(score) {
1910
- if (score >= 70) return 'var(--success)';
1911
- if (score >= 40) return 'var(--warning)';
1912
- return 'var(--danger)';
1913
- }
1914
- </script>
1915
- </body>
1916
- </html>