Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- var phase = @Phase
- var raw = @JSON
- var html = ""
- // Parse the JSON string
- var json = {};
- try {
- json = JSON.parse(raw);
- } catch (e) {
- // If parsing fails, create empty structure
- json = {
- de: [],
- tsk: [],
- item: [],
- att: []
- };
- }
- // Ensure all arrays exist
- json.de = json.de || [];
- json.tsk = json.tsk || [];
- json.item = json.item || [];
- json.att = json.att || [];
- // Helper function to format currency
- function formatCurrency(amount) {
- return '$' + amount.toFixed(2);
- }
- // Helper function to format dates
- function formatDate(dateStr) {
- if (!dateStr || dateStr === "No Date") return "No Date";
- const date = new Date(dateStr);
- if (isNaN(date)) return dateStr;
- return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
- }
- // Helper function to format date with time
- function formatDateTime(dateStr) {
- if (!dateStr) return null;
- const date = new Date(dateStr);
- if (isNaN(date)) return dateStr;
- return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) +
- ' ' + date.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true });
- }
- // Helper function to get stage pill colors
- function getStageColors(stage) {
- switch (stage) {
- case 'Design':
- return { background: '#e5e7eb', color: '#374151' }; // Grey
- case 'Quotation':
- case 'Awaiting Client Approval':
- return { background: '#fef3c7', color: '#92400e' }; // Yellow
- case 'Approved by Client':
- return { background: '#d1fae5', color: '#065f46' }; // Green
- case 'Construction / Ordering':
- return { background: '#ede9fe', color: '#6b21a8' }; // Purple
- case 'Delivered / Installed':
- return { background: '#dbeafe', color: '#1e40af' }; // Blue
- case 'Abandoned':
- return { background: '#fee2e2', color: '#dc2626' }; // Red
- case 'Change Order - Awaiting Approval':
- return { background: '#e5e7eb', color: '#374151' }; // Grey
- default:
- return { background: '#d1fae5', color: '#065f46' }; // Default green
- }
- }
- // Helper function to get task status pill colors
- function getTaskStatusColors(status) {
- switch (status) {
- case 'Not Started':
- case 'Abandoned':
- case 'Change Order - Awaiting Approval':
- return { background: '#e5e7eb', color: '#374151' }; // Grey
- case 'Open':
- return { background: '#fef3c7', color: '#92400e' }; // Yellow
- case 'Overdue':
- return { background: '#fee2e2', color: '#dc2626' }; // Red
- case 'On Hold':
- return { background: '#dbeafe', color: '#1e40af' }; // Blue
- case 'Completed':
- return { background: '#d1fae5', color: '#065f46' }; // Green
- default:
- return { background: '#d1fae5', color: '#065f46' }; // Default green
- }
- }
- // Helper function to get item status pill colors
- function getItemStatusColors(status) {
- switch (status) {
- case 'Entered':
- return { background: '#e5e7eb', color: '#374151' }; // Grey
- case 'Approved - Needs Ordering':
- case 'Received':
- return { background: '#fef3c7', color: '#92400e' }; // Yellow
- case 'Backordered':
- return { background: '#ede9fe', color: '#6b21a8' }; // Purple
- case 'On Hold':
- return { background: '#dbeafe', color: '#1e40af' }; // Blue
- case 'Installed':
- return { background: '#d1fae5', color: '#065f46' }; // Green
- case 'Abandoned':
- return { background: '#fee2e2', color: '#dc2626' }; // Red
- default:
- return { background: '#d1fae5', color: '#065f46' }; // Default green
- }
- }
- // Helper function to get attachment status pill colors
- function getAttachmentStatusColors(status) {
- switch (status) {
- case 'Active':
- return { background: '#d1fae5', color: '#065f46' }; // Green
- case 'Inactive':
- return { background: '#fee2e2', color: '#dc2626' }; // Red
- default:
- return { background: '#d1fae5', color: '#065f46' }; // Default green
- }
- }
- // Helper function to get attachment stage pill colors
- function getAttachmentStageColors(stage) {
- switch (stage) {
- case 'Initial Design':
- return { background: '#fef3c7', color: '#92400e' }; // Yellow
- case 'In Revisions':
- case 'Abandoned':
- return { background: '#fee2e2', color: '#dc2626' }; // Red
- case 'Final':
- return { background: '#d1fae5', color: '#065f46' }; // Green
- default:
- return { background: '#d1fae5', color: '#065f46' }; // Default green
- }
- }
- // Helper function to get attachment type pill colors
- function getAttachmentTypeColors(type) {
- switch (type) {
- case 'Floor Plan':
- case 'Schedule':
- case '3D Rendering':
- return { background: '#d1fae5', color: '#065f46' }; // Green
- case 'Inspiration':
- return { background: '#fee2e2', color: '#dc2626' }; // Red
- case 'Mood Board':
- case 'Websites':
- return { background: '#fef3c7', color: '#92400e' }; // Yellow
- case 'Pre-Project Photos':
- return { background: '#dbeafe', color: '#1e40af' }; // Blue
- default:
- return { background: '#d1fae5', color: '#065f46' }; // Default green
- }
- }
- // Helper function to get attachment source pill colors
- function getAttachmentSourceColors(source) {
- switch (source) {
- case 'Designer':
- return { background: '#ede9fe', color: '#6b21a8' }; // Purple
- case 'Client':
- return { background: '#d1fae5', color: '#065f46' }; // Green
- default:
- return { background: '#d1fae5', color: '#065f46' }; // Default green
- }
- }
- function createLink(id, name) {
- return '<a href="https://tapeapp.com/jb-ventures/record/' + id + '" style="color: #0066cc; text-decoration: none;">' + name + '</a>';
- }
- // Helper function to render an item (used for all item displays)
- function renderItem(item) {
- var html = '<div style="margin-bottom: 8px; padding: 8px; background-color: #ffffff; border-radius: 4px; border: 1px solid #e1e8ed; position: relative;">';
- // Status pill in top right with dynamic colors
- var itemColors = getItemStatusColors(item.status);
- html += '<span style="position: absolute; top: 8px; right: 8px; padding: 2px 6px; background-color: ' + itemColors.background + '; color: ' + itemColors.color + '; border-radius: 3px; font-size: 11px; font-weight: 500;">' + item.status + '</span>';
- html += '<div style="font-weight: 500; color: #2c3e50; margin-bottom: 4px; font-size: 13px; padding-right: 60px;">' + createLink(item.id, item.name) + '</div>';
- // Basic info
- html += '<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 4px; margin-bottom: 6px; font-size: 11px; color: #666;">';
- html += '<div><strong>Category:</strong> ' + item.cat + '</div>';
- html += '<div><strong>Procurement:</strong> ' + item.res + '</div>';
- html += '<div><strong>Unit Type:</strong> ' + item.unit_type + '</div>';
- html += '<div><strong>Quantity:</strong> ' + item.qr + '</div>';
- html += '</div>';
- // Financials (reorganized into 4 columns)
- html += '<div style="padding: 6px; background-color: #f8f9fa; border-radius: 3px; font-size: 10px;">';
- html += '<div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; color: #555;">';
- // Column 1: Suggested Retail, Multiplier, Estimated Cost
- html += '<div>';
- html += '<div style="margin-bottom: 2px;">Suggested Retail: ' + formatCurrency(item.price) + '</div>';
- html += '<div style="margin-bottom: 2px;">Multiplier: ' + item.multi.toFixed(2) + '</div>';
- html += '<div>Estimated Cost: ' + formatCurrency(item.price * item.multi * item.qr) + '</div>';
- html += '</div>';
- // Column 2: Retail MU, Retail MUA
- html += '<div>';
- html += '<div style="margin-bottom: 2px;">Retail MU: ' + item.rm.toFixed(2) + '</div>';
- html += '<div>Retail MUA: ' + formatCurrency(item.price * item.multi * item.qr * item.rm) + '</div>';
- html += '</div>';
- // Column 3: Discount MU, Discount MUA
- html += '<div>';
- html += '<div style="margin-bottom: 2px;">Discount MU: ' + item.dm.toFixed(2) + '</div>';
- html += '<div>Discount MUA: ' + formatCurrency(item.price * item.multi * item.qr * item.dm) + '</div>';
- html += '</div>';
- // Column 4: Difference, Potential Profit
- html += '<div>';
- html += '<div style="margin-bottom: 2px;">Difference: ' + formatCurrency((item.price * item.multi * item.qr * item.rm) - (item.price * item.multi * item.qr * item.dm)) + '</div>';
- html += '<div>Potential Profit: ' + formatCurrency((item.price * item.multi * item.qr * item.dm) - (item.price * item.multi * item.qr)) + '</div>';
- html += '</div>';
- html += '</div>';
- html += '</div>';
- html += '</div>';
- return html;
- }
- // Start building HTML
- html += '<div style="font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, sans-serif; max-width: 768px; margin: 0 auto; padding: 10px; background-color: #f8f9fa;">';
- // Project header (more compact)
- html += '<div style="background-color: #ffffff; border-radius: 8px; padding: 16px; margin-bottom: 12px; box-shadow: 0 1px 4px rgba(0,0,0,0.08);">';
- html += '<h1 style="margin: 0; color: #1a1a1a; font-size: 24px; font-weight: 600;">Project Summary</h1>';
- html += '</div>';
- // Check if all arrays are empty
- var isEmpty = (json.de.length === 0 && json.tsk.length === 0 && json.item.length === 0 && json.att.length === 0);
- if (isEmpty) {
- // Show "No Related Items" card
- html += '<div style="background-color: #ffffff; border-radius: 8px; padding: 16px; margin-bottom: 12px; box-shadow: 0 1px 4px rgba(0,0,0,0.08); text-align: center;">';
- html += '<div style="color: #666; font-size: 16px; font-weight: 500;">No Related Items</div>';
- html += '</div>';
- } else {
- // Group design elements by room
- var roomGroups = {};
- if (json.de && json.de.length > 0) {
- json.de.forEach(function(de) {
- if (!roomGroups[de.room_name]) {
- roomGroups[de.room_name] = [];
- }
- roomGroups[de.room_name].push(de);
- });
- }
- // Sort room names alphabetically
- var sortedRooms = Object.keys(roomGroups).sort();
- // Process each room
- sortedRooms.forEach(function(roomName) {
- html += '<div style="background-color: #ffffff; border-radius: 8px; padding: 16px; margin-bottom: 12px; box-shadow: 0 1px 4px rgba(0,0,0,0.08);">';
- html += '<h2 style="margin: 0 0 12px 0; color: #2c3e50; font-size: 18px; font-weight: 600; border-bottom: 1px solid #e1e8ed; padding-bottom: 8px;">' + roomName + '</h2>';
- roomGroups[roomName].forEach(function(de) {
- html += '<div style="margin-bottom: 16px; padding: 12px; background-color: #f8f9fa; border-radius: 6px; border-left: 3px solid #3498db; position: relative;">';
- // Stage pill in top right with dynamic colors
- var stageColors = getStageColors(de.stage);
- html += '<span style="position: absolute; top: 12px; right: 12px; padding: 2px 6px; background-color: ' + stageColors.background + '; color: ' + stageColors.color + '; border-radius: 3px; font-size: 11px; font-weight: 500;">' + de.stage + '</span>';
- html += '<h3 style="margin: 0 0 8px 0; font-size: 16px; font-weight: 500; color: #2c3e50; padding-right: 60px;">' + createLink(de.id, de.name) + '</h3>';
- // Tasks for this design element
- var deTasks = json.tsk.filter(function(task) { return task.de_id === de.id; });
- if (deTasks.length > 0) {
- html += '<div style="margin-top: 12px;">';
- deTasks.forEach(function(task) {
- html += '<div style="margin-bottom: 8px; padding: 10px; background-color: #ffffff; border-radius: 4px; border: 1px solid #e1e8ed; position: relative;">';
- // Status pill in top right with dynamic colors
- var taskColors = getTaskStatusColors(task.status);
- html += '<span style="position: absolute; top: 8px; right: 8px; padding: 3px 8px; background-color: ' + taskColors.background + '; color: ' + taskColors.color + '; border-radius: 3px; font-size: 11px; font-weight: 500;">' + task.status + '</span>';
- html += '<h5 style="margin: 0 0 4px 0; font-size: 14px; font-weight: 500; color: #2c3e50; padding-right: 60px;">' + createLink(task.id, task.name) + '</h5>';
- html += '<div style="font-size: 12px; color: #666; margin-bottom: 4px;">';
- html += '<strong>Due:</strong> ' + formatDate(task.due);
- html += '</div>';
- html += '<div style="font-size: 12px; color: #666;">';
- html += '<strong>Assigned To:</strong> ' + task.assigned.join(', ');
- html += '</div>';
- // Checklist items
- if (task.checklist && task.checklist.length > 0) {
- html += '<div style="margin-top: 6px; padding-top: 6px; border-top: 1px solid #e1e8ed;">';
- task.checklist.forEach(function(item) {
- html += '<div style="margin-bottom: 3px; padding-left: 12px; font-size: 11px; color: #555;">';
- html += '<span style="color: ' + (item.completed ? '#4caf50' : '#999') + '; margin-right: 4px;">○</span>';
- html += item.title;
- if (item.description) {
- html += ' <span style="color: #888; font-style: italic;">(' + item.description + ')</span>';
- }
- if (item.dueAt) {
- html += ' <span style="color: #666; font-size: 10px;">[Due: ' + formatDateTime(item.dueAt) + ']</span>';
- }
- html += '</div>';
- });
- html += '</div>';
- }
- // Items for this task
- var taskItems = json.item.filter(function(item) { return item.task_id === task.id; });
- if (taskItems.length > 0) {
- html += '<div style="margin-top: 8px; padding-top: 8px; border-top: 1px solid #e1e8ed;">';
- taskItems.forEach(function(item) {
- html += renderItem(item);
- });
- html += '</div>';
- }
- html += '</div>';
- });
- html += '</div>';
- }
- // Items for this design element (no task)
- var deItems = json.item.filter(function(item) { return item.de_id === de.id && !item.task_id; });
- if (deItems.length > 0) {
- html += '<div style="margin-top: 12px;">';
- html += '<h4 style="margin: 0 0 8px 0; font-size: 14px; font-weight: 500; color: #34495e;">Design Element Items</h4>';
- deItems.forEach(function(item) {
- html += renderItem(item);
- });
- html += '</div>';
- }
- html += '</div>';
- });
- html += '</div>';
- });
- // Project-specific tasks (orphaned tasks)
- var projectTasks = json.tsk ? json.tsk.filter(function(task) { return !task.de_id; }) : [];
- if (projectTasks.length > 0) {
- html += '<div style="background-color: #ffffff; border-radius: 8px; padding: 16px; margin-bottom: 12px; box-shadow: 0 1px 4px rgba(0,0,0,0.08);">';
- html += '<h2 style="margin: 0 0 12px 0; color: #2c3e50; font-size: 18px; font-weight: 600; border-bottom: 1px solid #e1e8ed; padding-bottom: 8px;">Project Specific Tasks</h2>';
- projectTasks.forEach(function(task) {
- html += '<div style="margin-bottom: 8px; padding: 10px; background-color: #f8f9fa; border-radius: 4px; border: 1px solid #e1e8ed; position: relative;">';
- // Status pill in top right with dynamic colors
- var taskColors = getTaskStatusColors(task.status);
- html += '<span style="position: absolute; top: 8px; right: 8px; padding: 3px 8px; background-color: ' + taskColors.background + '; color: ' + taskColors.color + '; border-radius: 3px; font-size: 11px; font-weight: 500;">' + task.status + '</span>';
- html += '<h5 style="margin: 0 0 4px 0; font-size: 14px; font-weight: 500; color: #2c3e50; padding-right: 60px;">' + createLink(task.id, task.name) + '</h5>';
- html += '<div style="font-size: 12px; color: #666; margin-bottom: 4px;">';
- html += '<strong>Due:</strong> ' + formatDate(task.due);
- html += '</div>';
- html += '<div style="font-size: 12px; color: #666;">';
- html += '<strong>Assigned To:</strong> ' + task.assigned.join(', ');
- html += '</div>';
- // Checklist items
- if (task.checklist && task.checklist.length > 0) {
- html += '<div style="margin-top: 6px; padding-top: 6px; border-top: 1px solid #e1e8ed;">';
- task.checklist.forEach(function(item) {
- html += '<div style="margin-bottom: 3px; padding-left: 12px; font-size: 11px; color: #555;">';
- html += '<span style="color: ' + (item.completed ? '#4caf50' : '#999') + '; margin-right: 4px;">○</span>';
- html += item.title;
- if (item.description) {
- html += ' <span style="color: #888; font-style: italic;">(' + item.description + ')</span>';
- }
- if (item.dueAt) {
- html += ' <span style="color: #666; font-size: 10px;">[Due: ' + formatDateTime(item.dueAt) + ']</span>';
- }
- html += '</div>';
- });
- html += '</div>';
- }
- html += '</div>';
- });
- html += '</div>';
- }
- // Project-specific items
- var projectItems = json.item ? json.item.filter(function(item) { return !item.de_id && !item.task_id; }) : [];
- if (projectItems.length > 0) {
- html += '<div style="background-color: #ffffff; border-radius: 8px; padding: 16px; margin-bottom: 12px; box-shadow: 0 1px 4px rgba(0,0,0,0.08);">';
- html += '<h2 style="margin: 0 0 12px 0; color: #2c3e50; font-size: 18px; font-weight: 600; border-bottom: 1px solid #e1e8ed; padding-bottom: 8px;">Project Specific Items</h2>';
- projectItems.forEach(function(item) {
- html += renderItem(item);
- });
- html += '</div>';
- }
- // Attachments
- if (json.att && json.att.length > 0) {
- html += '<div style="background-color: #ffffff; border-radius: 8px; padding: 16px; margin-bottom: 12px; box-shadow: 0 1px 4px rgba(0,0,0,0.08);">';
- html += '<h2 style="margin: 0 0 12px 0; color: #2c3e50; font-size: 18px; font-weight: 600; border-bottom: 1px solid #e1e8ed; padding-bottom: 8px;">Attachments</h2>';
- json.att.forEach(function(att) {
- html += '<div style="margin-bottom: 8px; padding: 10px 10px ' + (att.type && att.type.length > 0 ? '35px' : '10px') + ' 10px; background-color: #f8f9fa; border-radius: 4px; border: 1px solid #e1e8ed; position: relative;">';
- // Source, Status, and Stage pills in top right (first row)
- html += '<div style="position: absolute; top: 8px; right: 8px; display: flex; gap: 4px;">';
- // Source pill (first)
- var sourceColors = getAttachmentSourceColors(att.source);
- html += '<span style="padding: 2px 6px; background-color: ' + sourceColors.background + '; color: ' + sourceColors.color + '; border-radius: 3px; font-size: 11px; font-weight: 500;">' + att.source + '</span>';
- // Status pill (second)
- var statusColors = getAttachmentStatusColors(att.status);
- html += '<span style="padding: 2px 6px; background-color: ' + statusColors.background + '; color: ' + statusColors.color + '; border-radius: 3px; font-size: 11px; font-weight: 500;">' + att.status + '</span>';
- // Stage pill (third)
- var stageColors = getAttachmentStageColors(att.stage);
- html += '<span style="padding: 2px 6px; background-color: ' + stageColors.background + '; color: ' + stageColors.color + '; border-radius: 3px; font-size: 11px; font-weight: 500;">' + att.stage + '</span>';
- html += '</div>';
- // Type pills on second row (flush right)
- if (att.type && att.type.length > 0) {
- html += '<div style="position: absolute; bottom: 8px; right: 8px; display: flex; gap: 4px;">';
- att.type.sort().forEach(function(type) {
- var typeColors = getAttachmentTypeColors(type);
- html += '<span style="padding: 2px 6px; background-color: ' + typeColors.background + '; color: ' + typeColors.color + '; border-radius: 3px; font-size: 11px; font-weight: 500;">' + type + '</span>';
- });
- html += '</div>';
- }
- html += '<h5 style="margin: 0 0 6px 0; font-size: 13px; font-weight: 500; color: #2c3e50; padding-right: 50%;">' + createLink(att.id, att.name) + '</h5>';
- html += '</div>';
- });
- html += '</div>';
- }
- }
- html += '</div>';
- html
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement