Compare commits

..

No commits in common. "current" and "dev" have entirely different histories.
current ... dev

16 changed files with 10479 additions and 61781 deletions

File diff suppressed because one or more lines are too long

View File

@ -20,7 +20,6 @@ public with sharing class PropertyDataController {
'pcrm__Sub_Community_Propertyfinder__c, pcrm__Property_Name_Propertyfinder__c, ' +
'pcrm__City_Propertyfinder__c, ' +
'pcrm__Rent_Available_From__c, pcrm__Rent_Available_To__c, ' +
'Private_Amenities__c, ' +
'Contact__c, Contact__r.FirstName, Contact__r.LastName, Contact__r.Email, Contact__r.Phone, ' +
'Email__c, Phone__c, ' +
'CreatedBy.Name, LastModifiedBy.Name, Owner.Name, ' +
@ -56,7 +55,6 @@ public with sharing class PropertyDataController {
System.debug('Build Year: ' + firstProp.pcrm__Build_Year__c);
System.debug('Parking Spaces: ' + firstProp.pcrm__Parking_Spaces__c);
System.debug('Offering Type: ' + firstProp.pcrm__Offering_Type__c);
System.debug('Private Amenities: ' + firstProp.Private_Amenities__c);
}
return properties;
@ -89,7 +87,6 @@ public with sharing class PropertyDataController {
'pcrm__Sub_Community_Propertyfinder__c, pcrm__Property_Name_Propertyfinder__c, ' +
'pcrm__City_Propertyfinder__c, ' +
'pcrm__Rent_Available_From__c, pcrm__Rent_Available_To__c, ' +
'Private_Amenities__c, ' +
'Contact__c, Contact__r.FirstName, Contact__r.LastName, Contact__r.Email, Contact__r.Phone, ' +
'Email__c, Phone__c, ' +
'CreatedBy.Name, LastModifiedBy.Name, Owner.Name, ' +
@ -120,7 +117,6 @@ public with sharing class PropertyDataController {
System.debug('Build Year: ' + property.pcrm__Build_Year__c);
System.debug('Parking Spaces: ' + property.pcrm__Parking_Spaces__c);
System.debug('Offering Type: ' + property.pcrm__Offering_Type__c);
System.debug('Private Amenities: ' + property.Private_Amenities__c);
}
return property;
@ -179,142 +175,4 @@ public with sharing class PropertyDataController {
throw new AuraHandledException('Failed to fetch property images: ' + e.getMessage());
}
}
@AuraEnabled(cacheable=true)
public static User getAgentData(String propertyId) {
try {
System.debug('=== FETCHING AGENT DATA FOR PROPERTY ===');
System.debug('Property ID: ' + propertyId);
// First, get the property to find the related agent/owner
pcrm__Property__c property = [
SELECT Id, OwnerId, CreatedById, LastModifiedById, Contact__c, Contact__r.OwnerId
FROM pcrm__Property__c
WHERE Id = :propertyId
LIMIT 1
];
if (property == null) {
System.debug('Property not found for ID: ' + propertyId);
return null;
}
// Try to get agent data from different sources in priority order
User agentUser = null;
// Priority 1: Contact's owner (if contact exists)
if (property.Contact__c != null && property.Contact__r.OwnerId != null) {
try {
agentUser = [
SELECT Id, Name, FirstName, LastName, Email, Phone, MobilePhone,
Title, Department, CompanyName, SmallPhotoUrl, FullPhotoUrl,
Profile.Name, UserRole.Name
FROM User
WHERE Id = :property.Contact__r.OwnerId
AND IsActive = true
LIMIT 1
];
System.debug('Found agent from Contact Owner: ' + agentUser?.Name);
} catch (Exception e) {
System.debug('Error fetching Contact Owner: ' + e.getMessage());
}
}
// Priority 2: Property Owner (if not found above)
if (agentUser == null && property.OwnerId != null) {
try {
agentUser = [
SELECT Id, Name, FirstName, LastName, Email, Phone, MobilePhone,
Title, Department, CompanyName, SmallPhotoUrl, FullPhotoUrl,
Profile.Name, UserRole.Name
FROM User
WHERE Id = :property.OwnerId
AND IsActive = true
LIMIT 1
];
System.debug('Found agent from Property Owner: ' + agentUser?.Name);
} catch (Exception e) {
System.debug('Error fetching Property Owner: ' + e.getMessage());
}
}
// Priority 3: Property Creator (if not found above)
if (agentUser == null && property.CreatedById != null) {
try {
agentUser = [
SELECT Id, Name, FirstName, LastName, Email, Phone, MobilePhone,
Title, Department, CompanyName, SmallPhotoUrl, FullPhotoUrl,
Profile.Name, UserRole.Name
FROM User
WHERE Id = :property.CreatedById
AND IsActive = true
LIMIT 1
];
System.debug('Found agent from Property Creator: ' + agentUser?.Name);
} catch (Exception e) {
System.debug('Error fetching Property Creator: ' + e.getMessage());
}
}
if (agentUser != null) {
System.debug('=== AGENT DATA FETCHED ===');
System.debug('Agent Name: ' + agentUser.Name);
System.debug('Agent Email: ' + agentUser.Email);
System.debug('Agent Phone: ' + agentUser.Phone);
System.debug('Agent Title: ' + agentUser.Title);
System.debug('Agent Department: ' + agentUser.Department);
} else {
System.debug('No agent found for property: ' + propertyId);
}
return agentUser;
} catch (Exception e) {
System.debug('Error fetching agent data: ' + e.getMessage());
System.debug('Stack trace: ' + e.getStackTraceString());
throw new AuraHandledException('Failed to fetch agent data: ' + e.getMessage());
}
}
@AuraEnabled(cacheable=true)
public static pcrm__Listing__c getListingData(String propertyId) {
try {
System.debug('=== FETCHING LISTING DATA BY PROPERTY ===');
System.debug('Property ID: ' + propertyId);
// Query listing with related property and agent data using property ID
String query = 'SELECT Id, Name, ' +
'Property__r.Id, Property__r.Name, ' +
'Listing_Agent__r.Id, Listing_Agent__r.Name, Listing_Agent__r.Email, Listing_Agent__r.Phone, Listing_Agent__r.Title, ' +
'Select_Agent__r.Id, Select_Agent__r.Name, Select_Agent__r.Email, Select_Agent__r.Phone, Select_Agent__r.Title ' +
'FROM pcrm__Listing__c ' +
'WHERE Property__c = :propertyId ' +
'ORDER BY CreatedDate DESC LIMIT 1';
List<pcrm__Listing__c> listings = Database.query(query);
pcrm__Listing__c listing = listings.isEmpty() ? null : listings[0];
if (listing != null) {
System.debug('=== LISTING DATA FETCHED ===');
System.debug('Listing Name: ' + listing.Name);
System.debug('Property ID: ' + listing.Property__r?.Id);
System.debug('Property Name: ' + listing.Property__r?.Name);
System.debug('Listing Agent ID: ' + listing.Listing_Agent__r?.Id);
System.debug('Listing Agent Name: ' + listing.Listing_Agent__r?.Name);
System.debug('Listing Agent Email: ' + listing.Listing_Agent__r?.Email);
System.debug('Listing Agent Phone: ' + listing.Listing_Agent__r?.Phone);
System.debug('Select Agent ID: ' + listing.Select_Agent__r?.Id);
System.debug('Select Agent Name: ' + listing.Select_Agent__r?.Name);
} else {
System.debug('No listing found for Property ID: ' + propertyId);
}
return listing;
} catch (Exception e) {
System.debug('Error fetching listing data: ' + e.getMessage());
System.debug('Stack trace: ' + e.getStackTraceString());
throw new AuraHandledException('Failed to fetch listing data: ' + e.getMessage());
}
}
}

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<CspTrustedSite xmlns="http://soap.sforce.com/2006/04/metadata">
<context>Communities</context>
<description>Font Awesome CDN Trusted Site</description>
<endpointUrl>https://cdnjs.cloudflare.com</endpointUrl>
<isActive>true</isActive>
</CspTrustedSite>

View File

@ -5,12 +5,10 @@
width: 100vw;
height: 100vh;
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
z-index: 99999;
z-index: 9999;
overflow-y: auto;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: #ffffff;
display: flex;
flex-direction: column;
}
.dev-header {
@ -48,69 +46,30 @@
letter-spacing: 1px;
}
.dev-exit-section {
margin-top: 20px;
padding: 15px;
background: rgba(255, 255, 255, 0.05);
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.dev-input {
width: 100%;
max-width: 200px;
padding: 8px 12px;
margin: 0 auto;
display: block;
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 4px;
background: rgba(255, 255, 255, 0.1);
color: #fff;
font-size: 0.9rem;
font-weight: 400;
text-align: center;
letter-spacing: 1px;
outline: none;
transition: all 0.3s ease;
}
.dev-input:focus {
border-color: rgba(255, 255, 255, 0.6);
background: rgba(255, 255, 255, 0.15);
box-shadow: 0 0 5px rgba(255, 255, 255, 0.2);
}
.dev-input::placeholder {
color: rgba(255, 255, 255, 0.5);
font-style: normal;
}
.dev-close-btn {
margin-top: 10px;
padding: 8px 16px;
background: #ff6b6b;
.close-dev-btn {
position: absolute;
top: 20px;
right: 20px;
background: #ff4757;
color: white;
border: none;
border-radius: 4px;
border-radius: 50%;
width: 40px;
height: 40px;
font-size: 1.5rem;
cursor: pointer;
font-size: 0.9rem;
font-weight: 600;
transition: all 0.3s ease;
}
.dev-close-btn:hover {
background: #ff5252;
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
.close-dev-btn:hover {
background: #ff3742;
transform: scale(1.1);
}
.dev-content {
padding: 30px;
max-width: 1200px;
margin: 0 auto;
flex: 1;
overflow-y: auto;
}
.dev-section {

View File

@ -3,17 +3,6 @@
<div class="dev-header">
<h1>🚧 Development Area 🚧</h1>
<p class="dev-warning">UNDER DEVELOPMENT - DO NOT TEST</p>
<div class="dev-exit-section">
<input
type="text"
class="dev-input"
value={tbizzInput}
onchange={handleTbizzInputChange}
onkeydown={handleKeyPress}
placeholder="Enter 'bweixx' to show/hide dev mode"
/>
<button class="dev-close-btn" onclick={hideDevPage}>✕ Close</button>
</div>
</div>
<div class="dev-content">

View File

@ -1,18 +1,17 @@
import { LightningElement, track } from 'lwc';
export default class DevelopmentPage extends LightningElement {
@track showDevPage = false; // Hidden by default, can be shown by entering bweixx
@track showDevPage = false;
@track currentStep = 1;
@track selectedTemplateId = '';
@track selectedPropertyId = '';
@track selectedPageSize = 'A4';
@track currentTimestamp = '';
@track debugMode = false;
@track tbizzInput = ''; // Input field value for tbizz
// tbizz sequence detection for opening development mode
tbizzSequence = '';
tbizzTimeout = null;
// V-key click counter
vKeyCount = 0;
vKeyTimeout = null;
connectedCallback() {
this.updateTimestamp();
@ -21,8 +20,8 @@ export default class DevelopmentPage extends LightningElement {
disconnectedCallback() {
this.removeKeyListener();
if (this.tbizzTimeout) {
clearTimeout(this.tbizzTimeout);
if (this.vKeyTimeout) {
clearTimeout(this.vKeyTimeout);
}
}
@ -35,23 +34,34 @@ export default class DevelopmentPage extends LightningElement {
}
handleKeyPress(event) {
// Listen for Enter key to check bweixx input
if (event.key === 'Enter') {
if (this.tbizzInput.toLowerCase() === 'bweixx') {
this.showDevPage = true; // Show development page when bweixx is entered
this.tbizzInput = ''; // Clear input
// Only listen for 'V' key (case insensitive)
if (event.key.toLowerCase() === 'v') {
this.vKeyCount++;
// Clear any existing timeout
if (this.vKeyTimeout) {
clearTimeout(this.vKeyTimeout);
}
// Reset counter after 3 seconds of inactivity
this.vKeyTimeout = setTimeout(() => {
this.vKeyCount = 0;
}, 3000);
// Hide dev page after 4 V key presses
if (this.vKeyCount >= 4) {
this.showDevPage = false;
this.vKeyCount = 0; // Reset counter
}
}
}
// Handle input field changes
handleTbizzInputChange(event) {
this.tbizzInput = event.target.value;
}
// Hide development page
hideDevPage() {
closeDevPage() {
this.showDevPage = false;
this.vKeyCount = 0;
if (this.vKeyTimeout) {
clearTimeout(this.vKeyTimeout);
}
}
updateTimestamp() {

File diff suppressed because one or more lines are too long

View File

@ -143,30 +143,6 @@
<div class="gallery-item g-item-4" style="background-image:url('https://images.unsplash.com/photo-1595526114035-0d45ed16433d?auto=format&fit=crop&w=800&q=80');"><span>Bathroom</span></div>
</div>
</section>
<!-- Draggable Gallery Section -->
<template if:true={realPropertyImages}>
<section class="draggable-gallery-section">
<h2 class="gallery-title">Drag to Reorder Images</h2>
<div class="gallery-grid">
<template for:each={realPropertyImages} for:item="img" for:index="index">
<div key={img.Id} class="draggable-gallery-item"
draggable="true"
data-index={index}
ondragstart={handleDragStart}
ondragend={handleDragEnd}
ondragover={handleDragOver}
ondragleave={handleDragLeave}
ondrop={handleDrop}>
<img src={img.url} alt={img.title} />
<div class="drag-handle">
<i class="fa-solid fa-grip-vertical"></i>
</div>
</div>
</template>
</div>
</section>
</template>
<div class="agent-footer">
<div class="agent-info">
@ -464,54 +440,15 @@
<div class="property-selector">
<label for="propertySelect">Property:</label>
<!-- Simple Searchable Dropdown -->
<div class="simple-dropdown-container">
<!-- Search Input -->
<div class="simple-search-container">
<input
type="text"
placeholder="Search..."
value={propertySearchTerm}
oninput={handlePropertySearch}
class="simple-search-input"
/>
</div>
<!-- Property Options List -->
<div class="simple-options-container">
<!-- Selected Property at Top -->
<template if:true={selectedProperty}>
<div class="simple-option selected-at-top"
data-value={selectedProperty.Id}
data-selected="true"
onclick={handlePropertySelection}>
✓ {selectedProperty.Name} - {selectedProperty.pcrm__Title_English__c} - {selectedProperty.pcrm__Property_Type__c} - {selectedProperty.pcrm__City_Bayut_Dubizzle__c}
</div>
<div class="separator-line"></div>
</template>
<!-- Default Option -->
<template if:false={selectedProperty}>
<div class="simple-option" data-value="" onclick={handlePropertySelection}>
-- Select a Property --
</div>
</template>
<!-- Other Properties -->
<template for:each={filteredPropertiesWithSelected} for:item="property">
<template if:false={property._selected}>
<div key={property.Id}
class="simple-option"
data-value={property.Id}
data-selected="false"
onclick={handlePropertySelection}>
{property.Name} - {property.pcrm__Title_English__c} - {property.pcrm__Property_Type__c} - {property.pcrm__City_Bayut_Dubizzle__c}
</div>
</template>
</template>
</div>
</div>
<select id="propertySelect" value={selectedPropertyId} onchange={handlePropertySelection}>
<option value="">-- Select a Property --</option>
<template for:each={propertiesWithSelected} for:item="property">
<option key={property.Id} value={property.Id} selected={property._selected}>
{property.Name} - {property.pcrm__Title_English__c} - {property.pcrm__Property_Type__c} -
{property.pcrm__City_Bayut_Dubizzle__c}
</option>
</template>
</select>
</div>
</div>
@ -561,73 +498,9 @@
</div>
</div>
<!-- Row 1.5: Pricing Information Options -->
<div class="step2-grid-row-1-5">
<div class="pricing-information-section">
<h3>Pricing Information Options</h3>
<p>Select which pricing fields to include in your report</p>
<!-- Price Display Toggle -->
<div class="price-display-toggle">
<label class="checkbox-item price-toggle-item">
<input type="checkbox" name="showPrice" checked={showPrice} onchange={handlePriceToggleChange}>
<span class="checkmark price-toggle-checkmark"></span>
<div class="price-toggle-content">
<span class="price-toggle-label">Show Actual Price</span>
<span class="price-toggle-description">Uncheck to show "Price on Request" instead</span>
</div>
</label>
</div>
<div class="pricing-options">
<label class="checkbox-item pricing-checkbox-item">
<input type="checkbox" name="includeRentPriceMin"
checked={pricingSelection.includeRentPriceMin} onchange={handlePricingSelectionChange}>
<span class="checkmark pricing-checkmark"></span>
<div class="pricing-label-content">
<span class="pricing-title">Rent Price (Min)</span>
<span class="pricing-value">{propertyData.rentPriceMin}</span>
</div>
</label>
<label class="checkbox-item pricing-checkbox-item">
<input type="checkbox" name="includeRentPriceMax"
checked={pricingSelection.includeRentPriceMax} onchange={handlePricingSelectionChange}>
<span class="checkmark pricing-checkmark"></span>
<div class="pricing-label-content">
<span class="pricing-title">Rent Price (Max)</span>
<span class="pricing-value">{propertyData.rentPriceMax}</span>
</div>
</label>
<label class="checkbox-item pricing-checkbox-item">
<input type="checkbox" name="includeSalePriceMin"
checked={pricingSelection.includeSalePriceMin} onchange={handlePricingSelectionChange}>
<span class="checkmark pricing-checkmark"></span>
<div class="pricing-label-content">
<span class="pricing-title">Sale Price (Min)</span>
<span class="pricing-value">{propertyData.salePriceMin}</span>
</div>
</label>
<label class="checkbox-item pricing-checkbox-item">
<input type="checkbox" name="includeSalePriceMax"
checked={pricingSelection.includeSalePriceMax} onchange={handlePricingSelectionChange}>
<span class="checkmark pricing-checkmark"></span>
<div class="pricing-label-content">
<span class="pricing-title">Sale Price (Max)</span>
<span class="pricing-value">{propertyData.salePriceMax}</span>
</div>
</label>
</div>
</div>
</div>
<!-- Row 3: Property Details Display - Full Width -->
<!-- Row 2: Property Details Display - Full Width -->
<template if:true={selectedPropertyId}>
<div class="step2-grid-row-3">
<div class="step2-grid-row-2">
<div class="property-details-layout">
<h3>Property Details Preview</h3>
@ -672,33 +545,6 @@
</div>
</div>
</div>
<!-- Agent Information -->
<div class="property-section-group agent-details-section">
<h5>Agent Information</h5>
<div class="property-grid">
<div class="property-field">
<span class="label">Agent Name:</span>
<span class="value">{agentData.name}</span>
</div>
<div class="property-field">
<span class="label">Agent Email:</span>
<span class="value">{agentData.email}</span>
</div>
<div class="property-field">
<span class="label">Agent Phone:</span>
<span class="value">{agentData.phone}</span>
</div>
<div class="property-field">
<span class="label">Agent Title:</span>
<span class="value">{agentData.title}</span>
</div>
<div class="property-field">
<span class="label">Company:</span>
<span class="value">{agentData.company}</span>
</div>
</div>
</div>
</div>
<!-- Right Top Rectangle: Specifications + Pricing -->
@ -730,6 +576,28 @@
</div>
</div>
<!-- Pricing Information -->
<div class="property-section-group pricing-section">
<h5>Pricing Information</h5>
<div class="property-grid">
<div class="property-field">
<span class="label">Rent Price (Min):</span>
<span class="value">{propertyData.rentPriceMin}</span>
</div>
<div class="property-field">
<span class="label">Rent Price (Max):</span>
<span class="value">{propertyData.rentPriceMax}</span>
</div>
<div class="property-field">
<span class="label">Sale Price (Min):</span>
<span class="value">{propertyData.salePriceMin}</span>
</div>
<div class="property-field">
<span class="label">Sale Price (Max):</span>
<span class="value">{propertyData.salePriceMax}</span>
</div>
</div>
</div>
</div>
</div>
@ -801,17 +669,6 @@
<span class="value">{propertyData.offeringType}</span>
</div>
</div>
<!-- Private Amenities -->
<template if:true={propertyData.privateAmenities}>
<div class="amenities-list">
<span class="label">Private Amenities:</span>
<div class="amenities-display">
<template for:each={propertyAmenitiesList} for:item="amenity">
<span key={amenity} class="amenity-tag">{amenity}</span>
</template>
</div>
</div>
</template>
</div>
<!-- Rent Availability -->
@ -957,7 +814,6 @@
</button>
</div>
</div>
</template>
</div>
@ -990,71 +846,37 @@
<div class="toolbar-section">
<div class="toolbar-section-title">Insert Property Data</div>
<div class="property-insert-grid">
<!-- Basic Information -->
<button class="property-insert-btn" onclick={insertPropertyName}
title="Insert Property Name">
Name
</button>
<button class="property-insert-btn" onclick={insertPropertyTitle}
title="Insert Property Title">
Title
<button class="property-insert-btn" onclick={insertPropertyPrice}
title="Insert Property Price">
Price
</button>
<button class="property-insert-btn" onclick={insertPropertyType}
title="Insert Property Type">
Type
</button>
<button class="property-insert-btn" onclick={insertPropertyBedrooms}
title="Insert Bedrooms">
Beds
</button>
<button class="property-insert-btn" onclick={insertPropertyBathrooms}
title="Insert Bathrooms">
Baths
</button>
<button class="property-insert-btn" onclick={insertPropertySqft}
title="Insert Square Footage">
Sq Ft
</button>
<button class="property-insert-btn" onclick={insertProplsertyFloor}
title="Insert Floor">
Floor
<button class="property-insert-btn" onclick={insertPropertyAddress} title="Insert Address">
Address
</button>
<button class="property-insert-btn" onclick={insertPropertyBuildYear}
title="Insert Build Year">
Year
<button class="property-insert-btn" onclick={insertPropertyDescription}
title="Insert Description">
Description
</button>
<button class="property-insert-btn" onclick={insertPropertyParking}
title="Insert Parking">
Parking
</button>
<button class="property-insert-btn" onclick={insertPropertyFurnished}
title="Insert Furnished Status">
Furnished
</button>
<button class="property-insert-btn" onclick={insertPropertyOfferingType}
title="Insert Offering Type">
Offering
</button>
<!-- Location Information -->
<button class="property-insert-btn" onclick={insertPropertyCity}
title="Insert City">
City
</button>
<button class="property-insert-btn" onclick={insertPropertyContactEmail}
title="Insert Contact Email">
Email
</button>
<button class="property-insert-btn" onclick={insertPropertyContactPhone}
title="Insert Contact Phone">
Phone
</button>
</div>
</div>
@ -1180,12 +1002,12 @@
<button class="toolbar-button" onclick={handleBulletList}>
<lightning-icon icon-name="utility:bullet_list"
size="x-small"></lightning-icon>
Bullet
Bullet(*)
</button>
<button class="toolbar-button" onclick={handleNumberList}>
<lightning-icon icon-name="utility:numbered_list"
size="x-small"></lightning-icon>
Number
Number(1)
</button>
<button class="toolbar-button" onclick={handleIndent}>
<lightning-icon icon-name="utility:indent" size="x-small"></lightning-icon>
@ -1211,12 +1033,6 @@
Image
</button>
</div>
<!-- <div class="toolbar-group">
<button class="toolbar-button" onclick={addNewPageWithDataType} disabled>
<lightning-icon icon-name="utility:page" size="x-small"></lightning-icon>
Add Page
</button>
</div> -->
<div class="toolbar-group">
<button class="toolbar-button" onclick={toggleSelectorMode}>
<lightning-icon icon-name="utility:target" size="x-small"></lightning-icon>
@ -1249,6 +1065,8 @@
</div>
</div> <!-- Close enhanced-toolbar-scroll -->
</div>
</div>
@ -1260,42 +1078,40 @@
<div class="editor-right">
<!-- Page Size and PDF Generation Header -->
<div class="template-header-area">
<!-- All buttons in a single line -->
<div class="header-controls-line">
<!-- Back Button -->
<!-- New Back Button -->
<div class="header-left-actions">
<button class="btn btn-secondary" onclick={previousStep} title="Back">
← Back
</button>
<!-- Page Size Options -->
<div class="page-size-group">
<label class="page-size-label">Page Size:</label>
<div class="page-size-options">
<label class="page-size-option">
<input type="radio" name="pageSize" value="A4" checked
onchange={handlePageSizeChange}>
<span class="page-size-text">A4</span>
</label>
<!-- <label class="page-size-option">
<input type="radio" name="pageSize" value="A3" onchange={handlePageSizeChange}>
<span class="page-size-text">A3</span>
</label> -->
</div>
</div>
<!-- Page Size Options -->
<div class="page-size-section">
<label class="page-size-label">Page Size:</label>
<div class="page-size-options">
<label class="page-size-option">
<input type="radio" name="pageSize" value="A4" checked
onchange={handlePageSizeChange}>
<span class="page-size-text">A4</span>
</label>
<label class="page-size-option">
<input type="radio" name="pageSize" value="A3" onchange={handlePageSizeChange}>
<span class="page-size-text">A3</span>
</label>
</div>
<!-- Generate PDF Button -->
<template if:true={showGeneratePdfButton}>
<button class="btn btn-primary generate-pdf-btn" onclick={generatePdfSimple} disabled={isGeneratingPdf}>
<template if:false={isGeneratingPdf}>
<span class="btn-icon">📄</span>
Generate PDF
</template>
<template if:true={isGeneratingPdf}>
<span class="loading-spinner"></span>
Wait, our AI is generating the report...
</template>
</button>
</template>
</div>
<!-- Generate PDF Button -->
<div class="generate-pdf-section">
<button class="btn btn-primary generate-pdf-btn" onclick={generatePdfSimple} disabled={isGeneratingPdf}>
<template if:false={isGeneratingPdf}>
<span class="btn-icon">📄</span>
Generate PDF
</template>
<template if:true={isGeneratingPdf}>
<span class="loading-spinner"></span>
Wait, our AI is generating the report...
</template>
</button>
</div>
</div>
@ -1308,13 +1124,22 @@
<template if:true={previewPages}>
<template for:each={previewPages} for:item="page" for:index="pageIndex">
<div key={page.id} class="preview-page" data-page-size={selectedPageSize} data-page-number={pageIndex}>
<div class="enhanced-editor-content" contenteditable="true" onkeyup={handleContentChangeWithDynamicSizing}
onpaste={handleContentChangeWithDynamicSizing} ondragover={handleEditorDragOver} ondrop={handleEditorDrop}>
<div class="enhanced-editor-content" contenteditable="true" onkeyup={handleContentChange}
onpaste={handleContentChange} ondragover={handleEditorDragOver} ondrop={handleEditorDrop}>
{page.content}
</div>
</div>
</template>
</template>
<template if:false={previewPages}>
<div class="preview-page" data-page-size={selectedPageSize} data-page-number="1">
<div class="enhanced-editor-content" contenteditable="true" onkeyup={handleContentChange}
onpaste={handleContentChange} ondragover={handleEditorDragOver} ondrop={handleEditorDrop}>
<!-- Template content will be loaded here -->
{htmlContent}
</div>
</div>
</template>
</div>
<template if:false={hasPropertyImages}>
<div class="floating-placeholder" data-preview-only="true" style="position: absolute; bottom: 12px; left: 12px; display: flex; align-items: center; gap: 8px; z-index: 2000; pointer-events: none;">
@ -1332,7 +1157,6 @@
<!-- Image Review Modal -->
<div if:true={showImageReview} class="image-review-overlay">
<div class="image-review-modal">
@ -1468,7 +1292,6 @@
<!-- Action Buttons -->
<div class="image-replacement-actions">
<button class="btn btn-secondary" onclick={closeImageReplacement}>Cancel</button>
<button class="btn btn-primary" onclick={insertSelectedReplacementImage}>Insert Image</button>
</div>
</div>
</div>
@ -1567,99 +1390,4 @@
</div>
</div>
</div>
<!-- New Section Modal -->
<div if:true={showNewSectionModal} class="new-section-modal-overlay">
<div class="new-section-modal">
<div class="new-section-modal-header">
<h3>Add New Section</h3>
<button class="close-btn" onclick={closeNewSectionModal}></button>
</div>
<div class="new-section-modal-content">
<div class="section-type-selection">
<h4>Choose Section Type:</h4>
<div class="section-type-grid">
<div class="section-type-option" onclick={selectSectionType} data-type="text">
<div class="section-type-icon">📝</div>
<div class="section-type-title">Text Section</div>
<div class="section-type-description">Add a text-based section with title and content</div>
</div>
<div class="section-type-option" onclick={selectSectionType} data-type="image">
<div class="section-type-icon">🖼️</div>
<div class="section-type-title">Image Gallery</div>
<div class="section-type-description">Add an image gallery section</div>
</div>
<div class="section-type-option" onclick={selectSectionType} data-type="features">
<div class="section-type-icon"></div>
<div class="section-type-title">Features List</div>
<div class="section-type-description">Add a features and amenities section</div>
</div>
<div class="section-type-option" onclick={selectSectionType} data-type="contact">
<div class="section-type-icon">📞</div>
<div class="section-type-title">Contact Info</div>
<div class="section-type-description">Add contact information section</div>
</div>
</div>
</div>
<div if:true={selectedSectionType} class="section-configuration">
<h4>Section Configuration:</h4>
<div class="form-group">
<label>Section Title:</label>
<input type="text" class="form-input" value={newSectionTitle} onchange={handleSectionTitleChange} placeholder="Enter section title">
</div>
<div if:true={showSectionContentInput} class="form-group">
<label>Section Content:</label>
<textarea class="form-textarea" value={newSectionContent} onchange={handleSectionContentChange} placeholder="Enter section content"></textarea>
</div>
</div>
</div>
<div class="new-section-modal-actions">
<button class="btn btn-secondary" onclick={closeNewSectionModal}>Cancel</button>
</div>
</div>
</div>
<!-- Data Type Selection Modal -->
<div if:true={showDataTypeModal} class="data-type-modal-overlay" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.6); z-index: 9999; display: flex; align-items: center; justify-content: center; animation: fadeIn 0.3s ease-out;">
<div class="data-type-modal" style="background: white; border-radius: 16px; box-shadow: 0 20px 60px rgba(0,0,0,0.4); max-width: 700px; width: 90%; max-height: 85vh; overflow-y: auto; position: relative; animation: slideIn 0.3s ease-out; border: 1px solid #e0e0e0;">
<div class="data-type-modal-header" style="padding: 24px 24px 16px 24px; border-bottom: 1px solid #e0e0e0; display: flex; justify-content: space-between; align-items: center;">
<h3 style="margin: 0; font-size: 24px; font-weight: 600; color: #333;">Select Page Type</h3>
<button class="close-btn" onclick={closeDataTypeModal} style="background: none; border: none; font-size: 24px; color: #666; cursor: pointer; padding: 4px; border-radius: 4px; transition: all 0.2s;"></button>
</div>
<div class="data-type-modal-content" style="padding: 24px;">
<div class="data-type-grid" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 16px;">
<div class="data-type-option" onclick={handleDataTypeSelection} data-type="text" style="border: 2px solid #e0e0e0; border-radius: 12px; padding: 20px; cursor: pointer; transition: all 0.3s ease; background: #fafafa; hover:border-color: #007bff; hover:background: #f0f8ff;">
<div class="data-type-icon" style="font-size: 32px; margin-bottom: 12px;">📝</div>
<div class="data-type-title" style="font-size: 18px; font-weight: 600; color: #333; margin-bottom: 8px;">Text Page</div>
<div class="data-type-description" style="font-size: 14px; color: #666; line-height: 1.4;">Add a text-focused page for detailed content</div>
</div>
<div class="data-type-option" onclick={handleDataTypeSelection} data-type="gallery" style="border: 2px solid #e0e0e0; border-radius: 12px; padding: 20px; cursor: pointer; transition: all 0.3s ease; background: #fafafa; hover:border-color: #007bff; hover:background: #f0f8ff;">
<div class="data-type-icon" style="font-size: 32px; margin-bottom: 12px;">🖼️</div>
<div class="data-type-title" style="font-size: 18px; font-weight: 600; color: #333; margin-bottom: 8px;">Gallery Page</div>
<div class="data-type-description" style="font-size: 14px; color: #666; line-height: 1.4;">Add an image gallery page</div>
</div>
<div class="data-type-option" onclick={handleDataTypeSelection} data-type="features" style="border: 2px solid #e0e0e0; border-radius: 12px; padding: 20px; cursor: pointer; transition: all 0.3s ease; background: #fafafa; hover:border-color: #007bff; hover:background: #f0f8ff;">
<div class="data-type-icon" style="font-size: 32px; margin-bottom: 12px;"></div>
<div class="data-type-title" style="font-size: 18px; font-weight: 600; color: #333; margin-bottom: 8px;">Features Page</div>
<div class="data-type-description" style="font-size: 14px; color: #666; line-height: 1.4;">Add a features and amenities page</div>
</div>
<div class="data-type-option" onclick={handleDataTypeSelection} data-type="contact" style="border: 2px solid #e0e0e0; border-radius: 12px; padding: 20px; cursor: pointer; transition: all 0.3s ease; background: #fafafa; hover:border-color: #007bff; hover:background: #f0f8ff;">
<div class="data-type-icon" style="font-size: 32px; margin-bottom: 12px;">📞</div>
<div class="data-type-title" style="font-size: 18px; font-weight: 600; color: #333; margin-bottom: 8px;">Contact Page</div>
<div class="data-type-description" style="font-size: 14px; color: #666; line-height: 1.4;">Add a contact information page</div>
</div>
<div class="data-type-option" onclick={handleDataTypeSelection} data-type="blank" style="border: 2px solid #e0e0e0; border-radius: 12px; padding: 20px; cursor: pointer; transition: all 0.3s ease; background: #fafafa; hover:border-color: #007bff; hover:background: #f0f8ff;">
<div class="data-type-icon" style="font-size: 32px; margin-bottom: 12px;">📄</div>
<div class="data-type-title" style="font-size: 18px; font-weight: 600; color: #333; margin-bottom: 8px;">Blank Page</div>
<div class="data-type-description" style="font-size: 14px; color: #666; line-height: 1.4;">Add a blank page for custom content</div>
</div>
</div>
</div>
<div class="data-type-modal-actions" style="padding: 16px 24px 24px 24px; border-top: 1px solid #e0e0e0; display: flex; justify-content: flex-end; gap: 12px;">
<button class="btn btn-secondary" onclick={closeDataTypeModal} style="padding: 10px 20px; border: 1px solid #ccc; background: white; color: #333; border-radius: 6px; cursor: pointer; font-size: 14px; font-weight: 500;">Cancel</button>
<button class="btn btn-primary" onclick={addPageWithSelectedDataType} disabled={selectedDataTypeDisabled} style="padding: 10px 20px; border: none; background: #007bff; color: white; border-radius: 6px; cursor: pointer; font-size: 14px; font-weight: 500;">Add Page</button>
</div>
</div>
</div>
</template>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<StaticResource xmlns="http://soap.sforce.com/2006/04/metadata">
<cacheControl>Public</cacheControl>
<contentType>image/svg+xml</contentType>
</StaticResource>

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<StaticResource xmlns="http://soap.sforce.com/2006/04/metadata">
<cacheControl>Public</cacheControl>
<contentType>image/svg+xml</contentType>
</StaticResource>

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB