@letthem/backstage-plugin-cost-insights 0.1.0

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.
@@ -0,0 +1,445 @@
1
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
+ import { Box, Card, CardContent, Typography, TableContainer, Paper, Table, TableHead, TableRow, TableCell, TableBody, ButtonGroup, Button } from '@mui/material';
3
+ import Grid2 from '@mui/material/Grid2';
4
+ import { useState, useMemo } from 'react';
5
+ import { ResponsiveContainer, LineChart, CartesianGrid, XAxis, YAxis, Tooltip, Legend, Line, BarChart, Bar } from 'recharts';
6
+ import { DateTime } from 'luxon';
7
+
8
+ function EC2Overview({ resources, monthlyData = [], startDate, endDate }) {
9
+ const [monthsToShow, setMonthsToShow] = useState(6);
10
+ const instancesCost = resources.filter((r) => r.resourceType === "instance").reduce((sum, r) => sum + r.totalCost, 0);
11
+ const volumeCost = resources.filter((r) => r.resourceType === "snapshot" || r.resourceType === "volume").reduce((sum, r) => sum + r.totalCost, 0);
12
+ const elasticIpCost = resources.filter((r) => r.resourceType === "elastic-ip").reduce((sum, r) => sum + r.totalCost, 0);
13
+ const natGatewayCost = resources.filter((r) => r.resourceType === "nat-gateway").reduce((sum, r) => sum + r.totalCost, 0);
14
+ const dataTransferCost = resources.filter((r) => r.resourceType === "data-transfer").reduce((sum, r) => sum + r.totalCost, 0);
15
+ const vpcCost = resources.filter((r) => r.resourceType === "vpc").reduce((sum, r) => sum + r.totalCost, 0);
16
+ const totalCost = instancesCost + volumeCost + elasticIpCost + natGatewayCost + dataTransferCost + vpcCost;
17
+ const dailyTrendData = useMemo(() => {
18
+ const dailyMap = /* @__PURE__ */ new Map();
19
+ resources.forEach((resource) => {
20
+ resource.dailyCosts.forEach(({ date, cost }) => {
21
+ if (!dailyMap.has(date)) {
22
+ dailyMap.set(date, {
23
+ instances: 0,
24
+ volume: 0,
25
+ elasticIp: 0,
26
+ natGateway: 0,
27
+ dataTransfer: 0,
28
+ vpc: 0
29
+ });
30
+ }
31
+ const entry = dailyMap.get(date);
32
+ if (resource.resourceType === "instance") {
33
+ entry.instances += cost;
34
+ } else if (resource.resourceType === "snapshot" || resource.resourceType === "volume") {
35
+ entry.volume += cost;
36
+ } else if (resource.resourceType === "elastic-ip") {
37
+ entry.elasticIp += cost;
38
+ } else if (resource.resourceType === "nat-gateway") {
39
+ entry.natGateway += cost;
40
+ } else if (resource.resourceType === "data-transfer") {
41
+ entry.dataTransfer += cost;
42
+ } else if (resource.resourceType === "vpc") {
43
+ entry.vpc += cost;
44
+ }
45
+ });
46
+ });
47
+ return Array.from(dailyMap.entries()).map(([date, costs]) => ({
48
+ date,
49
+ Instances: costs.instances,
50
+ Volume: costs.volume,
51
+ "Elastic IP": costs.elasticIp,
52
+ "NAT Gateway": costs.natGateway,
53
+ "Data Transfer": costs.dataTransfer,
54
+ VPC: costs.vpc,
55
+ Total: costs.instances + costs.volume + costs.elasticIp + costs.natGateway + costs.dataTransfer + costs.vpc
56
+ })).sort((a, b) => a.date.localeCompare(b.date));
57
+ }, [resources]);
58
+ const topResources = useMemo(() => {
59
+ return [...resources].sort((a, b) => b.totalCost - a.totalCost).slice(0, 5).map((resource) => ({
60
+ ...resource,
61
+ percentage: totalCost > 0 ? resource.totalCost / totalCost * 100 : 0
62
+ }));
63
+ }, [resources, totalCost]);
64
+ const predictedMonthEndCost = useMemo(() => {
65
+ if (dailyTrendData.length === 0) return null;
66
+ const now = DateTime.now();
67
+ const currentMonthStart = now.startOf("month");
68
+ if (!startDate || !endDate) return null;
69
+ const isCurrentMonthStart = startDate.hasSame(currentMonthStart, "day");
70
+ const isCurrentMonth = endDate.hasSame(now, "month") && endDate.hasSame(now, "year");
71
+ if (!isCurrentMonthStart || !isCurrentMonth) return null;
72
+ const daysInMonth = now.daysInMonth || 30;
73
+ const currentDay = now.day;
74
+ if (currentDay <= 0) return null;
75
+ const avgDailyCost = totalCost / currentDay;
76
+ const remainingDays = daysInMonth - currentDay;
77
+ const predictedTotal = totalCost + avgDailyCost * remainingDays;
78
+ return {
79
+ current: totalCost,
80
+ predicted: predictedTotal,
81
+ remainingDays,
82
+ avgDailyCost
83
+ };
84
+ }, [dailyTrendData, totalCost, startDate, endDate]);
85
+ return /* @__PURE__ */ jsxs(Box, { children: [
86
+ /* @__PURE__ */ jsxs(Grid2, { container: true, spacing: 3, children: [
87
+ /* @__PURE__ */ jsx(Grid2, { size: { sm: 12, md: 3 }, children: /* @__PURE__ */ jsx(
88
+ Card,
89
+ {
90
+ sx: {
91
+ height: "100%",
92
+ position: "relative",
93
+ bgcolor: "background.paper"
94
+ },
95
+ children: /* @__PURE__ */ jsxs(CardContent, { children: [
96
+ /* @__PURE__ */ jsx(Typography, { sx: { fontSize: 14, color: "text.secondary", mb: 1 }, children: "Total EC2 Cost" }),
97
+ /* @__PURE__ */ jsxs(Typography, { sx: { fontSize: 32, fontWeight: 600 }, children: [
98
+ "$",
99
+ totalCost.toFixed(2)
100
+ ] })
101
+ ] })
102
+ }
103
+ ) }),
104
+ /* @__PURE__ */ jsx(Grid2, { size: { sm: 12, md: 3 }, children: /* @__PURE__ */ jsx(
105
+ Card,
106
+ {
107
+ sx: {
108
+ height: "100%",
109
+ position: "relative",
110
+ bgcolor: "background.paper"
111
+ },
112
+ children: /* @__PURE__ */ jsxs(CardContent, { children: [
113
+ /* @__PURE__ */ jsx(Typography, { sx: { fontSize: 14, color: "text.secondary", mb: 1 }, children: "EC2 Instances" }),
114
+ /* @__PURE__ */ jsxs(Typography, { sx: { fontSize: 32, fontWeight: 600 }, children: [
115
+ "$",
116
+ instancesCost.toFixed(2)
117
+ ] })
118
+ ] })
119
+ }
120
+ ) }),
121
+ /* @__PURE__ */ jsx(Grid2, { size: { sm: 12, md: 3 }, children: /* @__PURE__ */ jsx(
122
+ Card,
123
+ {
124
+ sx: {
125
+ height: "100%",
126
+ position: "relative",
127
+ bgcolor: "background.paper"
128
+ },
129
+ children: /* @__PURE__ */ jsxs(CardContent, { children: [
130
+ /* @__PURE__ */ jsx(Typography, { sx: { fontSize: 14, color: "text.secondary", mb: 1 }, children: "Volumes" }),
131
+ /* @__PURE__ */ jsxs(Typography, { sx: { fontSize: 32, fontWeight: 600 }, children: [
132
+ "$",
133
+ volumeCost.toFixed(2)
134
+ ] })
135
+ ] })
136
+ }
137
+ ) }),
138
+ /* @__PURE__ */ jsx(Grid2, { size: { sm: 12, md: 3 }, children: /* @__PURE__ */ jsx(
139
+ Card,
140
+ {
141
+ sx: {
142
+ height: "100%",
143
+ position: "relative",
144
+ bgcolor: "background.paper"
145
+ },
146
+ children: /* @__PURE__ */ jsxs(CardContent, { children: [
147
+ /* @__PURE__ */ jsx(Typography, { sx: { fontSize: 14, color: "text.secondary", mb: 1 }, children: "Elastic IP" }),
148
+ /* @__PURE__ */ jsxs(Typography, { sx: { fontSize: 32, fontWeight: 600 }, children: [
149
+ "$",
150
+ elasticIpCost.toFixed(2)
151
+ ] })
152
+ ] })
153
+ }
154
+ ) }),
155
+ /* @__PURE__ */ jsx(Grid2, { size: { sm: 12, md: 3 }, children: /* @__PURE__ */ jsx(
156
+ Card,
157
+ {
158
+ sx: {
159
+ height: "100%",
160
+ position: "relative",
161
+ bgcolor: "background.paper"
162
+ },
163
+ children: /* @__PURE__ */ jsxs(CardContent, { children: [
164
+ /* @__PURE__ */ jsx(Typography, { sx: { fontSize: 14, color: "text.secondary", mb: 1 }, children: "NAT Gateway" }),
165
+ /* @__PURE__ */ jsxs(Typography, { sx: { fontSize: 32, fontWeight: 600 }, children: [
166
+ "$",
167
+ natGatewayCost.toFixed(2)
168
+ ] })
169
+ ] })
170
+ }
171
+ ) }),
172
+ /* @__PURE__ */ jsx(Grid2, { size: { sm: 12, md: 3 }, children: /* @__PURE__ */ jsx(
173
+ Card,
174
+ {
175
+ sx: {
176
+ height: "100%",
177
+ position: "relative",
178
+ bgcolor: "background.paper"
179
+ },
180
+ children: /* @__PURE__ */ jsxs(CardContent, { children: [
181
+ /* @__PURE__ */ jsx(Typography, { sx: { fontSize: 14, color: "text.secondary", mb: 1 }, children: "Data Transfer" }),
182
+ /* @__PURE__ */ jsxs(Typography, { sx: { fontSize: 32, fontWeight: 600 }, children: [
183
+ "$",
184
+ dataTransferCost.toFixed(2)
185
+ ] })
186
+ ] })
187
+ }
188
+ ) }),
189
+ /* @__PURE__ */ jsx(Grid2, { size: { sm: 12, md: 3 }, children: /* @__PURE__ */ jsx(
190
+ Card,
191
+ {
192
+ sx: {
193
+ height: "100%",
194
+ position: "relative",
195
+ bgcolor: "background.paper"
196
+ },
197
+ children: /* @__PURE__ */ jsxs(CardContent, { children: [
198
+ /* @__PURE__ */ jsx(Typography, { sx: { fontSize: 14, color: "text.secondary", mb: 1 }, children: "VPC" }),
199
+ /* @__PURE__ */ jsxs(Typography, { sx: { fontSize: 32, fontWeight: 600 }, children: [
200
+ "$",
201
+ vpcCost.toFixed(2)
202
+ ] })
203
+ ] })
204
+ }
205
+ ) })
206
+ ] }),
207
+ predictedMonthEndCost && /* @__PURE__ */ jsx(Box, { sx: { mt: 3 }, children: /* @__PURE__ */ jsx(
208
+ Card,
209
+ {
210
+ sx: {
211
+ backgroundColor: "rgba(33, 150, 243, 0.08)",
212
+ borderLeft: "4px solid",
213
+ borderColor: "info.main"
214
+ },
215
+ children: /* @__PURE__ */ jsxs(CardContent, { children: [
216
+ /* @__PURE__ */ jsx(Typography, { variant: "h6", children: "Month-End Forecast" }),
217
+ /* @__PURE__ */ jsxs(Typography, { variant: "body2", sx: { mt: 1 }, children: [
218
+ "Current spend:",
219
+ " ",
220
+ /* @__PURE__ */ jsxs("strong", { children: [
221
+ "$",
222
+ predictedMonthEndCost.current.toFixed(2)
223
+ ] })
224
+ ] }),
225
+ /* @__PURE__ */ jsxs(Typography, { variant: "body2", children: [
226
+ "Predicted month-end:",
227
+ " ",
228
+ /* @__PURE__ */ jsxs("strong", { children: [
229
+ "$",
230
+ predictedMonthEndCost.predicted.toFixed(2)
231
+ ] })
232
+ ] }),
233
+ /* @__PURE__ */ jsxs(Typography, { variant: "body2", children: [
234
+ "Average daily cost: $",
235
+ predictedMonthEndCost.avgDailyCost.toFixed(2),
236
+ " (",
237
+ predictedMonthEndCost.remainingDays,
238
+ " days remaining)"
239
+ ] })
240
+ ] })
241
+ }
242
+ ) }),
243
+ /* @__PURE__ */ jsx(Typography, { variant: "h6", sx: { pt: 6, pb: 2, fontWeight: 600 }, children: "Current Month Daily Trend" }),
244
+ /* @__PURE__ */ jsx(Box, { sx: { mt: 3, mb: 3 }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: 300, children: /* @__PURE__ */ jsxs(LineChart, { data: dailyTrendData, children: [
245
+ /* @__PURE__ */ jsx(CartesianGrid, { strokeDasharray: "3 3", stroke: "#e0e0e0" }),
246
+ /* @__PURE__ */ jsx(
247
+ XAxis,
248
+ {
249
+ dataKey: "date",
250
+ tick: { fontSize: 12 },
251
+ tickFormatter: (value) => {
252
+ const date = new Date(value);
253
+ return `${date.getMonth() + 1}/${date.getDate()}`;
254
+ }
255
+ }
256
+ ),
257
+ /* @__PURE__ */ jsx(YAxis, { tick: { fontSize: 12 } }),
258
+ /* @__PURE__ */ jsx(
259
+ Tooltip,
260
+ {
261
+ formatter: (value) => value !== void 0 ? `$${value.toFixed(2)}` : "",
262
+ labelFormatter: (label) => `Date: ${label}`
263
+ }
264
+ ),
265
+ /* @__PURE__ */ jsx(Legend, {}),
266
+ /* @__PURE__ */ jsx(
267
+ Line,
268
+ {
269
+ type: "monotone",
270
+ dataKey: "Instances",
271
+ stroke: "#6ac2e5",
272
+ strokeWidth: 2
273
+ }
274
+ ),
275
+ /* @__PURE__ */ jsx(
276
+ Line,
277
+ {
278
+ type: "monotone",
279
+ dataKey: "Volume",
280
+ stroke: "#1fd9a7",
281
+ strokeWidth: 2
282
+ }
283
+ ),
284
+ /* @__PURE__ */ jsx(
285
+ Line,
286
+ {
287
+ type: "monotone",
288
+ dataKey: "Elastic IP",
289
+ stroke: "#f4b630",
290
+ strokeWidth: 2
291
+ }
292
+ ),
293
+ /* @__PURE__ */ jsx(
294
+ Line,
295
+ {
296
+ type: "monotone",
297
+ dataKey: "NAT Gateway",
298
+ stroke: "#1976d2",
299
+ strokeWidth: 2
300
+ }
301
+ ),
302
+ /* @__PURE__ */ jsx(
303
+ Line,
304
+ {
305
+ type: "monotone",
306
+ dataKey: "Data Transfer",
307
+ stroke: "#603fba",
308
+ strokeWidth: 2
309
+ }
310
+ ),
311
+ /* @__PURE__ */ jsx(
312
+ Line,
313
+ {
314
+ type: "monotone",
315
+ dataKey: "VPC",
316
+ stroke: "#aa51f7",
317
+ strokeWidth: 2
318
+ }
319
+ ),
320
+ /* @__PURE__ */ jsx(
321
+ Line,
322
+ {
323
+ type: "monotone",
324
+ dataKey: "Total",
325
+ stroke: "#e552d1",
326
+ strokeWidth: 3
327
+ }
328
+ )
329
+ ] }) }) }),
330
+ /* @__PURE__ */ jsx(Typography, { variant: "h6", sx: { pt: 6, pb: 2, fontWeight: 600 }, children: "Top Cost Resources This Month" }),
331
+ /* @__PURE__ */ jsx(TableContainer, { component: Paper, children: /* @__PURE__ */ jsxs(Table, { children: [
332
+ /* @__PURE__ */ jsx(TableHead, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
333
+ /* @__PURE__ */ jsx(TableCell, { children: "Rank" }),
334
+ /* @__PURE__ */ jsx(TableCell, { children: "Resource ID" }),
335
+ /* @__PURE__ */ jsx(TableCell, { children: "Type" }),
336
+ /* @__PURE__ */ jsx(TableCell, { align: "right", children: "Cost" }),
337
+ /* @__PURE__ */ jsx(TableCell, { align: "right", children: "% of Total" })
338
+ ] }) }),
339
+ /* @__PURE__ */ jsx(TableBody, { children: topResources.map((resource, index) => /* @__PURE__ */ jsxs(
340
+ TableRow,
341
+ {
342
+ sx: { "&:hover": { backgroundColor: "action.hover" } },
343
+ children: [
344
+ /* @__PURE__ */ jsx(TableCell, { children: index + 1 }),
345
+ /* @__PURE__ */ jsx(TableCell, { children: resource.resourceId }),
346
+ /* @__PURE__ */ jsx(TableCell, { children: resource.resourceType === "instance" && resource.instanceType ? resource.instanceType : resource.resourceType === "snapshot" || resource.resourceType === "volume" ? resource.volumeType ? `${resource.resourceType} (${resource.volumeType})` : resource.resourceType : resource.resourceType }),
347
+ /* @__PURE__ */ jsx(TableCell, { align: "right", children: /* @__PURE__ */ jsxs("strong", { children: [
348
+ "$",
349
+ resource.totalCost.toFixed(2)
350
+ ] }) }),
351
+ /* @__PURE__ */ jsxs(TableCell, { align: "right", children: [
352
+ resource.percentage.toFixed(1),
353
+ "%"
354
+ ] })
355
+ ]
356
+ },
357
+ resource.resourceId
358
+ )) })
359
+ ] }) }),
360
+ monthlyData.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
361
+ /* @__PURE__ */ jsxs(Box, { sx: { pt: 6, pb: 2, display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
362
+ /* @__PURE__ */ jsx(Typography, { variant: "h6", sx: { fontWeight: 600 }, children: "Monthly Comparison" }),
363
+ /* @__PURE__ */ jsxs(ButtonGroup, { size: "small", variant: "outlined", children: [
364
+ /* @__PURE__ */ jsx(
365
+ Button,
366
+ {
367
+ variant: monthsToShow === 6 ? "contained" : "outlined",
368
+ onClick: () => setMonthsToShow(6),
369
+ children: "6 Months"
370
+ }
371
+ ),
372
+ /* @__PURE__ */ jsx(
373
+ Button,
374
+ {
375
+ variant: monthsToShow === 12 ? "contained" : "outlined",
376
+ onClick: () => setMonthsToShow(12),
377
+ children: "12 Months"
378
+ }
379
+ )
380
+ ] })
381
+ ] }),
382
+ /* @__PURE__ */ jsx(Box, { sx: { mt: 3, mb: 3 }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: 300, children: /* @__PURE__ */ jsxs(BarChart, { data: monthlyData.slice(-monthsToShow), children: [
383
+ /* @__PURE__ */ jsx(CartesianGrid, { strokeDasharray: "3 3", stroke: "#e0e0e0" }),
384
+ /* @__PURE__ */ jsx(XAxis, { dataKey: "month", tick: { fontSize: 12 } }),
385
+ /* @__PURE__ */ jsx(YAxis, { tick: { fontSize: 12 } }),
386
+ /* @__PURE__ */ jsx(
387
+ Tooltip,
388
+ {
389
+ formatter: (value) => value !== void 0 ? `$${value.toFixed(2)}` : ""
390
+ }
391
+ ),
392
+ /* @__PURE__ */ jsx(Legend, {}),
393
+ /* @__PURE__ */ jsx(
394
+ Bar,
395
+ {
396
+ dataKey: "instances",
397
+ stackId: "a",
398
+ fill: "#6ac2e5",
399
+ name: "Instances"
400
+ }
401
+ ),
402
+ /* @__PURE__ */ jsx(
403
+ Bar,
404
+ {
405
+ dataKey: "volume",
406
+ stackId: "a",
407
+ fill: "#1fd9a7",
408
+ name: "Volume"
409
+ }
410
+ ),
411
+ /* @__PURE__ */ jsx(
412
+ Bar,
413
+ {
414
+ dataKey: "elasticIp",
415
+ stackId: "a",
416
+ fill: "#f4b630",
417
+ name: "Elastic IP"
418
+ }
419
+ ),
420
+ /* @__PURE__ */ jsx(
421
+ Bar,
422
+ {
423
+ dataKey: "natGateway",
424
+ stackId: "a",
425
+ fill: "#1976d2",
426
+ name: "NAT Gateway"
427
+ }
428
+ ),
429
+ /* @__PURE__ */ jsx(
430
+ Bar,
431
+ {
432
+ dataKey: "dataTransfer",
433
+ stackId: "a",
434
+ fill: "#603fba",
435
+ name: "Data Transfer"
436
+ }
437
+ ),
438
+ /* @__PURE__ */ jsx(Bar, { dataKey: "vpc", stackId: "a", fill: "#aa51f7", name: "VPC" })
439
+ ] }) }) })
440
+ ] })
441
+ ] });
442
+ }
443
+
444
+ export { EC2Overview };
445
+ //# sourceMappingURL=EC2Overview.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EC2Overview.esm.js","sources":["../../src/components/EC2Overview.tsx"],"sourcesContent":["import {\n Box,\n Button,\n ButtonGroup,\n Card,\n CardContent,\n Paper,\n Table,\n TableBody,\n TableCell,\n TableContainer,\n TableHead,\n TableRow,\n Typography,\n} from '@mui/material';\nimport Grid2 from '@mui/material/Grid2';\nimport { useMemo, useState } from 'react';\nimport {\n Bar,\n BarChart,\n CartesianGrid,\n Legend,\n Line,\n LineChart,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts';\nimport { DateTime } from 'luxon';\n\ninterface EC2Resource {\n resourceId: string;\n resourceType:\n | 'instance'\n | 'elastic-ip'\n | 'other'\n | 'snapshot'\n | 'volume'\n | 'nat-gateway'\n | 'data-transfer'\n | 'vpc';\n instanceType?: string;\n volumeType?: string;\n totalCost: number;\n usageAmount: number;\n dailyCosts: Array<{ date: string; cost: number }>;\n}\n\ninterface EC2OverviewProps {\n resources: EC2Resource[];\n monthlyData?: Array<{\n month: string;\n instances: number;\n volume: number;\n elasticIp: number;\n natGateway: number;\n dataTransfer: number;\n vpc: number;\n total: number;\n }>;\n startDate?: DateTime | null;\n endDate?: DateTime | null;\n}\n\nexport function EC2Overview({ resources, monthlyData = [], startDate, endDate }: EC2OverviewProps) {\n const [monthsToShow, setMonthsToShow] = useState<6 | 12>(6);\n\n const instancesCost = resources\n .filter(r => r.resourceType === 'instance')\n .reduce((sum, r) => sum + r.totalCost, 0);\n\n const volumeCost = resources\n .filter(r => r.resourceType === 'snapshot' || r.resourceType === 'volume')\n .reduce((sum, r) => sum + r.totalCost, 0);\n\n const elasticIpCost = resources\n .filter(r => r.resourceType === 'elastic-ip')\n .reduce((sum, r) => sum + r.totalCost, 0);\n\n const natGatewayCost = resources\n .filter(r => r.resourceType === 'nat-gateway')\n .reduce((sum, r) => sum + r.totalCost, 0);\n\n const dataTransferCost = resources\n .filter(r => r.resourceType === 'data-transfer')\n .reduce((sum, r) => sum + r.totalCost, 0);\n\n const vpcCost = resources\n .filter(r => r.resourceType === 'vpc')\n .reduce((sum, r) => sum + r.totalCost, 0);\n\n const totalCost =\n instancesCost +\n volumeCost +\n elasticIpCost +\n natGatewayCost +\n dataTransferCost +\n vpcCost;\n\n\n const dailyTrendData = useMemo(() => {\n const dailyMap = new Map<\n string,\n {\n instances: number;\n volume: number;\n elasticIp: number;\n natGateway: number;\n dataTransfer: number;\n vpc: number;\n }\n >();\n\n resources.forEach(resource => {\n resource.dailyCosts.forEach(({ date, cost }) => {\n if (!dailyMap.has(date)) {\n dailyMap.set(date, {\n instances: 0,\n volume: 0,\n elasticIp: 0,\n natGateway: 0,\n dataTransfer: 0,\n vpc: 0,\n });\n }\n\n const entry = dailyMap.get(date) as {\n instances: number;\n volume: number;\n elasticIp: number;\n natGateway: number;\n dataTransfer: number;\n vpc: number;\n };\n if (resource.resourceType === 'instance') {\n entry.instances += cost;\n } else if (\n resource.resourceType === 'snapshot' ||\n resource.resourceType === 'volume'\n ) {\n entry.volume += cost;\n } else if (resource.resourceType === 'elastic-ip') {\n entry.elasticIp += cost;\n } else if (resource.resourceType === 'nat-gateway') {\n entry.natGateway += cost;\n } else if (resource.resourceType === 'data-transfer') {\n entry.dataTransfer += cost;\n } else if (resource.resourceType === 'vpc') {\n entry.vpc += cost;\n }\n });\n });\n\n return Array.from(dailyMap.entries())\n .map(([date, costs]) => ({\n date,\n Instances: costs.instances,\n Volume: costs.volume,\n 'Elastic IP': costs.elasticIp,\n 'NAT Gateway': costs.natGateway,\n 'Data Transfer': costs.dataTransfer,\n VPC: costs.vpc,\n Total:\n costs.instances +\n costs.volume +\n costs.elasticIp +\n costs.natGateway +\n costs.dataTransfer +\n costs.vpc,\n }))\n .sort((a, b) => a.date.localeCompare(b.date));\n }, [resources]);\n\n const topResources = useMemo(() => {\n return [...resources]\n .sort((a, b) => b.totalCost - a.totalCost)\n .slice(0, 5)\n .map(resource => ({\n ...resource,\n percentage: totalCost > 0 ? (resource.totalCost / totalCost) * 100 : 0,\n }));\n }, [resources, totalCost]);\n\n const predictedMonthEndCost = useMemo(() => {\n if (dailyTrendData.length === 0) return null;\n\n // Only show forecast when the ENTIRE current month is selected\n const now = DateTime.now();\n const currentMonthStart = now.startOf('month');\n\n // Check if startDate and endDate represent the current month period\n if (!startDate || !endDate) return null;\n\n const isCurrentMonthStart = startDate.hasSame(currentMonthStart, 'day');\n const isCurrentMonth = endDate.hasSame(now, 'month') && endDate.hasSame(now, 'year');\n\n if (!isCurrentMonthStart || !isCurrentMonth) return null;\n\n const daysInMonth = now.daysInMonth || 30;\n const currentDay = now.day;\n\n // Avoid division by zero\n if (currentDay <= 0) return null;\n\n const avgDailyCost = totalCost / currentDay;\n\n const remainingDays = daysInMonth - currentDay;\n const predictedTotal = totalCost + avgDailyCost * remainingDays;\n\n return {\n current: totalCost,\n predicted: predictedTotal,\n remainingDays,\n avgDailyCost,\n };\n }, [dailyTrendData, totalCost, startDate, endDate]);\n\n\n return (\n <Box>\n <Grid2 container spacing={3}>\n <Grid2 size={{ sm: 12, md: 3 }}>\n <Card\n sx={{\n height: '100%',\n position: 'relative',\n bgcolor: 'background.paper',\n }}\n >\n <CardContent>\n <Typography sx={{ fontSize: 14, color: 'text.secondary', mb: 1 }}>\n Total EC2 Cost\n </Typography>\n <Typography sx={{ fontSize: 32, fontWeight: 600 }}>\n ${totalCost.toFixed(2)}\n </Typography>\n </CardContent>\n </Card>\n </Grid2>\n\n <Grid2 size={{ sm: 12, md: 3 }}>\n <Card\n sx={{\n height: '100%',\n position: 'relative',\n bgcolor: 'background.paper',\n }}\n >\n <CardContent>\n <Typography sx={{ fontSize: 14, color: 'text.secondary', mb: 1 }}>\n EC2 Instances\n </Typography>\n <Typography sx={{ fontSize: 32, fontWeight: 600 }}>\n ${instancesCost.toFixed(2)}\n </Typography>\n </CardContent>\n </Card>\n </Grid2>\n\n <Grid2 size={{ sm: 12, md: 3 }}>\n <Card\n sx={{\n height: '100%',\n position: 'relative',\n bgcolor: 'background.paper',\n }}\n >\n <CardContent>\n <Typography sx={{ fontSize: 14, color: 'text.secondary', mb: 1 }}>\n Volumes\n </Typography>\n <Typography sx={{ fontSize: 32, fontWeight: 600 }}>\n ${volumeCost.toFixed(2)}\n </Typography>\n </CardContent>\n </Card>\n </Grid2>\n\n <Grid2 size={{ sm: 12, md: 3 }}>\n <Card\n sx={{\n height: '100%',\n position: 'relative',\n bgcolor: 'background.paper',\n }}\n >\n <CardContent>\n <Typography sx={{ fontSize: 14, color: 'text.secondary', mb: 1 }}>\n Elastic IP\n </Typography>\n <Typography sx={{ fontSize: 32, fontWeight: 600 }}>\n ${elasticIpCost.toFixed(2)}\n </Typography>\n </CardContent>\n </Card>\n </Grid2>\n\n <Grid2 size={{ sm: 12, md: 3 }}>\n <Card\n sx={{\n height: '100%',\n position: 'relative',\n bgcolor: 'background.paper',\n }}\n >\n <CardContent>\n <Typography sx={{ fontSize: 14, color: 'text.secondary', mb: 1 }}>\n NAT Gateway\n </Typography>\n <Typography sx={{ fontSize: 32, fontWeight: 600 }}>\n ${natGatewayCost.toFixed(2)}\n </Typography>\n </CardContent>\n </Card>\n </Grid2>\n\n <Grid2 size={{ sm: 12, md: 3 }}>\n <Card\n sx={{\n height: '100%',\n position: 'relative',\n bgcolor: 'background.paper',\n }}\n >\n <CardContent>\n <Typography sx={{ fontSize: 14, color: 'text.secondary', mb: 1 }}>\n Data Transfer\n </Typography>\n <Typography sx={{ fontSize: 32, fontWeight: 600 }}>\n ${dataTransferCost.toFixed(2)}\n </Typography>\n </CardContent>\n </Card>\n </Grid2>\n\n <Grid2 size={{ sm: 12, md: 3 }}>\n <Card\n sx={{\n height: '100%',\n position: 'relative',\n bgcolor: 'background.paper',\n }}\n >\n <CardContent>\n <Typography sx={{ fontSize: 14, color: 'text.secondary', mb: 1 }}>\n VPC\n </Typography>\n <Typography sx={{ fontSize: 32, fontWeight: 600 }}>\n ${vpcCost.toFixed(2)}\n </Typography>\n </CardContent>\n </Card>\n </Grid2>\n </Grid2>\n\n {predictedMonthEndCost && (\n <Box sx={{ mt: 3 }}>\n <Card\n sx={{\n backgroundColor: 'rgba(33, 150, 243, 0.08)',\n borderLeft: '4px solid',\n borderColor: 'info.main',\n }}\n >\n <CardContent>\n <Typography variant=\"h6\">Month-End Forecast</Typography>\n <Typography variant=\"body2\" sx={{ mt: 1 }}>\n Current spend:{' '}\n <strong>${predictedMonthEndCost.current.toFixed(2)}</strong>\n </Typography>\n <Typography variant=\"body2\">\n Predicted month-end:{' '}\n <strong>${predictedMonthEndCost.predicted.toFixed(2)}</strong>\n </Typography>\n <Typography variant=\"body2\">\n Average daily cost: $\n {predictedMonthEndCost.avgDailyCost.toFixed(2)} (\n {predictedMonthEndCost.remainingDays} days remaining)\n </Typography>\n </CardContent>\n </Card>\n </Box>\n )}\n\n <Typography variant=\"h6\" sx={{ pt: 6, pb: 2, fontWeight: 600 }}>\n Current Month Daily Trend\n </Typography>\n <Box sx={{ mt: 3, mb: 3 }}>\n <ResponsiveContainer width=\"100%\" height={300}>\n <LineChart data={dailyTrendData}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke=\"#e0e0e0\" />\n <XAxis\n dataKey=\"date\"\n tick={{ fontSize: 12 }}\n tickFormatter={value => {\n const date = new Date(value);\n return `${date.getMonth() + 1}/${date.getDate()}`;\n }}\n />\n <YAxis tick={{ fontSize: 12 }} />\n <Tooltip\n formatter={(value: number | undefined) =>\n value !== undefined ? `$${value.toFixed(2)}` : ''\n }\n labelFormatter={label => `Date: ${label}`}\n />\n <Legend />\n <Line\n type=\"monotone\"\n dataKey=\"Instances\"\n stroke=\"#6ac2e5\"\n strokeWidth={2}\n />\n <Line\n type=\"monotone\"\n dataKey=\"Volume\"\n stroke=\"#1fd9a7\"\n strokeWidth={2}\n />\n <Line\n type=\"monotone\"\n dataKey=\"Elastic IP\"\n stroke=\"#f4b630\"\n strokeWidth={2}\n />\n <Line\n type=\"monotone\"\n dataKey=\"NAT Gateway\"\n stroke=\"#1976d2\"\n strokeWidth={2}\n />\n <Line\n type=\"monotone\"\n dataKey=\"Data Transfer\"\n stroke=\"#603fba\"\n strokeWidth={2}\n />\n <Line\n type=\"monotone\"\n dataKey=\"VPC\"\n stroke=\"#aa51f7\"\n strokeWidth={2}\n />\n <Line\n type=\"monotone\"\n dataKey=\"Total\"\n stroke=\"#e552d1\"\n strokeWidth={3}\n />\n </LineChart>\n </ResponsiveContainer>\n </Box>\n\n <Typography variant=\"h6\" sx={{ pt: 6, pb: 2, fontWeight: 600 }}>\n Top Cost Resources This Month\n </Typography>\n <TableContainer component={Paper}>\n <Table>\n <TableHead>\n <TableRow>\n <TableCell>Rank</TableCell>\n <TableCell>Resource ID</TableCell>\n <TableCell>Type</TableCell>\n <TableCell align=\"right\">Cost</TableCell>\n <TableCell align=\"right\">% of Total</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {topResources.map((resource, index) => (\n <TableRow\n key={resource.resourceId}\n sx={{ '&:hover': { backgroundColor: 'action.hover' } }}\n >\n <TableCell>{index + 1}</TableCell>\n <TableCell>{resource.resourceId}</TableCell>\n <TableCell>\n {resource.resourceType === 'instance' && resource.instanceType\n ? resource.instanceType\n : resource.resourceType === 'snapshot' ||\n resource.resourceType === 'volume'\n ? resource.volumeType\n ? `${resource.resourceType} (${resource.volumeType})`\n : resource.resourceType\n : resource.resourceType}\n </TableCell>\n <TableCell align=\"right\">\n <strong>${resource.totalCost.toFixed(2)}</strong>\n </TableCell>\n <TableCell align=\"right\">\n {resource.percentage.toFixed(1)}%\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </TableContainer>\n\n {monthlyData.length > 0 && (\n <>\n <Box sx={{ pt: 6, pb: 2, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>\n <Typography variant=\"h6\" sx={{ fontWeight: 600 }}>\n Monthly Comparison\n </Typography>\n <ButtonGroup size=\"small\" variant=\"outlined\">\n <Button\n variant={monthsToShow === 6 ? 'contained' : 'outlined'}\n onClick={() => setMonthsToShow(6)}\n >\n 6 Months\n </Button>\n <Button\n variant={monthsToShow === 12 ? 'contained' : 'outlined'}\n onClick={() => setMonthsToShow(12)}\n >\n 12 Months\n </Button>\n </ButtonGroup>\n </Box>\n <Box sx={{ mt: 3, mb: 3 }}>\n <ResponsiveContainer width=\"100%\" height={300}>\n <BarChart data={monthlyData.slice(-monthsToShow)}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke=\"#e0e0e0\" />\n <XAxis dataKey=\"month\" tick={{ fontSize: 12 }} />\n <YAxis tick={{ fontSize: 12 }} />\n <Tooltip\n formatter={(value: number | undefined) =>\n value !== undefined ? `$${value.toFixed(2)}` : ''\n }\n />\n <Legend />\n <Bar\n dataKey=\"instances\"\n stackId=\"a\"\n fill=\"#6ac2e5\"\n name=\"Instances\"\n />\n <Bar\n dataKey=\"volume\"\n stackId=\"a\"\n fill=\"#1fd9a7\"\n name=\"Volume\"\n />\n <Bar\n dataKey=\"elasticIp\"\n stackId=\"a\"\n fill=\"#f4b630\"\n name=\"Elastic IP\"\n />\n <Bar\n dataKey=\"natGateway\"\n stackId=\"a\"\n fill=\"#1976d2\"\n name=\"NAT Gateway\"\n />\n <Bar\n dataKey=\"dataTransfer\"\n stackId=\"a\"\n fill=\"#603fba\"\n name=\"Data Transfer\"\n />\n <Bar dataKey=\"vpc\" stackId=\"a\" fill=\"#aa51f7\" name=\"VPC\" />\n </BarChart>\n </ResponsiveContainer>\n </Box>\n </>\n )}\n </Box>\n );\n}\n"],"names":[],"mappings":"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"}