591 lines
28 KiB
JavaScript
591 lines
28 KiB
JavaScript
// Rents page logic moved to external file to satisfy CSP (no inline scripts or handlers)
|
|
|
|
const API_BASE = '/api';
|
|
|
|
// Area dropdown values for rents
|
|
const areas = [
|
|
'al mamzer', 'jabal ali first', 'al nahda second', 'burj khalifa',
|
|
'al merkadh', 'dubai investment park second', 'al yelayiss 2',
|
|
'dubai investment park first', 'al yelayiss 1', 'al jadaf',
|
|
'al nahda first', 'al suq al kabeer', 'mirdif', 'business bay',
|
|
'madinat hind 4', 'al thanyah third',
|
|
'al qusais industrial fourth', 'al qusais industrial fifth',
|
|
'al warqa first', 'muhaisanah fourth', 'al qusais second',
|
|
'al karama', 'al hudaiba', 'madinat dubai almelaheyah',
|
|
'al safouh second', 'al qusais first', 'wadi al amardi', 'al rega',
|
|
'wadi al safa 5', 'marsa dubai',
|
|
'hadaeq sheikh mohammed bin rashid', 'me\'aisem first',
|
|
'ras al khor industrial third', 'al qusais industrial first',
|
|
'al murqabat', 'wadi al safa 6', 'naif', 'nad al shiba third',
|
|
'al saffa first', 'um suqaim third', 'al khairan first',
|
|
'madinat al mataar', 'saih shuaib 2', 'mankhool',
|
|
'al thanyah fifth', 'al hebiah fourth', 'trade center second',
|
|
'al warsan first', 'nadd hessa', 'port saeed',
|
|
'trade center first', 'al wasl', 'jumeirah first',
|
|
'al goze industrial second', 'nad al shiba first', 'al muteena',
|
|
'al barsha first', 'jabal ali industrial first', 'palm jumeirah',
|
|
'al raffa', 'margham', 'al barshaa south third', 'al satwa',
|
|
'al khawaneej second', 'al bada', 'al hamriya', 'al thanyah first',
|
|
'al barsha south fourth', 'um hurair second', 'al baraha',
|
|
'ras al khor industrial second', 'al goze industrial first',
|
|
'al hebiah fifth', 'jumeirah second', 'al mararr',
|
|
'wadi al safa 3', 'um suqaim second', 'hor al anz', 'al kheeran',
|
|
'wadi al safa 2', 'hor al anz east', 'al manara', 'eyal nasser',
|
|
'al yufrah 1', 'al khawaneej first', 'hatta', 'warsan fourth',
|
|
'um ramool', 'al goze fourth', 'al goze third',
|
|
'al goze industrial third', 'al barsha south fifth',
|
|
'al hebiah sixth', 'saih shuaib 3', 'al goze first', 'abu hail',
|
|
'al hebiah third', 'al hebiah second', 'rega al buteen',
|
|
'al goze industrial fourth', 'nad al hamar', 'al jafliya',
|
|
'al barshaa south second', 'al qusais industrial second',
|
|
'oud metha', 'um suqaim first', 'jabal ali', 'jumeirah third',
|
|
'lehbab second', 'al dhagaya', 'al lusaily', 'hessyan first',
|
|
'al khabeesi', 'wadi al safa 7', 'al hebiah first',
|
|
'al thanayah fourth', 'al ras', 'muhaisanah second',
|
|
'muhaisanah first', 'al-cornich', 'al mizhar third',
|
|
'al rashidiya', 'cornich deira', 'lehbab first', 'um al sheif',
|
|
'al garhoud', 'al yufrah 2', 'al yufrah 3', 'al saffa second',
|
|
'madinat hind 1', 'al sabkha', 'ras al khor industrial first',
|
|
'al buteen', 'jabal ali industrial second', 'al safouh first',
|
|
'al aweer first', 'al eyas', 'al mizhar first',
|
|
'al qusais industrial third', 'um hurair first', 'al kifaf',
|
|
'zaabeel first', 'al waheda', 'zaabeel second', 'ghadeer al tair',
|
|
'al twar first', 'grayteesah', 'al warsan third', 'al ttay',
|
|
'nad al shiba second', 'al barsha second', 'al athbah',
|
|
'al warqa fourth'
|
|
];
|
|
|
|
// Projects list from rents
|
|
const projects = [
|
|
'starz tower by danube', 'azizi feirouz i',
|
|
'candace acacia hotel apartments', 'burj al nujoom',
|
|
'azizi riviera 35', 'shams townhouses', 'reem-mira community ph 1',
|
|
'schon business park', 'damac hills (2) - albizia',
|
|
'reem - mira oasis community', 'trident grand', 'collective 2.0',
|
|
'lakeside', 'marina vista', 'madinat jumeriah living - phase 2',
|
|
'creek beach - surf', 'creek beach - bayshore',
|
|
'creek beach - sunset', 'creek beach - breeze',
|
|
'creek beach - vida residences', 'creek beach - orchid',
|
|
'creek beach - savanna-cedar-mangrove',
|
|
'creek beach - canopy - moor', 'creek beach - summer',
|
|
'creek beach - grove', 'creek beach - rosewater',
|
|
'creek beach - lotus', 'azizi riviera 46', 'sahara meadows2',
|
|
'palace beach residence', 'blue wave', 'new dubai gate1',
|
|
'elite 4 sports residence', 'binghatti canal', 'azizi riviera 4',
|
|
'liva', 'una', 'azizi park avenue', 'la residence 4 at the lotus',
|
|
'damac towers by paramount', 'la residence 3 at the lotus',
|
|
'damac hills (2) - viridis', 'vera tower', 'maple iii',
|
|
'the lakes deema 2', 'harbour gate', 'luma22', 'sunset gardens b',
|
|
'reem-mira community ph5', 'canal front residences cf1 & cf2',
|
|
'westburry tower', 'arabian ranches lll - june', 'remraam',
|
|
'remraam - al ramth 2', 'remraam - al ramth',
|
|
'living legends phase 5', 'damac hills (2) - pacifica',
|
|
'qpoint liwan-plot r054', 'qline (qpoint phaseii) 3c-lw-r-054',
|
|
'hds business centre', 'jumeirah business centre 4',
|
|
'gold crest views2', 'le grand chateau', 'the spirit',
|
|
'the valley - orania', 'latifa tower',
|
|
'serenia residences the palm', 'mag218', 'empire heights',
|
|
'the fields at d11 - mbrmc', 'equiti arcade', 'al jawhara tower',
|
|
'mudon views', 'sondos orchid', 'sky courts',
|
|
'the pulse beachfront 2', 'damac hills - rochester',
|
|
'glitz residence 3', 'burj vista', 'grand boulevard', 'sidra',
|
|
'the regent', 'the valley - eden', 'collective', 'iris bay',
|
|
'stallion tower', 'sondos zinnia', 'damac heights',
|
|
'the polo residence',
|
|
'mohammed bin rashid al maktoum city- district one, phase 1',
|
|
'the grand', 'maple 2', 'al habtoor city', 'al habtoor tower',
|
|
'ajmal sarah', 'the haven', 'elite ii sports residence',
|
|
'arabian gate', 'hayat boulevard', 'prime gardens', 'coopet',
|
|
'azizi riviera 41', 'the apricot', 'executive bay a',
|
|
'executive bay b', 'elite 10 sports residence', 'mag 5 boulevard',
|
|
'the court',
|
|
'mohammed bin rashid al maktoum city-district one phase ii villas',
|
|
'manhattan', 'panorama', 'badra phase 1',
|
|
'mirdif hills- nasayem avenue', 'jannat', 'midtown - mesk',
|
|
'midtown - afnan', 'midtown - dania', 'midtown - noor',
|
|
'azizi riviera 20', 'trillionaire residences by binghatti',
|
|
'boris becker business tower', 'rukan', 'opalz by danube',
|
|
'oakley square residences', 'royale residence1', 'diamond views 3',
|
|
'ag tower', 'the address dubai opera', 'burj park v', 'il primo',
|
|
'grande', 'act one | act two', 'the mansion', 'burj park iii',
|
|
'opera grand', 'the st. regis residences, downtown dubai',
|
|
'm burj', 'the residence | burj khalifa', 'burj khalifa towers',
|
|
'sharena residence 1', 'sherena residence', 'burj royale',
|
|
'azizi riviera 33', 'the vybe', 'damac hills (2) - victoria 2',
|
|
'emirates living - springs 2', 'arabella 2 - townhouses at mudon',
|
|
'binghatti onyx', 'escan marina tower', 'fawad azizi residence',
|
|
'azizi riviera 17', 'the hills', 'park ridge', 'peninsula one',
|
|
'emirates garden 1 (lavender - gardenia - rose)',
|
|
'port de la mer - la voile',
|
|
'terhab hotel & towers at jumeirah village triangle', 'la rosa 3',
|
|
'confident lancaster', 'elite 8 sports residence',
|
|
'silicon gates 4', 'reem - mira oasis community phase 3',
|
|
'port de la mer - la cote', 'atrium gold towers',
|
|
'alduaa marina tower', 'jumeirah living marina gate',
|
|
'urban oasis', 'd1', 'palazzo versace', 'azizi riviera 39',
|
|
'fair view residency', 'regina', 'i - rise tower', 'time 1',
|
|
'sobha hartland - the crest', '17 icon bay', 'rukan 3', 'it plaza',
|
|
'dd stand point', 'axis silver', 'maha townhouses',
|
|
'damac hills (2) - claret', 'qpoint liwan-plot r071',
|
|
'no.17, no.18a,no.18b and no.19 citywalk residential',
|
|
'elysee iii by pantheon', 'royale garden residence',
|
|
'park heights i', 'azizi riviera 22', 'the pad', 'hockey tower',
|
|
'saba tower 3', 'citadel tower', 'new dubai gate2',
|
|
'azure residence', 'rasha 2', 'azizi riviera 67',
|
|
'damac hills (2) - mimosa', 'mudon al ranim 2',
|
|
'sobha hartland waves', 'emirates living - springs 7',
|
|
'the bridge', 'sapphire residence', 'azizi riviera 63',
|
|
'bay square', 'laguna tower', 'glitz residence 1',
|
|
'axis residences 3', '15 northside', 'santevill', 'syann park1',
|
|
'jadeel -madinat jumeirah living', 'qpoint liwan-plot r068',
|
|
'jasmine lane', 'the onyx',
|
|
'mohammed bin rashid al maktoum city , district one phase iii , residences 20',
|
|
'rigel', 'elash', 'parkside', 'international city emarati',
|
|
'donna towers', 'emirates living - springs 12', 'al furjan',
|
|
'the crescent', 'gold crest executive', 'uniestate prime tower',
|
|
'al khail heights', 'fairmont palm residence',
|
|
'emirates living - springs 10', 'damac hills (2) - centaury',
|
|
'upside living', 'lawnsi', 'tanaro', 'mag 22',
|
|
'palace residences - dubai creek harbour', 'smart heights',
|
|
'binghatti avenue', 'vincitore benessere', 'suberbia',
|
|
'alef noon residence', 'damac hills (2) - amargo',
|
|
'green community west- extension- phase iii', 'town central',
|
|
'celestia', 'celia residence', 'merano tower', 'sami q tower',
|
|
'living legends phase 3', 'town square zahra', 'dezire residences',
|
|
'harbour residences', 'aykon city 2', 'aykon city', 'aykon city 3',
|
|
'binghatti emerald', 'plaza residences', 'the lakes ghadeer',
|
|
'the binary by omniyat', 'stadium point', 'b2b tower',
|
|
'the pulse townhouses', 'elite residence', 'palma residence',
|
|
'uniestate supreme residence', 'ghalia', 'the concourse',
|
|
'farhad azizi residence', 'silver tower', 'marquis signature',
|
|
'creekside 18', 'sandoval lane', 'miraclz tower', 'orion building',
|
|
'mayfair residency', 'dunes village', 'the dubai creek residences',
|
|
'asayel at madinat jumeirah living', 'ontario tower',
|
|
'damac hills - carson', 'global golf residence 2', 'lake view',
|
|
'damac hills (2) - avencia', 'azizi shaista residence',
|
|
'jumeirah business centre 5', 'the haven residences',
|
|
'avenue residence three', 'serena resedence',
|
|
'lawnz residence by danube', 'azizi riviera 45', 'park islands',
|
|
'villa lantana 1', 'the terraces', '1 residences', 'fahad 2',
|
|
'au tower', 'prive by damac', 'the valley - talia', 'ac3', 'mudon',
|
|
'marina residence', 'reem townhouses', 'orra marina',
|
|
'ellington beach house', 'q - zone (qpoint - phase iii) mu007',
|
|
'qpoint liwan- plot mu007', 'aura', 'binghatti tulip',
|
|
'downtown views ii', 'mada\'in',
|
|
'mohammed bin rashid al maktoum city , district one phase iii , residences 30',
|
|
'matex tower', 'mag 318', 'mag eye phase 1', 'jewelz residence',
|
|
'the ivy', 'palace estates', 'tiara residence', 'la vista 05',
|
|
'reem - mira oasis community phase 2', 'mulberry at park heights',
|
|
'greenview 3', 'royale residence2', 'binghatti venus',
|
|
'green valley tower', 'ocean heights', 'one za\'abeel', 'maple',
|
|
'westwood grande ii by imtiaz', 'grandeur residences',
|
|
'creek edge', 'rawda apartments', 'azizi riviera 43',
|
|
'silicon gate 1', 'emirates living - springs 5',
|
|
'azizi riviera 61', 'la riviera azure', 'lake central',
|
|
'the matrix', 'lagoon views at district one',
|
|
'emirates living - springs 11', 'the pulse boulevard apartments',
|
|
'dubai marina mall', 'reva residences',
|
|
'jumeirah business centre 6', 'me do re', 'signature livings',
|
|
'vida residence downtown dubai', 'windsor manor', 'amaranta 2',
|
|
'madina tower', 'creek rise', 'azizi riviera 27',
|
|
'jumeirah business centre2', 'urbana ii', 'avenue residence 2',
|
|
'damac hills (2) - coursetia', 'town square jenna and warda',
|
|
'arabian ranches iii - sun', 'azizi riviera 3', 'harbour views',
|
|
'the signature', 'centrium tower', 'binghatti corner',
|
|
'premiers twin tower', 'mag 5', 'bloom towers', 'the point',
|
|
'continental tower', 'clayton residency', 'global green view ii',
|
|
'binghatti orchid', 'dunes tower', 'reef residence',
|
|
'azizi riviera 25', 'hera tower', 'lakeside residence',
|
|
'manam prime', 'trafalgar central', 'elite sports residence',
|
|
'dd boulevard central', 'the pulse residence', 'zada tower',
|
|
'blue bay', 'warsan village - b & c',
|
|
'mohammad aqil ali & ahmad ali alzarooni', 'peninsula five',
|
|
'sulafa tower', 'the concourse 2', 'tower 108', 'cadi4',
|
|
'dusk by binghatti', 'ariyana', 'zumurud dubai marina',
|
|
'joya verde residences dubai', 'wilton terraces',
|
|
'avenue residence1', 'elite 6 sports residence',
|
|
'diamond views 1- villas b', 'myka residence',
|
|
'vida residences dubai marina', 'hamilton residency',
|
|
'madison residency', 'the royal atlantis,resort and residences',
|
|
'ariana park', 'belgravia iii', 'j&g plexs', 'alandalus townhouse',
|
|
'golf ville', 'majestine', 'creek palace', 'jumeirah gate',
|
|
'silicon avenue', 'noor townhouses', 'golf tower',
|
|
'damac hills (2) - amazonia',
|
|
'the address residence fountain views ii',
|
|
'the address residence fountain views iii', 'boulevard point',
|
|
'vida dubai mall', 'the address residence-fountain views',
|
|
'luxury family residence ii', 'iris crystal', 'montrose', 'mirar',
|
|
'29 boulevard', 'azizi riviera 12', 'azizi samia residence',
|
|
'dm marina plaza', 'golf views', 'la visita 02', 'the autograph',
|
|
'canal views', 'bloom heights', 'la rive', 'la vista 04',
|
|
'rukan residence', 'qpoint liwan-plot mu002', 'lake terrace',
|
|
'damac hills (2) - avencia-2', 'burj crown',
|
|
'uniestate sports tower', 'cappadocia', 'riah towers',
|
|
'yaass tower', 'townhouses at jumeirah islands',
|
|
'damac hills (2) - aquilegia',
|
|
'mohammed bin rashid al maktoum city , district one phase iii , residences 24',
|
|
'oberoi centre', 'elite 5 sports residence',
|
|
'the sterling east house', 'sol avenue', 'forte',
|
|
'arabian ranches iii - spring', 'daytona house', 'the palm tower',
|
|
'hamza tower', 'oxford boulevard', 'the pulse- beachfront',
|
|
'sobha creek vistas reserve', 'pearl house i by imtiaz',
|
|
'silicon information technology tower', 'binghatti mirage',
|
|
'al ferdows', 'damac hills (2) - victoria', 'torch tower',
|
|
'azizi riviera 11',
|
|
'no.20, no.21a, no.21b and no.22 citywalk residential',
|
|
'las casas',
|
|
'mohammed bin rashid al maktoum city , district one phase iii , residences 1',
|
|
'azizi riviera 9', 'burlington tower',
|
|
'damac hills - golf promenade', 'al waleed garden 2',
|
|
'residences du port, dubai marina, autograph collection residences',
|
|
'damac hills - brookfield-3', 'damac hills - artesia',
|
|
'qpoint liwan-plot r010', 'qline (qpoint phase ii) r010',
|
|
'sobha hartland waves grande', 'al andalus phase 2',
|
|
'alandalus building e', 'alandalus building g', 'alandalus',
|
|
'alandalus building d', 'champions tower1', 'park lane tower',
|
|
'the paragon by igo', 'vancouver', 'sidra tower', 'elan',
|
|
'mohammed bin rashid al maktoum city , district one phase iii , residences 18',
|
|
'solitaire cascades', 'bay central west & central towers',
|
|
'q-zone (qpoint - phase iii), mu005&6', 'qpoint liwan-plot mu005',
|
|
'qpointliwan-plot mu006', 'damac hills (2) - aster',
|
|
'qpoint liwan-plot r055',
|
|
'no.1, no.2a, no.2b, no.3a and 3b citywalk residential',
|
|
'marquise square tower', 'silver star tower',
|
|
'emirates living - springs 3',
|
|
'mohammed bin rashid al maktoum city , district one phase iii , residences 13',
|
|
'churchill tower', 'park horizon', 'binghatti crescent',
|
|
'la rosa 5', 'sobha hartland one park avenue', 'la violeta 2',
|
|
'villanova amaranta 4', 'beach vista', 'spica', 'water\'s edge',
|
|
'beach isle', 'park field', 'azizi riviera 13', 'liv marina',
|
|
'crystal tower', 'diamond views 4', 'gardenia 3', 'aura by grovy',
|
|
'mbl residence', 'cayan tower', 'claren 1', 'equiti apartments',
|
|
'la-riviera apartments', 'arabian & spainsh tower (phase 2)',
|
|
'canal residence west 2', 'elite business bay residence',
|
|
'palladium', 'the vortex tower', 'the valley-nara',
|
|
'belgravia heights i', 'creek crescent', 'jumeirah park 7b&c',
|
|
'condor classic', 'samana golf avenue', 'ellington house',
|
|
'arabian ranches lll - caya', 'safi townhouses', 'the wings',
|
|
'olivz residence', 'al jawzaa', 'prive residence',
|
|
'damac hills (2) - zinnia', 'town square hayat',
|
|
'the opus by omniyat', 'maria tower', 'naseem townhouses',
|
|
'downtown views', 'blvd heights', 'sol bay',
|
|
'damac hills - golf vista', 'urbana iii', 'indigo tower',
|
|
'azizi riviera 23', 'the pulse beachfront 3', 'apex atrium',
|
|
'creek gate', 'azizi riviera 7', 'concept 7 residences',
|
|
'silicon heights', 'the pulse residence park',
|
|
'platinum by vision', 'paramount tower hotel & residences',
|
|
'azizi riviera 2', 'tenora', 'binghatti creek',
|
|
'villanova amaranta 3', 'armada towers', 'town square safi',
|
|
'crystal residence', 'harmony', 'oia residence',
|
|
'casa flores and eden apartments', 'azizi riviera 14',
|
|
'clover bay', 'binghatti heights', 'gardenia livings',
|
|
'damac hills-park residences 1', 'arabian ranches iii - joy',
|
|
'silverene', 'elite downtown residence', 'profile residence',
|
|
'the anwa by omniyat', 'prime tower', 'damac hills (2) - vardon',
|
|
'shamal waves', 'tiffany towers', 'topaz residences 2',
|
|
'qpoint liwan-plot r069', 'azizi riviera 26', 'pearls by vision',
|
|
'azizi riviera 47', 'azizi riviera 42', 'azizi gardens',
|
|
'imperial', 'reem-mira community ph 4', 'azizi aura residences',
|
|
'prime business avenue',
|
|
'lincoln park(west side & lincoln park - b)',
|
|
'mohammed bin rashid al maktoum city district one- c villas',
|
|
'wavez residence', '51@business bay', 'arabian ranches lll - ruba',
|
|
'living legends phase 7', 'elz residence', 'burj views'
|
|
];
|
|
|
|
function populateAreas() {
|
|
const areaSelect = document.getElementById('area_name');
|
|
areas.forEach(area => {
|
|
const option = document.createElement('option');
|
|
option.value = area;
|
|
option.textContent = area.charAt(0).toUpperCase() + area.slice(1).replace(/\b\w/g, l => l.toUpperCase());
|
|
areaSelect.appendChild(option);
|
|
});
|
|
}
|
|
|
|
function loadProjects() {
|
|
const projectSelect = document.getElementById('project');
|
|
const sortedProjects = projects.slice().sort((a, b) => a.localeCompare(b, undefined, { sensitivity: 'base' }));
|
|
sortedProjects.forEach(project => {
|
|
const option = document.createElement('option');
|
|
option.value = project;
|
|
option.textContent = project.length > 70 ? project.substring(0, 70) + '...' : project;
|
|
projectSelect.appendChild(option);
|
|
});
|
|
}
|
|
|
|
function showLoading(show) {
|
|
document.getElementById('loading').style.display = show ? 'block' : 'none';
|
|
}
|
|
|
|
function showError(message) {
|
|
const errorDiv = document.getElementById('error');
|
|
errorDiv.textContent = message;
|
|
errorDiv.style.display = 'block';
|
|
}
|
|
|
|
function hideError() {
|
|
document.getElementById('error').style.display = 'none';
|
|
}
|
|
|
|
function showResults() {
|
|
document.getElementById('resultsSection').style.display = 'block';
|
|
}
|
|
|
|
function hideResults() {
|
|
document.getElementById('resultsSection').style.display = 'none';
|
|
}
|
|
|
|
function formatDate(dateString) {
|
|
if (!dateString) return 'N/A';
|
|
const date = new Date(dateString);
|
|
return date.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' });
|
|
}
|
|
|
|
function formatNumber(num, decimals = 0) {
|
|
if (num === null || num === undefined) return 'N/A';
|
|
return parseFloat(num).toLocaleString('en-US', { maximumFractionDigits: decimals });
|
|
}
|
|
|
|
function formatCurrency(amount) {
|
|
if (!amount) return 'N/A';
|
|
return 'AED ' + parseFloat(amount).toLocaleString('en-US', { maximumFractionDigits: 0 });
|
|
}
|
|
|
|
let currentPage = 1;
|
|
let lastPaging = { total: 0, page: null, page_size: 30, total_pages: 1, has_next: false, has_prev: false };
|
|
|
|
async function searchRents(pageOverride) {
|
|
const formData = new FormData(document.getElementById('filtersForm'));
|
|
const params = new URLSearchParams();
|
|
|
|
const area_name = formData.get('area_name');
|
|
const property_type = formData.get('property_type');
|
|
const size_min = formData.get('size_min');
|
|
const size_max = formData.get('size_max');
|
|
const rooms = formData.get('rooms');
|
|
const project = formData.get('project');
|
|
const pageSize = formData.get('page_size') || '30';
|
|
const page = pageOverride != null ? pageOverride : (formData.get('page') || currentPage || 1);
|
|
|
|
if (area_name) params.append('area_name', area_name);
|
|
if (property_type && property_type !== 'all') params.append('property_type', property_type);
|
|
if (size_min && !isNaN(parseFloat(size_min))) params.append('size_min', size_min);
|
|
if (size_max && !isNaN(parseFloat(size_max))) params.append('size_max', size_max);
|
|
if (rooms && rooms !== 'all') params.append('rooms', rooms);
|
|
if (project && project !== 'all') params.append('project', project);
|
|
// pagination params
|
|
if (page) params.append('page', page);
|
|
if (pageSize) params.append('page_size', pageSize);
|
|
|
|
showLoading(true);
|
|
hideError();
|
|
hideResults();
|
|
|
|
try {
|
|
const response = await fetch(`${API_BASE}/rents/recent?${params.toString()}`);
|
|
const data = await response.json();
|
|
if (data.success) {
|
|
currentPage = data.data.page || 1;
|
|
lastPaging = {
|
|
total: data.data.total ?? data.data.count,
|
|
page: data.data.page,
|
|
page_size: data.data.page_size ?? parseInt(pageSize,10),
|
|
total_pages: data.data.total_pages ?? 1,
|
|
has_next: !!data.data.has_next,
|
|
has_prev: !!data.data.has_prev
|
|
};
|
|
displayResults(data.data);
|
|
} else {
|
|
showError(data.message || 'Failed to fetch rents');
|
|
}
|
|
} catch (error) {
|
|
showError('Network error: ' + error.message);
|
|
} finally {
|
|
showLoading(false);
|
|
}
|
|
}
|
|
|
|
function displayResults(data) {
|
|
const { rents, count, total, page, page_size, total_pages, has_next, has_prev } = data;
|
|
const tbody = document.getElementById('rentsBody');
|
|
const resultsCount = document.getElementById('resultsCount');
|
|
const showing = count;
|
|
const grandTotal = total ?? count;
|
|
resultsCount.textContent = `Showing ${showing} of ${grandTotal} rents`;
|
|
const pageInfo = document.getElementById('pageInfo');
|
|
if (pageInfo) {
|
|
if (page && total_pages) {
|
|
pageInfo.textContent = `Page ${page} of ${total_pages}`;
|
|
} else {
|
|
pageInfo.textContent = '';
|
|
}
|
|
}
|
|
const prevBtn = document.getElementById('prevPage');
|
|
const nextBtn = document.getElementById('nextPage');
|
|
if (prevBtn) prevBtn.disabled = !(has_prev);
|
|
if (nextBtn) nextBtn.disabled = !(has_next);
|
|
|
|
if (rents.length === 0) {
|
|
const colCount = document.querySelectorAll('#rentsTable thead th').length;
|
|
tbody.innerHTML = (
|
|
'<tr>' +
|
|
`<td colspan="${colCount}" class="no-results">` +
|
|
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">' +
|
|
'<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>' +
|
|
'</svg>' +
|
|
'<div>No rents found matching your filters</div>' +
|
|
'</td>' +
|
|
'</tr>'
|
|
);
|
|
showResults();
|
|
return;
|
|
}
|
|
|
|
tbody.innerHTML = rents.map(r => (
|
|
'<tr>' +
|
|
`<td>${r.rent_id ?? 'N/A'}</td>` +
|
|
`<td>${formatDate(r.registration_date)}</td>` +
|
|
`<td>${formatDate(r.start_date)}</td>` +
|
|
`<td>${formatDate(r.end_date)}</td>` +
|
|
`<td>${r.version_en ?? 'N/A'}</td>` +
|
|
`<td>${r.area_en ?? 'N/A'}</td>` +
|
|
`<td>${formatCurrency(r.contract_amount)}</td>` +
|
|
`<td>${formatCurrency(r.annual_amount)}</td>` +
|
|
`<td>${r.is_free_hold_en ?? 'N/A'}</td>` +
|
|
`<td>${formatNumber(r.actual_area)}</td>` +
|
|
`<td>${r.prop_type_en ?? 'N/A'}</td>` +
|
|
`<td>${r.prop_sub_type_en ?? 'N/A'}</td>` +
|
|
`<td>${r.rooms != null ? formatNumber(r.rooms, 1) : 'N/A'}</td>` +
|
|
`<td>${r.usage_en ?? 'N/A'}</td>` +
|
|
`<td>${r.nearest_metro_en ?? 'N/A'}</td>` +
|
|
`<td>${r.nearest_mall_en ?? 'N/A'}</td>` +
|
|
`<td>${r.nearest_landmark_en ?? 'N/A'}</td>` +
|
|
`<td>${r.parking != null ? formatNumber(r.parking, 1) : 'N/A'}</td>` +
|
|
`<td>${r.total_properties ?? '0'}</td>` +
|
|
`<td>${r.master_project_en ?? 'N/A'}</td>` +
|
|
`<td>${r.project_en ?? 'N/A'}</td>` +
|
|
`<td>${formatDate(r.created_at)}</td>` +
|
|
`<td>${formatDate(r.updated_at)}</td>` +
|
|
'</tr>'
|
|
)).join('');
|
|
|
|
showResults();
|
|
}
|
|
|
|
function resetFilters() {
|
|
document.getElementById('filtersForm').reset();
|
|
document.getElementById('size_min').value = '';
|
|
document.getElementById('size_max').value = '';
|
|
document.getElementById('sizeValue').textContent = 'All Sizes';
|
|
hideResults();
|
|
hideError();
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
populateAreas();
|
|
loadProjects();
|
|
|
|
const sizeMinHidden = document.getElementById('size_min');
|
|
const sizeMaxHidden = document.getElementById('size_max');
|
|
const sizeMinRange = document.getElementById('size_min_range');
|
|
const sizeMaxRange = document.getElementById('size_max_range');
|
|
const sizeFill = document.getElementById('sizeFill');
|
|
const sizeValue = document.getElementById('sizeValue');
|
|
const MIN_VAL = parseFloat(sizeMinRange.min);
|
|
const MAX_VAL = parseFloat(sizeMinRange.max);
|
|
const STEP = parseFloat(sizeMinRange.step) || 100;
|
|
|
|
function updateSizeLabel() {
|
|
const min = parseFloat(sizeMinRange.value);
|
|
const max = parseFloat(sizeMaxRange.value);
|
|
const hasMin = !isNaN(min);
|
|
const hasMax = !isNaN(max);
|
|
if (!hasMin && !hasMax) {
|
|
sizeValue.textContent = 'All Sizes';
|
|
} else if (hasMin && hasMax) {
|
|
sizeValue.textContent = `${min.toLocaleString('en-US')} - ${max.toLocaleString('en-US')} sq.ft`;
|
|
} else if (hasMin) {
|
|
sizeValue.textContent = `≥ ${min.toLocaleString('en-US')} sq.ft`;
|
|
} else {
|
|
sizeValue.textContent = `≤ ${max.toLocaleString('en-US')} sq.ft`;
|
|
}
|
|
// Persist only when different from full range
|
|
sizeMinHidden.value = (min > MIN_VAL) ? min : '';
|
|
sizeMaxHidden.value = (max < MAX_VAL) ? max : '';
|
|
// Update fill track
|
|
const left = ((Math.max(MIN_VAL, Math.min(min, max)) - MIN_VAL) / (MAX_VAL - MIN_VAL)) * 100;
|
|
const right = ((Math.max(MIN_VAL, Math.max(min, max)) - MIN_VAL) / (MAX_VAL - MIN_VAL)) * 100;
|
|
sizeFill.style.left = `${left}%`;
|
|
sizeFill.style.width = `${Math.max(0, right - left)}%`;
|
|
}
|
|
|
|
function clampRanges() {
|
|
if (parseFloat(sizeMinRange.value) > parseFloat(sizeMaxRange.value) - STEP) {
|
|
sizeMinRange.value = (parseFloat(sizeMaxRange.value) - STEP).toString();
|
|
}
|
|
if (parseFloat(sizeMaxRange.value) < parseFloat(sizeMinRange.value) + STEP) {
|
|
sizeMaxRange.value = (parseFloat(sizeMinRange.value) + STEP).toString();
|
|
}
|
|
}
|
|
sizeMinRange.addEventListener('input', () => { clampRanges(); updateSizeLabel(); });
|
|
sizeMaxRange.addEventListener('input', () => { clampRanges(); updateSizeLabel(); });
|
|
|
|
// Ensure both handles are draggable when overlapping by toggling z-index on interaction
|
|
function bringMinToFront() {
|
|
sizeMinRange.style.zIndex = '6';
|
|
sizeMaxRange.style.zIndex = '5';
|
|
}
|
|
function bringMaxToFront() {
|
|
sizeMinRange.style.zIndex = '5';
|
|
sizeMaxRange.style.zIndex = '6';
|
|
}
|
|
['mousedown','pointerdown','touchstart'].forEach(evt => {
|
|
sizeMinRange.addEventListener(evt, bringMinToFront, { passive: true });
|
|
sizeMaxRange.addEventListener(evt, bringMaxToFront, { passive: true });
|
|
});
|
|
// Initialize
|
|
sizeMinRange.value = MIN_VAL;
|
|
sizeMaxRange.value = MAX_VAL;
|
|
updateSizeLabel();
|
|
|
|
document.getElementById('filtersForm').addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
currentPage = 1;
|
|
const pageInput = document.getElementById('page');
|
|
if (pageInput) pageInput.value = '1';
|
|
await searchRents(1);
|
|
});
|
|
|
|
const resetBtn = document.getElementById('resetBtn');
|
|
if (resetBtn) {
|
|
resetBtn.addEventListener('click', resetFilters);
|
|
}
|
|
|
|
// pagination buttons
|
|
const prevBtn = document.getElementById('prevPage');
|
|
const nextBtn = document.getElementById('nextPage');
|
|
if (prevBtn) {
|
|
prevBtn.addEventListener('click', async () => {
|
|
if (lastPaging.has_prev && currentPage > 1) {
|
|
currentPage -= 1;
|
|
const pageInput2 = document.getElementById('page');
|
|
if (pageInput2) pageInput2.value = String(currentPage);
|
|
await searchRents(currentPage);
|
|
}
|
|
});
|
|
}
|
|
if (nextBtn) {
|
|
nextBtn.addEventListener('click', async () => {
|
|
if (lastPaging.has_next) {
|
|
currentPage += 1;
|
|
const pageInput3 = document.getElementById('page');
|
|
if (pageInput3) pageInput3.value = String(currentPage);
|
|
await searchRents(currentPage);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
|