Skip to content

Commit 6ad30ed

Browse files
committed
Status
1 parent 68d53d8 commit 6ad30ed

File tree

2 files changed

+261
-60
lines changed

2 files changed

+261
-60
lines changed

src/Pages/StatusPage/index.jsx

Lines changed: 163 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
"use client";
2-
32
import { useContext, useState } from "react";
43
import * as s from "./style";
54
import Navbar from "../../Components/Navbar";
@@ -172,11 +171,161 @@ const logos = imageNames.reduce((acc, name) => {
172171
return acc;
173172
}, {});
174173

175-
// 드롭다운 서버 카드 컴포넌트
174+
const calculateServerStats = () => {
175+
const totalServers = serverData.length;
176+
177+
const memoryStats = {
178+
DDR3: 0,
179+
DDR4: 0,
180+
DDR5: 0,
181+
LPDDR4X: 0,
182+
total: 0,
183+
};
184+
185+
const storageStats = {
186+
HDD: 0,
187+
"SATA SSD": 0,
188+
"NVMe SSD": 0,
189+
total: 0,
190+
};
191+
192+
serverData.forEach((server) => {
193+
const memoryMatch = server.memory.match(/(\d+)GB/);
194+
const memorySize = memoryMatch ? Number.parseInt(memoryMatch[1]) : 0;
195+
196+
if (server.memory.includes("DDR5")) {
197+
memoryStats.DDR5 += memorySize;
198+
} else if (server.memory.includes("DDR4")) {
199+
memoryStats.DDR4 += memorySize;
200+
} else if (server.memory.includes("DDR3")) {
201+
memoryStats.DDR3 += memorySize;
202+
} else if (server.memory.includes("LPDDR4X")) {
203+
memoryStats.LPDDR4X += memorySize;
204+
}
205+
memoryStats.total += memorySize;
206+
207+
server.storage.forEach((storageItem) => {
208+
const capacityMatch = storageItem.match(/(\d+(?:\.\d+)?)(GB|TB)/i);
209+
const multiplierMatch = storageItem.match(/x\s*(\d+)/i);
210+
211+
if (capacityMatch) {
212+
const capacity = Number.parseFloat(capacityMatch[1]);
213+
const unit = capacityMatch[2].toUpperCase();
214+
const multiplier = multiplierMatch
215+
? Number.parseInt(multiplierMatch[1])
216+
: 1;
217+
218+
let capacityInGB = capacity;
219+
if (unit === "TB") {
220+
capacityInGB = capacity * 1024;
221+
}
222+
223+
const totalCapacity = capacityInGB * multiplier;
224+
225+
if (storageItem.includes("HDD")) {
226+
storageStats.HDD += totalCapacity;
227+
} else if (storageItem.includes("NVMe")) {
228+
storageStats["NVMe SSD"] += totalCapacity;
229+
} else if (storageItem.includes("SSD")) {
230+
storageStats["SATA SSD"] += totalCapacity;
231+
}
232+
233+
storageStats.total += totalCapacity;
234+
}
235+
});
236+
});
237+
238+
return { totalServers, memoryStats, storageStats };
239+
};
240+
241+
const formatCapacity = (capacityGB) => {
242+
if (capacityGB >= 1024) {
243+
const capacityTB = capacityGB / 1024;
244+
return capacityTB % 1 === 0
245+
? `${capacityTB}TB`
246+
: `${capacityTB.toFixed(1)}TB`;
247+
}
248+
return capacityGB % 1 === 0
249+
? `${capacityGB}GB`
250+
: `${capacityGB.toFixed(1)}GB`;
251+
};
252+
253+
const ServerStatsOverview = ({ isKorean }) => {
254+
const { totalServers, memoryStats, storageStats } = calculateServerStats();
255+
256+
return (
257+
<s.StatsContainer>
258+
<s.StatsGrid>
259+
<s.StatCard>
260+
<s.StatContent>
261+
<s.StatLabel>
262+
{isKorean ? "총 서버 대수" : "Total Servers"}
263+
</s.StatLabel>
264+
<s.StatValue>{totalServers}</s.StatValue>
265+
<s.StatUnit>{isKorean ? "대" : "units"}</s.StatUnit>
266+
</s.StatContent>
267+
</s.StatCard>
268+
269+
<s.StatCard>
270+
<s.StatContent>
271+
<s.StatLabel>
272+
{isKorean ? "총 메모리" : "Total Memory"}
273+
</s.StatLabel>
274+
<s.StatValue>{memoryStats.total}GB</s.StatValue>
275+
<s.StatBreakdown>
276+
{memoryStats.DDR5 > 0 && (
277+
<span>DDR5: {memoryStats.DDR5}GB</span>
278+
)}
279+
{memoryStats.DDR4 > 0 && (
280+
<span>DDR4: {memoryStats.DDR4}GB</span>
281+
)}
282+
{memoryStats.DDR3 > 0 && (
283+
<span>DDR3: {memoryStats.DDR3}GB</span>
284+
)}
285+
{memoryStats.LPDDR4X > 0 && (
286+
<span>LPDDR4X: {memoryStats.LPDDR4X}GB</span>
287+
)}
288+
</s.StatBreakdown>
289+
</s.StatContent>
290+
</s.StatCard>
291+
292+
<s.StatCard>
293+
<s.StatContent>
294+
<s.StatLabel>
295+
{isKorean ? "총 스토리지" : "Total Storage"}
296+
</s.StatLabel>
297+
<s.StatValue>
298+
{formatCapacity(storageStats.total)}
299+
</s.StatValue>
300+
<s.StatBreakdown>
301+
{storageStats.HDD > 0 && (
302+
<span>
303+
HDD: {formatCapacity(storageStats.HDD)}
304+
</span>
305+
)}
306+
{storageStats["NVMe SSD"] > 0 && (
307+
<span>
308+
NVMe:{" "}
309+
{formatCapacity(storageStats["NVMe SSD"])}
310+
</span>
311+
)}
312+
{storageStats["SATA SSD"] > 0 && (
313+
<span>
314+
SATA SSD:{" "}
315+
{formatCapacity(storageStats["SATA SSD"])}
316+
</span>
317+
)}
318+
</s.StatBreakdown>
319+
</s.StatContent>
320+
</s.StatCard>
321+
</s.StatsGrid>
322+
</s.StatsContainer>
323+
);
324+
};
325+
176326
const DropdownServerCard = ({ server, index, isKorean }) => {
177327
const [isOpen, setIsOpen] = useState(false);
178328

179-
// 간략한 정보 추출
180329
const getServerType = (name) => {
181330
if (name.includes("Hypervisor")) return "Hypervisor";
182331
if (name.includes("Truenas")) return "Storage";
@@ -202,33 +351,23 @@ const DropdownServerCard = ({ server, index, isKorean }) => {
202351
if (cpu.includes("Intel Celeron J4125")) return "Intel Celeron J4125";
203352
if (cpu.includes("Apple Silicon M1")) return "Apple Silicon M1";
204353
if (cpu.includes("Intel Celeron N2930")) return "Intel Celeron N2930";
205-
return cpu.split(" @")[0]; // Fallback to CPU name without frequency
354+
return cpu.split(" @")[0];
206355
};
207356

208357
const getMemorySize = (memory) => {
209358
const sizeMatch = memory.match(/(\d+)GB/);
210359
const ddrMatch = memory.match(/(DDR\d+L?|LPDDR\d+X?)/i);
211-
212360
const size = sizeMatch ? `${sizeMatch[1]}GB` : "RAM";
213361
const ddrType = ddrMatch ? ddrMatch[1] : "";
214-
215362
return ddrType ? `${ddrType} ${size}` : size;
216363
};
217364

218365
const getTotalStorage = (storageArray) => {
219-
if (!storageArray || storageArray.length === 0) {
220-
return "0GB";
221-
}
366+
if (!storageArray || storageArray.length === 0) return "0GB";
222367

223368
let totalGB = 0;
224-
225369
storageArray.forEach((storageItem) => {
226-
// Extract capacity and multiplier from storage string
227-
// Examples: "Gen4 NVMe 512GB x 2", "SATA HDD 4TB x 2", "16TB SATA HDD"
228-
229-
// Match patterns like "512GB", "4TB", etc.
230370
const capacityMatch = storageItem.match(/(\d+(?:\.\d+)?)(GB|TB)/i);
231-
// Match multiplier patterns like "x 2", "x 10", etc.
232371
const multiplierMatch = storageItem.match(/x\s*(\d+)/i);
233372

234373
if (capacityMatch) {
@@ -238,33 +377,24 @@ const DropdownServerCard = ({ server, index, isKorean }) => {
238377
? Number.parseInt(multiplierMatch[1])
239378
: 1;
240379

241-
// Convert to GB
242380
let capacityInGB = capacity;
243381
if (unit === "TB") {
244-
capacityInGB = capacity * 1024; // Convert TB to GB
382+
capacityInGB = capacity * 1024;
245383
}
246384

247-
// Apply multiplier
248385
totalGB += capacityInGB * multiplier;
249386
}
250387
});
251388

252-
// Format the result
253389
if (totalGB >= 1024) {
254390
const totalTB = totalGB / 1024;
255-
// If it's a whole number, don't show decimals
256-
if (totalTB % 1 === 0) {
257-
return `${totalTB}TB`;
258-
} else {
259-
return `${totalTB.toFixed(1)}TB`;
260-
}
391+
return totalTB % 1 === 0
392+
? `${totalTB}TB`
393+
: `${totalTB.toFixed(1)}TB`;
261394
} else {
262-
// If it's a whole number, don't show decimals
263-
if (totalGB % 1 === 0) {
264-
return `${totalGB}GB`;
265-
} else {
266-
return `${totalGB.toFixed(1)}GB`;
267-
}
395+
return totalGB % 1 === 0
396+
? `${totalGB}GB`
397+
: `${totalGB.toFixed(1)}GB`;
268398
}
269399
};
270400

@@ -319,7 +449,6 @@ const DropdownServerCard = ({ server, index, isKorean }) => {
319449
</svg>
320450
</s.DropdownIcon>
321451
</s.ServerCardHeader>
322-
323452
<s.ServerCardContent isOpen={isOpen}>
324453
<s.ServerCardGrid>
325454
<s.ServerCardColumn>
@@ -383,7 +512,6 @@ const StatusPage = () => {
383512
zzuniHomelab의 리소스를 확인하세요.
384513
</s.MainContainerSubTitle>
385514
</s.MainContainer>
386-
387515
<s.SubContainer1>
388516
<s.SubContainer1Items>
389517
{hardwareItemsKR.map((item, index) => (
@@ -393,8 +521,8 @@ const StatusPage = () => {
393521
))}
394522
</s.SubContainer1Items>
395523
</s.SubContainer1>
396-
397524
<s.SubContainer2>
525+
<ServerStatsOverview isKorean={true} />
398526
<s.ServerSection>
399527
{serverData.map((server, index) => (
400528
<DropdownServerCard
@@ -406,7 +534,6 @@ const StatusPage = () => {
406534
))}
407535
</s.ServerSection>
408536
</s.SubContainer2>
409-
410537
<s.SubContainer3>
411538
<s.SliderContainer>
412539
<s.SliderTrack>
@@ -417,7 +544,6 @@ const StatusPage = () => {
417544
<img
418545
src={
419546
logos[key] ||
420-
"/placeholder.svg" ||
421547
"/placeholder.svg"
422548
}
423549
alt={key}
@@ -431,7 +557,6 @@ const StatusPage = () => {
431557
<img
432558
src={
433559
logos[key] ||
434-
"/placeholder.svg" ||
435560
"/placeholder.svg"
436561
}
437562
alt={key}
@@ -452,7 +577,6 @@ const StatusPage = () => {
452577
Check out zzuniHomelab's computing resources.
453578
</s.MainContainerSubTitle>
454579
</s.MainContainer>
455-
456580
<s.SubContainer1>
457581
<s.SubContainer1Items>
458582
{hardwareItemsEN.map((item, index) => (
@@ -462,8 +586,8 @@ const StatusPage = () => {
462586
))}
463587
</s.SubContainer1Items>
464588
</s.SubContainer1>
465-
466589
<s.SubContainer2>
590+
<ServerStatsOverview isKorean={false} />
467591
<s.ServerSection>
468592
{serverData.map((server, index) => (
469593
<DropdownServerCard
@@ -475,7 +599,6 @@ const StatusPage = () => {
475599
))}
476600
</s.ServerSection>
477601
</s.SubContainer2>
478-
479602
<s.SubContainer3>
480603
<s.SliderContainer>
481604
<s.SliderTrack>
@@ -486,7 +609,6 @@ const StatusPage = () => {
486609
<img
487610
src={
488611
logos[key] ||
489-
"/placeholder.svg" ||
490612
"/placeholder.svg"
491613
}
492614
alt={key}
@@ -500,7 +622,6 @@ const StatusPage = () => {
500622
<img
501623
src={
502624
logos[key] ||
503-
"/placeholder.svg" ||
504625
"/placeholder.svg"
505626
}
506627
alt={key}

0 commit comments

Comments
 (0)