// TenerifeProp - API Client const API_BASE = '/api'; class API { // Properties static async getProperties(filters = {}) { const params = new URLSearchParams(filters); const response = await fetch(`${API_BASE}/properties?${params}`); return response.json(); } static async getProperty(slug, lang = 'es') { const response = await fetch(`${API_BASE}/properties/${slug}?lang=${lang}`); return response.json(); } static async getPropertyBySlug(slug, lang = 'es') { const response = await fetch(`${API_BASE}/properties/${slug}?lang=${lang}`); return response.json(); } static async getFeaturedProperties(lang = 'es') { const response = await fetch(`${API_BASE}/properties/featured?lang=${lang}`); return response.json(); } // Leads static async createLead(data) { // Input validation if (!data.name || typeof data.name !== 'string' || data.name.trim().length < 2) { return { success: false, error: 'Name is required (min 2 characters)' } } // Proper email validation const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ if (!data.email || typeof data.email !== 'string' || !emailRegex.test(data.email)) { return { success: false, error: 'Valid email is required' } } // Sanitize inputs to prevent XSS const sanitize = (str) => str ? String(str).replace(/[<>]/g, '') : '' const sanitizedData = { name: sanitize(data.name), email: data.email, phone: sanitize(data.phone), message: sanitize(data.message), property_id: data.property_id, language: data.language } const response = await fetch(`${API_BASE}/leads`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(sanitizedData) }); return response.json(); } static async getLeads(filters = {}) { const params = new URLSearchParams(filters); const response = await fetch(`${API_BASE}/leads?${params}`); return response.json(); } // Content static async getTestimonials(lang = 'es') { const response = await fetch(`${API_BASE}/testimonials?lang=${lang}`); return response.json(); } static async getFAQ(lang = 'es') { const response = await fetch(`${API_BASE}/faq?lang=${lang}`); return response.json(); } static async getServices(lang = 'es') { const response = await fetch(`${API_BASE}/services?lang=${lang}`); return response.json(); } static async getSettings() { const response = await fetch(`${API_BASE}/settings`); return response.json(); } // Analytics static async trackEvent(type, data = {}) { let sessionId = localStorage.getItem('session_id'); if (!sessionId) { // Fallback for non-secure contexts (HTTP) sessionId = crypto.randomUUID ? crypto.randomUUID() : 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); localStorage.setItem('session_id', sessionId); } await fetch(`${API_BASE}/analytics/event`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ type, session_id: sessionId, ...data }) }); } // Cities static async getCities() { const response = await fetch(`${API_BASE}/cities`); return response.json(); } } // Export for use window.API = API;