Move components inside folders
Signed-off-by: Andrea Pavone <info@andreapavone.com>
This commit is contained in:
66
resources/js/Components/Dashboard/DashboardHeader.tsx
Normal file
66
resources/js/Components/Dashboard/DashboardHeader.tsx
Normal file
@ -0,0 +1,66 @@
|
||||
import {SecuritySummaryReportResultType} from "@/types/security-summary";
|
||||
import {Card, CardContent, CardHeader, CardTitle} from "@/Components/ui/card";
|
||||
import {Check, Copy, ShieldAlert} from "lucide-react";
|
||||
import {Button} from "@/Components/ui/button";
|
||||
import React, {useState} from "react";
|
||||
import {useClipboard} from "use-clipboard-copy";
|
||||
|
||||
export default function DashboardHeader({ reportData }: { reportData: SecuritySummaryReportResultType }) {
|
||||
|
||||
const [isCopied, setIsCopied] = useState(false);
|
||||
const clipboard = useClipboard();
|
||||
|
||||
|
||||
|
||||
const handleCopy = () => {
|
||||
clipboard.copy(reportData.idsummary)
|
||||
setIsCopied(true)
|
||||
setTimeout(() => setIsCopied(false), 2000)
|
||||
}
|
||||
|
||||
return (
|
||||
<Card className="mb-6">
|
||||
<CardHeader>
|
||||
<div className="flex justify-between items-center">
|
||||
<CardTitle className="text-2xl">Security report for: {reportData.domain_name}</CardTitle>
|
||||
<div className="flex items-center gap-2">
|
||||
<ShieldAlert
|
||||
className={`w-6 h-6 ${parseInt(reportData.risk_score) > 75 ? 'text-red-500' : 'text-yellow-500'}`}/>
|
||||
<span className="text-xl font-bold">Risk Score: {reportData.risk_score}/100</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex sm:flex-row flex-col sm:items-center gap-2 text-gray-500">
|
||||
<span className="flex flex-row gap-1">
|
||||
<span className="font-bold mr-2">Scan ID:</span>
|
||||
<pre className="px-2 bg-muted rounded-md">
|
||||
<code className="text-sm whitespace-nowrap">{reportData.idsummary}</code>
|
||||
</pre>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-8 w-8 p-0"
|
||||
onClick={handleCopy}
|
||||
aria-label={isCopied ? "Copied" : "Copy to clipboard"}
|
||||
>
|
||||
{isCopied ? (
|
||||
<Check className="w-4 h-4 text-green-500"/>
|
||||
) : (
|
||||
<Copy className="w-4 h-4"/>
|
||||
)}
|
||||
</Button>
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex sm:flex-row flex-col sm:items-center gap-2 text-gray-500">
|
||||
<span>
|
||||
<span className="font-bold mr-2">Scan Date:</span>
|
||||
<span>{reportData.creation_date}</span>
|
||||
</span>
|
||||
<span>
|
||||
<span className="font-bold mr-2">Last Edit:</span>
|
||||
<span>{reportData.last_edit}</span>
|
||||
</span>
|
||||
</div>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
import {SecuritySummaryReportResultType} from "@/types/security-summary";
|
||||
import {Card, CardContent, CardHeader, CardTitle} from "@/Components/ui/card";
|
||||
import {Database} from "lucide-react";
|
||||
import React from "react";
|
||||
|
||||
export default function LeaksEnumerationCard({ reportData }: { reportData: SecuritySummaryReportResultType }) {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Database className="w-5 h-5"/>
|
||||
Enumeration
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div
|
||||
className="text-3xl font-bold">{reportData.n_dataleak.enumeration}</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
import {SecuritySummaryReportResultType} from "@/types/security-summary";
|
||||
import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/Components/ui/card";
|
||||
import {Database} from "lucide-react";
|
||||
import React from "react";
|
||||
|
||||
export default function LeaksResolvedCard({ reportData }: { reportData: SecuritySummaryReportResultType }) {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Database className="w-5 h-5"/>
|
||||
Resolved
|
||||
</CardTitle>
|
||||
<CardDescription>Resolved data leak incidents</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div
|
||||
className="text-3xl font-bold">{reportData.n_dataleak.resolved.potential_stealer}</div>
|
||||
<div className="text-xs text-muted-foreground mt-1">
|
||||
Including {reportData.n_dataleak.resolved.domain_stealer} domain stealer
|
||||
and {reportData.n_dataleak.resolved.other_stealer} other leaks
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
import {SecuritySummaryReportResultType} from "@/types/security-summary";
|
||||
import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/Components/ui/card";
|
||||
import {Database} from "lucide-react";
|
||||
import React from "react";
|
||||
|
||||
export default function LeaksUnresolvedCard({ reportData }: { reportData: SecuritySummaryReportResultType }) {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Database className="w-5 h-5"/>
|
||||
Unresolved
|
||||
</CardTitle>
|
||||
<CardDescription>Unresolved data leak incidents</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div
|
||||
className="text-3xl font-bold">{reportData.n_dataleak.unresolved.potential_stealer}</div>
|
||||
<div className="text-xs text-muted-foreground mt-1">
|
||||
Including {reportData.n_dataleak.unresolved.domain_stealer} domain stealer
|
||||
and {reportData.n_dataleak.unresolved.other_stealer} other leaks
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
import {SecuritySummaryReportResultType} from "@/types/security-summary";
|
||||
import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/Components/ui/card";
|
||||
import {LockIcon} from "lucide-react";
|
||||
import React from "react";
|
||||
|
||||
export default function OverviewCertificatesCard({ reportData }: { reportData: SecuritySummaryReportResultType }) {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<LockIcon className="w-5 h-5"/>
|
||||
Certificates
|
||||
</CardTitle>
|
||||
<CardDescription>Number of active and expired certificates</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-3xl font-bold">Active: {reportData.n_cert_attivi}</div>
|
||||
<div
|
||||
className="text-3xl font-bold text-red-700">Expired: {reportData.n_cert_scaduti}</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
import {SecuritySummaryReportResultType} from "@/types/security-summary";
|
||||
import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/Components/ui/card";
|
||||
import {Database} from "lucide-react";
|
||||
import React from "react";
|
||||
|
||||
export default function OverviewDataLeaksCard({ reportData }: { reportData: SecuritySummaryReportResultType }) {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Database className="w-5 h-5"/>
|
||||
Data Leaks
|
||||
</CardTitle>
|
||||
<CardDescription>Total data leak incidents</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div
|
||||
className="text-3xl font-bold">{reportData.n_dataleak.total.potential_stealer}</div>
|
||||
<div className="text-xs text-muted-foreground mt-1">
|
||||
Including {reportData.n_dataleak.total.domain_stealer} domain stealer
|
||||
and {reportData.n_dataleak.total.other_stealer} other leaks
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
import {SecuritySummaryReportResultType} from "@/types/security-summary";
|
||||
import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/Components/ui/card";
|
||||
import {LockIcon} from "lucide-react";
|
||||
import React from "react";
|
||||
|
||||
export default function OverviewEmailSecurityCard({ reportData }: { reportData: SecuritySummaryReportResultType }) {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<LockIcon className="w-5 h-5"/>
|
||||
Email Security
|
||||
</CardTitle>
|
||||
<CardDescription>Email security overview</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-3xl font-bold">{reportData.email_security.spoofable}</div>
|
||||
<div className="flex flex-col gap-3 mt-1">
|
||||
<span><span
|
||||
className="font-bold">DMARC Policy:</span> {reportData.email_security.dmarc_policy}</span>
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground mt-1">
|
||||
Black List Detections: <span
|
||||
className="font-bold">{reportData.email_security.blacklist_detections}</span> and
|
||||
Black Lists Total List: <span
|
||||
className="font-bold">{reportData.email_security.blacklist_total_list}</span>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
import {SecuritySummaryReportResultType} from "@/types/security-summary";
|
||||
import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/Components/ui/card";
|
||||
import {Globe} from "lucide-react";
|
||||
import React from "react";
|
||||
|
||||
export default function OverviewNetworkAssetsCard({ reportData }: { reportData: SecuritySummaryReportResultType }) {
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Globe className="w-5 h-5"/>
|
||||
Network Assets
|
||||
</CardTitle>
|
||||
<CardDescription>Total assets and IP addresses</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-3xl font-bold">{reportData.n_asset}</div>
|
||||
<div className="flex justify-between text-xs text-muted-foreground mt-1">
|
||||
<span>IPv4: {reportData.unique_ipv4}</span>
|
||||
<span>IPv6: {reportData.unique_ipv6}</span>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
import {SecuritySummaryReportResultType} from "@/types/security-summary";
|
||||
import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/Components/ui/card";
|
||||
import {Globe} from "lucide-react";
|
||||
import React from "react";
|
||||
|
||||
export default function OverviewSimilarDomainsCard({ reportData }: { reportData: SecuritySummaryReportResultType }) {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Globe className="w-5 h-5"/>
|
||||
Similar Domains
|
||||
</CardTitle>
|
||||
<CardDescription>Number of similar Domains</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-3xl font-bold">{reportData.n_similar_domains}</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
import {SecuritySummaryReportResultType} from "@/types/security-summary";
|
||||
import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/Components/ui/card";
|
||||
import {ShieldAlert} from "lucide-react";
|
||||
import {Progress} from "@/Components/ui/progress";
|
||||
import React from "react";
|
||||
|
||||
export default function OverviewVulnerabilityScoreCard({ reportData }: { reportData: SecuritySummaryReportResultType }) {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<ShieldAlert className="w-5 h-5"/>
|
||||
Vulnerability Score
|
||||
</CardTitle>
|
||||
<CardDescription>Active and passive vulnerability scores</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-2">
|
||||
<div>
|
||||
<div className="text-xs text-muted-foreground">Active Score</div>
|
||||
<Progress value={reportData.vulnerability_score_active} className="mt-1"/>
|
||||
<div className="text-sm font-medium">{reportData.vulnerability_score_active}%
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-xs text-muted-foreground">Passive Score</div>
|
||||
<Progress value={reportData.vulnerability_score_passive} className="mt-1"/>
|
||||
<div className="text-sm font-medium">{reportData.vulnerability_score_passive}%
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
import {SecuritySummaryReportResultType} from "@/types/security-summary";
|
||||
import {Card, CardContent, CardHeader, CardTitle} from "@/Components/ui/card";
|
||||
import {DatabaseZap} from "lucide-react";
|
||||
import React from "react";
|
||||
|
||||
export default function ServicesCdnCard({ reportData }: { reportData: SecuritySummaryReportResultType }) {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<DatabaseZap className="w-5 h-5"/>
|
||||
CDN
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div
|
||||
className="text-3xl font-bold">{reportData.cdn.count}</div>
|
||||
<div className="text-xs text-muted-foreground mt-1">
|
||||
<div><span className="font-bold">CDN assets:</span></div>
|
||||
<div className="flex flex-col gap-2 mt-3">
|
||||
{reportData.cdn.assets.map((cdn_asset,index) => (
|
||||
<code key={index}>{cdn_asset}</code>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
import React from 'react';
|
||||
import {Bar, BarChart, ResponsiveContainer, Tooltip, XAxis, YAxis} from "recharts";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/Components/ui/card";
|
||||
import { SecuritySummaryReportResultType } from "@/types/security-summary";
|
||||
|
||||
export default function ServicesPortExposureCard({ reportData }: { reportData: SecuritySummaryReportResultType }) {
|
||||
|
||||
const portData = Object.entries(reportData.n_port).map(([port, data]) => ({
|
||||
name: `Port ${port}`,
|
||||
value: data.n
|
||||
}));
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Port Exposure Analysis</CardTitle>
|
||||
<CardDescription>Distribution of exposed ports</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="pl-2">
|
||||
<div className="h-[300px]">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<BarChart data={portData}>
|
||||
<XAxis
|
||||
dataKey="name"
|
||||
stroke="#888888"
|
||||
fontSize={12}
|
||||
tickLine={false}
|
||||
axisLine={false}
|
||||
/>
|
||||
<YAxis
|
||||
stroke="#888888"
|
||||
fontSize={12}
|
||||
tickLine={false}
|
||||
axisLine={false}
|
||||
/>
|
||||
<Bar
|
||||
dataKey="value"
|
||||
fill="currentColor"
|
||||
radius={[4, 4, 0, 0]}
|
||||
className="fill-primary"
|
||||
/>
|
||||
<Tooltip
|
||||
cursor={{
|
||||
fill: 'rgba(0, 0, 0, 0.1)',
|
||||
}}
|
||||
content={({active, payload}) => {
|
||||
if (active && payload && payload.length) {
|
||||
return (
|
||||
<div
|
||||
className="rounded-lg border bg-background p-2 shadow-sm">
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div className="flex flex-col">
|
||||
<span
|
||||
className="text-[0.70rem] uppercase text-muted-foreground">
|
||||
Port
|
||||
</span>
|
||||
<span className="font-bold">
|
||||
{payload[0].payload.name}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<span
|
||||
className="text-[0.70rem] uppercase text-muted-foreground">
|
||||
Count
|
||||
</span>
|
||||
<span className="font-bold">
|
||||
{payload[0].value}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return null
|
||||
}}
|
||||
/>
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
import {SecuritySummaryReportResultType} from "@/types/security-summary";
|
||||
import {Card, CardContent, CardHeader, CardTitle} from "@/Components/ui/card";
|
||||
import {BrickWall} from "lucide-react";
|
||||
import React from "react";
|
||||
|
||||
export default function ServicesWafCard({ reportData }: { reportData: SecuritySummaryReportResultType }) {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<BrickWall className="w-5 h-5"/>
|
||||
WAF
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div
|
||||
className="text-3xl font-bold">{reportData.waf.count}</div>
|
||||
<div className="text-xs text-muted-foreground mt-1">
|
||||
<div><span className="font-bold">WAF assets:</span></div>
|
||||
<div className="flex flex-col gap-2 mt-3">
|
||||
{reportData.waf.assets.map((waf_asset,index) => (
|
||||
<code key={index}>{waf_asset}</code>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/Components/ui/card";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/Components/ui/select";
|
||||
import {SecuritySummaryReportResultType} from "@/types/security-summary";
|
||||
import VulnerabilityPieChart from "@/Components/VulnerabilityPieChart";
|
||||
|
||||
export default function VulnerabilitiesActiveCard({reportData}: { reportData: SecuritySummaryReportResultType }) {
|
||||
const vulnerabilityData = useMemo(() => [
|
||||
{ name: 'Critical', value: reportData.n_vulns.active.critical, fill: 'hsl(var(--chart-1))' },
|
||||
{ name: 'High', value: reportData.n_vulns.active.high, fill: 'hsl(var(--chart-2))' },
|
||||
{ name: 'Medium', value: reportData.n_vulns.active.medium, fill: 'hsl(var(--chart-3))' },
|
||||
], [reportData]);
|
||||
|
||||
const [activeMetric, setActiveMetric] = useState(vulnerabilityData[0].name);
|
||||
|
||||
const activeIndex = useMemo(
|
||||
() => vulnerabilityData.findIndex((item) => item.name === activeMetric),
|
||||
[activeMetric, vulnerabilityData]
|
||||
);
|
||||
|
||||
const metrics = useMemo(() => vulnerabilityData.map((item) => item.name), [vulnerabilityData]);
|
||||
|
||||
const chartConfig: any = {
|
||||
'Critical': {
|
||||
label: "Critical",
|
||||
color: 'hsl(var(--chart-1))'
|
||||
},
|
||||
'High': {
|
||||
label: "High",
|
||||
color: 'hsl(var(--chart-2))'
|
||||
},
|
||||
'Medium': {
|
||||
label: "Medium",
|
||||
color: 'hsl(var(--chart-3))'
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-start justify-between space-y-0 pb-0">
|
||||
<div className="grid gap-1">
|
||||
<CardTitle>Active Vulnerabilities</CardTitle>
|
||||
<CardDescription>Number of Active Vulnerabilities</CardDescription>
|
||||
</div>
|
||||
<Select value={activeMetric} onValueChange={setActiveMetric}>
|
||||
<SelectTrigger
|
||||
className="ml-auto h-8 w-[180px] rounded-lg"
|
||||
aria-label="Select security metric"
|
||||
>
|
||||
<SelectValue placeholder="Select metric" />
|
||||
</SelectTrigger>
|
||||
<SelectContent align="end" className="rounded-lg">
|
||||
{metrics.map((metric) => (
|
||||
<SelectItem
|
||||
key={metric}
|
||||
value={metric}
|
||||
className="rounded-lg [&_span]:flex"
|
||||
>
|
||||
<div className="flex items-center gap-2 text-xs">
|
||||
<span
|
||||
className="h-3 w-3 rounded-sm"
|
||||
style={{
|
||||
backgroundColor: chartConfig[metric]?.color
|
||||
}}
|
||||
/>
|
||||
{chartConfig[metric].label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-1 justify-center pb-0">
|
||||
<VulnerabilityPieChart vulnerabilityData={vulnerabilityData} activeIndex={activeIndex} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/Components/ui/card";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/Components/ui/select";
|
||||
import {SecuritySummaryReportResultType} from "@/types/security-summary";
|
||||
import VulnerabilityPieChart from "@/Components/VulnerabilityPieChart";
|
||||
|
||||
export default function VulnerabilitiesPassiveCard({reportData}: { reportData: SecuritySummaryReportResultType }) {
|
||||
const vulnerabilityData = useMemo(() => [
|
||||
{ name: 'High', value: reportData.n_vulns.passive.high, fill: 'hsl(var(--chart-4))' },
|
||||
{ name: 'Medium', value: reportData.n_vulns.passive.medium, fill: 'hsl(var(--chart-5))' }
|
||||
], [reportData]);
|
||||
|
||||
const [activeMetric, setActiveMetric] = useState(vulnerabilityData[0].name);
|
||||
|
||||
const activeIndex = useMemo(
|
||||
() => vulnerabilityData.findIndex((item) => item.name === activeMetric),
|
||||
[activeMetric, vulnerabilityData]
|
||||
);
|
||||
|
||||
const metrics = useMemo(() => vulnerabilityData.map((item) => item.name), [vulnerabilityData]);
|
||||
|
||||
const chartConfig: any = {
|
||||
'High': {
|
||||
label: "High",
|
||||
color: 'hsl(var(--chart-4))'
|
||||
},
|
||||
'Medium': {
|
||||
label: "Medium",
|
||||
color: 'hsl(var(--chart-5))'
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-start justify-between space-y-0 pb-0">
|
||||
<div className="grid gap-1">
|
||||
<CardTitle>Passive Vulnerabilities</CardTitle>
|
||||
<CardDescription>Number of Passive Vulnerabilities</CardDescription>
|
||||
</div>
|
||||
<Select value={activeMetric} onValueChange={setActiveMetric}>
|
||||
<SelectTrigger
|
||||
className="ml-auto h-8 w-[180px] rounded-lg"
|
||||
aria-label="Select security metric"
|
||||
>
|
||||
<SelectValue placeholder="Select metric" />
|
||||
</SelectTrigger>
|
||||
<SelectContent align="end" className="rounded-lg">
|
||||
{metrics.map((metric) => (
|
||||
<SelectItem
|
||||
key={metric}
|
||||
value={metric}
|
||||
className="rounded-lg [&_span]:flex"
|
||||
>
|
||||
<div className="flex items-center gap-2 text-xs">
|
||||
<span
|
||||
className="h-3 w-3 rounded-sm"
|
||||
style={{
|
||||
backgroundColor: chartConfig[metric]?.color
|
||||
}}
|
||||
/>
|
||||
{chartConfig[metric].label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-1 justify-center pb-0">
|
||||
<VulnerabilityPieChart vulnerabilityData={vulnerabilityData} activeIndex={activeIndex} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user