191 lines
6.3 KiB
JavaScript
191 lines
6.3 KiB
JavaScript
|
/**
|
||
|
* Pricing Data Manager - Handles API calls and data extraction
|
||
|
*/
|
||
|
class PricingDataManager {
|
||
|
constructor(currentOffering) {
|
||
|
this.currentOffering = currentOffering;
|
||
|
this.pricingData = null;
|
||
|
this.storagePrice = null;
|
||
|
this.replicaInfo = null;
|
||
|
this.addonsData = null;
|
||
|
}
|
||
|
|
||
|
// Load pricing data from API endpoint
|
||
|
async loadPricingData() {
|
||
|
try {
|
||
|
const response = await fetch(`/offering/${this.currentOffering.provider_slug}/${this.currentOffering.service_slug}/?pricing=json`);
|
||
|
|
||
|
if (!response.ok) {
|
||
|
throw new Error(`Failed to load pricing data: ${response.status} ${response.statusText}`);
|
||
|
}
|
||
|
|
||
|
const data = await response.json();
|
||
|
|
||
|
this.pricingData = data.pricing || data;
|
||
|
|
||
|
// Extract addons data from the plans - addons are embedded in each plan
|
||
|
this.extractAddonsData();
|
||
|
|
||
|
// Extract storage price from the first available plan
|
||
|
this.extractStoragePrice();
|
||
|
|
||
|
return this.pricingData;
|
||
|
} catch (error) {
|
||
|
console.error('Error loading pricing data:', error);
|
||
|
throw error;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Extract replica information and storage price from pricing data
|
||
|
extractStoragePrice() {
|
||
|
if (!this.pricingData) return;
|
||
|
|
||
|
// Find the first plan with storage pricing data and replica info
|
||
|
for (const groupName of Object.keys(this.pricingData)) {
|
||
|
const group = this.pricingData[groupName];
|
||
|
for (const serviceLevel of Object.keys(group)) {
|
||
|
const plans = group[serviceLevel];
|
||
|
if (plans.length > 0 && plans[0].storage_price !== undefined) {
|
||
|
this.storagePrice = parseFloat(plans[0].storage_price);
|
||
|
this.replicaInfo = {
|
||
|
ha_replica_min: plans[0].ha_replica_min || 1,
|
||
|
ha_replica_max: plans[0].ha_replica_max || 1
|
||
|
};
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Extract addons data from pricing plans
|
||
|
extractAddonsData() {
|
||
|
if (!this.pricingData) return;
|
||
|
|
||
|
this.addonsData = {};
|
||
|
|
||
|
// Extract addons from the first available plan for each service level
|
||
|
Object.keys(this.pricingData).forEach(groupName => {
|
||
|
const group = this.pricingData[groupName];
|
||
|
Object.keys(group).forEach(serviceLevel => {
|
||
|
const plans = group[serviceLevel];
|
||
|
if (plans.length > 0) {
|
||
|
// Use the first plan's addon data for this service level
|
||
|
const plan = plans[0];
|
||
|
const allAddons = [];
|
||
|
|
||
|
// Add mandatory addons
|
||
|
if (plan.mandatory_addons) {
|
||
|
plan.mandatory_addons.forEach(addon => {
|
||
|
allAddons.push({
|
||
|
...addon,
|
||
|
is_mandatory: true,
|
||
|
addon_type: addon.addon_type === "Base Fee" ? "BASE_FEE" : "UNIT_RATE"
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// Add optional addons
|
||
|
if (plan.optional_addons) {
|
||
|
plan.optional_addons.forEach(addon => {
|
||
|
allAddons.push({
|
||
|
...addon,
|
||
|
is_mandatory: false,
|
||
|
addon_type: addon.addon_type === "Base Fee" ? "BASE_FEE" : "UNIT_RATE"
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
this.addonsData[serviceLevel] = allAddons;
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// Get available service levels from pricing data
|
||
|
getAvailableServiceLevels() {
|
||
|
if (!this.pricingData) return new Set();
|
||
|
|
||
|
const availableServiceLevels = new Set();
|
||
|
Object.keys(this.pricingData).forEach(groupName => {
|
||
|
const group = this.pricingData[groupName];
|
||
|
Object.keys(group).forEach(serviceLevel => {
|
||
|
availableServiceLevels.add(serviceLevel);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
return availableServiceLevels;
|
||
|
}
|
||
|
|
||
|
// Get maximum CPU and memory values from all plans
|
||
|
getSliderMaximums() {
|
||
|
if (!this.pricingData) return { maxCpus: 0, maxMemory: 0 };
|
||
|
|
||
|
let maxCpus = 0;
|
||
|
let maxMemory = 0;
|
||
|
|
||
|
// Find maximum CPU and memory across all plans
|
||
|
Object.keys(this.pricingData).forEach(groupName => {
|
||
|
const group = this.pricingData[groupName];
|
||
|
Object.keys(group).forEach(serviceLevel => {
|
||
|
group[serviceLevel].forEach(plan => {
|
||
|
const planCpus = parseFloat(plan.vcpus);
|
||
|
const planMemory = parseFloat(plan.ram);
|
||
|
|
||
|
if (planCpus > maxCpus) maxCpus = planCpus;
|
||
|
if (planMemory > maxMemory) maxMemory = planMemory;
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
return { maxCpus, maxMemory };
|
||
|
}
|
||
|
|
||
|
// Get all plans for a specific service level
|
||
|
getPlansForServiceLevel(serviceLevel) {
|
||
|
if (!this.pricingData || !serviceLevel) return [];
|
||
|
|
||
|
const availablePlans = [];
|
||
|
Object.keys(this.pricingData).forEach(groupName => {
|
||
|
const group = this.pricingData[groupName];
|
||
|
if (group[serviceLevel]) {
|
||
|
group[serviceLevel].forEach(plan => {
|
||
|
availablePlans.push({
|
||
|
...plan,
|
||
|
groupName: groupName
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// Sort plans by vCPU, then by RAM
|
||
|
availablePlans.sort((a, b) => {
|
||
|
if (parseFloat(a.vcpus) !== parseFloat(b.vcpus)) {
|
||
|
return parseFloat(a.vcpus) - parseFloat(b.vcpus);
|
||
|
}
|
||
|
return parseFloat(a.ram) - parseFloat(b.ram);
|
||
|
});
|
||
|
|
||
|
return availablePlans;
|
||
|
}
|
||
|
|
||
|
// Getters
|
||
|
getPricingData() {
|
||
|
return this.pricingData;
|
||
|
}
|
||
|
|
||
|
getStoragePrice() {
|
||
|
return this.storagePrice;
|
||
|
}
|
||
|
|
||
|
getReplicaInfo() {
|
||
|
return this.replicaInfo;
|
||
|
}
|
||
|
|
||
|
getAddonsData() {
|
||
|
return this.addonsData;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Export for use in other modules
|
||
|
window.PricingDataManager = PricingDataManager;
|