@electrolux-oss/plugin-infrawallet 1.1.0-20251218080406-fbaf733 → 1.1.0-20260112100533-68a81f8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -199,7 +199,7 @@ const formatCurrency = (number, currency) => {
199
199
  notation: "compact"
200
200
  }).format(number);
201
201
  };
202
- const calculateBudgetAnalytics = (monthlyCosts, annualBudget) => {
202
+ const calculateBudgetAnalytics = (monthlyCosts, annualBudget, forecast) => {
203
203
  const currentMonth = moment().month() + 1;
204
204
  const currentYear = moment().year();
205
205
  const daysIntoCurrentMonth = moment().date();
@@ -214,7 +214,7 @@ const calculateBudgetAnalytics = (monthlyCosts, annualBudget) => {
214
214
  yearToDateSpent += monthCost;
215
215
  monthlySpending.push(monthCost);
216
216
  } else if (month === currentMonth) {
217
- projectedCurrentMonthCost = monthCost / daysIntoCurrentMonth * daysInCurrentMonth;
217
+ projectedCurrentMonthCost = forecast ?? monthCost / daysIntoCurrentMonth * daysInCurrentMonth;
218
218
  yearToDateSpent += monthCost;
219
219
  monthlySpending.push(projectedCurrentMonthCost);
220
220
  }
@@ -1 +1 @@
1
- {"version":3,"file":"functions.esm.js","sources":["../../src/api/functions.ts"],"sourcesContent":["import { format, parse, subDays, subMonths } from 'date-fns';\nimport { reduce } from 'lodash';\nimport moment from 'moment';\nimport { Filters, Report, Tag } from './types';\n\nexport const mergeCostReports = (reports: Report[], threshold?: number): Report[] => {\n const totalCosts: { id: string; total: number }[] = [];\n reports.forEach(report => {\n let total = 0;\n Object.values(report.reports).forEach(v => {\n total += v as number;\n });\n totalCosts.push({ id: report.id, total: total });\n });\n totalCosts.sort((a, b) => b.total - a.total);\n const idsToBeKept = totalCosts.slice(0, threshold).map(v => v.id);\n\n const mergedReports = reduce(\n reports,\n (accumulator: { [key: string]: Report }, report) => {\n let keyName = 'Others';\n if (idsToBeKept.includes(report.id)) {\n keyName = report.id;\n }\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n reports: {},\n };\n }\n\n Object.keys(report.reports).forEach(key => {\n if (accumulator[keyName].reports[key]) {\n accumulator[keyName].reports[key] += report.reports[key];\n } else {\n accumulator[keyName].reports[key] = report.reports[key];\n }\n });\n return accumulator;\n },\n {},\n );\n\n return Object.values(mergedReports).sort((a, b) => a.id.localeCompare(b.id));\n};\n\nexport const filterCostReports = (reports: Report[], filters: Filters): Report[] => {\n const filteredReports = reports.filter(report => {\n let match = true;\n Object.keys(filters).forEach(key => {\n if (filters[key].length > 0) {\n const reportValue = report[key] as string | undefined;\n\n // If the report doesn't have this field at all, it doesn't match\n if (reportValue === undefined) {\n match = false;\n return;\n }\n\n // Check if the report value matches any of the filter values\n const valueMatches = filters[key].some(filterValue => {\n // For exact matches\n if (reportValue === filterValue) {\n return true;\n }\n\n // For account field: match with or without account ID suffix\n // e.g., \"AWS/aws-staging-mock\" should match \"AWS/aws-staging-mock (012345678901)\"\n if (key === 'account') {\n // Extract the base account name (everything before the parentheses)\n const baseAccountName = reportValue.split(' (')[0];\n const filterAccountName = filterValue.split(' (')[0];\n if (baseAccountName === filterAccountName) {\n return true;\n }\n }\n\n // For service field: handle provider prefix matching\n // e.g., \"AWS/Lambda\" in filter should match \"AWS/Lambda\" in report\n if (key === 'service' && reportValue.includes('/') && filterValue.includes('/')) {\n return reportValue === filterValue;\n }\n\n return false;\n });\n\n if (!valueMatches) {\n match = false;\n }\n }\n });\n return match;\n });\n\n return filteredReports;\n};\n\nexport const aggregateCostReports = (reports: Report[], aggregatedBy?: string): Report[] => {\n const aggregatedReports: { [key: string]: Report } = reduce(\n reports,\n (accumulator, report) => {\n let keyName: string = 'no value';\n if (aggregatedBy && aggregatedBy in report) {\n keyName = report[aggregatedBy] as string;\n } else if (aggregatedBy === 'none') {\n keyName = 'Total';\n }\n\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n provider: report.provider,\n reports: {},\n } as {\n id: string;\n reports: { [key: string]: number };\n [key: string]: any;\n };\n\n if (aggregatedBy !== undefined) {\n accumulator[keyName][aggregatedBy] = keyName;\n }\n }\n\n Object.keys(report.reports).forEach(key => {\n if (accumulator[keyName].reports[key]) {\n accumulator[keyName].reports[key] += report.reports[key];\n } else {\n accumulator[keyName].reports[key] = report.reports[key];\n }\n });\n return accumulator;\n },\n {} as { [key: string]: Report },\n );\n return Object.values(aggregatedReports);\n};\n\nexport const getReportKeyAndValues = (reports: Report[] | undefined): { [key: string]: string[] } => {\n const excludedKeys = ['id', 'reports'];\n const keyValueSets: { [key: string]: Set<string> } = {};\n reports?.forEach(report => {\n Object.keys(report).forEach(key => {\n if (!excludedKeys.includes(key)) {\n if (keyValueSets[key] === undefined) {\n keyValueSets[key] = new Set<string>();\n }\n\n keyValueSets[key].add(report[key] as string);\n }\n });\n });\n\n const keyValues: { [key: string]: string[] } = {};\n Object.keys(keyValueSets).forEach((key: string) => {\n keyValues[key] = Array.from(keyValueSets[key]);\n keyValues[key].sort((a, b) => a.localeCompare(b));\n });\n return keyValues;\n};\n\nexport const extractProvider = (input: string): string | undefined => {\n let provider = undefined;\n if (input && input.indexOf('/') !== -1) {\n provider = input.split('/')[0];\n }\n\n return provider;\n};\n\nexport const extractAccountInfo = (input: string): { accountName: string; accountId?: string } => {\n // try to match format: accountName (accountId), e.g. aws-dev (123456789012)\n const regex = /^(.*?)\\s*\\(([^)]+)\\)$/;\n const match = input.match(regex);\n\n if (match) {\n const accountName = match[1];\n const accountId = match[2];\n return { accountName: accountName, accountId: accountId };\n }\n\n return { accountName: input };\n};\n\n// check if targetTag exists in tags\nexport function tagExists(tags: Tag[], targetTag: Tag): boolean {\n return tags.some(\n tag => tag.provider === targetTag.provider && tag.key === targetTag.key && tag.value === targetTag.value,\n );\n}\n\n// convert Tag array to (provider1:key1=value1 OR provider2:key2=value2) format\nexport const tagsToString = (tags: Tag[]): string => {\n if (tags.length === 0) {\n return '()';\n }\n\n const keyValuePairs = tags.map(tag => `${tag.provider}:${tag.key}=${tag.value}`);\n return `(${keyValuePairs.join(' OR ')})`;\n};\n\nexport const getAllReportTags = (reports: Report[]): string[] => {\n const tags = new Set<string>();\n const reservedKeys = ['id', 'account', 'service', 'category', 'provider', 'reports'];\n reports.forEach(report => {\n Object.keys(report).forEach(key => {\n if (reservedKeys.indexOf(key) === -1) {\n tags.add(key);\n }\n });\n });\n return Array.from(tags);\n};\n\nexport const getPreviousMonth = (month: string): string => {\n const date = parse(month, 'yyyy-MM', new Date());\n const previousMonth = subMonths(date, 1);\n return format(previousMonth, 'yyyy-MM');\n};\n\nexport const getPreviousDay = (day: string): string => {\n const date = parse(day, 'yyyy-MM-dd', new Date());\n const previousDay = subDays(date, 1);\n return format(previousDay, 'yyyy-MM-dd');\n};\n\nexport const getPeriodStrings = (granularity: string, startTime: Date, endTime: Date): string[] => {\n const result: string[] = [];\n const current = moment(startTime);\n\n while (current.isSameOrBefore(endTime) && current.isSameOrBefore(moment())) {\n if (granularity === 'monthly') {\n result.push(current.format('YYYY-MM'));\n current.add(1, 'months');\n } else {\n result.push(current.format('YYYY-MM-DD'));\n current.add(1, 'days');\n }\n }\n\n return result;\n};\n\nexport const formatCurrency = (number: number, currency?: string): string => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency || 'USD',\n notation: 'compact',\n }).format(number);\n};\n\nexport interface BudgetAnalytics {\n yearToDateSpent: number;\n monthlyRunRate: number;\n projectedAnnualSpending: number;\n projectedCurrentMonthCost: number;\n budgetHealthStatus: 'healthy' | 'warning' | 'critical';\n budgetUtilizationPercent: number;\n targetMonthlySpending: number;\n monthsRemaining: number;\n averageMonthlySpending: number;\n spendingVelocity: number;\n confidenceRange: {\n low: number;\n high: number;\n };\n}\n\nexport const calculateBudgetAnalytics = (\n monthlyCosts: Record<string, number>,\n annualBudget: number,\n): BudgetAnalytics => {\n const currentMonth = moment().month() + 1;\n const currentYear = moment().year();\n const daysIntoCurrentMonth = moment().date();\n const daysInCurrentMonth = moment().daysInMonth();\n\n let yearToDateSpent = 0;\n let projectedCurrentMonthCost = 0;\n const monthlySpending: number[] = [];\n\n for (let month = 1; month <= currentMonth; month++) {\n const monthKey = `${currentYear}-${month.toString().padStart(2, '0')}`;\n const monthCost = monthlyCosts[monthKey] || 0;\n\n if (month < currentMonth) {\n yearToDateSpent += monthCost;\n monthlySpending.push(monthCost);\n } else if (month === currentMonth) {\n projectedCurrentMonthCost = (monthCost / daysIntoCurrentMonth) * daysInCurrentMonth;\n yearToDateSpent += monthCost;\n monthlySpending.push(projectedCurrentMonthCost);\n }\n }\n\n const monthsRemaining = 12 - currentMonth + (1 - daysIntoCurrentMonth / daysInCurrentMonth);\n const averageMonthlySpending =\n monthlySpending.length > 0 ? monthlySpending.reduce((sum, cost) => sum + cost, 0) / monthlySpending.length : 0;\n\n const monthlyRunRate = monthlySpending.length > 0 ? monthlySpending[monthlySpending.length - 1] || 0 : 0;\n\n const projectedAnnualSpending = yearToDateSpent + averageMonthlySpending * monthsRemaining;\n\n const budgetUtilizationPercent = annualBudget > 0 ? (yearToDateSpent / annualBudget) * 100 : 0;\n const expectedUtilizationPercent = ((currentMonth - 1 + daysIntoCurrentMonth / daysInCurrentMonth) / 12) * 100;\n\n let budgetHealthStatus: 'healthy' | 'warning' | 'critical' = 'healthy';\n if (budgetUtilizationPercent > expectedUtilizationPercent + 20) {\n budgetHealthStatus = 'critical';\n } else if (budgetUtilizationPercent > expectedUtilizationPercent + 10) {\n budgetHealthStatus = 'warning';\n }\n\n const targetMonthlySpending = monthsRemaining > 0 ? (annualBudget - yearToDateSpent) / monthsRemaining : 0;\n\n const spendingVariance =\n monthlySpending.length > 1\n ? Math.sqrt(\n monthlySpending.reduce((sum, cost) => sum + Math.pow(cost - averageMonthlySpending, 2), 0) /\n (monthlySpending.length - 1),\n )\n : 0;\n\n const spendingVelocity =\n monthlySpending.length >= 2\n ? ((monthlySpending[monthlySpending.length - 1] - monthlySpending[monthlySpending.length - 2]) /\n monthlySpending[monthlySpending.length - 2]) *\n 100\n : 0;\n\n const confidenceRange = {\n low: Math.max(0, projectedAnnualSpending - spendingVariance * 2 * Math.sqrt(monthsRemaining)),\n high: projectedAnnualSpending + spendingVariance * 2 * Math.sqrt(monthsRemaining),\n };\n\n return {\n yearToDateSpent,\n monthlyRunRate,\n projectedAnnualSpending,\n projectedCurrentMonthCost,\n budgetHealthStatus,\n budgetUtilizationPercent,\n targetMonthlySpending,\n monthsRemaining,\n averageMonthlySpending,\n spendingVelocity,\n confidenceRange,\n };\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"functions.esm.js","sources":["../../src/api/functions.ts"],"sourcesContent":["import { format, parse, subDays, subMonths } from 'date-fns';\nimport { reduce } from 'lodash';\nimport moment from 'moment';\nimport { Filters, Report, Tag } from './types';\n\nexport const mergeCostReports = (reports: Report[], threshold?: number): Report[] => {\n const totalCosts: { id: string; total: number }[] = [];\n reports.forEach(report => {\n let total = 0;\n Object.values(report.reports).forEach(v => {\n total += v as number;\n });\n totalCosts.push({ id: report.id, total: total });\n });\n totalCosts.sort((a, b) => b.total - a.total);\n const idsToBeKept = totalCosts.slice(0, threshold).map(v => v.id);\n\n const mergedReports = reduce(\n reports,\n (accumulator: { [key: string]: Report }, report) => {\n let keyName = 'Others';\n if (idsToBeKept.includes(report.id)) {\n keyName = report.id;\n }\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n reports: {},\n };\n }\n\n Object.keys(report.reports).forEach(key => {\n if (accumulator[keyName].reports[key]) {\n accumulator[keyName].reports[key] += report.reports[key];\n } else {\n accumulator[keyName].reports[key] = report.reports[key];\n }\n });\n return accumulator;\n },\n {},\n );\n\n return Object.values(mergedReports).sort((a, b) => a.id.localeCompare(b.id));\n};\n\nexport const filterCostReports = (reports: Report[], filters: Filters): Report[] => {\n const filteredReports = reports.filter(report => {\n let match = true;\n Object.keys(filters).forEach(key => {\n if (filters[key].length > 0) {\n const reportValue = report[key] as string | undefined;\n\n // If the report doesn't have this field at all, it doesn't match\n if (reportValue === undefined) {\n match = false;\n return;\n }\n\n // Check if the report value matches any of the filter values\n const valueMatches = filters[key].some(filterValue => {\n // For exact matches\n if (reportValue === filterValue) {\n return true;\n }\n\n // For account field: match with or without account ID suffix\n // e.g., \"AWS/aws-staging-mock\" should match \"AWS/aws-staging-mock (012345678901)\"\n if (key === 'account') {\n // Extract the base account name (everything before the parentheses)\n const baseAccountName = reportValue.split(' (')[0];\n const filterAccountName = filterValue.split(' (')[0];\n if (baseAccountName === filterAccountName) {\n return true;\n }\n }\n\n // For service field: handle provider prefix matching\n // e.g., \"AWS/Lambda\" in filter should match \"AWS/Lambda\" in report\n if (key === 'service' && reportValue.includes('/') && filterValue.includes('/')) {\n return reportValue === filterValue;\n }\n\n return false;\n });\n\n if (!valueMatches) {\n match = false;\n }\n }\n });\n return match;\n });\n\n return filteredReports;\n};\n\nexport const aggregateCostReports = (reports: Report[], aggregatedBy?: string): Report[] => {\n const aggregatedReports: { [key: string]: Report } = reduce(\n reports,\n (accumulator, report) => {\n let keyName: string = 'no value';\n if (aggregatedBy && aggregatedBy in report) {\n keyName = report[aggregatedBy] as string;\n } else if (aggregatedBy === 'none') {\n keyName = 'Total';\n }\n\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n provider: report.provider,\n reports: {},\n } as {\n id: string;\n reports: { [key: string]: number };\n [key: string]: any;\n };\n\n if (aggregatedBy !== undefined) {\n accumulator[keyName][aggregatedBy] = keyName;\n }\n }\n\n Object.keys(report.reports).forEach(key => {\n if (accumulator[keyName].reports[key]) {\n accumulator[keyName].reports[key] += report.reports[key];\n } else {\n accumulator[keyName].reports[key] = report.reports[key];\n }\n });\n return accumulator;\n },\n {} as { [key: string]: Report },\n );\n return Object.values(aggregatedReports);\n};\n\nexport const getReportKeyAndValues = (reports: Report[] | undefined): { [key: string]: string[] } => {\n const excludedKeys = ['id', 'reports'];\n const keyValueSets: { [key: string]: Set<string> } = {};\n reports?.forEach(report => {\n Object.keys(report).forEach(key => {\n if (!excludedKeys.includes(key)) {\n if (keyValueSets[key] === undefined) {\n keyValueSets[key] = new Set<string>();\n }\n\n keyValueSets[key].add(report[key] as string);\n }\n });\n });\n\n const keyValues: { [key: string]: string[] } = {};\n Object.keys(keyValueSets).forEach((key: string) => {\n keyValues[key] = Array.from(keyValueSets[key]);\n keyValues[key].sort((a, b) => a.localeCompare(b));\n });\n return keyValues;\n};\n\nexport const extractProvider = (input: string): string | undefined => {\n let provider = undefined;\n if (input && input.indexOf('/') !== -1) {\n provider = input.split('/')[0];\n }\n\n return provider;\n};\n\nexport const extractAccountInfo = (input: string): { accountName: string; accountId?: string } => {\n // try to match format: accountName (accountId), e.g. aws-dev (123456789012)\n const regex = /^(.*?)\\s*\\(([^)]+)\\)$/;\n const match = input.match(regex);\n\n if (match) {\n const accountName = match[1];\n const accountId = match[2];\n return { accountName: accountName, accountId: accountId };\n }\n\n return { accountName: input };\n};\n\n// check if targetTag exists in tags\nexport function tagExists(tags: Tag[], targetTag: Tag): boolean {\n return tags.some(\n tag => tag.provider === targetTag.provider && tag.key === targetTag.key && tag.value === targetTag.value,\n );\n}\n\n// convert Tag array to (provider1:key1=value1 OR provider2:key2=value2) format\nexport const tagsToString = (tags: Tag[]): string => {\n if (tags.length === 0) {\n return '()';\n }\n\n const keyValuePairs = tags.map(tag => `${tag.provider}:${tag.key}=${tag.value}`);\n return `(${keyValuePairs.join(' OR ')})`;\n};\n\nexport const getAllReportTags = (reports: Report[]): string[] => {\n const tags = new Set<string>();\n const reservedKeys = ['id', 'account', 'service', 'category', 'provider', 'reports'];\n reports.forEach(report => {\n Object.keys(report).forEach(key => {\n if (reservedKeys.indexOf(key) === -1) {\n tags.add(key);\n }\n });\n });\n return Array.from(tags);\n};\n\nexport const getPreviousMonth = (month: string): string => {\n const date = parse(month, 'yyyy-MM', new Date());\n const previousMonth = subMonths(date, 1);\n return format(previousMonth, 'yyyy-MM');\n};\n\nexport const getPreviousDay = (day: string): string => {\n const date = parse(day, 'yyyy-MM-dd', new Date());\n const previousDay = subDays(date, 1);\n return format(previousDay, 'yyyy-MM-dd');\n};\n\nexport const getPeriodStrings = (granularity: string, startTime: Date, endTime: Date): string[] => {\n const result: string[] = [];\n const current = moment(startTime);\n\n while (current.isSameOrBefore(endTime) && current.isSameOrBefore(moment())) {\n if (granularity === 'monthly') {\n result.push(current.format('YYYY-MM'));\n current.add(1, 'months');\n } else {\n result.push(current.format('YYYY-MM-DD'));\n current.add(1, 'days');\n }\n }\n\n return result;\n};\n\nexport const formatCurrency = (number: number, currency?: string): string => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency || 'USD',\n notation: 'compact',\n }).format(number);\n};\n\nexport interface BudgetAnalytics {\n yearToDateSpent: number;\n monthlyRunRate: number;\n projectedAnnualSpending: number;\n projectedCurrentMonthCost: number;\n budgetHealthStatus: 'healthy' | 'warning' | 'critical';\n budgetUtilizationPercent: number;\n targetMonthlySpending: number;\n monthsRemaining: number;\n averageMonthlySpending: number;\n spendingVelocity: number;\n confidenceRange: {\n low: number;\n high: number;\n };\n}\n\nexport const calculateBudgetAnalytics = (\n monthlyCosts: Record<string, number>,\n annualBudget: number,\n forecast?: number,\n): BudgetAnalytics => {\n const currentMonth = moment().month() + 1;\n const currentYear = moment().year();\n const daysIntoCurrentMonth = moment().date();\n const daysInCurrentMonth = moment().daysInMonth();\n let yearToDateSpent = 0;\n let projectedCurrentMonthCost = 0;\n const monthlySpending: number[] = [];\n for (let month = 1; month <= currentMonth; month++) {\n const monthKey = `${currentYear}-${month.toString().padStart(2, '0')}`;\n const monthCost = monthlyCosts[monthKey] || 0;\n\n if (month < currentMonth) {\n yearToDateSpent += monthCost;\n monthlySpending.push(monthCost);\n } else if (month === currentMonth) {\n projectedCurrentMonthCost = forecast ?? (monthCost / daysIntoCurrentMonth) * daysInCurrentMonth;\n yearToDateSpent += monthCost;\n monthlySpending.push(projectedCurrentMonthCost);\n }\n }\n\n const monthsRemaining = 12 - currentMonth + (1 - daysIntoCurrentMonth / daysInCurrentMonth);\n const averageMonthlySpending =\n monthlySpending.length > 0 ? monthlySpending.reduce((sum, cost) => sum + cost, 0) / monthlySpending.length : 0;\n\n const monthlyRunRate = monthlySpending.length > 0 ? monthlySpending[monthlySpending.length - 1] || 0 : 0;\n\n const projectedAnnualSpending = yearToDateSpent + averageMonthlySpending * monthsRemaining;\n\n const budgetUtilizationPercent = annualBudget > 0 ? (yearToDateSpent / annualBudget) * 100 : 0;\n const expectedUtilizationPercent = ((currentMonth - 1 + daysIntoCurrentMonth / daysInCurrentMonth) / 12) * 100;\n\n let budgetHealthStatus: 'healthy' | 'warning' | 'critical' = 'healthy';\n if (budgetUtilizationPercent > expectedUtilizationPercent + 20) {\n budgetHealthStatus = 'critical';\n } else if (budgetUtilizationPercent > expectedUtilizationPercent + 10) {\n budgetHealthStatus = 'warning';\n }\n\n const targetMonthlySpending = monthsRemaining > 0 ? (annualBudget - yearToDateSpent) / monthsRemaining : 0;\n\n const spendingVariance =\n monthlySpending.length > 1\n ? Math.sqrt(\n monthlySpending.reduce((sum, cost) => sum + Math.pow(cost - averageMonthlySpending, 2), 0) /\n (monthlySpending.length - 1),\n )\n : 0;\n\n const spendingVelocity =\n monthlySpending.length >= 2\n ? ((monthlySpending[monthlySpending.length - 1] - monthlySpending[monthlySpending.length - 2]) /\n monthlySpending[monthlySpending.length - 2]) *\n 100\n : 0;\n\n const confidenceRange = {\n low: Math.max(0, projectedAnnualSpending - spendingVariance * 2 * Math.sqrt(monthsRemaining)),\n high: projectedAnnualSpending + spendingVariance * 2 * Math.sqrt(monthsRemaining),\n };\n\n return {\n yearToDateSpent,\n monthlyRunRate,\n projectedAnnualSpending,\n projectedCurrentMonthCost,\n budgetHealthStatus,\n budgetUtilizationPercent,\n targetMonthlySpending,\n monthsRemaining,\n averageMonthlySpending,\n spendingVelocity,\n confidenceRange,\n };\n};\n"],"names":[],"mappings":"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"}
@@ -99,12 +99,12 @@ function getRecommendationColor(type) {
99
99
  function BudgetChart(props) {
100
100
  const { height } = useDrawingArea();
101
101
  const theme = useTheme();
102
- const { provider, monthlyCosts, view, budgets, setBudgets } = props;
102
+ const { provider, monthlyCosts, view, budgets, setBudgets, forecast } = props;
103
103
  const infraWalletApi = useApi(infraWalletApiRef);
104
104
  const annualBudget = budgets.find((b) => b.provider.toLowerCase() === provider.toLowerCase());
105
105
  const annualBudgetAmount = annualBudget?.amount || 0;
106
106
  const [openManageBudget, setOpenManageBudget] = useState(false);
107
- const budgetAnalytics = calculateBudgetAnalytics(monthlyCosts, annualBudgetAmount);
107
+ const budgetAnalytics = calculateBudgetAnalytics(monthlyCosts, annualBudgetAmount, forecast);
108
108
  const updateBudget = async (event) => {
109
109
  event.preventDefault();
110
110
  const formData = new FormData(event.currentTarget);
@@ -155,7 +155,7 @@ function BudgetChart(props) {
155
155
  const lastActualCost = lastIndex >= 0 ? nonAccumulatedCosts[lastIndex] : 0;
156
156
  const projectedCurrentMonthCost = budgetAnalytics.projectedCurrentMonthCost;
157
157
  const projectedDelta = projectedCurrentMonthCost - lastActualCost;
158
- const monthlyMax = max([...nonAccumulatedCosts, budgetAmount]) || 0;
158
+ const monthlyMax = max([...nonAccumulatedCosts, budgetAmount, projectedCurrentMonthCost]) || 0;
159
159
  chartSeries = [
160
160
  {
161
161
  id: "actual-spend",
@@ -398,6 +398,7 @@ const Budgets = ({ providerErrorsSetter }) => {
398
398
  const [reportsAggregatedAndMerged, setReportsAggregatedAndMerged] = useState(void 0);
399
399
  const [budgetView, setBudgetView] = useState("Annual" /* ANNUAL */);
400
400
  const [budgets, setBudgets] = useState([]);
401
+ const [forecasts, setForecasts] = useState({});
401
402
  const infraWalletApi = useApi(infraWalletApiRef);
402
403
  const alertApi = useApi(alertApiRef);
403
404
  const fetchCosts = useCallback(async () => {
@@ -406,6 +407,7 @@ const Budgets = ({ providerErrorsSetter }) => {
406
407
  const aggregatedReports = aggregateCostReports(reportsResponse.data, "provider");
407
408
  const aggregatedAndMergedReports = mergeCostReports(aggregatedReports);
408
409
  setReportsAggregatedAndMerged(aggregatedAndMergedReports);
410
+ setForecasts(reportsResponse.forecasts || {});
409
411
  }
410
412
  if (reportsResponse.status === 207 && reportsResponse.errors) {
411
413
  providerErrorsSetter(reportsResponse.errors);
@@ -438,7 +440,8 @@ const Budgets = ({ providerErrorsSetter }) => {
438
440
  monthlyCosts: report.reports,
439
441
  view: budgetView,
440
442
  budgets,
441
- setBudgets
443
+ setBudgets,
444
+ forecast: forecasts[report.id]
442
445
  }
443
446
  ))) : /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(
444
447
  Paper,
@@ -1 +1 @@
1
- {"version":3,"file":"Budgets.esm.js","sources":["../../../src/components/Budgets/Budgets.tsx"],"sourcesContent":["import { alertApiRef, useApi } from '@backstage/core-plugin-api';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Card from '@mui/material/Card';\nimport CardContent from '@mui/material/CardContent';\nimport Chip from '@mui/material/Chip';\nimport Dialog from '@mui/material/Dialog';\nimport DialogActions from '@mui/material/DialogActions';\nimport DialogContent from '@mui/material/DialogContent';\nimport DialogContentText from '@mui/material/DialogContentText';\nimport DialogTitle from '@mui/material/DialogTitle';\nimport FormControl from '@mui/material/FormControl';\nimport Grid from '@mui/material/Grid';\nimport Input from '@mui/material/Input';\nimport InputAdornment from '@mui/material/InputAdornment';\nimport InputLabel from '@mui/material/InputLabel';\nimport Paper from '@mui/material/Paper';\nimport Skeleton from '@mui/material/Skeleton';\nimport { useTheme } from '@mui/material/styles';\nimport Switch from '@mui/material/Switch';\nimport Typography from '@mui/material/Typography';\nimport {\n BarPlot,\n ResponsiveChartContainer,\n ChartsAxisHighlight,\n ChartsGrid,\n ChartsReferenceLine,\n ChartsTooltip,\n ChartsXAxis,\n ChartsYAxis,\n LineHighlightPlot,\n LinePlot,\n MarkPlot,\n useDrawingArea,\n} from '@mui/x-charts';\nimport { max } from 'lodash';\nimport moment from 'moment';\nimport React, { FC, useCallback, useEffect, useState } from 'react';\nimport {\n aggregateCostReports,\n formatCurrency,\n mergeCostReports,\n calculateBudgetAnalytics,\n BudgetAnalytics,\n} from '../../api/functions';\nimport { infraWalletApiRef } from '../../api/InfraWalletApi';\nimport { Budget, Report } from '../../api/types';\nimport { colorList } from '../constants';\nimport { ProviderIcon } from '../ProviderIcon';\nimport { BudgetsProps } from '../types';\n\nconst enum BUDGET_VIEW {\n MONTHLY = 'Monthly',\n ANNUAL = 'Annual',\n}\n\nconst monthList = {\n '01': 'Jan',\n '02': 'Feb',\n '03': 'Mar',\n '04': 'Apr',\n '05': 'May',\n '06': 'Jun',\n '07': 'Jul',\n '08': 'Aug',\n '09': 'Sep',\n '10': 'Oct',\n '11': 'Nov',\n '12': 'Dec',\n};\n\ninterface BudgetHealthIndicatorProps {\n status: 'healthy' | 'warning' | 'critical';\n utilizationPercent: number;\n}\n\nfunction BudgetHealthIndicator({ status, utilizationPercent }: BudgetHealthIndicatorProps) {\n const getStatusColor = () => {\n switch (status) {\n case 'healthy':\n return '#4caf50';\n case 'warning':\n return '#ff9800';\n case 'critical':\n return '#f44336';\n default:\n return '#9e9e9e';\n }\n };\n\n const getStatusLabel = () => {\n switch (status) {\n case 'healthy':\n return 'On Track';\n case 'warning':\n return 'At Risk';\n case 'critical':\n return 'Over Budget';\n default:\n return 'Unknown';\n }\n };\n\n return (\n <Chip\n label={`${getStatusLabel()} (${utilizationPercent.toFixed(1)}%)`}\n size=\"small\"\n sx={{\n backgroundColor: getStatusColor(),\n color: 'white',\n fontWeight: 'bold',\n '& .MuiChip-label': { fontWeight: 'bold' },\n }}\n />\n );\n}\n\ninterface BudgetChartProps {\n provider: string;\n monthlyCosts: Record<string, number>;\n view: string;\n budgets: Budget[];\n setBudgets: React.Dispatch<React.SetStateAction<Budget[]>>;\n}\n\nfunction getSpendingVelocityColor(velocity: number) {\n if (velocity > 10) return 'error';\n if (velocity < -10) return 'success.main';\n return 'textSecondary';\n}\n\nfunction getSpendingVelocityIcon(velocity: number) {\n if (velocity > 0) return '↑';\n if (velocity < 0) return '↓';\n return '→';\n}\n\nfunction getRecommendationColor(type: string) {\n if (type === 'critical') return 'error';\n if (type === 'warning') return 'warning';\n return 'info';\n}\n\nfunction BudgetChart(props: Readonly<BudgetChartProps>) {\n const { height } = useDrawingArea();\n const theme = useTheme();\n const { provider, monthlyCosts, view, budgets, setBudgets } = props;\n const infraWalletApi = useApi(infraWalletApiRef);\n\n const annualBudget = budgets.find(b => b.provider.toLowerCase() === provider.toLowerCase());\n const annualBudgetAmount = annualBudget?.amount || 0;\n\n const [openManageBudget, setOpenManageBudget] = useState(false);\n\n const budgetAnalytics: BudgetAnalytics = calculateBudgetAnalytics(monthlyCosts, annualBudgetAmount);\n\n const updateBudget = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const formData = new FormData(event.currentTarget);\n const amount = Number(formData.get('amount') || 0);\n const updated: Budget = {\n id: annualBudget?.id,\n provider: provider,\n name: annualBudget?.name || `${provider} annual budget`,\n amount: amount,\n };\n await infraWalletApi.updateBudget('default', updated);\n setBudgets(prev => {\n const index = prev.findIndex(b => b.provider.toLowerCase() === provider.toLowerCase());\n if (index >= 0) {\n const copy = [...prev];\n copy[index] = { ...copy[index], ...updated };\n return copy;\n }\n return [...prev, updated];\n });\n setOpenManageBudget(false);\n };\n\n const nonAccumulatedCosts: number[] = [];\n const accumulatedCosts: number[] = [];\n for (const month of Object.keys(monthList).sort((a, b) => Number(a) - Number(b))) {\n const yearMonth = `${moment().year()}-${month}`;\n\n let cost;\n if (yearMonth in monthlyCosts) {\n cost = monthlyCosts[yearMonth];\n } else if (Number(month) < moment().month()) {\n cost = 0;\n } else {\n break;\n }\n\n nonAccumulatedCosts.push(cost);\n if (month === '01') {\n accumulatedCosts.push(cost);\n } else {\n accumulatedCosts.push(accumulatedCosts[accumulatedCosts.length - 1] + cost);\n }\n }\n\n let budgetAmount = annualBudgetAmount;\n\n let chartSeries: any[];\n let yAxis: any[];\n\n if (view === BUDGET_VIEW.MONTHLY) {\n budgetAmount = budgetAmount / 12;\n\n const lastIndex = nonAccumulatedCosts.length - 1;\n const lastActualCost = lastIndex >= 0 ? nonAccumulatedCosts[lastIndex] : 0;\n const projectedCurrentMonthCost = budgetAnalytics.projectedCurrentMonthCost;\n const projectedDelta = projectedCurrentMonthCost - lastActualCost;\n const monthlyMax = max([...nonAccumulatedCosts, budgetAmount]) || 0;\n\n chartSeries = [\n {\n id: 'actual-spend',\n yAxisKey: 'spendAxis',\n data: nonAccumulatedCosts,\n type: 'bar',\n stack: 'combined',\n label: 'Actual Spend',\n color: colorList[0],\n valueFormatter: (value: number | null) => formatCurrency(value || 0),\n },\n ];\n\n if (lastIndex >= 0 && projectedDelta > 0) {\n const deltaData = nonAccumulatedCosts.map((_, i) => (i === lastIndex ? projectedDelta : 0));\n\n chartSeries.push({\n id: 'projected-delta',\n yAxisKey: 'deltaAxis',\n data: deltaData,\n type: 'bar',\n stack: 'combined',\n label: 'Projected Delta',\n color: theme.palette.warning.main,\n valueFormatter: (value: number | null) => {\n if (value === 0) return null;\n return formatCurrency(value || 0);\n },\n });\n }\n\n yAxis = [\n {\n id: 'spendAxis',\n min: 0,\n max: monthlyMax,\n valueFormatter: (value: number | null) => formatCurrency(value || 0),\n colorMap: {\n type: 'piecewise',\n thresholds: [budgetAmount > 0 ? budgetAmount : Number.MAX_SAFE_INTEGER],\n colors: [colorList[0], theme.palette.error.main],\n },\n },\n {\n id: 'deltaAxis',\n min: 0,\n max: monthlyMax,\n },\n ];\n } else {\n chartSeries = [\n {\n id: 'yearAxis',\n yAxisKey: 'spendAxis',\n data: accumulatedCosts,\n type: 'line',\n showMark: false,\n valueFormatter: (value: number | null) => formatCurrency(value || 0),\n },\n ];\n\n yAxis = [\n {\n id: 'spendAxis',\n min: 0,\n max: max([...accumulatedCosts, budgetAmount, budgetAnalytics.confidenceRange.high]),\n valueFormatter: (value: number | null) => formatCurrency(value || 0),\n colorMap: {\n type: 'piecewise',\n thresholds: [budgetAmount > 0 ? budgetAmount : Number.MAX_SAFE_INTEGER],\n colors: [colorList[0], theme.palette.error.main],\n },\n },\n ];\n }\n\n return (\n <Paper sx={{ padding: 2 }}>\n {/* Budget Health Header */}\n <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>\n <Box sx={{ display: 'flex', alignItems: 'center' }}>\n <ProviderIcon provider={provider} />\n <Typography variant=\"h6\" sx={{ ml: 1, fontWeight: 'bold' }}>\n {provider}\n </Typography>\n </Box>\n {annualBudgetAmount > 0 && (\n <BudgetHealthIndicator\n status={budgetAnalytics.budgetHealthStatus}\n utilizationPercent={budgetAnalytics.budgetUtilizationPercent}\n />\n )}\n </Box>\n\n {/* Budget Metrics Cards */}\n {annualBudgetAmount > 0 && (\n <Grid container spacing={1} sx={{ mb: 2 }}>\n <Grid item xs={6}>\n <Card variant=\"outlined\" sx={{ textAlign: 'center' }}>\n <CardContent sx={{ py: 1, '&:last-child': { pb: 1 } }}>\n <Typography variant=\"caption\" color=\"textSecondary\">\n YTD Spent\n </Typography>\n <Typography variant=\"body2\" fontWeight=\"bold\">\n {formatCurrency(budgetAnalytics.yearToDateSpent)}\n </Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n of {formatCurrency(annualBudgetAmount)}\n </Typography>\n </CardContent>\n </Card>\n </Grid>\n <Grid item xs={6}>\n <Card variant=\"outlined\" sx={{ textAlign: 'center' }}>\n <CardContent sx={{ py: 1, '&:last-child': { pb: 1 } }}>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Projected Annual\n </Typography>\n <Typography\n variant=\"body2\"\n fontWeight=\"bold\"\n color={budgetAnalytics.projectedAnnualSpending > annualBudgetAmount ? 'error' : 'inherit'}\n >\n {formatCurrency(budgetAnalytics.projectedAnnualSpending)}\n </Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n {budgetAnalytics.projectedAnnualSpending > annualBudgetAmount\n ? `+${formatCurrency(budgetAnalytics.projectedAnnualSpending - annualBudgetAmount)} over`\n : `${formatCurrency(annualBudgetAmount - budgetAnalytics.projectedAnnualSpending)} under`}\n </Typography>\n </CardContent>\n </Card>\n </Grid>\n <Grid item xs={6}>\n <Card variant=\"outlined\" sx={{ textAlign: 'center' }}>\n <CardContent sx={{ py: 1, '&:last-child': { pb: 1 } }}>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Monthly Run Rate\n </Typography>\n <Typography variant=\"body2\" fontWeight=\"bold\">\n {formatCurrency(budgetAnalytics.monthlyRunRate)}\n </Typography>\n <Typography variant=\"caption\" color={getSpendingVelocityColor(budgetAnalytics.spendingVelocity)}>\n {getSpendingVelocityIcon(budgetAnalytics.spendingVelocity)}\n {Math.abs(budgetAnalytics.spendingVelocity).toFixed(1)}% MoM\n </Typography>\n </CardContent>\n </Card>\n </Grid>\n <Grid item xs={6}>\n <Card variant=\"outlined\" sx={{ textAlign: 'center' }}>\n <CardContent sx={{ py: 1, '&:last-child': { pb: 1 } }}>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Target Monthly\n </Typography>\n <Typography\n variant=\"body2\"\n fontWeight=\"bold\"\n color={\n budgetAnalytics.targetMonthlySpending < budgetAnalytics.monthlyRunRate ? 'error' : 'success.main'\n }\n >\n {formatCurrency(budgetAnalytics.targetMonthlySpending)}\n </Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n {budgetAnalytics.monthsRemaining.toFixed(1)} months left\n </Typography>\n </CardContent>\n </Card>\n </Grid>\n </Grid>\n )}\n\n <ResponsiveChartContainer\n height={height}\n series={chartSeries}\n xAxis={[\n {\n data: Object.entries(monthList)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([_, value]) => value),\n scaleType: 'band',\n },\n ]}\n yAxis={yAxis}\n >\n <ChartsGrid horizontal />\n <ChartsAxisHighlight x={view === BUDGET_VIEW.ANNUAL ? 'line' : 'band'} />\n <LinePlot />\n <BarPlot />\n <MarkPlot />\n <LineHighlightPlot />\n <ChartsReferenceLine\n y={budgetAmount}\n label={budgetAmount ? formatCurrency(budgetAmount) : undefined}\n labelAlign=\"end\"\n lineStyle={{\n stroke: budgetAmount ? theme.palette.error.main : 'transparent',\n strokeDasharray: '5 5',\n strokeWidth: 1.5,\n strokeOpacity: 0.8,\n }}\n labelStyle={{ fill: theme.palette.error.main, fontSize: '0.9em' }}\n />\n {/* Add projection line for annual view */}\n {view === BUDGET_VIEW.ANNUAL && annualBudgetAmount > 0 && (\n <>\n <ChartsReferenceLine\n y={budgetAnalytics.projectedAnnualSpending}\n label={`Projected: ${formatCurrency(budgetAnalytics.projectedAnnualSpending)}`}\n labelAlign=\"start\"\n lineStyle={{\n stroke: theme.palette.warning.main,\n strokeDasharray: '3 3',\n strokeWidth: 1.5,\n strokeOpacity: 0.8,\n }}\n labelStyle={{ fill: theme.palette.warning.main, fontSize: '0.8em' }}\n />\n {/* Confidence Range - High */}\n <ChartsReferenceLine\n y={budgetAnalytics.confidenceRange.high}\n label={`High: ${formatCurrency(budgetAnalytics.confidenceRange.high)}`}\n labelAlign=\"start\"\n lineStyle={{\n stroke: theme.palette.grey[400],\n strokeDasharray: '2 2',\n strokeWidth: 1,\n strokeOpacity: 0.5,\n }}\n labelStyle={{ fill: theme.palette.grey[600], fontSize: '0.7em' }}\n />\n {/* Confidence Range - Low */}\n <ChartsReferenceLine\n y={budgetAnalytics.confidenceRange.low}\n label={`Low: ${formatCurrency(budgetAnalytics.confidenceRange.low)}`}\n labelAlign=\"start\"\n lineStyle={{\n stroke: theme.palette.grey[400],\n strokeDasharray: '2 2',\n strokeWidth: 1,\n strokeOpacity: 0.5,\n }}\n labelStyle={{ fill: theme.palette.grey[600], fontSize: '0.7em' }}\n />\n </>\n )}\n <ChartsXAxis />\n <ChartsYAxis />\n <ChartsTooltip />\n </ResponsiveChartContainer>\n\n <Box sx={{ textAlign: 'center' }}>\n <Button onClick={() => setOpenManageBudget(true)}>Manage budget</Button>\n <Dialog fullWidth maxWidth=\"sm\" open={openManageBudget} onClose={() => setOpenManageBudget(false)}>\n <form onSubmit={updateBudget}>\n <DialogTitle>Manage Budget</DialogTitle>\n <DialogContent>\n <DialogContentText>Please enter your {props.provider} annual budget here.</DialogContentText>\n <Box sx={{ display: 'flex', alignItems: 'flex-end' }}>\n <ProviderIcon provider={provider} />\n &nbsp;&nbsp;\n <FormControl variant=\"standard\">\n <InputLabel>Amount</InputLabel>\n <Input\n id=\"amount\"\n name=\"amount\"\n type=\"number\"\n startAdornment={<InputAdornment position=\"start\">$</InputAdornment>}\n defaultValue={annualBudgetAmount}\n />\n </FormControl>\n </Box>\n </DialogContent>\n <DialogActions>\n <Button type=\"submit\" variant=\"contained\">\n Submit\n </Button>\n <Button onClick={() => setOpenManageBudget(false)}>Cancel</Button>\n </DialogActions>\n </form>\n </Dialog>\n </Box>\n </Paper>\n );\n}\n\ninterface BudgetInsightsProps {\n reports: Report[];\n budgets: Budget[];\n}\n\nfunction BudgetInsights({ reports, budgets }: BudgetInsightsProps) {\n const insights = reports\n .map(report => {\n const budget = budgets.find(b => b.provider.toLowerCase() === report.id.toLowerCase());\n if (!budget?.amount) return null;\n\n const analytics = calculateBudgetAnalytics(report.reports, budget.amount);\n return { provider: report.id, budget, analytics };\n })\n .filter(Boolean);\n\n const totalBudget = budgets.reduce((sum, b) => sum + (b.amount || 0), 0);\n const totalProjected = insights.reduce((sum, i) => sum + (i?.analytics.projectedAnnualSpending || 0), 0);\n const overBudgetProviders = insights.filter(i => i?.analytics.budgetHealthStatus === 'critical');\n const atRiskProviders = insights.filter(i => i?.analytics.budgetHealthStatus === 'warning');\n\n const getRecommendations = () => {\n const recommendations = [];\n\n if (overBudgetProviders.length > 0) {\n recommendations.push({\n type: 'critical',\n message: `${overBudgetProviders.length} provider(s) are over budget: ${overBudgetProviders.map(p => p?.provider).join(', ')}`,\n });\n }\n\n if (atRiskProviders.length > 0) {\n recommendations.push({\n type: 'warning',\n message: `${atRiskProviders.length} provider(s) at risk: ${atRiskProviders.map(p => p?.provider).join(', ')}`,\n });\n }\n\n if (totalProjected > totalBudget) {\n recommendations.push({\n type: 'info',\n message: `Total projected spending (${formatCurrency(totalProjected)}) exceeds total budget (${formatCurrency(totalBudget)}) by ${formatCurrency(totalProjected - totalBudget)}`,\n });\n }\n\n const highVelocityProviders = insights.filter(i => i?.analytics && i.analytics.spendingVelocity > 20);\n if (highVelocityProviders.length > 0) {\n recommendations.push({\n type: 'warning',\n message: `High spending acceleration detected in: ${highVelocityProviders.map(p => p?.provider).join(', ')}`,\n });\n }\n\n return recommendations;\n };\n\n const recommendations = getRecommendations();\n\n if (insights.length === 0) return null;\n\n return (\n <Card sx={{ mb: 3 }}>\n <CardContent>\n <Typography variant=\"h6\" gutterBottom>\n Budget Insights\n </Typography>\n\n {/* Overview Stats */}\n <Grid container spacing={2} sx={{ mb: 2 }}>\n <Grid item xs={3}>\n <Box textAlign=\"center\">\n <Typography variant=\"h4\" color=\"primary\">\n {insights.length}\n </Typography>\n <Typography variant=\"caption\">Providers</Typography>\n </Box>\n </Grid>\n <Grid item xs={3}>\n <Box textAlign=\"center\">\n <Typography variant=\"h4\" color={overBudgetProviders.length > 0 ? 'error' : 'success.main'}>\n {overBudgetProviders.length}\n </Typography>\n <Typography variant=\"caption\">Over Budget</Typography>\n </Box>\n </Grid>\n <Grid item xs={3}>\n <Box textAlign=\"center\">\n <Typography variant=\"h4\" color={atRiskProviders.length > 0 ? 'warning.main' : 'success.main'}>\n {atRiskProviders.length}\n </Typography>\n <Typography variant=\"caption\">At Risk</Typography>\n </Box>\n </Grid>\n <Grid item xs={3}>\n <Box textAlign=\"center\">\n <Typography variant=\"h4\" color={totalProjected > totalBudget ? 'error' : 'success.main'}>\n {((totalProjected / totalBudget) * 100).toFixed(0)}%\n </Typography>\n <Typography variant=\"caption\">Projected vs Budget</Typography>\n </Box>\n </Grid>\n </Grid>\n\n {/* Recommendations */}\n {recommendations.length > 0 && (\n <Box>\n <Typography variant=\"subtitle2\" gutterBottom>\n Recommendations\n </Typography>\n {recommendations.map(rec => (\n <Chip\n key={`${rec.type}-${rec.message}`}\n label={rec.message}\n size=\"small\"\n color={getRecommendationColor(rec.type)}\n variant=\"outlined\"\n sx={{ mr: 1, mb: 1, maxWidth: '100%' }}\n />\n ))}\n </Box>\n )}\n </CardContent>\n </Card>\n );\n}\n\nexport const Budgets: FC<BudgetsProps> = ({ providerErrorsSetter }) => {\n const [reportsAggregatedAndMerged, setReportsAggregatedAndMerged] = useState<Report[] | undefined>(undefined);\n const [budgetView, setBudgetView] = useState(BUDGET_VIEW.ANNUAL);\n const [budgets, setBudgets] = useState<Budget[]>([]);\n\n const infraWalletApi = useApi(infraWalletApiRef);\n const alertApi = useApi(alertApiRef);\n\n const fetchCosts = useCallback(async () => {\n await infraWalletApi\n .getCostReports('', [], '', 'monthly', moment().startOf('y').toDate(), moment().endOf('d').toDate())\n .then(reportsResponse => {\n if (reportsResponse.data) {\n const aggregatedReports = aggregateCostReports(reportsResponse.data, 'provider');\n const aggregatedAndMergedReports = mergeCostReports(aggregatedReports);\n setReportsAggregatedAndMerged(aggregatedAndMergedReports);\n }\n if (reportsResponse.status === 207 && reportsResponse.errors) {\n providerErrorsSetter(reportsResponse.errors);\n }\n })\n .catch(e => alertApi.post({ message: `${e.message}`, severity: 'error' }));\n }, [alertApi, infraWalletApi, providerErrorsSetter]);\n\n useEffect(() => {\n fetchCosts();\n }, [fetchCosts]);\n\n useEffect(() => {\n const fetchBudgets = async () => {\n try {\n const response = await infraWalletApi.getBudgets('default');\n setBudgets(response.data || []);\n } catch (error) {\n // Failed to fetch budgets - silent error handling\n }\n };\n fetchBudgets();\n }, [infraWalletApi]);\n\n return (\n <Grid container spacing={3}>\n <Grid item xs={12}>\n <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>\n <Typography variant=\"h5\">\n {moment().year()} {budgetView} Budgets\n </Typography>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>\n <Typography variant=\"body2\">Annual</Typography>\n <Switch\n size=\"small\"\n onChange={event => setBudgetView(event.target.checked ? BUDGET_VIEW.MONTHLY : BUDGET_VIEW.ANNUAL)}\n />\n <Typography variant=\"body2\">Monthly</Typography>\n </Box>\n </Box>\n </Grid>\n\n {/* Budget Insights Panel */}\n {reportsAggregatedAndMerged && (\n <Grid item xs={12}>\n <BudgetInsights reports={reportsAggregatedAndMerged} budgets={budgets} />\n </Grid>\n )}\n {reportsAggregatedAndMerged !== undefined ? (\n reportsAggregatedAndMerged.map(report => (\n <Grid item key={`${report.id}-grid`} xs={4}>\n <BudgetChart\n provider={report.id}\n monthlyCosts={report.reports}\n view={budgetView}\n budgets={budgets}\n setBudgets={setBudgets}\n />\n </Grid>\n ))\n ) : (\n <Grid item xs={12}>\n <Paper\n sx={{\n display: 'flex',\n flexDirection: 'column',\n height: 500,\n backgroundColor: 'transparent',\n boxShadow: 'none',\n }}\n >\n <div style={{ width: '60%', margin: 'auto' }}>\n <Skeleton />\n <Skeleton />\n <Skeleton />\n </div>\n </Paper>\n </Grid>\n )}\n </Grid>\n );\n};\n"],"names":["recommendations"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDA,MAAM,SAAA,GAAY;AAAA,EAChB,IAAA,EAAM,KAAA;AAAA,EACN,IAAA,EAAM,KAAA;AAAA,EACN,IAAA,EAAM,KAAA;AAAA,EACN,IAAA,EAAM,KAAA;AAAA,EACN,IAAA,EAAM,KAAA;AAAA,EACN,IAAA,EAAM,KAAA;AAAA,EACN,IAAA,EAAM,KAAA;AAAA,EACN,IAAA,EAAM,KAAA;AAAA,EACN,IAAA,EAAM,KAAA;AAAA,EACN,IAAA,EAAM,KAAA;AAAA,EACN,IAAA,EAAM,KAAA;AAAA,EACN,IAAA,EAAM;AACR,CAAA;AAOA,SAAS,qBAAA,CAAsB,EAAE,MAAA,EAAQ,kBAAA,EAAmB,EAA+B;AACzF,EAAA,MAAM,iBAAiB,MAAM;AAC3B,IAAA,QAAQ,MAAA;AAAQ,MACd,KAAK,SAAA;AACH,QAAA,OAAO,SAAA;AAAA,MACT,KAAK,SAAA;AACH,QAAA,OAAO,SAAA;AAAA,MACT,KAAK,UAAA;AACH,QAAA,OAAO,SAAA;AAAA,MACT;AACE,QAAA,OAAO,SAAA;AAAA;AACX,GACF;AAEA,EAAA,MAAM,iBAAiB,MAAM;AAC3B,IAAA,QAAQ,MAAA;AAAQ,MACd,KAAK,SAAA;AACH,QAAA,OAAO,UAAA;AAAA,MACT,KAAK,SAAA;AACH,QAAA,OAAO,SAAA;AAAA,MACT,KAAK,UAAA;AACH,QAAA,OAAO,aAAA;AAAA,MACT;AACE,QAAA,OAAO,SAAA;AAAA;AACX,GACF;AAEA,EAAA,uBACE,KAAA,CAAA,aAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,GAAG,cAAA,EAAgB,KAAK,kBAAA,CAAmB,OAAA,CAAQ,CAAC,CAAC,CAAA,EAAA,CAAA;AAAA,MAC5D,IAAA,EAAK,OAAA;AAAA,MACL,EAAA,EAAI;AAAA,QACF,iBAAiB,cAAA,EAAe;AAAA,QAChC,KAAA,EAAO,OAAA;AAAA,QACP,UAAA,EAAY,MAAA;AAAA,QACZ,kBAAA,EAAoB,EAAE,UAAA,EAAY,MAAA;AAAO;AAC3C;AAAA,GACF;AAEJ;AAUA,SAAS,yBAAyB,QAAA,EAAkB;AAClD,EAAA,IAAI,QAAA,GAAW,IAAI,OAAO,OAAA;AAC1B,EAAA,IAAI,QAAA,GAAW,KAAK,OAAO,cAAA;AAC3B,EAAA,OAAO,eAAA;AACT;AAEA,SAAS,wBAAwB,QAAA,EAAkB;AACjD,EAAA,IAAI,QAAA,GAAW,GAAG,OAAO,QAAA;AACzB,EAAA,IAAI,QAAA,GAAW,GAAG,OAAO,QAAA;AACzB,EAAA,OAAO,QAAA;AACT;AAEA,SAAS,uBAAuB,IAAA,EAAc;AAC5C,EAAA,IAAI,IAAA,KAAS,YAAY,OAAO,OAAA;AAChC,EAAA,IAAI,IAAA,KAAS,WAAW,OAAO,SAAA;AAC/B,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,YAAY,KAAA,EAAmC;AACtD,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,cAAA,EAAe;AAClC,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,MAAM,EAAE,QAAA,EAAU,YAAA,EAAc,IAAA,EAAM,OAAA,EAAS,YAAW,GAAI,KAAA;AAC9D,EAAA,MAAM,cAAA,GAAiB,OAAO,iBAAiB,CAAA;AAE/C,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,SAAS,WAAA,EAAY,KAAM,QAAA,CAAS,WAAA,EAAa,CAAA;AAC1F,EAAA,MAAM,kBAAA,GAAqB,cAAc,MAAA,IAAU,CAAA;AAEnD,EAAA,MAAM,CAAC,gBAAA,EAAkB,mBAAmB,CAAA,GAAI,SAAS,KAAK,CAAA;AAE9D,EAAA,MAAM,eAAA,GAAmC,wBAAA,CAAyB,YAAA,EAAc,kBAAkB,CAAA;AAElG,EAAA,MAAM,YAAA,GAAe,OAAO,KAAA,KAA4C;AACtE,IAAA,KAAA,CAAM,cAAA,EAAe;AACrB,IAAA,MAAM,QAAA,GAAW,IAAI,QAAA,CAAS,KAAA,CAAM,aAAa,CAAA;AACjD,IAAA,MAAM,SAAS,MAAA,CAAO,QAAA,CAAS,GAAA,CAAI,QAAQ,KAAK,CAAC,CAAA;AACjD,IAAA,MAAM,OAAA,GAAkB;AAAA,MACtB,IAAI,YAAA,EAAc,EAAA;AAAA,MAClB,QAAA;AAAA,MACA,IAAA,EAAM,YAAA,EAAc,IAAA,IAAQ,CAAA,EAAG,QAAQ,CAAA,cAAA,CAAA;AAAA,MACvC;AAAA,KACF;AACA,IAAA,MAAM,cAAA,CAAe,YAAA,CAAa,SAAA,EAAW,OAAO,CAAA;AACpD,IAAA,UAAA,CAAW,CAAA,IAAA,KAAQ;AACjB,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,SAAA,CAAU,CAAA,CAAA,KAAK,CAAA,CAAE,SAAS,WAAA,EAAY,KAAM,QAAA,CAAS,WAAA,EAAa,CAAA;AACrF,MAAA,IAAI,SAAS,CAAA,EAAG;AACd,QAAA,MAAM,IAAA,GAAO,CAAC,GAAG,IAAI,CAAA;AACrB,QAAA,IAAA,CAAK,KAAK,IAAI,EAAE,GAAG,KAAK,KAAK,CAAA,EAAG,GAAG,OAAA,EAAQ;AAC3C,QAAA,OAAO,IAAA;AAAA;AAET,MAAA,OAAO,CAAC,GAAG,IAAA,EAAM,OAAO,CAAA;AAAA,KACzB,CAAA;AACD,IAAA,mBAAA,CAAoB,KAAK,CAAA;AAAA,GAC3B;AAEA,EAAA,MAAM,sBAAgC,EAAC;AACvC,EAAA,MAAM,mBAA6B,EAAC;AACpC,EAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,IAAA,CAAK,SAAS,EAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,OAAO,CAAC,CAAA,GAAI,MAAA,CAAO,CAAC,CAAC,CAAA,EAAG;AAChF,IAAA,MAAM,YAAY,CAAA,EAAG,MAAA,GAAS,IAAA,EAAM,IAAI,KAAK,CAAA,CAAA;AAE7C,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI,aAAa,YAAA,EAAc;AAC7B,MAAA,IAAA,GAAO,aAAa,SAAS,CAAA;AAAA,eACpB,MAAA,CAAO,KAAK,IAAI,MAAA,EAAO,CAAE,OAAM,EAAG;AAC3C,MAAA,IAAA,GAAO,CAAA;AAAA,KACT,MAAO;AACL,MAAA;AAAA;AAGF,IAAA,mBAAA,CAAoB,KAAK,IAAI,CAAA;AAC7B,IAAA,IAAI,UAAU,IAAA,EAAM;AAClB,MAAA,gBAAA,CAAiB,KAAK,IAAI,CAAA;AAAA,KAC5B,MAAO;AACL,MAAA,gBAAA,CAAiB,KAAK,gBAAA,CAAiB,gBAAA,CAAiB,MAAA,GAAS,CAAC,IAAI,IAAI,CAAA;AAAA;AAC5E;AAGF,EAAA,IAAI,YAAA,GAAe,kBAAA;AAEnB,EAAA,IAAI,WAAA;AACJ,EAAA,IAAI,KAAA;AAEJ,EAAA,IAAI,SAAS,SAAA,gBAAqB;AAChC,IAAA,YAAA,GAAe,YAAA,GAAe,EAAA;AAE9B,IAAA,MAAM,SAAA,GAAY,oBAAoB,MAAA,GAAS,CAAA;AAC/C,IAAA,MAAM,cAAA,GAAiB,SAAA,IAAa,CAAA,GAAI,mBAAA,CAAoB,SAAS,CAAA,GAAI,CAAA;AACzE,IAAA,MAAM,4BAA4B,eAAA,CAAgB,yBAAA;AAClD,IAAA,MAAM,iBAAiB,yBAAA,GAA4B,cAAA;AACnD,IAAA,MAAM,aAAa,GAAA,CAAI,CAAC,GAAG,mBAAA,EAAqB,YAAY,CAAC,CAAA,IAAK,CAAA;AAElE,IAAA,WAAA,GAAc;AAAA,MACZ;AAAA,QACE,EAAA,EAAI,cAAA;AAAA,QACJ,QAAA,EAAU,WAAA;AAAA,QACV,IAAA,EAAM,mBAAA;AAAA,QACN,IAAA,EAAM,KAAA;AAAA,QACN,KAAA,EAAO,UAAA;AAAA,QACP,KAAA,EAAO,cAAA;AAAA,QACP,KAAA,EAAO,UAAU,CAAC,CAAA;AAAA,QAClB,cAAA,EAAgB,CAAC,KAAA,KAAyB,cAAA,CAAe,SAAS,CAAC;AAAA;AACrE,KACF;AAEA,IAAA,IAAI,SAAA,IAAa,CAAA,IAAK,cAAA,GAAiB,CAAA,EAAG;AACxC,MAAA,MAAM,SAAA,GAAY,oBAAoB,GAAA,CAAI,CAAC,GAAG,CAAA,KAAO,CAAA,KAAM,SAAA,GAAY,cAAA,GAAiB,CAAE,CAAA;AAE1F,MAAA,WAAA,CAAY,IAAA,CAAK;AAAA,QACf,EAAA,EAAI,iBAAA;AAAA,QACJ,QAAA,EAAU,WAAA;AAAA,QACV,IAAA,EAAM,SAAA;AAAA,QACN,IAAA,EAAM,KAAA;AAAA,QACN,KAAA,EAAO,UAAA;AAAA,QACP,KAAA,EAAO,iBAAA;AAAA,QACP,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,OAAA,CAAQ,IAAA;AAAA,QAC7B,cAAA,EAAgB,CAAC,KAAA,KAAyB;AACxC,UAAA,IAAI,KAAA,KAAU,GAAG,OAAO,IAAA;AACxB,UAAA,OAAO,cAAA,CAAe,SAAS,CAAC,CAAA;AAAA;AAClC,OACD,CAAA;AAAA;AAGH,IAAA,KAAA,GAAQ;AAAA,MACN;AAAA,QACE,EAAA,EAAI,WAAA;AAAA,QACJ,GAAA,EAAK,CAAA;AAAA,QACL,GAAA,EAAK,UAAA;AAAA,QACL,cAAA,EAAgB,CAAC,KAAA,KAAyB,cAAA,CAAe,SAAS,CAAC,CAAA;AAAA,QACnE,QAAA,EAAU;AAAA,UACR,IAAA,EAAM,WAAA;AAAA,UACN,YAAY,CAAC,YAAA,GAAe,CAAA,GAAI,YAAA,GAAe,OAAO,gBAAgB,CAAA;AAAA,UACtE,MAAA,EAAQ,CAAC,SAAA,CAAU,CAAC,GAAG,KAAA,CAAM,OAAA,CAAQ,MAAM,IAAI;AAAA;AACjD,OACF;AAAA,MACA;AAAA,QACE,EAAA,EAAI,WAAA;AAAA,QACJ,GAAA,EAAK,CAAA;AAAA,QACL,GAAA,EAAK;AAAA;AACP,KACF;AAAA,GACF,MAAO;AACL,IAAA,WAAA,GAAc;AAAA,MACZ;AAAA,QACE,EAAA,EAAI,UAAA;AAAA,QACJ,QAAA,EAAU,WAAA;AAAA,QACV,IAAA,EAAM,gBAAA;AAAA,QACN,IAAA,EAAM,MAAA;AAAA,QACN,QAAA,EAAU,KAAA;AAAA,QACV,cAAA,EAAgB,CAAC,KAAA,KAAyB,cAAA,CAAe,SAAS,CAAC;AAAA;AACrE,KACF;AAEA,IAAA,KAAA,GAAQ;AAAA,MACN;AAAA,QACE,EAAA,EAAI,WAAA;AAAA,QACJ,GAAA,EAAK,CAAA;AAAA,QACL,GAAA,EAAK,IAAI,CAAC,GAAG,kBAAkB,YAAA,EAAc,eAAA,CAAgB,eAAA,CAAgB,IAAI,CAAC,CAAA;AAAA,QAClF,cAAA,EAAgB,CAAC,KAAA,KAAyB,cAAA,CAAe,SAAS,CAAC,CAAA;AAAA,QACnE,QAAA,EAAU;AAAA,UACR,IAAA,EAAM,WAAA;AAAA,UACN,YAAY,CAAC,YAAA,GAAe,CAAA,GAAI,YAAA,GAAe,OAAO,gBAAgB,CAAA;AAAA,UACtE,MAAA,EAAQ,CAAC,SAAA,CAAU,CAAC,GAAG,KAAA,CAAM,OAAA,CAAQ,MAAM,IAAI;AAAA;AACjD;AACF,KACF;AAAA;AAGF,EAAA,uBACE,KAAA,CAAA,aAAA,CAAC,SAAM,EAAA,EAAI,EAAE,SAAS,CAAA,EAAE,EAAA,kBAEtB,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,EAAI,EAAA,EAAI,EAAE,SAAS,MAAA,EAAQ,cAAA,EAAgB,iBAAiB,UAAA,EAAY,QAAA,EAAU,IAAI,CAAA,EAAE,EAAA,kBACvF,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,EAAI,EAAA,EAAI,EAAE,SAAS,MAAA,EAAQ,UAAA,EAAY,UAAS,EAAA,kBAC/C,KAAA,CAAA,aAAA,CAAC,gBAAa,QAAA,EAAoB,CAAA,kBAClC,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,IAAA,EAAK,IAAI,EAAE,EAAA,EAAI,GAAG,UAAA,EAAY,MAAA,MAC/C,QACH,CACF,CAAA,EACC,kBAAA,GAAqB,CAAA,oBACpB,KAAA,CAAA,aAAA;AAAA,IAAC,qBAAA;AAAA,IAAA;AAAA,MACC,QAAQ,eAAA,CAAgB,kBAAA;AAAA,MACxB,oBAAoB,eAAA,CAAgB;AAAA;AAAA,GAG1C,CAAA,EAGC,kBAAA,GAAqB,CAAA,oBACpB,KAAA,CAAA,aAAA,CAAC,QAAK,SAAA,EAAS,IAAA,EAAC,OAAA,EAAS,CAAA,EAAG,EAAA,EAAI,EAAE,IAAI,CAAA,EAAE,EAAA,kBACtC,KAAA,CAAA,aAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAI,IAAA,EAAC,IAAI,CAAA,EAAA,kBACb,KAAA,CAAA,aAAA,CAAC,IAAA,EAAA,EAAK,OAAA,EAAQ,UAAA,EAAW,EAAA,EAAI,EAAE,SAAA,EAAW,QAAA,EAAS,EAAA,kBACjD,KAAA,CAAA,aAAA,CAAC,WAAA,EAAA,EAAY,EAAA,EAAI,EAAE,EAAA,EAAI,CAAA,EAAG,cAAA,EAAgB,EAAE,EAAA,EAAI,CAAA,IAAI,EAAA,kBAClD,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAA,EAAU,KAAA,EAAM,mBAAgB,WAEpD,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EAAQ,YAAW,MAAA,EAAA,EACpC,cAAA,CAAe,eAAA,CAAgB,eAAe,CACjD,CAAA,sCACC,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAA,EAAU,KAAA,EAAM,eAAA,EAAA,EAAgB,KAAA,EAC9C,eAAe,kBAAkB,CACvC,CACF,CACF,CACF,CAAA,sCACC,IAAA,EAAA,EAAK,IAAA,EAAI,IAAA,EAAC,EAAA,EAAI,CAAA,EAAA,kBACb,KAAA,CAAA,aAAA,CAAC,QAAK,OAAA,EAAQ,UAAA,EAAW,EAAA,EAAI,EAAE,SAAA,EAAW,QAAA,sBACxC,KAAA,CAAA,aAAA,CAAC,WAAA,EAAA,EAAY,EAAA,EAAI,EAAE,EAAA,EAAI,CAAA,EAAG,gBAAgB,EAAE,EAAA,EAAI,CAAA,EAAE,EAAE,EAAA,kBAClD,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAA,EAAU,KAAA,EAAM,eAAA,EAAA,EAAgB,kBAEpD,CAAA,kBACA,KAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAQ,OAAA;AAAA,MACR,UAAA,EAAW,MAAA;AAAA,MACX,KAAA,EAAO,eAAA,CAAgB,uBAAA,GAA0B,kBAAA,GAAqB,OAAA,GAAU;AAAA,KAAA;AAAA,IAE/E,cAAA,CAAe,gBAAgB,uBAAuB;AAAA,GACzD,kBACA,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAA,EAAU,KAAA,EAAM,eAAA,EAAA,EACjC,eAAA,CAAgB,uBAAA,GAA0B,kBAAA,GACvC,CAAA,CAAA,EAAI,cAAA,CAAe,gBAAgB,uBAAA,GAA0B,kBAAkB,CAAC,CAAA,KAAA,CAAA,GAChF,CAAA,EAAG,cAAA,CAAe,kBAAA,GAAqB,eAAA,CAAgB,uBAAuB,CAAC,CAAA,MAAA,CACrF,CACF,CACF,CACF,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,QAAK,IAAA,EAAI,IAAA,EAAC,EAAA,EAAI,CAAA,EAAA,kBACb,KAAA,CAAA,aAAA,CAAC,IAAA,EAAA,EAAK,OAAA,EAAQ,UAAA,EAAW,EAAA,EAAI,EAAE,SAAA,EAAW,QAAA,EAAS,EAAA,kBACjD,KAAA,CAAA,aAAA,CAAC,WAAA,EAAA,EAAY,EAAA,EAAI,EAAE,EAAA,EAAI,CAAA,EAAG,cAAA,EAAgB,EAAE,EAAA,EAAI,CAAA,EAAE,EAAE,EAAA,sCACjD,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAA,EAAU,KAAA,EAAM,eAAA,EAAA,EAAgB,kBAEpD,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAA,EAAQ,OAAA,EAAQ,UAAA,EAAW,MAAA,EAAA,EACpC,cAAA,CAAe,eAAA,CAAgB,cAAc,CAChD,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAA,EAAU,KAAA,EAAO,wBAAA,CAAyB,eAAA,CAAgB,gBAAgB,CAAA,EAAA,EAC3F,uBAAA,CAAwB,eAAA,CAAgB,gBAAgB,CAAA,EACxD,IAAA,CAAK,GAAA,CAAI,eAAA,CAAgB,gBAAgB,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA,EAAE,OACzD,CACF,CACF,CACF,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAI,IAAA,EAAC,EAAA,EAAI,CAAA,EAAA,kBACb,KAAA,CAAA,aAAA,CAAC,IAAA,EAAA,EAAK,OAAA,EAAQ,UAAA,EAAW,EAAA,EAAI,EAAE,SAAA,EAAW,QAAA,EAAS,EAAA,sCAChD,WAAA,EAAA,EAAY,EAAA,EAAI,EAAE,EAAA,EAAI,CAAA,EAAG,cAAA,EAAgB,EAAE,EAAA,EAAI,GAAE,EAAE,EAAA,kBAClD,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAA,EAAU,KAAA,EAAM,eAAA,EAAA,EAAgB,gBAEpD,CAAA,kBACA,KAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAQ,OAAA;AAAA,MACR,UAAA,EAAW,MAAA;AAAA,MACX,KAAA,EACE,eAAA,CAAgB,qBAAA,GAAwB,eAAA,CAAgB,iBAAiB,OAAA,GAAU;AAAA,KAAA;AAAA,IAGpF,cAAA,CAAe,gBAAgB,qBAAqB;AAAA,qBAEvD,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAA,EAAU,OAAM,eAAA,EAAA,EACjC,eAAA,CAAgB,eAAA,CAAgB,OAAA,CAAQ,CAAC,CAAA,EAAE,cAC9C,CACF,CACF,CACF,CACF,CAAA,kBAGF,KAAA,CAAA,aAAA;AAAA,IAAC,wBAAA;AAAA,IAAA;AAAA,MACC,MAAA;AAAA,MACA,MAAA,EAAQ,WAAA;AAAA,MACR,KAAA,EAAO;AAAA,QACL;AAAA,UACE,IAAA,EAAM,MAAA,CAAO,OAAA,CAAQ,SAAS,CAAA,CAC3B,KAAK,CAAC,CAAC,CAAC,CAAA,EAAG,CAAC,CAAC,MAAM,CAAA,CAAE,aAAA,CAAc,CAAC,CAAC,CAAA,CACrC,GAAA,CAAI,CAAC,CAAC,CAAA,EAAG,KAAK,CAAA,KAAM,KAAK,CAAA;AAAA,UAC5B,SAAA,EAAW;AAAA;AACb,OACF;AAAA,MACA;AAAA,KAAA;AAAA,oBAEA,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,UAAA,EAAU,IAAA,EAAC,CAAA;AAAA,wCACtB,mBAAA,EAAA,EAAoB,CAAA,EAAG,IAAA,KAAS,QAAA,gBAAqB,SAAS,MAAA,EAAQ,CAAA;AAAA,wCACtE,QAAA,EAAA,IAAS,CAAA;AAAA,wCACT,OAAA,EAAA,IAAQ,CAAA;AAAA,wCACR,QAAA,EAAA,IAAS,CAAA;AAAA,wCACT,iBAAA,EAAA,IAAkB,CAAA;AAAA,oBACnB,KAAA,CAAA,aAAA;AAAA,MAAC,mBAAA;AAAA,MAAA;AAAA,QACC,CAAA,EAAG,YAAA;AAAA,QACH,KAAA,EAAO,YAAA,GAAe,cAAA,CAAe,YAAY,CAAA,GAAI,MAAA;AAAA,QACrD,UAAA,EAAW,KAAA;AAAA,QACX,SAAA,EAAW;AAAA,UACT,MAAA,EAAQ,YAAA,GAAe,KAAA,CAAM,OAAA,CAAQ,MAAM,IAAA,GAAO,aAAA;AAAA,UAClD,eAAA,EAAiB,KAAA;AAAA,UACjB,WAAA,EAAa,GAAA;AAAA,UACb,aAAA,EAAe;AAAA,SACjB;AAAA,QACA,UAAA,EAAY,EAAE,IAAA,EAAM,KAAA,CAAM,QAAQ,KAAA,CAAM,IAAA,EAAM,UAAU,OAAA;AAAQ;AAAA,KAClE;AAAA,IAEC,IAAA,KAAS,QAAA,iBAAsB,kBAAA,GAAqB,CAAA,oBACnD,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,kBACE,KAAA,CAAA,aAAA;AAAA,MAAC,mBAAA;AAAA,MAAA;AAAA,QACC,GAAG,eAAA,CAAgB,uBAAA;AAAA,QACnB,KAAA,EAAO,CAAA,WAAA,EAAc,cAAA,CAAe,eAAA,CAAgB,uBAAuB,CAAC,CAAA,CAAA;AAAA,QAC5E,UAAA,EAAW,OAAA;AAAA,QACX,SAAA,EAAW;AAAA,UACT,MAAA,EAAQ,KAAA,CAAM,OAAA,CAAQ,OAAA,CAAQ,IAAA;AAAA,UAC9B,eAAA,EAAiB,KAAA;AAAA,UACjB,WAAA,EAAa,GAAA;AAAA,UACb,aAAA,EAAe;AAAA,SACjB;AAAA,QACA,UAAA,EAAY,EAAE,IAAA,EAAM,KAAA,CAAM,QAAQ,OAAA,CAAQ,IAAA,EAAM,UAAU,OAAA;AAAQ;AAAA,KACpE,kBAEA,KAAA,CAAA,aAAA;AAAA,MAAC,mBAAA;AAAA,MAAA;AAAA,QACC,CAAA,EAAG,gBAAgB,eAAA,CAAgB,IAAA;AAAA,QACnC,OAAO,CAAA,MAAA,EAAS,cAAA,CAAe,eAAA,CAAgB,eAAA,CAAgB,IAAI,CAAC,CAAA,CAAA;AAAA,QACpE,UAAA,EAAW,OAAA;AAAA,QACX,SAAA,EAAW;AAAA,UACT,MAAA,EAAQ,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,GAAG,CAAA;AAAA,UAC9B,eAAA,EAAiB,KAAA;AAAA,UACjB,WAAA,EAAa,CAAA;AAAA,UACb,aAAA,EAAe;AAAA,SACjB;AAAA,QACA,UAAA,EAAY,EAAE,IAAA,EAAM,KAAA,CAAM,QAAQ,IAAA,CAAK,GAAG,CAAA,EAAG,QAAA,EAAU,OAAA;AAAQ;AAAA,KACjE,kBAEA,KAAA,CAAA,aAAA;AAAA,MAAC,mBAAA;AAAA,MAAA;AAAA,QACC,CAAA,EAAG,gBAAgB,eAAA,CAAgB,GAAA;AAAA,QACnC,OAAO,CAAA,KAAA,EAAQ,cAAA,CAAe,eAAA,CAAgB,eAAA,CAAgB,GAAG,CAAC,CAAA,CAAA;AAAA,QAClE,UAAA,EAAW,OAAA;AAAA,QACX,SAAA,EAAW;AAAA,UACT,MAAA,EAAQ,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,GAAG,CAAA;AAAA,UAC9B,eAAA,EAAiB,KAAA;AAAA,UACjB,WAAA,EAAa,CAAA;AAAA,UACb,aAAA,EAAe;AAAA,SACjB;AAAA,QACA,UAAA,EAAY,EAAE,IAAA,EAAM,KAAA,CAAM,QAAQ,IAAA,CAAK,GAAG,CAAA,EAAG,QAAA,EAAU,OAAA;AAAQ;AAAA,KAEnE,CAAA;AAAA,wCAED,WAAA,EAAA,IAAY,CAAA;AAAA,wCACZ,WAAA,EAAA,IAAY,CAAA;AAAA,wCACZ,aAAA,EAAA,IAAc;AAAA,GACjB,kBAEA,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,EAAI,EAAA,EAAI,EAAE,SAAA,EAAW,QAAA,EAAS,EAAA,kBAC7B,KAAA,CAAA,aAAA,CAAC,MAAA,EAAA,EAAO,OAAA,EAAS,MAAM,mBAAA,CAAoB,IAAI,CAAA,EAAA,EAAG,eAAa,CAAA,kBAC/D,KAAA,CAAA,aAAA,CAAC,MAAA,EAAA,EAAO,SAAA,EAAS,IAAA,EAAC,QAAA,EAAS,MAAK,IAAA,EAAM,gBAAA,EAAkB,OAAA,EAAS,MAAM,mBAAA,CAAoB,KAAK,CAAA,EAAA,kBAC9F,KAAA,CAAA,aAAA,CAAC,UAAK,QAAA,EAAU,YAAA,EAAA,kBACd,KAAA,CAAA,aAAA,CAAC,WAAA,EAAA,IAAA,EAAY,eAAa,CAAA,kBAC1B,KAAA,CAAA,aAAA,CAAC,aAAA,EAAA,IAAA,sCACE,iBAAA,EAAA,IAAA,EAAkB,oBAAA,EAAmB,KAAA,CAAM,QAAA,EAAS,sBAAoB,CAAA,kBACzE,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,EAAI,IAAI,EAAE,OAAA,EAAS,MAAA,EAAQ,UAAA,EAAY,UAAA,EAAW,EAAA,kBACjD,KAAA,CAAA,aAAA,CAAC,YAAA,EAAA,EAAa,UAAoB,CAAA,EAAE,UAAA,kBAEpC,KAAA,CAAA,aAAA,CAAC,WAAA,EAAA,EAAY,OAAA,EAAQ,UAAA,EAAA,kBACnB,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,IAAA,EAAW,QAAM,CAAA,kBAClB,KAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,EAAA,EAAG,QAAA;AAAA,MACH,IAAA,EAAK,QAAA;AAAA,MACL,IAAA,EAAK,QAAA;AAAA,MACL,cAAA,kBAAgB,KAAA,CAAA,aAAA,CAAC,cAAA,EAAA,EAAe,QAAA,EAAS,WAAQ,GAAC,CAAA;AAAA,MAClD,YAAA,EAAc;AAAA;AAAA,GAElB,CACF,CACF,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,aAAA,EAAA,IAAA,kBACC,KAAA,CAAA,aAAA,CAAC,MAAA,EAAA,EAAO,IAAA,EAAK,QAAA,EAAS,OAAA,EAAQ,WAAA,EAAA,EAAY,QAE1C,mBACA,KAAA,CAAA,aAAA,CAAC,MAAA,EAAA,EAAO,OAAA,EAAS,MAAM,mBAAA,CAAoB,KAAK,CAAA,EAAA,EAAG,QAAM,CAC3D,CACF,CACF,CACF,CACF,CAAA;AAEJ;AAOA,SAAS,cAAA,CAAe,EAAE,OAAA,EAAS,OAAA,EAAQ,EAAwB;AACjE,EAAA,MAAM,QAAA,GAAW,OAAA,CACd,GAAA,CAAI,CAAA,MAAA,KAAU;AACb,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,QAAA,CAAS,WAAA,EAAY,KAAM,MAAA,CAAO,EAAA,CAAG,WAAA,EAAa,CAAA;AACrF,IAAA,IAAI,CAAC,MAAA,EAAQ,MAAA,EAAQ,OAAO,IAAA;AAE5B,IAAA,MAAM,SAAA,GAAY,wBAAA,CAAyB,MAAA,CAAO,OAAA,EAAS,OAAO,MAAM,CAAA;AACxE,IAAA,OAAO,EAAE,QAAA,EAAU,MAAA,CAAO,EAAA,EAAI,QAAQ,SAAA,EAAU;AAAA,GACjD,CAAA,CACA,MAAA,CAAO,OAAO,CAAA;AAEjB,EAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,MAAA,CAAO,CAAC,GAAA,EAAK,MAAM,GAAA,IAAO,CAAA,CAAE,MAAA,IAAU,CAAA,CAAA,EAAI,CAAC,CAAA;AACvE,EAAA,MAAM,cAAA,GAAiB,QAAA,CAAS,MAAA,CAAO,CAAC,GAAA,EAAK,CAAA,KAAM,GAAA,IAAO,CAAA,EAAG,SAAA,CAAU,uBAAA,IAA2B,CAAA,CAAA,EAAI,CAAC,CAAA;AACvG,EAAA,MAAM,sBAAsB,QAAA,CAAS,MAAA,CAAO,OAAK,CAAA,EAAG,SAAA,CAAU,uBAAuB,UAAU,CAAA;AAC/F,EAAA,MAAM,kBAAkB,QAAA,CAAS,MAAA,CAAO,OAAK,CAAA,EAAG,SAAA,CAAU,uBAAuB,SAAS,CAAA;AAE1F,EAAA,MAAM,qBAAqB,MAAM;AAC/B,IAAA,MAAMA,mBAAkB,EAAC;AAEzB,IAAA,IAAI,mBAAA,CAAoB,SAAS,CAAA,EAAG;AAClC,MAAAA,iBAAgB,IAAA,CAAK;AAAA,QACnB,IAAA,EAAM,UAAA;AAAA,QACN,OAAA,EAAS,CAAA,EAAG,mBAAA,CAAoB,MAAM,CAAA,8BAAA,EAAiC,mBAAA,CAAoB,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,EAAG,QAAQ,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,OAC5H,CAAA;AAAA;AAGH,IAAA,IAAI,eAAA,CAAgB,SAAS,CAAA,EAAG;AAC9B,MAAAA,iBAAgB,IAAA,CAAK;AAAA,QACnB,IAAA,EAAM,SAAA;AAAA,QACN,OAAA,EAAS,CAAA,EAAG,eAAA,CAAgB,MAAM,CAAA,sBAAA,EAAyB,eAAA,CAAgB,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,EAAG,QAAQ,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,OAC5G,CAAA;AAAA;AAGH,IAAA,IAAI,iBAAiB,WAAA,EAAa;AAChC,MAAAA,iBAAgB,IAAA,CAAK;AAAA,QACnB,IAAA,EAAM,MAAA;AAAA,QACN,OAAA,EAAS,CAAA,0BAAA,EAA6B,cAAA,CAAe,cAAc,CAAC,CAAA,wBAAA,EAA2B,cAAA,CAAe,WAAW,CAAC,CAAA,KAAA,EAAQ,cAAA,CAAe,cAAA,GAAiB,WAAW,CAAC,CAAA;AAAA,OAC/K,CAAA;AAAA;AAGH,IAAA,MAAM,qBAAA,GAAwB,SAAS,MAAA,CAAO,CAAA,CAAA,KAAK,GAAG,SAAA,IAAa,CAAA,CAAE,SAAA,CAAU,gBAAA,GAAmB,EAAE,CAAA;AACpG,IAAA,IAAI,qBAAA,CAAsB,SAAS,CAAA,EAAG;AACpC,MAAAA,iBAAgB,IAAA,CAAK;AAAA,QACnB,IAAA,EAAM,SAAA;AAAA,QACN,OAAA,EAAS,CAAA,wCAAA,EAA2C,qBAAA,CAAsB,GAAA,CAAI,CAAA,CAAA,KAAK,GAAG,QAAQ,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,OAC3G,CAAA;AAAA;AAGH,IAAA,OAAOA,gBAAAA;AAAA,GACT;AAEA,EAAA,MAAM,kBAAkB,kBAAA,EAAmB;AAE3C,EAAA,IAAI,QAAA,CAAS,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAElC,EAAA,2CACG,IAAA,EAAA,EAAK,EAAA,EAAI,EAAE,EAAA,EAAI,GAAE,EAAA,kBAChB,KAAA,CAAA,aAAA,CAAC,WAAA,EAAA,IAAA,kBACC,KAAA,CAAA,aAAA,CAAC,cAAW,OAAA,EAAQ,IAAA,EAAK,cAAY,IAAA,EAAA,EAAC,iBAEtC,mBAGA,KAAA,CAAA,aAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAS,IAAA,EAAC,SAAS,CAAA,EAAG,EAAA,EAAI,EAAE,EAAA,EAAI,CAAA,sBACpC,KAAA,CAAA,aAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAI,IAAA,EAAC,IAAI,CAAA,EAAA,kBACb,KAAA,CAAA,aAAA,CAAC,OAAI,SAAA,EAAU,QAAA,EAAA,sCACZ,UAAA,EAAA,EAAW,OAAA,EAAQ,IAAA,EAAK,KAAA,EAAM,aAC5B,QAAA,CAAS,MACZ,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAA,EAAQ,SAAA,EAAA,EAAU,WAAS,CACzC,CACF,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,QAAK,IAAA,EAAI,IAAA,EAAC,IAAI,CAAA,EAAA,kBACb,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAU,4BACb,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,SAAQ,IAAA,EAAK,KAAA,EAAO,oBAAoB,MAAA,GAAS,CAAA,GAAI,OAAA,GAAU,cAAA,EAAA,EACxE,oBAAoB,MACvB,CAAA,sCACC,UAAA,EAAA,EAAW,OAAA,EAAQ,aAAU,aAAW,CAC3C,CACF,CAAA,sCACC,IAAA,EAAA,EAAK,IAAA,EAAI,IAAA,EAAC,EAAA,EAAI,qBACb,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAU,QAAA,EAAA,sCACZ,UAAA,EAAA,EAAW,OAAA,EAAQ,MAAK,KAAA,EAAO,eAAA,CAAgB,SAAS,CAAA,GAAI,cAAA,GAAiB,cAAA,EAAA,EAC3E,eAAA,CAAgB,MACnB,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAA,EAAQ,SAAA,EAAA,EAAU,SAAO,CACvC,CACF,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,QAAK,IAAA,EAAI,IAAA,EAAC,IAAI,CAAA,EAAA,kBACb,KAAA,CAAA,aAAA,CAAC,OAAI,SAAA,EAAU,QAAA,EAAA,kBACb,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,SAAQ,IAAA,EAAK,KAAA,EAAO,cAAA,GAAiB,WAAA,GAAc,UAAU,cAAA,EAAA,EAAA,CACpE,cAAA,GAAiB,WAAA,GAAe,GAAA,EAAK,QAAQ,CAAC,CAAA,EAAE,GACrD,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAA,EAAQ,SAAA,EAAA,EAAU,qBAAmB,CACnD,CACF,CACF,CAAA,EAGC,gBAAgB,MAAA,GAAS,CAAA,wCACvB,GAAA,EAAA,IAAA,kBACC,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,aAAY,YAAA,EAAY,IAAA,EAAA,EAAC,iBAE7C,CAAA,EACC,eAAA,CAAgB,IAAI,CAAA,GAAA,qBACnB,KAAA,CAAA,aAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,KAAK,CAAA,EAAG,GAAA,CAAI,IAAI,CAAA,CAAA,EAAI,IAAI,OAAO,CAAA,CAAA;AAAA,MAC/B,OAAO,GAAA,CAAI,OAAA;AAAA,MACX,IAAA,EAAK,OAAA;AAAA,MACL,KAAA,EAAO,sBAAA,CAAuB,GAAA,CAAI,IAAI,CAAA;AAAA,MACtC,OAAA,EAAQ,UAAA;AAAA,MACR,IAAI,EAAE,EAAA,EAAI,GAAG,EAAA,EAAI,CAAA,EAAG,UAAU,MAAA;AAAO;AAAA,GAExC,CACH,CAEJ,CACF,CAAA;AAEJ;AAEO,MAAM,OAAA,GAA4B,CAAC,EAAE,oBAAA,EAAqB,KAAM;AACrE,EAAA,MAAM,CAAC,0BAAA,EAA4B,6BAA6B,CAAA,GAAI,SAA+B,MAAS,CAAA;AAC5G,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,SAAS,QAAA,cAAkB;AAC/D,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,QAAA,CAAmB,EAAE,CAAA;AAEnD,EAAA,MAAM,cAAA,GAAiB,OAAO,iBAAiB,CAAA;AAC/C,EAAA,MAAM,QAAA,GAAW,OAAO,WAAW,CAAA;AAEnC,EAAA,MAAM,UAAA,GAAa,YAAY,YAAY;AACzC,IAAA,MAAM,cAAA,CACH,eAAe,EAAA,EAAI,IAAI,EAAA,EAAI,SAAA,EAAW,MAAA,EAAO,CAAE,OAAA,CAAQ,GAAG,EAAE,MAAA,EAAO,EAAG,MAAA,EAAO,CAAE,KAAA,CAAM,GAAG,EAAE,MAAA,EAAQ,CAAA,CAClG,IAAA,CAAK,CAAA,eAAA,KAAmB;AACvB,MAAA,IAAI,gBAAgB,IAAA,EAAM;AACxB,QAAA,MAAM,iBAAA,GAAoB,oBAAA,CAAqB,eAAA,CAAgB,IAAA,EAAM,UAAU,CAAA;AAC/E,QAAA,MAAM,0BAAA,GAA6B,iBAAiB,iBAAiB,CAAA;AACrE,QAAA,6BAAA,CAA8B,0BAA0B,CAAA;AAAA;AAE1D,MAAA,IAAI,eAAA,CAAgB,MAAA,KAAW,GAAA,IAAO,eAAA,CAAgB,MAAA,EAAQ;AAC5D,QAAA,oBAAA,CAAqB,gBAAgB,MAAM,CAAA;AAAA;AAC7C,KACD,CAAA,CACA,KAAA,CAAM,CAAA,CAAA,KAAK,SAAS,IAAA,CAAK,EAAE,OAAA,EAAS,CAAA,EAAG,EAAE,OAAO,CAAA,CAAA,EAAI,QAAA,EAAU,OAAA,EAAS,CAAC,CAAA;AAAA,GAC7E,EAAG,CAAC,QAAA,EAAU,cAAA,EAAgB,oBAAoB,CAAC,CAAA;AAEnD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,UAAA,EAAW;AAAA,GACb,EAAG,CAAC,UAAU,CAAC,CAAA;AAEf,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,eAAe,YAAY;AAC/B,MAAA,IAAI;AACF,QAAA,MAAM,QAAA,GAAW,MAAM,cAAA,CAAe,UAAA,CAAW,SAAS,CAAA;AAC1D,QAAA,UAAA,CAAW,QAAA,CAAS,IAAA,IAAQ,EAAE,CAAA;AAAA,eACvB,KAAA,EAAO;AAAA;AAEhB,KACF;AACA,IAAA,YAAA,EAAa;AAAA,GACf,EAAG,CAAC,cAAc,CAAC,CAAA;AAEnB,EAAA,uBACE,KAAA,CAAA,aAAA,CAAC,QAAK,SAAA,EAAS,IAAA,EAAC,SAAS,CAAA,EAAA,kBACvB,KAAA,CAAA,aAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAI,IAAA,EAAC,EAAA,EAAI,sBACb,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,EAAI,EAAA,EAAI,EAAE,OAAA,EAAS,MAAA,EAAQ,gBAAgB,eAAA,EAAiB,UAAA,EAAY,QAAA,EAAS,EAAA,kBAChF,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,SAAQ,IAAA,EAAA,EACjB,MAAA,EAAO,CAAE,IAAA,EAAK,EAAE,GAAA,EAAE,YAAW,UAChC,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,GAAA,EAAA,EAAI,EAAA,EAAI,EAAE,SAAS,MAAA,EAAQ,UAAA,EAAY,QAAA,EAAU,GAAA,EAAK,CAAA,EAAE,EAAA,sCACtD,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EAAA,EAAQ,QAAM,CAAA,kBAClC,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,OAAA;AAAA,MACL,UAAU,CAAA,KAAA,KAAS,aAAA,CAAc,MAAM,MAAA,CAAO,OAAA,GAAU,0BAAsB,QAAA;AAAkB;AAAA,qBAElG,KAAA,CAAA,aAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EAAA,EAAQ,SAAO,CACrC,CACF,CACF,CAAA,EAGC,8CACC,KAAA,CAAA,aAAA,CAAC,IAAA,EAAA,EAAK,MAAI,IAAA,EAAC,EAAA,EAAI,sBACb,KAAA,CAAA,aAAA,CAAC,cAAA,EAAA,EAAe,OAAA,EAAS,0BAAA,EAA4B,SAAkB,CACzE,CAAA,EAED,+BAA+B,MAAA,GAC9B,0BAAA,CAA2B,IAAI,CAAA,MAAA,qBAC7B,KAAA,CAAA,aAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAI,MAAC,GAAA,EAAK,CAAA,EAAG,OAAO,EAAE,CAAA,KAAA,CAAA,EAAS,IAAI,CAAA,EAAA,kBACvC,KAAA,CAAA,aAAA;AAAA,IAAC,WAAA;AAAA,IAAA;AAAA,MACC,UAAU,MAAA,CAAO,EAAA;AAAA,MACjB,cAAc,MAAA,CAAO,OAAA;AAAA,MACrB,IAAA,EAAM,UAAA;AAAA,MACN,OAAA;AAAA,MACA;AAAA;AAAA,GAEJ,CACD,CAAA,mBAED,KAAA,CAAA,aAAA,CAAC,QAAK,IAAA,EAAI,IAAA,EAAC,IAAI,EAAA,EAAA,kBACb,KAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,EAAA,EAAI;AAAA,QACF,OAAA,EAAS,MAAA;AAAA,QACT,aAAA,EAAe,QAAA;AAAA,QACf,MAAA,EAAQ,GAAA;AAAA,QACR,eAAA,EAAiB,aAAA;AAAA,QACjB,SAAA,EAAW;AAAA;AACb,KAAA;AAAA,wCAEC,KAAA,EAAA,EAAI,KAAA,EAAO,EAAE,KAAA,EAAO,OAAO,MAAA,EAAQ,MAAA,EAAO,EAAA,kBACzC,KAAA,CAAA,aAAA,CAAC,cAAS,CAAA,kBACV,KAAA,CAAA,aAAA,CAAC,cAAS,CAAA,kBACV,KAAA,CAAA,aAAA,CAAC,cAAS,CACZ;AAAA,GAEJ,CAEJ,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"Budgets.esm.js","sources":["../../../src/components/Budgets/Budgets.tsx"],"sourcesContent":["import { alertApiRef, useApi } from '@backstage/core-plugin-api';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Card from '@mui/material/Card';\nimport CardContent from '@mui/material/CardContent';\nimport Chip from '@mui/material/Chip';\nimport Dialog from '@mui/material/Dialog';\nimport DialogActions from '@mui/material/DialogActions';\nimport DialogContent from '@mui/material/DialogContent';\nimport DialogContentText from '@mui/material/DialogContentText';\nimport DialogTitle from '@mui/material/DialogTitle';\nimport FormControl from '@mui/material/FormControl';\nimport Grid from '@mui/material/Grid';\nimport Input from '@mui/material/Input';\nimport InputAdornment from '@mui/material/InputAdornment';\nimport InputLabel from '@mui/material/InputLabel';\nimport Paper from '@mui/material/Paper';\nimport Skeleton from '@mui/material/Skeleton';\nimport { useTheme } from '@mui/material/styles';\nimport Switch from '@mui/material/Switch';\nimport Typography from '@mui/material/Typography';\nimport {\n BarPlot,\n ResponsiveChartContainer,\n ChartsAxisHighlight,\n ChartsGrid,\n ChartsReferenceLine,\n ChartsTooltip,\n ChartsXAxis,\n ChartsYAxis,\n LineHighlightPlot,\n LinePlot,\n MarkPlot,\n useDrawingArea,\n} from '@mui/x-charts';\nimport { max } from 'lodash';\nimport moment from 'moment';\nimport React, { FC, useCallback, useEffect, useState } from 'react';\nimport {\n aggregateCostReports,\n formatCurrency,\n mergeCostReports,\n calculateBudgetAnalytics,\n BudgetAnalytics,\n} from '../../api/functions';\nimport { infraWalletApiRef } from '../../api/InfraWalletApi';\nimport { Budget, Report } from '../../api/types';\nimport { colorList } from '../constants';\nimport { ProviderIcon } from '../ProviderIcon';\nimport { BudgetsProps } from '../types';\n\nconst enum BUDGET_VIEW {\n MONTHLY = 'Monthly',\n ANNUAL = 'Annual',\n}\n\nconst monthList = {\n '01': 'Jan',\n '02': 'Feb',\n '03': 'Mar',\n '04': 'Apr',\n '05': 'May',\n '06': 'Jun',\n '07': 'Jul',\n '08': 'Aug',\n '09': 'Sep',\n '10': 'Oct',\n '11': 'Nov',\n '12': 'Dec',\n};\n\ninterface BudgetHealthIndicatorProps {\n status: 'healthy' | 'warning' | 'critical';\n utilizationPercent: number;\n}\n\nfunction BudgetHealthIndicator({ status, utilizationPercent }: BudgetHealthIndicatorProps) {\n const getStatusColor = () => {\n switch (status) {\n case 'healthy':\n return '#4caf50';\n case 'warning':\n return '#ff9800';\n case 'critical':\n return '#f44336';\n default:\n return '#9e9e9e';\n }\n };\n\n const getStatusLabel = () => {\n switch (status) {\n case 'healthy':\n return 'On Track';\n case 'warning':\n return 'At Risk';\n case 'critical':\n return 'Over Budget';\n default:\n return 'Unknown';\n }\n };\n\n return (\n <Chip\n label={`${getStatusLabel()} (${utilizationPercent.toFixed(1)}%)`}\n size=\"small\"\n sx={{\n backgroundColor: getStatusColor(),\n color: 'white',\n fontWeight: 'bold',\n '& .MuiChip-label': { fontWeight: 'bold' },\n }}\n />\n );\n}\n\ninterface BudgetChartProps {\n provider: string;\n monthlyCosts: Record<string, number>;\n view: string;\n budgets: Budget[];\n forecast?: number;\n setBudgets: React.Dispatch<React.SetStateAction<Budget[]>>;\n}\n\nfunction getSpendingVelocityColor(velocity: number) {\n if (velocity > 10) return 'error';\n if (velocity < -10) return 'success.main';\n return 'textSecondary';\n}\n\nfunction getSpendingVelocityIcon(velocity: number) {\n if (velocity > 0) return '↑';\n if (velocity < 0) return '↓';\n return '→';\n}\n\nfunction getRecommendationColor(type: string) {\n if (type === 'critical') return 'error';\n if (type === 'warning') return 'warning';\n return 'info';\n}\n\nfunction BudgetChart(props: Readonly<BudgetChartProps>) {\n const { height } = useDrawingArea();\n const theme = useTheme();\n const { provider, monthlyCosts, view, budgets, setBudgets, forecast } = props;\n const infraWalletApi = useApi(infraWalletApiRef);\n\n const annualBudget = budgets.find(b => b.provider.toLowerCase() === provider.toLowerCase());\n const annualBudgetAmount = annualBudget?.amount || 0;\n\n const [openManageBudget, setOpenManageBudget] = useState(false);\n\n const budgetAnalytics: BudgetAnalytics = calculateBudgetAnalytics(monthlyCosts, annualBudgetAmount, forecast);\n\n const updateBudget = async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const formData = new FormData(event.currentTarget);\n const amount = Number(formData.get('amount') || 0);\n const updated: Budget = {\n id: annualBudget?.id,\n provider: provider,\n name: annualBudget?.name || `${provider} annual budget`,\n amount: amount,\n };\n await infraWalletApi.updateBudget('default', updated);\n setBudgets(prev => {\n const index = prev.findIndex(b => b.provider.toLowerCase() === provider.toLowerCase());\n if (index >= 0) {\n const copy = [...prev];\n copy[index] = { ...copy[index], ...updated };\n return copy;\n }\n return [...prev, updated];\n });\n setOpenManageBudget(false);\n };\n\n const nonAccumulatedCosts: number[] = [];\n const accumulatedCosts: number[] = [];\n for (const month of Object.keys(monthList).sort((a, b) => Number(a) - Number(b))) {\n const yearMonth = `${moment().year()}-${month}`;\n\n let cost;\n if (yearMonth in monthlyCosts) {\n cost = monthlyCosts[yearMonth];\n } else if (Number(month) < moment().month()) {\n cost = 0;\n } else {\n break;\n }\n\n nonAccumulatedCosts.push(cost);\n if (month === '01') {\n accumulatedCosts.push(cost);\n } else {\n accumulatedCosts.push(accumulatedCosts[accumulatedCosts.length - 1] + cost);\n }\n }\n\n let budgetAmount = annualBudgetAmount;\n\n let chartSeries: any[];\n let yAxis: any[];\n\n if (view === BUDGET_VIEW.MONTHLY) {\n budgetAmount = budgetAmount / 12;\n\n const lastIndex = nonAccumulatedCosts.length - 1;\n const lastActualCost = lastIndex >= 0 ? nonAccumulatedCosts[lastIndex] : 0;\n const projectedCurrentMonthCost = budgetAnalytics.projectedCurrentMonthCost;\n const projectedDelta = projectedCurrentMonthCost - lastActualCost;\n const monthlyMax = max([...nonAccumulatedCosts, budgetAmount, projectedCurrentMonthCost]) || 0;\n\n chartSeries = [\n {\n id: 'actual-spend',\n yAxisKey: 'spendAxis',\n data: nonAccumulatedCosts,\n type: 'bar',\n stack: 'combined',\n label: 'Actual Spend',\n color: colorList[0],\n valueFormatter: (value: number | null) => formatCurrency(value || 0),\n },\n ];\n\n if (lastIndex >= 0 && projectedDelta > 0) {\n const deltaData = nonAccumulatedCosts.map((_, i) => (i === lastIndex ? projectedDelta : 0));\n\n chartSeries.push({\n id: 'projected-delta',\n yAxisKey: 'deltaAxis',\n data: deltaData,\n type: 'bar',\n stack: 'combined',\n label: 'Projected Delta',\n color: theme.palette.warning.main,\n valueFormatter: (value: number | null) => {\n if (value === 0) return null;\n return formatCurrency(value || 0);\n },\n });\n }\n\n yAxis = [\n {\n id: 'spendAxis',\n min: 0,\n max: monthlyMax,\n valueFormatter: (value: number | null) => formatCurrency(value || 0),\n colorMap: {\n type: 'piecewise',\n thresholds: [budgetAmount > 0 ? budgetAmount : Number.MAX_SAFE_INTEGER],\n colors: [colorList[0], theme.palette.error.main],\n },\n },\n {\n id: 'deltaAxis',\n min: 0,\n max: monthlyMax,\n },\n ];\n } else {\n chartSeries = [\n {\n id: 'yearAxis',\n yAxisKey: 'spendAxis',\n data: accumulatedCosts,\n type: 'line',\n showMark: false,\n valueFormatter: (value: number | null) => formatCurrency(value || 0),\n },\n ];\n\n yAxis = [\n {\n id: 'spendAxis',\n min: 0,\n max: max([...accumulatedCosts, budgetAmount, budgetAnalytics.confidenceRange.high]),\n valueFormatter: (value: number | null) => formatCurrency(value || 0),\n colorMap: {\n type: 'piecewise',\n thresholds: [budgetAmount > 0 ? budgetAmount : Number.MAX_SAFE_INTEGER],\n colors: [colorList[0], theme.palette.error.main],\n },\n },\n ];\n }\n\n return (\n <Paper sx={{ padding: 2 }}>\n {/* Budget Health Header */}\n <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>\n <Box sx={{ display: 'flex', alignItems: 'center' }}>\n <ProviderIcon provider={provider} />\n <Typography variant=\"h6\" sx={{ ml: 1, fontWeight: 'bold' }}>\n {provider}\n </Typography>\n </Box>\n {annualBudgetAmount > 0 && (\n <BudgetHealthIndicator\n status={budgetAnalytics.budgetHealthStatus}\n utilizationPercent={budgetAnalytics.budgetUtilizationPercent}\n />\n )}\n </Box>\n\n {/* Budget Metrics Cards */}\n {annualBudgetAmount > 0 && (\n <Grid container spacing={1} sx={{ mb: 2 }}>\n <Grid item xs={6}>\n <Card variant=\"outlined\" sx={{ textAlign: 'center' }}>\n <CardContent sx={{ py: 1, '&:last-child': { pb: 1 } }}>\n <Typography variant=\"caption\" color=\"textSecondary\">\n YTD Spent\n </Typography>\n <Typography variant=\"body2\" fontWeight=\"bold\">\n {formatCurrency(budgetAnalytics.yearToDateSpent)}\n </Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n of {formatCurrency(annualBudgetAmount)}\n </Typography>\n </CardContent>\n </Card>\n </Grid>\n <Grid item xs={6}>\n <Card variant=\"outlined\" sx={{ textAlign: 'center' }}>\n <CardContent sx={{ py: 1, '&:last-child': { pb: 1 } }}>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Projected Annual\n </Typography>\n <Typography\n variant=\"body2\"\n fontWeight=\"bold\"\n color={budgetAnalytics.projectedAnnualSpending > annualBudgetAmount ? 'error' : 'inherit'}\n >\n {formatCurrency(budgetAnalytics.projectedAnnualSpending)}\n </Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n {budgetAnalytics.projectedAnnualSpending > annualBudgetAmount\n ? `+${formatCurrency(budgetAnalytics.projectedAnnualSpending - annualBudgetAmount)} over`\n : `${formatCurrency(annualBudgetAmount - budgetAnalytics.projectedAnnualSpending)} under`}\n </Typography>\n </CardContent>\n </Card>\n </Grid>\n <Grid item xs={6}>\n <Card variant=\"outlined\" sx={{ textAlign: 'center' }}>\n <CardContent sx={{ py: 1, '&:last-child': { pb: 1 } }}>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Monthly Run Rate\n </Typography>\n <Typography variant=\"body2\" fontWeight=\"bold\">\n {formatCurrency(budgetAnalytics.monthlyRunRate)}\n </Typography>\n <Typography variant=\"caption\" color={getSpendingVelocityColor(budgetAnalytics.spendingVelocity)}>\n {getSpendingVelocityIcon(budgetAnalytics.spendingVelocity)}\n {Math.abs(budgetAnalytics.spendingVelocity).toFixed(1)}% MoM\n </Typography>\n </CardContent>\n </Card>\n </Grid>\n <Grid item xs={6}>\n <Card variant=\"outlined\" sx={{ textAlign: 'center' }}>\n <CardContent sx={{ py: 1, '&:last-child': { pb: 1 } }}>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Target Monthly\n </Typography>\n <Typography\n variant=\"body2\"\n fontWeight=\"bold\"\n color={\n budgetAnalytics.targetMonthlySpending < budgetAnalytics.monthlyRunRate ? 'error' : 'success.main'\n }\n >\n {formatCurrency(budgetAnalytics.targetMonthlySpending)}\n </Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n {budgetAnalytics.monthsRemaining.toFixed(1)} months left\n </Typography>\n </CardContent>\n </Card>\n </Grid>\n </Grid>\n )}\n\n <ResponsiveChartContainer\n height={height}\n series={chartSeries}\n xAxis={[\n {\n data: Object.entries(monthList)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([_, value]) => value),\n scaleType: 'band',\n },\n ]}\n yAxis={yAxis}\n >\n <ChartsGrid horizontal />\n <ChartsAxisHighlight x={view === BUDGET_VIEW.ANNUAL ? 'line' : 'band'} />\n <LinePlot />\n <BarPlot />\n <MarkPlot />\n <LineHighlightPlot />\n <ChartsReferenceLine\n y={budgetAmount}\n label={budgetAmount ? formatCurrency(budgetAmount) : undefined}\n labelAlign=\"end\"\n lineStyle={{\n stroke: budgetAmount ? theme.palette.error.main : 'transparent',\n strokeDasharray: '5 5',\n strokeWidth: 1.5,\n strokeOpacity: 0.8,\n }}\n labelStyle={{ fill: theme.palette.error.main, fontSize: '0.9em' }}\n />\n {/* Add projection line for annual view */}\n {view === BUDGET_VIEW.ANNUAL && annualBudgetAmount > 0 && (\n <>\n <ChartsReferenceLine\n y={budgetAnalytics.projectedAnnualSpending}\n label={`Projected: ${formatCurrency(budgetAnalytics.projectedAnnualSpending)}`}\n labelAlign=\"start\"\n lineStyle={{\n stroke: theme.palette.warning.main,\n strokeDasharray: '3 3',\n strokeWidth: 1.5,\n strokeOpacity: 0.8,\n }}\n labelStyle={{ fill: theme.palette.warning.main, fontSize: '0.8em' }}\n />\n {/* Confidence Range - High */}\n <ChartsReferenceLine\n y={budgetAnalytics.confidenceRange.high}\n label={`High: ${formatCurrency(budgetAnalytics.confidenceRange.high)}`}\n labelAlign=\"start\"\n lineStyle={{\n stroke: theme.palette.grey[400],\n strokeDasharray: '2 2',\n strokeWidth: 1,\n strokeOpacity: 0.5,\n }}\n labelStyle={{ fill: theme.palette.grey[600], fontSize: '0.7em' }}\n />\n {/* Confidence Range - Low */}\n <ChartsReferenceLine\n y={budgetAnalytics.confidenceRange.low}\n label={`Low: ${formatCurrency(budgetAnalytics.confidenceRange.low)}`}\n labelAlign=\"start\"\n lineStyle={{\n stroke: theme.palette.grey[400],\n strokeDasharray: '2 2',\n strokeWidth: 1,\n strokeOpacity: 0.5,\n }}\n labelStyle={{ fill: theme.palette.grey[600], fontSize: '0.7em' }}\n />\n </>\n )}\n <ChartsXAxis />\n <ChartsYAxis />\n <ChartsTooltip />\n </ResponsiveChartContainer>\n\n <Box sx={{ textAlign: 'center' }}>\n <Button onClick={() => setOpenManageBudget(true)}>Manage budget</Button>\n <Dialog fullWidth maxWidth=\"sm\" open={openManageBudget} onClose={() => setOpenManageBudget(false)}>\n <form onSubmit={updateBudget}>\n <DialogTitle>Manage Budget</DialogTitle>\n <DialogContent>\n <DialogContentText>Please enter your {props.provider} annual budget here.</DialogContentText>\n <Box sx={{ display: 'flex', alignItems: 'flex-end' }}>\n <ProviderIcon provider={provider} />\n &nbsp;&nbsp;\n <FormControl variant=\"standard\">\n <InputLabel>Amount</InputLabel>\n <Input\n id=\"amount\"\n name=\"amount\"\n type=\"number\"\n startAdornment={<InputAdornment position=\"start\">$</InputAdornment>}\n defaultValue={annualBudgetAmount}\n />\n </FormControl>\n </Box>\n </DialogContent>\n <DialogActions>\n <Button type=\"submit\" variant=\"contained\">\n Submit\n </Button>\n <Button onClick={() => setOpenManageBudget(false)}>Cancel</Button>\n </DialogActions>\n </form>\n </Dialog>\n </Box>\n </Paper>\n );\n}\n\ninterface BudgetInsightsProps {\n reports: Report[];\n budgets: Budget[];\n}\n\nfunction BudgetInsights({ reports, budgets }: BudgetInsightsProps) {\n const insights = reports\n .map(report => {\n const budget = budgets.find(b => b.provider.toLowerCase() === report.id.toLowerCase());\n if (!budget?.amount) return null;\n\n const analytics = calculateBudgetAnalytics(report.reports, budget.amount);\n return { provider: report.id, budget, analytics };\n })\n .filter(Boolean);\n\n const totalBudget = budgets.reduce((sum, b) => sum + (b.amount || 0), 0);\n const totalProjected = insights.reduce((sum, i) => sum + (i?.analytics.projectedAnnualSpending || 0), 0);\n const overBudgetProviders = insights.filter(i => i?.analytics.budgetHealthStatus === 'critical');\n const atRiskProviders = insights.filter(i => i?.analytics.budgetHealthStatus === 'warning');\n\n const getRecommendations = () => {\n const recommendations = [];\n\n if (overBudgetProviders.length > 0) {\n recommendations.push({\n type: 'critical',\n message: `${overBudgetProviders.length} provider(s) are over budget: ${overBudgetProviders.map(p => p?.provider).join(', ')}`,\n });\n }\n\n if (atRiskProviders.length > 0) {\n recommendations.push({\n type: 'warning',\n message: `${atRiskProviders.length} provider(s) at risk: ${atRiskProviders.map(p => p?.provider).join(', ')}`,\n });\n }\n\n if (totalProjected > totalBudget) {\n recommendations.push({\n type: 'info',\n message: `Total projected spending (${formatCurrency(totalProjected)}) exceeds total budget (${formatCurrency(totalBudget)}) by ${formatCurrency(totalProjected - totalBudget)}`,\n });\n }\n\n const highVelocityProviders = insights.filter(i => i?.analytics && i.analytics.spendingVelocity > 20);\n if (highVelocityProviders.length > 0) {\n recommendations.push({\n type: 'warning',\n message: `High spending acceleration detected in: ${highVelocityProviders.map(p => p?.provider).join(', ')}`,\n });\n }\n\n return recommendations;\n };\n\n const recommendations = getRecommendations();\n\n if (insights.length === 0) return null;\n\n return (\n <Card sx={{ mb: 3 }}>\n <CardContent>\n <Typography variant=\"h6\" gutterBottom>\n Budget Insights\n </Typography>\n\n {/* Overview Stats */}\n <Grid container spacing={2} sx={{ mb: 2 }}>\n <Grid item xs={3}>\n <Box textAlign=\"center\">\n <Typography variant=\"h4\" color=\"primary\">\n {insights.length}\n </Typography>\n <Typography variant=\"caption\">Providers</Typography>\n </Box>\n </Grid>\n <Grid item xs={3}>\n <Box textAlign=\"center\">\n <Typography variant=\"h4\" color={overBudgetProviders.length > 0 ? 'error' : 'success.main'}>\n {overBudgetProviders.length}\n </Typography>\n <Typography variant=\"caption\">Over Budget</Typography>\n </Box>\n </Grid>\n <Grid item xs={3}>\n <Box textAlign=\"center\">\n <Typography variant=\"h4\" color={atRiskProviders.length > 0 ? 'warning.main' : 'success.main'}>\n {atRiskProviders.length}\n </Typography>\n <Typography variant=\"caption\">At Risk</Typography>\n </Box>\n </Grid>\n <Grid item xs={3}>\n <Box textAlign=\"center\">\n <Typography variant=\"h4\" color={totalProjected > totalBudget ? 'error' : 'success.main'}>\n {((totalProjected / totalBudget) * 100).toFixed(0)}%\n </Typography>\n <Typography variant=\"caption\">Projected vs Budget</Typography>\n </Box>\n </Grid>\n </Grid>\n\n {/* Recommendations */}\n {recommendations.length > 0 && (\n <Box>\n <Typography variant=\"subtitle2\" gutterBottom>\n Recommendations\n </Typography>\n {recommendations.map(rec => (\n <Chip\n key={`${rec.type}-${rec.message}`}\n label={rec.message}\n size=\"small\"\n color={getRecommendationColor(rec.type)}\n variant=\"outlined\"\n sx={{ mr: 1, mb: 1, maxWidth: '100%' }}\n />\n ))}\n </Box>\n )}\n </CardContent>\n </Card>\n );\n}\n\nexport const Budgets: FC<BudgetsProps> = ({ providerErrorsSetter }) => {\n const [reportsAggregatedAndMerged, setReportsAggregatedAndMerged] = useState<Report[] | undefined>(undefined);\n const [budgetView, setBudgetView] = useState(BUDGET_VIEW.ANNUAL);\n const [budgets, setBudgets] = useState<Budget[]>([]);\n const [forecasts, setForecasts] = useState<Record<string, number>>({});\n const infraWalletApi = useApi(infraWalletApiRef);\n const alertApi = useApi(alertApiRef);\n\n const fetchCosts = useCallback(async () => {\n await infraWalletApi\n .getCostReports('', [], '', 'monthly', moment().startOf('y').toDate(), moment().endOf('d').toDate())\n .then(reportsResponse => {\n if (reportsResponse.data) {\n const aggregatedReports = aggregateCostReports(reportsResponse.data, 'provider');\n const aggregatedAndMergedReports = mergeCostReports(aggregatedReports);\n setReportsAggregatedAndMerged(aggregatedAndMergedReports);\n setForecasts(reportsResponse.forecasts || {});\n }\n if (reportsResponse.status === 207 && reportsResponse.errors) {\n providerErrorsSetter(reportsResponse.errors);\n }\n })\n .catch(e => alertApi.post({ message: `${e.message}`, severity: 'error' }));\n }, [alertApi, infraWalletApi, providerErrorsSetter]);\n\n useEffect(() => {\n fetchCosts();\n }, [fetchCosts]);\n\n useEffect(() => {\n const fetchBudgets = async () => {\n try {\n const response = await infraWalletApi.getBudgets('default');\n setBudgets(response.data || []);\n } catch (error) {\n // Failed to fetch budgets - silent error handling\n }\n };\n fetchBudgets();\n }, [infraWalletApi]);\n\n return (\n <Grid container spacing={3}>\n <Grid item xs={12}>\n <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>\n <Typography variant=\"h5\">\n {moment().year()} {budgetView} Budgets\n </Typography>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>\n <Typography variant=\"body2\">Annual</Typography>\n <Switch\n size=\"small\"\n onChange={event => setBudgetView(event.target.checked ? BUDGET_VIEW.MONTHLY : BUDGET_VIEW.ANNUAL)}\n />\n <Typography variant=\"body2\">Monthly</Typography>\n </Box>\n </Box>\n </Grid>\n\n {/* Budget Insights Panel */}\n {reportsAggregatedAndMerged && (\n <Grid item xs={12}>\n <BudgetInsights reports={reportsAggregatedAndMerged} budgets={budgets} />\n </Grid>\n )}\n {reportsAggregatedAndMerged !== undefined ? (\n reportsAggregatedAndMerged.map(report => (\n <Grid item key={`${report.id}-grid`} xs={4}>\n <BudgetChart\n provider={report.id}\n monthlyCosts={report.reports}\n view={budgetView}\n budgets={budgets}\n setBudgets={setBudgets}\n forecast={forecasts[report.id]}\n />\n </Grid>\n ))\n ) : (\n <Grid item xs={12}>\n <Paper\n sx={{\n display: 'flex',\n flexDirection: 'column',\n height: 500,\n backgroundColor: 'transparent',\n boxShadow: 'none',\n }}\n >\n <div style={{ width: '60%', margin: 'auto' }}>\n <Skeleton />\n <Skeleton />\n <Skeleton />\n </div>\n </Paper>\n </Grid>\n )}\n </Grid>\n );\n};\n"],"names":["recommendations"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electrolux-oss/plugin-infrawallet",
3
- "version": "1.1.0-20251218080406-fbaf733",
3
+ "version": "1.1.0-20260112100533-68a81f8",
4
4
  "backstage": {
5
5
  "role": "frontend-plugin",
6
6
  "pluginId": "infrawallet",