mv folder

This commit is contained in:
2025-03-26 16:39:04 +08:00
parent 63a578ef38
commit e916eab92c
13 changed files with 150 additions and 88 deletions

View File

@@ -1,7 +1,8 @@
"use client"; "use client";
import { useState, useEffect, useRef } from 'react'; import { useState, useEffect, useRef } from 'react';
import { DeviceAnalytics } from '../../api/types'; import { fetchData } from '@/app/api/utils';
import { DeviceAnalytics } from '@/app/api/types';
import { Chart, PieController, ArcElement, Tooltip, Legend, CategoryScale, LinearScale } from 'chart.js'; import { Chart, PieController, ArcElement, Tooltip, Legend, CategoryScale, LinearScale } from 'chart.js';
// 注册Chart.js组件 // 注册Chart.js组件

View File

@@ -2,11 +2,11 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { addDays, format } from 'date-fns'; import { addDays, format } from 'date-fns';
import { DateRangePicker } from '../components/ui/DateRangePicker'; import { DateRangePicker } from '@/app/components/ui/DateRangePicker';
import TimeSeriesChart from '../components/charts/TimeSeriesChart'; import TimeSeriesChart from '@/app/components/charts/TimeSeriesChart';
import GeoAnalytics from '../components/analytics/GeoAnalytics'; import GeoAnalytics from '@/app/components/analytics/GeoAnalytics';
import DeviceAnalytics from '../components/analytics/DeviceAnalytics'; import DeviceAnalytics from '@/app/components/analytics/DeviceAnalytics';
import { EventsSummary, TimeSeriesData, GeoData, DeviceAnalytics as DeviceAnalyticsType } from '../api/types'; import { EventsSummary, TimeSeriesData, GeoData, DeviceAnalytics as DeviceAnalyticsType } from '@/app/api/types';
export default function DashboardPage() { export default function DashboardPage() {
const [dateRange, setDateRange] = useState({ const [dateRange, setDateRange] = useState({

View File

@@ -1,9 +1,9 @@
"use client"; "use client";
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { format } from 'date-fns'; import { addDays, format } from 'date-fns';
import { DateRangePicker } from '../components/ui/DateRangePicker'; import { DateRangePicker } from '@/app/components/ui/DateRangePicker';
import { Event } from '../api/types'; import { Event } from '@/app/api/types';
export default function EventsPage() { export default function EventsPage() {
const [dateRange, setDateRange] = useState({ const [dateRange, setDateRange] = useState({

66
app/(app)/layout.tsx Normal file
View File

@@ -0,0 +1,66 @@
import '../globals.css';
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import Link from 'next/link';
const inter = Inter({ subsets: ['latin'] });
export const metadata: Metadata = {
title: 'ShortURL Analytics',
description: 'Analytics dashboard for ShortURL service',
};
export default function AppLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className={inter.className}>
<div className="min-h-screen bg-gray-50 dark:bg-gray-900">
<nav className="bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700">
<div className="container mx-auto px-4">
<div className="flex items-center justify-between h-16">
<div className="flex items-center">
<Link href="/" className="text-xl font-bold text-gray-900 dark:text-gray-100">
ShortURL Analytics
</Link>
<div className="hidden md:block ml-10">
<div className="flex items-baseline space-x-4">
<Link
href="/dashboard"
className="text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 px-3 py-2 rounded-md text-sm font-medium"
>
Dashboard
</Link>
<Link
href="/events"
className="text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 px-3 py-2 rounded-md text-sm font-medium"
>
Events
</Link>
<Link
href="/analytics/geo"
className="text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 px-3 py-2 rounded-md text-sm font-medium"
>
Geographic
</Link>
<Link
href="/analytics/devices"
className="text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 px-3 py-2 rounded-md text-sm font-medium"
>
Devices
</Link>
</div>
</div>
</div>
</div>
</div>
</nav>
<main className="py-10">
{children}
</main>
</div>
</div>
);
}

59
app/(app)/page.tsx Normal file
View File

@@ -0,0 +1,59 @@
import Link from 'next/link';
export default function Home() {
return (
<div className="container mx-auto px-4">
<div className="max-w-2xl mx-auto py-16">
<h1 className="text-4xl font-bold text-gray-900 dark:text-gray-100 mb-8">
Welcome to ShortURL Analytics
</h1>
<div className="grid gap-6">
<Link
href="/dashboard"
className="block p-6 bg-white dark:bg-gray-800 rounded-lg shadow hover:shadow-md transition-shadow"
>
<h2 className="text-xl font-semibold text-gray-900 dark:text-gray-100 mb-2">
Dashboard
</h2>
<p className="text-gray-600 dark:text-gray-400">
View your overall analytics and key metrics
</p>
</Link>
<Link
href="/events"
className="block p-6 bg-white dark:bg-gray-800 rounded-lg shadow hover:shadow-md transition-shadow"
>
<h2 className="text-xl font-semibold text-gray-900 dark:text-gray-100 mb-2">
Events
</h2>
<p className="text-gray-600 dark:text-gray-400">
Track and analyze event data
</p>
</Link>
<Link
href="/analytics/geo"
className="block p-6 bg-white dark:bg-gray-800 rounded-lg shadow hover:shadow-md transition-shadow"
>
<h2 className="text-xl font-semibold text-gray-900 dark:text-gray-100 mb-2">
Geographic Analysis
</h2>
<p className="text-gray-600 dark:text-gray-400">
Explore visitor locations and geographic patterns
</p>
</Link>
<Link
href="/analytics/devices"
className="block p-6 bg-white dark:bg-gray-800 rounded-lg shadow hover:shadow-md transition-shadow"
>
<h2 className="text-xl font-semibold text-gray-900 dark:text-gray-100 mb-2">
Device Analytics
</h2>
<p className="text-gray-600 dark:text-gray-400">
Understand how users access your links
</p>
</Link>
</div>
</div>
</div>
);
}

View File

@@ -1,6 +1,8 @@
"use client"; "use client";
import { DeviceAnalytics as DeviceAnalyticsType } from '../../api/types'; import { useEffect, useRef } from 'react';
import { DeviceAnalytics as DeviceAnalyticsType } from '@/app/api/types';
import { Chart, PieController, ArcElement, Tooltip, Legend } from 'chart.js';
interface DeviceAnalyticsProps { interface DeviceAnalyticsProps {
data: DeviceAnalyticsType; data: DeviceAnalyticsType;

View File

@@ -1,6 +1,8 @@
"use client"; "use client";
import { GeoData } from '../../api/types'; import { useEffect, useRef } from 'react';
import { GeoData } from '@/app/api/types';
import { Chart, PieController, ArcElement, Tooltip, Legend } from 'chart.js';
interface GeoAnalyticsProps { interface GeoAnalyticsProps {
data: GeoData[]; data: GeoData[];

View File

@@ -16,7 +16,7 @@ import {
ChartOptions, ChartOptions,
TooltipItem TooltipItem
} from 'chart.js'; } from 'chart.js';
import { TimeSeriesData } from '../../api/types'; import { TimeSeriesData } from '@/app/api/types';
// 注册 Chart.js 组件 // 注册 Chart.js 组件
ChartJS.register( ChartJS.register(

View File

@@ -1,68 +1,21 @@
import './globals.css'; import './globals.css';
import type { Metadata } from 'next'; import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import Link from 'next/link';
const inter = Inter({ subsets: ['latin'] });
export const metadata: Metadata = { export const metadata: Metadata = {
title: 'ShortURL Analytics', title: 'Link Management & Analytics',
description: 'Analytics dashboard for ShortURL service', description: 'Track and analyze shortened links',
}; };
export default function RootLayout({ export default function RootLayout({
children, children,
}: { }: Readonly<{
children: React.ReactNode; children: React.ReactNode;
}) { }>) {
return ( return (
<html lang="en"> <html lang="en" suppressHydrationWarning>
<body className={inter.className}> <body>
<div className="min-h-screen bg-gray-50 dark:bg-gray-900"> {children}
<nav className="bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700">
<div className="container mx-auto px-4">
<div className="flex items-center justify-between h-16">
<div className="flex items-center">
<Link href="/" className="text-xl font-bold text-gray-900 dark:text-gray-100">
ShortURL Analytics
</Link>
<div className="hidden md:block ml-10">
<div className="flex items-baseline space-x-4">
<Link
href="/dashboard"
className="text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 px-3 py-2 rounded-md text-sm font-medium"
>
Dashboard
</Link>
<Link
href="/events"
className="text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 px-3 py-2 rounded-md text-sm font-medium"
>
Events
</Link>
<Link
href="/analytics/geo"
className="text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 px-3 py-2 rounded-md text-sm font-medium"
>
Geographic
</Link>
<Link
href="/analytics/devices"
className="text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 px-3 py-2 rounded-md text-sm font-medium"
>
Devices
</Link>
</div>
</div>
</div>
</div>
</div>
</nav>
<main className="py-10">
{children}
</main>
</div>
</body> </body>
</html> </html>
); );
} }

View File

@@ -1,21 +0,0 @@
import './globals.css';
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Link Management & Analytics',
description: 'Track and analyze shortened links',
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en" suppressHydrationWarning>
<body>
{children}
</body>
</html>
);
}