AgentSkillsCN

frontend-analytics

为brickston-ai打造分析仪表盘与关键绩效指标可视化

SKILL.md
--- frontmatter
name: frontend-analytics
description: Create analytics dashboards and KPI visualizations for brickston-ai

Frontend Analytics Skill

Overview

This skill guides you through creating analytics components and KPI dashboards in the Next.js frontend.

Directory Structure

code
apps/web/app/(dashboard)/
├── properties/          # Property-level analytics
├── providers/           # Vendor analytics
├── insights/            # General analytics dashboards
└── management-model/    # OpCo/RepairCo models
    └── revenue/         # Revenue forecasting

apps/web/components/
├── ui/                  # Shared UI components
├── charts/              # Chart components
└── analytics/           # Analytics-specific components

Creating a New Analytics Component

Step 1: Create the Component

Location: apps/web/components/analytics/<ComponentName>.tsx

tsx
"use client";

import { useState, useEffect } from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";

interface MetricData {
  label: string;
  value: number;
  change?: number;
}

interface AnalyticsProps {
  propertyId?: string;
  dateRange?: { start: Date; end: Date };
}

export function NewAnalyticsComponent({ propertyId, dateRange }: AnalyticsProps) {
  const [data, setData] = useState<MetricData[]>([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetchData();
  }, [propertyId, dateRange]);

  const fetchData = async () => {
    try {
      const params = new URLSearchParams();
      if (propertyId) params.set("property_id", propertyId);
      
      const res = await fetch(`/api/v1/analytics/endpoint?${params}`);
      const json = await res.json();
      setData(json.data);
    } catch (error) {
      console.error("Failed to fetch analytics:", error);
    } finally {
      setLoading(false);
    }
  };

  if (loading) return <div>Loading...</div>;

  return (
    <Card>
      <CardHeader>
        <CardTitle>Analytics Title</CardTitle>
      </CardHeader>
      <CardContent>
        <div className="grid grid-cols-3 gap-4">
          {data.map((metric) => (
            <div key={metric.label} className="text-center">
              <p className="text-2xl font-bold">{metric.value}</p>
              <p className="text-sm text-muted-foreground">{metric.label}</p>
              {metric.change && (
                <p className={metric.change > 0 ? "text-green-500" : "text-red-500"}>
                  {metric.change > 0 ? "+" : ""}{metric.change}%
                </p>
              )}
            </div>
          ))}
        </div>
      </CardContent>
    </Card>
  );
}

Step 2: Add Chart Visualization

Using Recharts (already installed):

tsx
import { LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer } from "recharts";

<ResponsiveContainer width="100%" height={300}>
  <LineChart data={chartData}>
    <XAxis dataKey="date" />
    <YAxis />
    <Tooltip />
    <Line type="monotone" dataKey="value" stroke="#8884d8" />
  </LineChart>
</ResponsiveContainer>

Step 3: Integrate into Page

Add to the relevant dashboard page:

tsx
import { NewAnalyticsComponent } from "@/components/analytics/NewAnalyticsComponent";

export default function InsightsPage() {
  return (
    <div className="space-y-6">
      <h1>Insights Dashboard</h1>
      <NewAnalyticsComponent propertyId={selectedProperty} />
    </div>
  );
}

Common Patterns

KPI Card Grid

tsx
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
  <KPICard title="Total Revenue" value="$1.2M" change={5.2} />
  <KPICard title="Occupancy" value="94%" change={-1.5} />
  <KPICard title="Avg Rent" value="$2,450" change={3.1} />
  <KPICard title="NOI" value="$850K" change={4.8} />
</div>

Tab-based Analytics

tsx
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";

<Tabs defaultValue="revenue">
  <TabsList>
    <TabsTrigger value="revenue">Revenue</TabsTrigger>
    <TabsTrigger value="expenses">Expenses</TabsTrigger>
    <TabsTrigger value="forecast">Forecast</TabsTrigger>
  </TabsList>
  <TabsContent value="revenue">
    <RevenueAnalytics />
  </TabsContent>
  {/* ... other tabs */}
</Tabs>

Date Range Filter

tsx
import { DatePickerWithRange } from "@/components/ui/date-range-picker";

const [dateRange, setDateRange] = useState({
  from: new Date(new Date().setMonth(new Date().getMonth() - 12)),
  to: new Date()
});

<DatePickerWithRange value={dateRange} onChange={setDateRange} />

Styling Guidelines

  • Use shadcn/ui components from @/components/ui/
  • Follow existing color scheme (dark mode aware)
  • Consistent spacing using space-y-* and gap-*
  • Responsive grids with breakpoint prefixes

Checklist

  • Component created in components/analytics/
  • Backend API endpoint exists for data
  • Loading and error states handled
  • Responsive layout for mobile/desktop
  • Integrated into relevant page
  • Follows existing styling patterns