Skip to Content
ExamplesAnalytics Report Example (iCignal)

Analytics Report Example (iCignal)

상세 분석 리포트 구현 예제


개요

iCignal의 AnalyticsCard와 차트를 결합한 종합 리포트 페이지 예제입니다.

주요 특징

  • ✅ 기간별 리포트 생성
  • ✅ 다양한 차트 타입
  • ✅ PDF 내보내기
  • ✅ 필터링 및 정렬
  • ✅ 데이터 비교

전체 코드

"use client"; import { useState } from "react"; import { AnalyticsCard } from "@vortex/ui-icignal"; import { Container } from "@/components/ui/container"; import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"; import { Button } from "@vortex/ui-icignal"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { DatePickerWithRange } from "@/components/ui/date-range-picker"; export default function AnalyticsReport() { const [period, setPeriod] = useState("30d"); const [dateRange, setDateRange] = useState(null); const exportToPDF = () => { // PDF 내보내기 로직 console.log("Exporting to PDF..."); }; return ( <Container size="xl" className="py-8 space-y-8"> {/* Header */} <div className="flex items-center justify-between"> <div> <h1 className="text-3xl font-bold">Analytics Report</h1> <p className="text-muted-foreground">기간별 상세 분석 리포트</p> </div> <div className="flex gap-2"> <Button variant="outline" onClick={exportToPDF}> Export PDF </Button> <Button>Share</Button> </div> </div> {/* Filters */} <Card> <CardContent className="py-4"> <div className="flex gap-4 flex-wrap"> <Select value={period} onValueChange={setPeriod}> <SelectTrigger className="w-[180px]"> <SelectValue placeholder="기간 선택" /> </SelectTrigger> <SelectContent> <SelectItem value="7d">최근 7일</SelectItem> <SelectItem value="30d">최근 30일</SelectItem> <SelectItem value="90d">최근 90일</SelectItem> <SelectItem value="custom">사용자 지정</SelectItem> </SelectContent> </Select> {period === "custom" && ( <DatePickerWithRange value={dateRange} onChange={setDateRange} /> )} <Button variant="outline">Apply Filters</Button> </div> </CardContent> </Card> {/* Summary Cards */} <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6"> <AnalyticsCard title="Page Views" value="45,678" trend="+15%" trendUp={true} description="vs. previous period" /> <AnalyticsCard title="Unique Visitors" value="12,345" trend="+8%" trendUp={true} description="vs. previous period" /> <AnalyticsCard title="Avg. Session" value="4m 32s" trend="-2%" trendUp={false} description="vs. previous period" /> <AnalyticsCard title="Bounce Rate" value="42.3%" trend="-5%" trendUp={true} description="vs. previous period" /> </div> {/* Charts */} <div className="grid grid-cols-1 lg:grid-cols-2 gap-6"> <Card> <CardHeader> <CardTitle>Traffic Over Time</CardTitle> </CardHeader> <CardContent> <div className="h-[300px] flex items-center justify-center bg-muted/50 rounded"> <p className="text-muted-foreground"> Line Chart: 시간별 트래픽 추이 </p> </div> </CardContent> </Card> <Card> <CardHeader> <CardTitle>Traffic Sources</CardTitle> </CardHeader> <CardContent> <div className="h-[300px] flex items-center justify-center bg-muted/50 rounded"> <p className="text-muted-foreground"> Pie Chart: 트래픽 소스 분포 </p> </div> </CardContent> </Card> <Card> <CardHeader> <CardTitle>Top Pages</CardTitle> </CardHeader> <CardContent> <div className="space-y-4"> <div className="flex items-center justify-between"> <div className="flex-1"> <p className="font-medium">/products</p> <div className="w-full bg-muted rounded-full h-2 mt-1"> <div className="bg-primary h-2 rounded-full" style={{ width: "85%" }} ></div> </div> </div> <span className="ml-4 text-sm font-medium">12,345</span> </div> <div className="flex items-center justify-between"> <div className="flex-1"> <p className="font-medium">/about</p> <div className="w-full bg-muted rounded-full h-2 mt-1"> <div className="bg-primary h-2 rounded-full" style={{ width: "65%" }} ></div> </div> </div> <span className="ml-4 text-sm font-medium">9,876</span> </div> <div className="flex items-center justify-between"> <div className="flex-1"> <p className="font-medium">/contact</p> <div className="w-full bg-muted rounded-full h-2 mt-1"> <div className="bg-primary h-2 rounded-full" style={{ width: "45%" }} ></div> </div> </div> <span className="ml-4 text-sm font-medium">6,543</span> </div> </div> </CardContent> </Card> <Card> <CardHeader> <CardTitle>User Demographics</CardTitle> </CardHeader> <CardContent> <div className="space-y-4"> <div> <div className="flex items-center justify-between mb-2"> <span className="text-sm">Desktop</span> <span className="text-sm font-medium">58%</span> </div> <div className="w-full bg-muted rounded-full h-2"> <div className="bg-blue-500 h-2 rounded-full" style={{ width: "58%" }} ></div> </div> </div> <div> <div className="flex items-center justify-between mb-2"> <span className="text-sm">Mobile</span> <span className="text-sm font-medium">35%</span> </div> <div className="w-full bg-muted rounded-full h-2"> <div className="bg-green-500 h-2 rounded-full" style={{ width: "35%" }} ></div> </div> </div> <div> <div className="flex items-center justify-between mb-2"> <span className="text-sm">Tablet</span> <span className="text-sm font-medium">7%</span> </div> <div className="w-full bg-muted rounded-full h-2"> <div className="bg-orange-500 h-2 rounded-full" style={{ width: "7%" }} ></div> </div> </div> </div> </CardContent> </Card> </div> {/* Detailed Table */} <Card> <CardHeader> <CardTitle>Detailed Metrics</CardTitle> </CardHeader> <CardContent> <div className="overflow-x-auto"> <table className="w-full"> <thead> <tr className="border-b"> <th className="text-left py-3 px-4">Date</th> <th className="text-right py-3 px-4">Views</th> <th className="text-right py-3 px-4">Visitors</th> <th className="text-right py-3 px-4">Bounce Rate</th> <th className="text-right py-3 px-4">Avg. Duration</th> </tr> </thead> <tbody> <tr className="border-b"> <td className="py-3 px-4">2025-01-15</td> <td className="text-right py-3 px-4">1,234</td> <td className="text-right py-3 px-4">987</td> <td className="text-right py-3 px-4">42.3%</td> <td className="text-right py-3 px-4">4:32</td> </tr> <tr className="border-b"> <td className="py-3 px-4">2025-01-14</td> <td className="text-right py-3 px-4">1,156</td> <td className="text-right py-3 px-4">923</td> <td className="text-right py-3 px-4">43.1%</td> <td className="text-right py-3 px-4">4:18</td> </tr> <tr className="border-b"> <td className="py-3 px-4">2025-01-13</td> <td className="text-right py-3 px-4">1,098</td> <td className="text-right py-3 px-4">876</td> <td className="text-right py-3 px-4">44.5%</td> <td className="text-right py-3 px-4">4:05</td> </tr> </tbody> </table> </div> </CardContent> </Card> </Container> ); }

주요 기능

기간 선택

<Select value={period} onValueChange={setPeriod}> <SelectTrigger className="w-[180px]"> <SelectValue placeholder="기간 선택" /> </SelectTrigger> <SelectContent> <SelectItem value="7d">최근 7일</SelectItem> <SelectItem value="30d">최근 30일</SelectItem> <SelectItem value="90d">최근 90일</SelectItem> <SelectItem value="custom">사용자 지정</SelectItem> </SelectContent> </Select>

PDF 내보내기

import jsPDF from "jspdf"; import html2canvas from "html2canvas"; const exportToPDF = async () => { const element = document.getElementById("report-content"); const canvas = await html2canvas(element); const imgData = canvas.toDataURL("image/png"); const pdf = new jsPDF(); pdf.addImage(imgData, "PNG", 10, 10, 190, 0); pdf.save("analytics-report.pdf"); };

차트 통합

Recharts 예제

import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend } from "recharts" const data = [ { date: "2025-01-01", views: 1200, visitors: 980 }, { date: "2025-01-02", views: 1350, visitors: 1050 }, // ... ] <LineChart width={600} height={300} data={data}> <CartesianGrid strokeDasharray="3 3" /> <XAxis dataKey="date" /> <YAxis /> <Tooltip /> <Legend /> <Line type="monotone" dataKey="views" stroke="#8884d8" /> <Line type="monotone" dataKey="visitors" stroke="#82ca9d" /> </LineChart>

다음 단계

Last updated on