diff --git a/Documents/Vibe Coding Projects/dedicatednodes-redesign/dedicatednodes-bare-metal/new-baremetal.html b/Documents/Vibe Coding Projects/dedicatednodes-redesign/dedicatednodes-bare-metal/new-baremetal.html
index b209838..9c36fb2 100644
--- a/Documents/Vibe Coding Projects/dedicatednodes-redesign/dedicatednodes-bare-metal/new-baremetal.html
+++ b/Documents/Vibe Coding Projects/dedicatednodes-redesign/dedicatednodes-bare-metal/new-baremetal.html
@@ -4251,7 +4251,8 @@ var wpcf7 = {
}
// Render options with the exact WHMCS preselected values
- renderDynamicOptions(options, true, preselected);
+ // Also pass the storage requirements for proper pre-filling
+ renderDynamicOptions(options, true, preselected, storageReqs);
} else {
renderFallbackOptions(container);
@@ -4606,7 +4607,7 @@ var wpcf7 = {
updateSummary();
};
- function renderDynamicOptions(options, isInstant = false, preselected = {}) {
+ function renderDynamicOptions(options, isInstant = false, preselected = {}, storageRequirements = []) {
const container = isInstant ? document.getElementById('instantDynamicConfigContainer') : document.getElementById('dynamicConfigContainer');
container.innerHTML = '';
@@ -4643,107 +4644,71 @@ var wpcf7 = {
}
}
- // For instant customization, don't group - show each slot individually
- // For custom servers, group similar slots together
- if (isInstant) {
- // Show each storage slot individually
- groups.storage.forEach((opt, index) => {
- const label = document.createElement('div');
- label.className = 'section-label';
- label.style.marginTop = '1.5rem';
- label.textContent = `💿 ${opt.label}`;
- container.appendChild(label);
+ // For both instant and custom, group storage options by signature
+ // This creates a pooled grid where we can prefill with the correct drives
+ const storageGroups = {};
+ const groupOrder = []; // Preserve order
- // Create visualizer for this single slot
- const visualContainer = document.createElement('div');
- visualContainer.className = 'storage-slots-container';
- const uniqueSuffix = '-instant-s' + index;
+ groups.storage.forEach(opt => {
+ // Create a signature based on available values
+ const signature = opt.values.map(v => v.text.trim().toLowerCase() + '|' + v.price).join('||');
- visualContainer.innerHTML = `
-
-
- `;
- container.appendChild(visualContainer);
+ if (!storageGroups[signature]) {
+ storageGroups[signature] = [];
+ groupOrder.push(signature);
+ }
+ storageGroups[signature].push(opt);
+ });
- // Create individual option grid for this slot
- // For instant customization, we need to pass the specific preselected value for this slot
- const slotPreselected = {};
- if (isInstant && preselected[opt.id]) {
- slotPreselected[opt.id] = preselected[opt.id];
- }
- container.appendChild(createOptionGrid(opt, true, -1, isInstant, slotPreselected));
- });
- } else {
- // Group storage options by signature for custom servers
- const storageGroups = {};
- const groupOrder = []; // Preserve order
+ // Render each group
+ groupOrder.forEach((sig, groupIndex) => {
+ const groupOpts = storageGroups[sig];
+ const firstOpt = groupOpts[0];
- groups.storage.forEach(opt => {
- // Create a signature based on available values
- const signature = opt.values.map(v => v.text.trim().toLowerCase() + '|' + v.price).join('||');
+ const label = document.createElement('div');
+ label.className = 'section-label';
+ label.style.marginTop = '1.5rem';
- if (!storageGroups[signature]) {
- storageGroups[signature] = [];
- groupOrder.push(signature);
- }
- storageGroups[signature].push(opt);
- });
+ // Detect Title based on content
+ const firstLabel = firstOpt.label.toLowerCase();
+ // Check values for keywords
+ const hasGen5 = firstOpt.values.some(v => v.text.toLowerCase().includes('gen5'));
+ const hasGen4 = firstOpt.values.some(v => v.text.toLowerCase().includes('gen4'));
+ const hasEnt = firstOpt.values.some(v => v.text.toLowerCase().includes('enterprise') || v.text.toLowerCase().includes('ent'));
- // Render each group
- groupOrder.forEach((sig, groupIndex) => {
- const groupOpts = storageGroups[sig];
- const firstOpt = groupOpts[0];
+ let title = '💿 STORAGE CONFIGURATION';
+ if (hasGen5) title = '🚀 GEN5 NVME STORAGE (ENTERPRISE)';
+ else if (hasGen4) title = '💿 GEN4 NVME STORAGE (CONSUMER)';
+ else if (hasEnt) title = '💾 ENTERPRISE STORAGE';
- const label = document.createElement('div');
- label.className = 'section-label';
- label.style.marginTop = '1.5rem';
+ // Append Group Index if multiple groups exist to differentiate
+ if (groupOrder.length > 1) {
+ title += ` (Group ${groupIndex + 1})`;
+ }
- // Detect Title based on content
- const firstLabel = firstOpt.label.toLowerCase();
- // Check values for keywords
- const hasGen5 = firstOpt.values.some(v => v.text.toLowerCase().includes('gen5'));
- const hasGen4 = firstOpt.values.some(v => v.text.toLowerCase().includes('gen4'));
- const hasEnt = firstOpt.values.some(v => v.text.toLowerCase().includes('enterprise') || v.text.toLowerCase().includes('ent'));
+ label.textContent = title;
+ container.appendChild(label);
- let title = '💿 STORAGE CONFIGURATION';
- if (hasGen5) title = '🚀 GEN5 NVME STORAGE (ENTERPRISE)';
- else if (hasGen4) title = '💿 GEN4 NVME STORAGE (CONSUMER)';
- else if (hasEnt) title = '💾 ENTERPRISE STORAGE';
+ // Visualizer for THIS group
+ const maxSlots = groupOpts.length;
+ const visualContainer = document.createElement('div');
+ visualContainer.className = 'storage-slots-container';
+ const uniqueSuffix = (isInstant ? '-instant' : '') + '-g' + groupIndex;
- // Append Group Index if multiple groups exist to differentiate
- if (groupOrder.length > 1) {
- title += ` (Group ${groupIndex + 1})`;
- }
+ visualContainer.innerHTML = `
+
+
+ ${Array(maxSlots).fill('
').join('')}
+
+ `;
+ container.appendChild(visualContainer);
- label.textContent = title;
- container.appendChild(label);
-
- // Visualizer for THIS group
- const maxSlots = groupOpts.length;
- const visualContainer = document.createElement('div');
- visualContainer.className = 'storage-slots-container';
- const uniqueSuffix = (isInstant ? '-instant' : '') + '-g' + groupIndex;
-
- visualContainer.innerHTML = `
-
-
- ${Array(maxSlots).fill('
').join('')}
-
- `;
- container.appendChild(visualContainer);
-
- // Always use pooled grid for these groups as they are by definition identical
- container.appendChild(createPooledStorageGrid(groupOpts, isInstant, preselected, groupIndex));
- });
- }
+ // Always use pooled grid for these groups as they are by definition identical
+ container.appendChild(createPooledStorageGrid(groupOpts, isInstant, preselected, groupIndex, storageRequirements));
+ });
}
// 3. Network & Other
@@ -4769,7 +4734,7 @@ var wpcf7 = {
}
// New Pooled Storage Grid
- function createPooledStorageGrid(storageOptions, isInstant, preselected = {}, groupIndex = 0) {
+ function createPooledStorageGrid(storageOptions, isInstant, preselected = {}, groupIndex = 0, storageRequirements = []) {
const grid = document.createElement('div');
grid.className = 'config-grid';
@@ -4800,29 +4765,72 @@ var wpcf7 = {
window.pooledState[poolKey] = { slots: initializedSlots };
- // For instant customization, track original drives
+ // For instant customization, track original drives and pre-fill with requirements
if (isInstant) {
window.originalDrives = [];
+ // First reset all slots to None
initializedSlots.forEach(slot => {
- // Track the preselected drives as "original"
- if (preselected[slot.id] && slot.currentVal.text !== '-' &&
- !slot.currentVal.text.toLowerCase().includes('none')) {
- window.originalDrives.push({
- slotId: slot.id,
- driveId: slot.currentVal.id,
- text: slot.currentVal.text,
- price: slot.currentVal.price
- });
-
- // Original drives have no additional cost (included in base price)
- configState[slot.label] = 0;
- } else {
- configState[slot.label] = slot.currentVal.price;
+ const noneOption = slot.values.find(v =>
+ v.text.trim() === '-' ||
+ v.text.toLowerCase().includes('none') ||
+ v.text.toLowerCase().includes('no hard drive')
+ );
+ if (noneOption) {
+ slot.currentVal = noneOption;
+ configState[slot.label] = noneOption.price;
+ configIds[slot.id] = noneOption.id;
}
-
- configIds[slot.id] = slot.currentVal.id;
});
+
+ // Fill slots based on storage requirements
+ if (storageRequirements && storageRequirements.length > 0) {
+ storageRequirements.forEach(req => {
+ for (let i = 0; i < req.qty; i++) {
+ // Find an empty slot
+ const emptySlot = initializedSlots.find(s =>
+ s.currentVal.text === '-' ||
+ s.currentVal.text.toLowerCase().includes('none')
+ );
+
+ if (emptySlot) {
+ // Find matching drive type
+ const match = emptySlot.values.find(v => {
+ const vText = v.text.toLowerCase();
+ const reqSpec = req.spec.toLowerCase();
+
+ // Extract capacity
+ const valCap = vText.match(/(\d+(?:\.\d+)?)\s*tb/i);
+ const reqCap = reqSpec.match(/(\d+(?:\.\d+)?)\s*tb/i);
+ if (valCap && reqCap && valCap[1] === reqCap[1]) {
+ // Check brand match
+ if ((vText.includes('crucial') && reqSpec.includes('crucial')) ||
+ (vText.includes('kioxia') && reqSpec.includes('kioxia')) ||
+ (vText.includes('t705') && reqSpec.includes('t705')) ||
+ (vText.includes('cm7') && reqSpec.includes('cm7'))) {
+ return true;
+ }
+ }
+ return false;
+ });
+
+ if (match) {
+ emptySlot.currentVal = match;
+ configState[emptySlot.label] = 0; // Included in base price
+ configIds[emptySlot.id] = match.id;
+
+ // Track as original drive
+ window.originalDrives.push({
+ slotId: emptySlot.id,
+ driveId: match.id,
+ text: match.text,
+ price: match.price
+ });
+ }
+ }
+ }
+ });
+ }
} else {
// Pre-set configState for custom servers
initializedSlots.forEach(slot => {