Skip to content

Commit 7f82658

Browse files
Merge pull request #37 from atf-inc/fix/fintuining
2 parents f4dc92e + 7fb3ebc commit 7f82658

File tree

5 files changed

+4691
-168
lines changed

5 files changed

+4691
-168
lines changed
Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
"use client"
2+
3+
import * as React from "react"
4+
import { Area, AreaChart, CartesianGrid, XAxis } from "recharts"
5+
6+
import {
7+
Card,
8+
CardContent,
9+
CardDescription,
10+
CardHeader,
11+
CardTitle,
12+
} from "@/components/ui/card"
13+
import {
14+
ChartContainer,
15+
ChartLegend,
16+
ChartLegendContent,
17+
ChartTooltip,
18+
ChartTooltipContent,
19+
type ChartConfig,
20+
} from "@/components/ui/chart"
21+
import {
22+
Select,
23+
SelectContent,
24+
SelectItem,
25+
SelectTrigger,
26+
SelectValue,
27+
} from "@/components/ui/select"
28+
29+
export const description = "Email activity chart showing threats detected and emails scanned"
30+
31+
const chartData = [
32+
{ date: "2024-10-01", threatsDetected: 222, emailsScanned: 150 },
33+
{ date: "2024-10-02", threatsDetected: 97, emailsScanned: 180 },
34+
{ date: "2024-10-03", threatsDetected: 167, emailsScanned: 120 },
35+
{ date: "2024-10-04", threatsDetected: 242, emailsScanned: 260 },
36+
{ date: "2024-10-05", threatsDetected: 373, emailsScanned: 290 },
37+
{ date: "2024-10-06", threatsDetected: 301, emailsScanned: 340 },
38+
{ date: "2024-10-07", threatsDetected: 245, emailsScanned: 180 },
39+
{ date: "2024-10-08", threatsDetected: 409, emailsScanned: 320 },
40+
{ date: "2024-10-09", threatsDetected: 59, emailsScanned: 110 },
41+
{ date: "2024-10-10", threatsDetected: 261, emailsScanned: 190 },
42+
{ date: "2024-10-11", threatsDetected: 327, emailsScanned: 350 },
43+
{ date: "2024-10-12", threatsDetected: 292, emailsScanned: 210 },
44+
{ date: "2024-10-13", threatsDetected: 342, emailsScanned: 380 },
45+
{ date: "2024-10-14", threatsDetected: 137, emailsScanned: 220 },
46+
{ date: "2024-10-15", threatsDetected: 120, emailsScanned: 170 },
47+
{ date: "2024-10-16", threatsDetected: 138, emailsScanned: 190 },
48+
{ date: "2024-10-17", threatsDetected: 446, emailsScanned: 360 },
49+
{ date: "2024-10-18", threatsDetected: 364, emailsScanned: 410 },
50+
{ date: "2024-10-19", threatsDetected: 243, emailsScanned: 180 },
51+
{ date: "2024-10-20", threatsDetected: 89, emailsScanned: 150 },
52+
{ date: "2024-10-21", threatsDetected: 137, emailsScanned: 200 },
53+
{ date: "2024-10-22", threatsDetected: 224, emailsScanned: 170 },
54+
{ date: "2024-10-23", threatsDetected: 138, emailsScanned: 230 },
55+
{ date: "2024-10-24", threatsDetected: 387, emailsScanned: 290 },
56+
{ date: "2024-10-25", threatsDetected: 215, emailsScanned: 250 },
57+
{ date: "2024-10-26", threatsDetected: 75, emailsScanned: 130 },
58+
{ date: "2024-10-27", threatsDetected: 383, emailsScanned: 420 },
59+
{ date: "2024-10-28", threatsDetected: 122, emailsScanned: 180 },
60+
{ date: "2024-10-29", threatsDetected: 315, emailsScanned: 240 },
61+
{ date: "2024-10-30", threatsDetected: 454, emailsScanned: 380 },
62+
{ date: "2024-10-31", threatsDetected: 165, emailsScanned: 220 },
63+
{ date: "2024-11-01", threatsDetected: 293, emailsScanned: 310 },
64+
{ date: "2024-11-02", threatsDetected: 247, emailsScanned: 190 },
65+
{ date: "2024-11-03", threatsDetected: 385, emailsScanned: 420 },
66+
{ date: "2024-11-04", threatsDetected: 481, emailsScanned: 390 },
67+
{ date: "2024-11-05", threatsDetected: 498, emailsScanned: 520 },
68+
{ date: "2024-11-06", threatsDetected: 388, emailsScanned: 300 },
69+
{ date: "2024-11-07", threatsDetected: 149, emailsScanned: 210 },
70+
{ date: "2024-11-08", threatsDetected: 227, emailsScanned: 180 },
71+
{ date: "2024-11-09", threatsDetected: 293, emailsScanned: 330 },
72+
{ date: "2024-11-10", threatsDetected: 335, emailsScanned: 270 },
73+
{ date: "2024-11-11", threatsDetected: 197, emailsScanned: 240 },
74+
{ date: "2024-11-12", threatsDetected: 197, emailsScanned: 160 },
75+
{ date: "2024-11-13", threatsDetected: 448, emailsScanned: 490 },
76+
{ date: "2024-11-14", threatsDetected: 473, emailsScanned: 380 },
77+
{ date: "2024-11-15", threatsDetected: 338, emailsScanned: 400 },
78+
{ date: "2024-11-16", threatsDetected: 499, emailsScanned: 420 },
79+
{ date: "2024-11-17", threatsDetected: 315, emailsScanned: 350 },
80+
{ date: "2024-11-18", threatsDetected: 235, emailsScanned: 180 },
81+
{ date: "2024-11-19", threatsDetected: 177, emailsScanned: 230 },
82+
{ date: "2024-11-20", threatsDetected: 82, emailsScanned: 140 },
83+
{ date: "2024-11-21", threatsDetected: 81, emailsScanned: 120 },
84+
{ date: "2024-11-22", threatsDetected: 252, emailsScanned: 290 },
85+
{ date: "2024-11-23", threatsDetected: 294, emailsScanned: 220 },
86+
{ date: "2024-11-24", threatsDetected: 201, emailsScanned: 250 },
87+
{ date: "2024-11-25", threatsDetected: 213, emailsScanned: 170 },
88+
{ date: "2024-11-26", threatsDetected: 420, emailsScanned: 460 },
89+
{ date: "2024-11-27", threatsDetected: 233, emailsScanned: 190 },
90+
{ date: "2024-11-28", threatsDetected: 78, emailsScanned: 130 },
91+
{ date: "2024-11-29", threatsDetected: 340, emailsScanned: 280 },
92+
{ date: "2024-11-30", threatsDetected: 178, emailsScanned: 230 },
93+
{ date: "2024-12-01", threatsDetected: 178, emailsScanned: 200 },
94+
{ date: "2024-12-02", threatsDetected: 470, emailsScanned: 410 },
95+
{ date: "2024-12-03", threatsDetected: 103, emailsScanned: 160 },
96+
{ date: "2024-12-04", threatsDetected: 439, emailsScanned: 380 },
97+
{ date: "2024-12-05", threatsDetected: 88, emailsScanned: 140 },
98+
{ date: "2024-12-06", threatsDetected: 294, emailsScanned: 250 },
99+
{ date: "2024-12-07", threatsDetected: 323, emailsScanned: 370 },
100+
{ date: "2024-12-08", threatsDetected: 385, emailsScanned: 320 },
101+
{ date: "2024-12-09", threatsDetected: 438, emailsScanned: 480 },
102+
{ date: "2024-12-10", threatsDetected: 155, emailsScanned: 200 },
103+
{ date: "2024-12-11", threatsDetected: 92, emailsScanned: 150 },
104+
{ date: "2024-12-12", threatsDetected: 492, emailsScanned: 420 },
105+
{ date: "2024-12-13", threatsDetected: 81, emailsScanned: 130 },
106+
{ date: "2024-12-14", threatsDetected: 426, emailsScanned: 380 },
107+
{ date: "2024-12-15", threatsDetected: 307, emailsScanned: 350 },
108+
{ date: "2024-12-16", threatsDetected: 371, emailsScanned: 310 },
109+
{ date: "2024-12-17", threatsDetected: 475, emailsScanned: 520 },
110+
{ date: "2024-12-18", threatsDetected: 107, emailsScanned: 170 },
111+
{ date: "2024-12-19", threatsDetected: 341, emailsScanned: 290 },
112+
{ date: "2024-12-20", threatsDetected: 408, emailsScanned: 450 },
113+
{ date: "2024-12-21", threatsDetected: 169, emailsScanned: 210 },
114+
{ date: "2024-12-22", threatsDetected: 317, emailsScanned: 270 },
115+
{ date: "2024-12-23", threatsDetected: 480, emailsScanned: 530 },
116+
{ date: "2024-12-24", threatsDetected: 132, emailsScanned: 180 },
117+
]
118+
119+
const chartConfig = {
120+
emailActivity: {
121+
label: "Email Activity",
122+
},
123+
threatsDetected: {
124+
label: "Threats Detected",
125+
color: "hsl(0 84% 60%)",
126+
},
127+
emailsScanned: {
128+
label: "Emails Scanned",
129+
color: "hsl(217 91% 60%)",
130+
},
131+
} satisfies ChartConfig
132+
133+
export function ChartAreaInteractive() {
134+
const [timeRange, setTimeRange] = React.useState("90d")
135+
136+
const filteredData = chartData.filter((item) => {
137+
const date = new Date(item.date)
138+
const referenceDate = new Date("2024-12-24")
139+
let daysToSubtract = 90
140+
if (timeRange === "30d") {
141+
daysToSubtract = 30
142+
} else if (timeRange === "7d") {
143+
daysToSubtract = 7
144+
}
145+
const startDate = new Date(referenceDate)
146+
startDate.setDate(startDate.getDate() - daysToSubtract)
147+
return date >= startDate
148+
})
149+
150+
return (
151+
<Card className="pt-0 border-border">
152+
<CardHeader className="flex items-center gap-2 space-y-0 border-b border-border py-5 sm:flex-row">
153+
<div className="grid flex-1 gap-1">
154+
<CardTitle className="text-foreground">Email Activity</CardTitle>
155+
<CardDescription>
156+
Showing email traffic for the last 3 months
157+
</CardDescription>
158+
</div>
159+
<Select value={timeRange} onValueChange={setTimeRange}>
160+
<SelectTrigger
161+
className="hidden w-[160px] rounded-lg sm:ml-auto sm:flex"
162+
aria-label="Select a value"
163+
>
164+
<SelectValue placeholder="Last 3 months" />
165+
</SelectTrigger>
166+
<SelectContent className="rounded-xl">
167+
<SelectItem value="90d" className="rounded-lg">
168+
Last 3 months
169+
</SelectItem>
170+
<SelectItem value="30d" className="rounded-lg">
171+
Last 30 days
172+
</SelectItem>
173+
<SelectItem value="7d" className="rounded-lg">
174+
Last 7 days
175+
</SelectItem>
176+
</SelectContent>
177+
</Select>
178+
</CardHeader>
179+
<CardContent className="px-2 pt-4 sm:px-6 sm:pt-6">
180+
<ChartContainer
181+
config={chartConfig}
182+
className="aspect-auto h-[250px] w-full"
183+
>
184+
<AreaChart data={filteredData}>
185+
<defs>
186+
<linearGradient id="fillThreats" x1="0" y1="0" x2="0" y2="1">
187+
<stop
188+
offset="5%"
189+
stopColor="var(--color-threatsDetected)"
190+
stopOpacity={0.8}
191+
/>
192+
<stop
193+
offset="95%"
194+
stopColor="var(--color-threatsDetected)"
195+
stopOpacity={0.1}
196+
/>
197+
</linearGradient>
198+
<linearGradient id="fillEmails" x1="0" y1="0" x2="0" y2="1">
199+
<stop
200+
offset="5%"
201+
stopColor="var(--color-emailsScanned)"
202+
stopOpacity={0.8}
203+
/>
204+
<stop
205+
offset="95%"
206+
stopColor="var(--color-emailsScanned)"
207+
stopOpacity={0.1}
208+
/>
209+
</linearGradient>
210+
</defs>
211+
<CartesianGrid vertical={false} strokeOpacity={0.1} />
212+
<XAxis
213+
dataKey="date"
214+
tickLine={false}
215+
axisLine={false}
216+
tickMargin={8}
217+
minTickGap={32}
218+
tickFormatter={(value) => {
219+
const date = new Date(value)
220+
return date.toLocaleDateString("en-US", {
221+
month: "short",
222+
day: "numeric",
223+
})
224+
}}
225+
/>
226+
<ChartTooltip
227+
cursor={false}
228+
content={
229+
<ChartTooltipContent
230+
labelFormatter={(value) => {
231+
return new Date(value).toLocaleDateString("en-US", {
232+
month: "short",
233+
day: "numeric",
234+
})
235+
}}
236+
indicator="dot"
237+
/>
238+
}
239+
/>
240+
<Area
241+
dataKey="threatsDetected"
242+
type="natural"
243+
fill="url(#fillThreats)"
244+
stroke="var(--color-threatsDetected)"
245+
stackId="a"
246+
/>
247+
<Area
248+
dataKey="emailsScanned"
249+
type="natural"
250+
fill="url(#fillEmails)"
251+
stroke="var(--color-emailsScanned)"
252+
stackId="a"
253+
/>
254+
<ChartLegend content={<ChartLegendContent />} />
255+
</AreaChart>
256+
</ChartContainer>
257+
</CardContent>
258+
</Card>
259+
)
260+
}

apps/web/components/dashboard-layout.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import type React from "react"
44
import { useState, useEffect, useRef } from "react"
55

6-
import { Shield, Mail, Settings, LayoutDashboard, Bell, ChevronDown } from "lucide-react"
6+
import { Shield, Mail, Settings, LayoutDashboard, ChevronDown } from "lucide-react"
77
import { Button } from "@/components/ui/button"
88
import {
99
DropdownMenu,
@@ -106,11 +106,6 @@ export function DashboardLayout({ children }: { children: React.ReactNode }) {
106106
</div>
107107

108108
<div className="flex items-center gap-4">
109-
<Button variant="ghost" size="icon" className="relative">
110-
<Bell className="h-5 w-5" />
111-
<span className="absolute top-1 right-1 w-2 h-2 bg-destructive rounded-full" />
112-
</Button>
113-
114109
<DropdownMenu>
115110
<DropdownMenuTrigger asChild>
116111
<Button variant="ghost" className="gap-2">

apps/web/components/overview-page.tsx

Lines changed: 3 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,9 @@ import { useSession } from "next-auth/react"
55
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
66
import { Shield, AlertTriangle, Mail, TrendingUp, TrendingDown, CheckCircle } from "lucide-react"
77
import { Badge } from "@/components/ui/badge"
8-
import { Line, LineChart, XAxis, YAxis, CartesianGrid, ResponsiveContainer, Tooltip } from "recharts"
9-
import { ChartContainer } from "@/components/ui/chart"
8+
import { ChartAreaInteractive } from "@/components/chart-area-interactive"
109
import { fetchEmails, type Email } from "@/lib/api"
1110

12-
// Sample chart data - in production this would come from API
13-
const threatData = [
14-
{ time: "00:00", threats: 2, blocked: 2, safe: 14 },
15-
{ time: "04:00", threats: 1, blocked: 1, safe: 16 },
16-
{ time: "08:00", threats: 3, blocked: 3, safe: 42 },
17-
{ time: "12:00", threats: 5, blocked: 5, safe: 58 },
18-
{ time: "16:00", threats: 3, blocked: 3, safe: 49 },
19-
{ time: "20:00", threats: 2, blocked: 2, safe: 27 },
20-
]
21-
2211
export function OverviewPage() {
2312
const { data: session } = useSession()
2413
const [emails, setEmails] = useState<Email[]>([])
@@ -128,51 +117,8 @@ export function OverviewPage() {
128117
</Card>
129118
</div>
130119

131-
{/* Threat Activity Chart */}
132-
<Card className="border-border">
133-
<CardHeader>
134-
<CardTitle className="text-foreground">Email Activity (Last 24 Hours)</CardTitle>
135-
<CardDescription>Real-time monitoring of your email security</CardDescription>
136-
</CardHeader>
137-
<CardContent>
138-
<ChartContainer
139-
id="email-activity-chart"
140-
config={{
141-
threats: {
142-
label: "Threats Detected",
143-
color: "oklch(0.58 0.24 27)",
144-
},
145-
blocked: {
146-
label: "Threats Blocked",
147-
color: "oklch(0.58 0.24 264)",
148-
},
149-
safe: {
150-
label: "Safe Emails",
151-
color: "oklch(0.65 0.18 162)",
152-
},
153-
}}
154-
className="h-[300px]"
155-
>
156-
<ResponsiveContainer width="100%" height="100%">
157-
<LineChart data={threatData}>
158-
<CartesianGrid strokeDasharray="3 3" stroke="oklch(0.22 0 0)" />
159-
<XAxis dataKey="time" stroke="oklch(0.65 0 0)" />
160-
<YAxis stroke="oklch(0.65 0 0)" />
161-
<Tooltip
162-
contentStyle={{
163-
backgroundColor: "oklch(0.16 0 0)",
164-
border: "1px solid oklch(0.22 0 0)",
165-
borderRadius: "8px",
166-
}}
167-
/>
168-
<Line type="monotone" dataKey="threats" stroke="oklch(0.58 0.24 27)" strokeWidth={2} />
169-
<Line type="monotone" dataKey="blocked" stroke="oklch(0.58 0.24 264)" strokeWidth={2} />
170-
<Line type="monotone" dataKey="safe" stroke="oklch(0.65 0.18 162)" strokeWidth={2} />
171-
</LineChart>
172-
</ResponsiveContainer>
173-
</ChartContainer>
174-
</CardContent>
175-
</Card>
120+
{/* Email Activity Chart */}
121+
<ChartAreaInteractive />
176122

177123
{/* Recent Email Activity */}
178124
<Card className="border-border">

0 commit comments

Comments
 (0)