diff --git a/force-app/main/default/lwc/developmentPage/developmentPage.css b/force-app/main/default/lwc/developmentPage/developmentPage.css index 5074011..495a8f4 100644 --- a/force-app/main/default/lwc/developmentPage/developmentPage.css +++ b/force-app/main/default/lwc/developmentPage/developmentPage.css @@ -5,10 +5,12 @@ width: 100vw; height: 100vh; background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%); - z-index: 9999; + z-index: 99999; overflow-y: auto; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; color: #ffffff; + display: flex; + flex-direction: column; } .dev-header { @@ -46,30 +48,13 @@ letter-spacing: 1px; } -.close-dev-btn { - position: absolute; - top: 20px; - right: 20px; - background: #ff4757; - color: white; - border: none; - border-radius: 50%; - width: 40px; - height: 40px; - font-size: 1.5rem; - cursor: pointer; - transition: all 0.3s ease; -} - -.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 { diff --git a/force-app/main/default/lwc/developmentPage/developmentPage.js b/force-app/main/default/lwc/developmentPage/developmentPage.js index c16ae58..f8a48a8 100644 --- a/force-app/main/default/lwc/developmentPage/developmentPage.js +++ b/force-app/main/default/lwc/developmentPage/developmentPage.js @@ -1,7 +1,7 @@ import { LightningElement, track } from 'lwc'; export default class DevelopmentPage extends LightningElement { - @track showDevPage = false; + @track showDevPage = true; // Always visible by default @track currentStep = 1; @track selectedTemplateId = ''; @track selectedPropertyId = ''; @@ -9,9 +9,9 @@ export default class DevelopmentPage extends LightningElement { @track currentTimestamp = ''; @track debugMode = false; - // V-key click counter - vKeyCount = 0; - vKeyTimeout = null; + // K-key click counter for closing development mode + kKeyCount = 0; + kKeyTimeout = null; connectedCallback() { this.updateTimestamp(); @@ -20,8 +20,8 @@ export default class DevelopmentPage extends LightningElement { disconnectedCallback() { this.removeKeyListener(); - if (this.vKeyTimeout) { - clearTimeout(this.vKeyTimeout); + if (this.kKeyTimeout) { + clearTimeout(this.kKeyTimeout); } } @@ -34,36 +34,28 @@ export default class DevelopmentPage extends LightningElement { } handleKeyPress(event) { - // Only listen for 'V' key (case insensitive) - if (event.key.toLowerCase() === 'v') { - this.vKeyCount++; + // Only listen for 'K' key (case insensitive) - completely silent + if (event.key.toLowerCase() === 'k') { + this.kKeyCount++; // Clear any existing timeout - if (this.vKeyTimeout) { - clearTimeout(this.vKeyTimeout); + if (this.kKeyTimeout) { + clearTimeout(this.kKeyTimeout); } // Reset counter after 3 seconds of inactivity - this.vKeyTimeout = setTimeout(() => { - this.vKeyCount = 0; + this.kKeyTimeout = setTimeout(() => { + this.kKeyCount = 0; }, 3000); - // Hide dev page after 4 V key presses - if (this.vKeyCount >= 4) { + // Close dev page after 5 K key presses (silent) + if (this.kKeyCount >= 5) { this.showDevPage = false; - this.vKeyCount = 0; // Reset counter + this.kKeyCount = 0; // Reset counter } } } - closeDevPage() { - this.showDevPage = false; - this.vKeyCount = 0; - if (this.vKeyTimeout) { - clearTimeout(this.vKeyTimeout); - } - } - updateTimestamp() { this.currentTimestamp = new Date().toLocaleString(); } diff --git a/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.css b/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.css index c3bf14c..cabd997 100644 --- a/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.css +++ b/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.css @@ -14015,4 +14015,198 @@ img[draggable="true"] { } } +/* ===== MODAL ANIMATIONS ===== */ +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +@keyframes slideIn { + from { + opacity: 0; + transform: translateY(-20px) scale(0.95); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +.data-type-option:hover { + border-color: #007bff !important; + background: #f0f8ff !important; + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0,123,255,0.15); +} + +.close-btn:hover { + background: #f5f5f5 !important; + color: #333 !important; +} + +.btn:hover:not(:disabled) { + transform: translateY(-1px); + box-shadow: 0 2px 8px rgba(0,0,0,0.15); +} + +/* ===== PDF GENERATION STYLING ===== */ +@media print { + .brochure-page { + page-break-before: always; + margin: 0; + padding: 0; + width: 210mm; + height: 297mm; + overflow: hidden; + display: flex !important; + flex-direction: column !important; + background: white !important; + box-shadow: 0 0 10px rgba(0,0,0,0.1) !important; + } + + /* Ensure newly added pages maintain A4 dimensions */ + .brochure-page.a4 { + width: 210mm !important; + height: 297mm !important; + margin: 0 !important; + padding: 0 !important; + overflow: hidden !important; + display: flex !important; + flex-direction: column !important; + background: white !important; + box-shadow: 0 0 10px rgba(0,0,0,0.1) !important; + } + + /* Ensure all brochure pages have consistent A4 dimensions */ + .brochure { + width: 210mm !important; + height: 297mm !important; + margin: 0 !important; + padding: 0 !important; + overflow: hidden !important; + display: flex !important; + flex-direction: column !important; + background: white !important; + box-shadow: 0 0 10px rgba(0,0,0,0.1) !important; + } + + /* Page break handling */ + .page-break { + page-break-before: always !important; + height: 0 !important; + margin: 0 !important; + padding: 0 !important; + } + + .brochure-page:first-child { + page-break-before: avoid; + } + + .page-header { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; + color: white !important; + padding: 20px !important; + margin-bottom: 20px !important; + border-radius: 10px !important; + text-align: center !important; + } + + .page-content { + padding: 20px !important; + background: white !important; + border-radius: 10px !important; + box-shadow: 0 2px 10px rgba(0,0,0,0.1) !important; + margin-bottom: 20px !important; + } + + .page-footer { + background: #003366 !important; + color: white !important; + padding: 20px !important; + display: flex !important; + justify-content: space-between !important; + align-items: center !important; + margin-top: 20px !important; + position: absolute !important; + bottom: 0 !important; + left: 0 !important; + right: 0 !important; + } + + /* Template-specific footer colors for PDF */ + .brochure-page[data-template="modern-home-template"] .page-footer { + background: #003366 !important; + } + + .brochure-page[data-template="grand-oak-villa-template"] .page-footer { + background: #1a1a1a !important; + } + + .brochure-page[data-template="serenity-house-template"] .page-footer { + background: #1a1a1a !important; + } + + .brochure-page[data-template="luxury-mansion-template"] .page-footer { + background: #1a1a1a !important; + } + + .content-section h2 { + color: #495057 !important; + border-bottom: 2px solid #e9ecef !important; + padding-bottom: 10px !important; + margin-bottom: 20px !important; + } + + .content-section p { + color: #6c757d !important; + line-height: 1.6 !important; + margin-bottom: 15px !important; + } + + .features-grid { + display: grid !important; + grid-template-columns: repeat(2, 1fr) !important; + gap: 20px !important; + } + + .feature-item { + display: flex !important; + align-items: center !important; + padding: 10px 0 !important; + } + + .feature-item i { + color: #28a745 !important; + margin-right: 10px !important; + } + + .gallery-grid { + display: grid !important; + grid-template-columns: repeat(2, 1fr) !important; + gap: 15px !important; + } + + .gallery-item { + background: #f8f9fa !important; + border: 2px dashed #dee2e6 !important; + padding: 20px !important; + text-align: center !important; + color: #6c757d !important; + height: 100% !important; + min-height: 250px !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + break-inside: avoid !important; + page-break-inside: avoid !important; + } + + .gallery-item img { + width: 100% !important; + height: 100% !important; + object-fit: cover !important; + display: block !important; + } +} + /* ===== END OF STYLES ===== */ diff --git a/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.html b/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.html index b356776..148998b 100644 --- a/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.html +++ b/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.html @@ -1187,6 +1187,16 @@ Image +
+ + +
- -
- -
@@ -1307,6 +1304,22 @@ + + + @@ -1598,4 +1611,47 @@ + + +
+
+
+

Select Page Type

+ +
+
+
+
+
📝
+
Text Page
+
Add a text-focused page for detailed content
+
+
+
🖼️
+
Gallery Page
+
Add an image gallery page
+
+
+
+
Features Page
+
Add a features and amenities page
+
+
+
📞
+
Contact Page
+
Add a contact information page
+
+
+
📄
+
Blank Page
+
Add a blank page for custom content
+
+
+
+
+ + +
+
+
\ No newline at end of file diff --git a/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.js b/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.js index 070815c..a06eab8 100644 --- a/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.js +++ b/force-app/main/default/lwc/propertyTemplateSelector/propertyTemplateSelector.js @@ -113,6 +113,41 @@ export default class PropertyTemplateSelector extends LightningElement { }; } + // Validate A4 page height compliance + validateA4HeightCompliance() { + const dimensions = this.getPageDimensions(); + const maxHeight = dimensions.heightPx; // 1123px for A4 + + // Check if content exceeds A4 height + const contentHeight = this.estimateContentHeight(); + + if (contentHeight > maxHeight) { + console.warn(`Content height (${contentHeight}px) exceeds A4 height (${maxHeight}px)`); + return false; + } + + return true; + } + + // Estimate content height for validation + estimateContentHeight() { + // Hero section: 90mm (approximately 340px at 96 DPI) - half height + const heroHeight = 340; + + // Content section: estimated based on description length + const description = this.propertyData?.Description_English__c || + this.propertyData?.descriptionEnglish || + this.propertyData?.description || ""; + const descriptionLines = Math.ceil(description.length / 80); // Approximate chars per line + const contentHeight = Math.min(descriptionLines * 20 + 100, 400); // Increased max for more content space + + // Footer: 60px + const footerHeight = 60; + + return heroHeight + contentHeight + footerHeight; + } + + // Image review properties @track showImageReview = false; @track selectedCategory = "Interior"; // Will be updated when images load @@ -3003,25 +3038,21 @@ export default class PropertyTemplateSelector extends LightningElement { // First, ensure we have template content loaded let htmlContent = ""; - // Check if preview frame has content - get from all editor elements - const previewFrames = this.template.querySelectorAll( + // Get content from the main editor frame + const editorFrame = this.template.querySelector( ".enhanced-editor-content" ); - if (!previewFrames || previewFrames.length === 0) { + if (!editorFrame) { throw new Error("Editor content not found"); } - // Combine content from all editor frames - htmlContent = ""; - previewFrames.forEach((frame, index) => { - if (frame.innerHTML && frame.innerHTML.trim()) { - if (htmlContent) { - htmlContent += `
${frame.innerHTML}`; - } else { - htmlContent = frame.innerHTML; - } - } - }); + // Get the HTML content from the editor + htmlContent = editorFrame.innerHTML; + + // Ensure we have content + if (!htmlContent || htmlContent.trim() === "") { + throw new Error("No content found in editor"); + } // Debug: Check if draggable elements are present before cleaning const tempDiv = document.createElement("div"); @@ -3060,7 +3091,7 @@ export default class PropertyTemplateSelector extends LightningElement { htmlContent = this.createCompleteTemplateHTML(); // Load it into the preview frame so user can see it - previewFrame.innerHTML = htmlContent; + editorFrame.innerHTML = htmlContent; } else { throw new Error("No template or property selected"); } @@ -4753,6 +4784,11 @@ export default class PropertyTemplateSelector extends LightningElement { const data = this.propertyData || {}; const dimensions = this.getPageDimensions(); console.log("data-----------", data); + + // Validate A4 height compliance + if (!this.validateA4HeightCompliance()) { + console.warn("Content may exceed A4 page height. Consider reducing description length."); + } const propertyName = data.Name || data.propertyName; const propertyType = data.Property_Type__c || data.propertyType; const location = data.Address__c || data.location; @@ -4787,12 +4823,18 @@ export default class PropertyTemplateSelector extends LightningElement { const bathrooms = data.Bathrooms__c || data.bathrooms; const area = data.Square_Feet__c || data.area; - const description = this.formatDescriptionForPDF( - data.Description_English__c || - data.descriptionEnglish || - data.description || - "This beautiful property offers exceptional value and modern amenities. Located in a prime area, it represents an excellent investment opportunity." - ); + // Get description and format it dynamically + const rawDescription = data.Description_English__c || + data.descriptionEnglish || + data.description || + "This beautiful property offers exceptional value and modern amenities. Located in a prime area, it represents an excellent investment opportunity."; + + const description = this.formatDescriptionForPDF(rawDescription); + + // Add dynamic class based on description length for CSS targeting + const descriptionLength = rawDescription.length; + const descriptionClass = descriptionLength > 500 ? 'description-long' : + descriptionLength > 200 ? 'description-medium' : 'description-short'; const referenceId = data.pcrm__Title_English__c || data.Name || data.propertyName || ""; @@ -4862,7 +4904,7 @@ export default class PropertyTemplateSelector extends LightningElement { const allImages = Array.isArray(this.realPropertyImages) ? this.realPropertyImages : []; - const imagesPerPage = 6; // Optimal for A4 with 2x3 grid + const imagesPerPage = 8; // 2x4 grid for better space utilization let galleryPagesHTML = ""; if (allImages.length > 0) { for (let i = 0; i < allImages.length; i += imagesPerPage) { @@ -4882,20 +4924,26 @@ export default class PropertyTemplateSelector extends LightningElement { img.url ? `https://salesforce.tech4biz.io${img.url}` : 'https://via.placeholder.com/400x200?text=No+Image'; - return `