Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 17a89486e0 | |||
| eab0d41a64 | |||
| 0c721ef7ed | |||
| c978c48fb6 | |||
| 8b183d96be | |||
| 55c207b3cf | |||
|
|
1e9dda64a6 | ||
|
|
82ef064e5e | ||
|
|
3cb9090248 | ||
|
|
9a33862445 | ||
|
|
2bb4747426 | ||
|
|
9bb7f6a727 |
18473
backup_propertyTemplateSelector.js
Normal file
18473
backup_propertyTemplateSelector.js
Normal file
File diff suppressed because one or more lines are too long
@ -20,6 +20,7 @@ public with sharing class PropertyDataController {
|
|||||||
'pcrm__Sub_Community_Propertyfinder__c, pcrm__Property_Name_Propertyfinder__c, ' +
|
'pcrm__Sub_Community_Propertyfinder__c, pcrm__Property_Name_Propertyfinder__c, ' +
|
||||||
'pcrm__City_Propertyfinder__c, ' +
|
'pcrm__City_Propertyfinder__c, ' +
|
||||||
'pcrm__Rent_Available_From__c, pcrm__Rent_Available_To__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, ' +
|
'Contact__c, Contact__r.FirstName, Contact__r.LastName, Contact__r.Email, Contact__r.Phone, ' +
|
||||||
'Email__c, Phone__c, ' +
|
'Email__c, Phone__c, ' +
|
||||||
'CreatedBy.Name, LastModifiedBy.Name, Owner.Name, ' +
|
'CreatedBy.Name, LastModifiedBy.Name, Owner.Name, ' +
|
||||||
@ -55,6 +56,7 @@ public with sharing class PropertyDataController {
|
|||||||
System.debug('Build Year: ' + firstProp.pcrm__Build_Year__c);
|
System.debug('Build Year: ' + firstProp.pcrm__Build_Year__c);
|
||||||
System.debug('Parking Spaces: ' + firstProp.pcrm__Parking_Spaces__c);
|
System.debug('Parking Spaces: ' + firstProp.pcrm__Parking_Spaces__c);
|
||||||
System.debug('Offering Type: ' + firstProp.pcrm__Offering_Type__c);
|
System.debug('Offering Type: ' + firstProp.pcrm__Offering_Type__c);
|
||||||
|
System.debug('Private Amenities: ' + firstProp.Private_Amenities__c);
|
||||||
}
|
}
|
||||||
|
|
||||||
return properties;
|
return properties;
|
||||||
@ -87,6 +89,7 @@ public with sharing class PropertyDataController {
|
|||||||
'pcrm__Sub_Community_Propertyfinder__c, pcrm__Property_Name_Propertyfinder__c, ' +
|
'pcrm__Sub_Community_Propertyfinder__c, pcrm__Property_Name_Propertyfinder__c, ' +
|
||||||
'pcrm__City_Propertyfinder__c, ' +
|
'pcrm__City_Propertyfinder__c, ' +
|
||||||
'pcrm__Rent_Available_From__c, pcrm__Rent_Available_To__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, ' +
|
'Contact__c, Contact__r.FirstName, Contact__r.LastName, Contact__r.Email, Contact__r.Phone, ' +
|
||||||
'Email__c, Phone__c, ' +
|
'Email__c, Phone__c, ' +
|
||||||
'CreatedBy.Name, LastModifiedBy.Name, Owner.Name, ' +
|
'CreatedBy.Name, LastModifiedBy.Name, Owner.Name, ' +
|
||||||
@ -117,6 +120,7 @@ public with sharing class PropertyDataController {
|
|||||||
System.debug('Build Year: ' + property.pcrm__Build_Year__c);
|
System.debug('Build Year: ' + property.pcrm__Build_Year__c);
|
||||||
System.debug('Parking Spaces: ' + property.pcrm__Parking_Spaces__c);
|
System.debug('Parking Spaces: ' + property.pcrm__Parking_Spaces__c);
|
||||||
System.debug('Offering Type: ' + property.pcrm__Offering_Type__c);
|
System.debug('Offering Type: ' + property.pcrm__Offering_Type__c);
|
||||||
|
System.debug('Private Amenities: ' + property.Private_Amenities__c);
|
||||||
}
|
}
|
||||||
|
|
||||||
return property;
|
return property;
|
||||||
@ -175,4 +179,142 @@ public with sharing class PropertyDataController {
|
|||||||
throw new AuraHandledException('Failed to fetch property images: ' + e.getMessage());
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
<?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>
|
||||||
@ -5,10 +5,12 @@
|
|||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
|
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
|
||||||
z-index: 9999;
|
z-index: 99999;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dev-header {
|
.dev-header {
|
||||||
@ -46,30 +48,69 @@
|
|||||||
letter-spacing: 1px;
|
letter-spacing: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-dev-btn {
|
.dev-exit-section {
|
||||||
position: absolute;
|
margin-top: 20px;
|
||||||
top: 20px;
|
padding: 15px;
|
||||||
right: 20px;
|
background: rgba(255, 255, 255, 0.05);
|
||||||
background: #ff4757;
|
border-radius: 8px;
|
||||||
color: white;
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
border: none;
|
}
|
||||||
border-radius: 50%;
|
|
||||||
width: 40px;
|
.dev-input {
|
||||||
height: 40px;
|
width: 100%;
|
||||||
font-size: 1.5rem;
|
max-width: 200px;
|
||||||
cursor: pointer;
|
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;
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-dev-btn:hover {
|
.dev-input:focus {
|
||||||
background: #ff3742;
|
border-color: rgba(255, 255, 255, 0.6);
|
||||||
transform: scale(1.1);
|
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;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.dev-content {
|
.dev-content {
|
||||||
padding: 30px;
|
padding: 30px;
|
||||||
max-width: 1200px;
|
max-width: 1200px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dev-section {
|
.dev-section {
|
||||||
|
|||||||
@ -3,6 +3,17 @@
|
|||||||
<div class="dev-header">
|
<div class="dev-header">
|
||||||
<h1>🚧 Development Area 🚧</h1>
|
<h1>🚧 Development Area 🚧</h1>
|
||||||
<p class="dev-warning">UNDER DEVELOPMENT - DO NOT TEST</p>
|
<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>
|
||||||
|
|
||||||
<div class="dev-content">
|
<div class="dev-content">
|
||||||
|
|||||||
@ -1,17 +1,18 @@
|
|||||||
import { LightningElement, track } from 'lwc';
|
import { LightningElement, track } from 'lwc';
|
||||||
|
|
||||||
export default class DevelopmentPage extends LightningElement {
|
export default class DevelopmentPage extends LightningElement {
|
||||||
@track showDevPage = false;
|
@track showDevPage = false; // Hidden by default, can be shown by entering bweixx
|
||||||
@track currentStep = 1;
|
@track currentStep = 1;
|
||||||
@track selectedTemplateId = '';
|
@track selectedTemplateId = '';
|
||||||
@track selectedPropertyId = '';
|
@track selectedPropertyId = '';
|
||||||
@track selectedPageSize = 'A4';
|
@track selectedPageSize = 'A4';
|
||||||
@track currentTimestamp = '';
|
@track currentTimestamp = '';
|
||||||
@track debugMode = false;
|
@track debugMode = false;
|
||||||
|
@track tbizzInput = ''; // Input field value for tbizz
|
||||||
|
|
||||||
// V-key click counter
|
// tbizz sequence detection for opening development mode
|
||||||
vKeyCount = 0;
|
tbizzSequence = '';
|
||||||
vKeyTimeout = null;
|
tbizzTimeout = null;
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
this.updateTimestamp();
|
this.updateTimestamp();
|
||||||
@ -20,8 +21,8 @@ export default class DevelopmentPage extends LightningElement {
|
|||||||
|
|
||||||
disconnectedCallback() {
|
disconnectedCallback() {
|
||||||
this.removeKeyListener();
|
this.removeKeyListener();
|
||||||
if (this.vKeyTimeout) {
|
if (this.tbizzTimeout) {
|
||||||
clearTimeout(this.vKeyTimeout);
|
clearTimeout(this.tbizzTimeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,34 +35,23 @@ export default class DevelopmentPage extends LightningElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleKeyPress(event) {
|
handleKeyPress(event) {
|
||||||
// Only listen for 'V' key (case insensitive)
|
// Listen for Enter key to check bweixx input
|
||||||
if (event.key.toLowerCase() === 'v') {
|
if (event.key === 'Enter') {
|
||||||
this.vKeyCount++;
|
if (this.tbizzInput.toLowerCase() === 'bweixx') {
|
||||||
|
this.showDevPage = true; // Show development page when bweixx is entered
|
||||||
// Clear any existing timeout
|
this.tbizzInput = ''; // Clear input
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
closeDevPage() {
|
// Handle input field changes
|
||||||
|
handleTbizzInputChange(event) {
|
||||||
|
this.tbizzInput = event.target.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide development page
|
||||||
|
hideDevPage() {
|
||||||
this.showDevPage = false;
|
this.showDevPage = false;
|
||||||
this.vKeyCount = 0;
|
|
||||||
if (this.vKeyTimeout) {
|
|
||||||
clearTimeout(this.vKeyTimeout);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTimestamp() {
|
updateTimestamp() {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -143,6 +143,30 @@
|
|||||||
<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 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>
|
</div>
|
||||||
</section>
|
</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-footer">
|
||||||
<div class="agent-info">
|
<div class="agent-info">
|
||||||
@ -440,15 +464,54 @@
|
|||||||
|
|
||||||
<div class="property-selector">
|
<div class="property-selector">
|
||||||
<label for="propertySelect">Property:</label>
|
<label for="propertySelect">Property:</label>
|
||||||
<select id="propertySelect" value={selectedPropertyId} onchange={handlePropertySelection}>
|
|
||||||
<option value="">-- Select a Property --</option>
|
<!-- Simple Searchable Dropdown -->
|
||||||
<template for:each={propertiesWithSelected} for:item="property">
|
<div class="simple-dropdown-container">
|
||||||
<option key={property.Id} value={property.Id} selected={property._selected}>
|
<!-- Search Input -->
|
||||||
{property.Name} - {property.pcrm__Title_English__c} - {property.pcrm__Property_Type__c} -
|
<div class="simple-search-container">
|
||||||
{property.pcrm__City_Bayut_Dubizzle__c}
|
<input
|
||||||
</option>
|
type="text"
|
||||||
</template>
|
placeholder="Search..."
|
||||||
</select>
|
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>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -498,9 +561,73 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Row 2: Property Details Display - Full Width -->
|
<!-- 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 -->
|
||||||
<template if:true={selectedPropertyId}>
|
<template if:true={selectedPropertyId}>
|
||||||
<div class="step2-grid-row-2">
|
<div class="step2-grid-row-3">
|
||||||
<div class="property-details-layout">
|
<div class="property-details-layout">
|
||||||
<h3>Property Details Preview</h3>
|
<h3>Property Details Preview</h3>
|
||||||
|
|
||||||
@ -545,6 +672,33 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
|
|
||||||
<!-- Right Top Rectangle: Specifications + Pricing -->
|
<!-- Right Top Rectangle: Specifications + Pricing -->
|
||||||
@ -576,28 +730,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -669,6 +801,17 @@
|
|||||||
<span class="value">{propertyData.offeringType}</span>
|
<span class="value">{propertyData.offeringType}</span>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
</div>
|
||||||
|
|
||||||
<!-- Rent Availability -->
|
<!-- Rent Availability -->
|
||||||
@ -814,6 +957,7 @@
|
|||||||
→
|
→
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
@ -846,37 +990,71 @@
|
|||||||
<div class="toolbar-section">
|
<div class="toolbar-section">
|
||||||
<div class="toolbar-section-title">Insert Property Data</div>
|
<div class="toolbar-section-title">Insert Property Data</div>
|
||||||
<div class="property-insert-grid">
|
<div class="property-insert-grid">
|
||||||
|
<!-- Basic Information -->
|
||||||
<button class="property-insert-btn" onclick={insertPropertyName}
|
<button class="property-insert-btn" onclick={insertPropertyName}
|
||||||
title="Insert Property Name">
|
title="Insert Property Name">
|
||||||
Name
|
Name
|
||||||
</button>
|
</button>
|
||||||
<button class="property-insert-btn" onclick={insertPropertyPrice}
|
<button class="property-insert-btn" onclick={insertPropertyTitle}
|
||||||
title="Insert Property Price">
|
title="Insert Property Title">
|
||||||
Price
|
Title
|
||||||
</button>
|
</button>
|
||||||
<button class="property-insert-btn" onclick={insertPropertyType}
|
<button class="property-insert-btn" onclick={insertPropertyType}
|
||||||
title="Insert Property Type">
|
title="Insert Property Type">
|
||||||
Type
|
Type
|
||||||
</button>
|
</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}
|
<button class="property-insert-btn" onclick={insertPropertySqft}
|
||||||
title="Insert Square Footage">
|
title="Insert Square Footage">
|
||||||
Sq Ft
|
Sq Ft
|
||||||
</button>
|
</button>
|
||||||
<button class="property-insert-btn" onclick={insertPropertyAddress} title="Insert Address">
|
<button class="property-insert-btn" onclick={insertProplsertyFloor}
|
||||||
Address
|
title="Insert Floor">
|
||||||
|
Floor
|
||||||
</button>
|
</button>
|
||||||
<button class="property-insert-btn" onclick={insertPropertyDescription}
|
<button class="property-insert-btn" onclick={insertPropertyBuildYear}
|
||||||
title="Insert Description">
|
title="Insert Build Year">
|
||||||
Description
|
Year
|
||||||
</button>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -1002,12 +1180,12 @@
|
|||||||
<button class="toolbar-button" onclick={handleBulletList}>
|
<button class="toolbar-button" onclick={handleBulletList}>
|
||||||
<lightning-icon icon-name="utility:bullet_list"
|
<lightning-icon icon-name="utility:bullet_list"
|
||||||
size="x-small"></lightning-icon>
|
size="x-small"></lightning-icon>
|
||||||
Bullet(*)
|
Bullet
|
||||||
</button>
|
</button>
|
||||||
<button class="toolbar-button" onclick={handleNumberList}>
|
<button class="toolbar-button" onclick={handleNumberList}>
|
||||||
<lightning-icon icon-name="utility:numbered_list"
|
<lightning-icon icon-name="utility:numbered_list"
|
||||||
size="x-small"></lightning-icon>
|
size="x-small"></lightning-icon>
|
||||||
Number(1)
|
Number
|
||||||
</button>
|
</button>
|
||||||
<button class="toolbar-button" onclick={handleIndent}>
|
<button class="toolbar-button" onclick={handleIndent}>
|
||||||
<lightning-icon icon-name="utility:indent" size="x-small"></lightning-icon>
|
<lightning-icon icon-name="utility:indent" size="x-small"></lightning-icon>
|
||||||
@ -1033,6 +1211,12 @@
|
|||||||
Image
|
Image
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</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">
|
<div class="toolbar-group">
|
||||||
<button class="toolbar-button" onclick={toggleSelectorMode}>
|
<button class="toolbar-button" onclick={toggleSelectorMode}>
|
||||||
<lightning-icon icon-name="utility:target" size="x-small"></lightning-icon>
|
<lightning-icon icon-name="utility:target" size="x-small"></lightning-icon>
|
||||||
@ -1065,8 +1249,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div> <!-- Close enhanced-toolbar-scroll -->
|
</div> <!-- Close enhanced-toolbar-scroll -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1078,40 +1260,42 @@
|
|||||||
<div class="editor-right">
|
<div class="editor-right">
|
||||||
<!-- Page Size and PDF Generation Header -->
|
<!-- Page Size and PDF Generation Header -->
|
||||||
<div class="template-header-area">
|
<div class="template-header-area">
|
||||||
<!-- New Back Button -->
|
<!-- All buttons in a single line -->
|
||||||
<div class="header-left-actions">
|
<div class="header-controls-line">
|
||||||
|
<!-- Back Button -->
|
||||||
<button class="btn btn-secondary" onclick={previousStep} title="Back">
|
<button class="btn btn-secondary" onclick={previousStep} title="Back">
|
||||||
← Back
|
← Back
|
||||||
</button>
|
</button>
|
||||||
</div>
|
|
||||||
<!-- Page Size Options -->
|
<!-- Page Size Options -->
|
||||||
<div class="page-size-section">
|
<div class="page-size-group">
|
||||||
<label class="page-size-label">Page Size:</label>
|
<label class="page-size-label">Page Size:</label>
|
||||||
<div class="page-size-options">
|
<div class="page-size-options">
|
||||||
<label class="page-size-option">
|
<label class="page-size-option">
|
||||||
<input type="radio" name="pageSize" value="A4" checked
|
<input type="radio" name="pageSize" value="A4" checked
|
||||||
onchange={handlePageSizeChange}>
|
onchange={handlePageSizeChange}>
|
||||||
<span class="page-size-text">A4</span>
|
<span class="page-size-text">A4</span>
|
||||||
</label>
|
</label>
|
||||||
<label class="page-size-option">
|
<!-- <label class="page-size-option">
|
||||||
<input type="radio" name="pageSize" value="A3" onchange={handlePageSizeChange}>
|
<input type="radio" name="pageSize" value="A3" onchange={handlePageSizeChange}>
|
||||||
<span class="page-size-text">A3</span>
|
<span class="page-size-text">A3</span>
|
||||||
</label>
|
</label> -->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<!-- Generate PDF Button -->
|
||||||
<!-- Generate PDF Button -->
|
<template if:true={showGeneratePdfButton}>
|
||||||
<div class="generate-pdf-section">
|
<button class="btn btn-primary generate-pdf-btn" onclick={generatePdfSimple} disabled={isGeneratingPdf}>
|
||||||
<button class="btn btn-primary generate-pdf-btn" onclick={generatePdfSimple} disabled={isGeneratingPdf}>
|
<template if:false={isGeneratingPdf}>
|
||||||
<template if:false={isGeneratingPdf}>
|
<span class="btn-icon">📄</span>
|
||||||
<span class="btn-icon">📄</span>
|
Generate PDF
|
||||||
Generate PDF
|
</template>
|
||||||
</template>
|
<template if:true={isGeneratingPdf}>
|
||||||
<template if:true={isGeneratingPdf}>
|
<span class="loading-spinner"></span>
|
||||||
<span class="loading-spinner"></span>
|
Wait, our AI is generating the report...
|
||||||
Wait, our AI is generating the report...
|
</template>
|
||||||
</template>
|
</button>
|
||||||
</button>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -1124,22 +1308,13 @@
|
|||||||
<template if:true={previewPages}>
|
<template if:true={previewPages}>
|
||||||
<template for:each={previewPages} for:item="page" for:index="pageIndex">
|
<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 key={page.id} class="preview-page" data-page-size={selectedPageSize} data-page-number={pageIndex}>
|
||||||
<div class="enhanced-editor-content" contenteditable="true" onkeyup={handleContentChange}
|
<div class="enhanced-editor-content" contenteditable="true" onkeyup={handleContentChangeWithDynamicSizing}
|
||||||
onpaste={handleContentChange} ondragover={handleEditorDragOver} ondrop={handleEditorDrop}>
|
onpaste={handleContentChangeWithDynamicSizing} ondragover={handleEditorDragOver} ondrop={handleEditorDrop}>
|
||||||
{page.content}
|
{page.content}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</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>
|
</div>
|
||||||
<template if:false={hasPropertyImages}>
|
<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;">
|
<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;">
|
||||||
@ -1157,6 +1332,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Image Review Modal -->
|
<!-- Image Review Modal -->
|
||||||
<div if:true={showImageReview} class="image-review-overlay">
|
<div if:true={showImageReview} class="image-review-overlay">
|
||||||
<div class="image-review-modal">
|
<div class="image-review-modal">
|
||||||
@ -1292,6 +1468,7 @@
|
|||||||
<!-- Action Buttons -->
|
<!-- Action Buttons -->
|
||||||
<div class="image-replacement-actions">
|
<div class="image-replacement-actions">
|
||||||
<button class="btn btn-secondary" onclick={closeImageReplacement}>Cancel</button>
|
<button class="btn btn-secondary" onclick={closeImageReplacement}>Cancel</button>
|
||||||
|
<button class="btn btn-primary" onclick={insertSelectedReplacementImage}>Insert Image</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1390,4 +1567,99 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</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>
|
</template>
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,5 @@
|
|||||||
|
<?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>
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
<?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>
|
||||||
3
force-app/main/default/staticresources/PropertyLogo.svg
Normal file
3
force-app/main/default/staticresources/PropertyLogo.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 31 KiB |
BIN
force-app/main/default/staticresources/companyLogo.jpeg
Normal file
BIN
force-app/main/default/staticresources/companyLogo.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
0
template samples/grand-oak.html
Normal file
0
template samples/grand-oak.html
Normal file
Loading…
Reference in New Issue
Block a user