Files
ai-showcase-platform/components/auth/activity-records-dialog.tsx

336 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import { useAuth } from "@/contexts/auth-context"
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Progress } from "@/components/ui/progress"
import { BarChart3, Clock, Heart, ImageIcon, MessageSquare, FileText, TrendingUp, Trash2, RefreshCw } from "lucide-react"
import { useState, useEffect } from "react"
interface ActivityRecordsDialogProps {
open: boolean
onOpenChange: (open: boolean) => void
}
// Mock data for demonstration - will be replaced with real data
const mockRecentApps: any[] = []
const mockCategoryData: any[] = []
export function ActivityRecordsDialog({ open, onOpenChange }: ActivityRecordsDialogProps) {
const {
user,
getViewCount,
getAppLikes,
getUserLikeHistory,
getAppLikesInPeriod
} = useAuth()
const [recentApps, setRecentApps] = useState<any[]>([])
const [categoryData, setCategoryData] = useState<any[]>([])
const [isResetting, setIsResetting] = useState(false)
if (!user) return null
// Calculate user statistics
const calculateUserStats = () => {
if (!user) return {
totalUsage: 0,
totalDuration: 0,
favoriteApps: 0,
daysJoined: 0
}
// Calculate total usage count (views)
const totalUsage = Object.values(user.recentApps || []).length
// Calculate total duration (simplified - 5 minutes per app view)
const totalDuration = totalUsage * 5 // minutes
// Get favorite apps count
const favoriteApps = user.favoriteApps?.length || 0
// Calculate days joined
const joinDate = new Date(user.joinDate)
const now = new Date()
// Check if joinDate is valid
let daysJoined = 0
if (!isNaN(joinDate.getTime())) {
daysJoined = Math.floor((now.getTime() - joinDate.getTime()) / (1000 * 60 * 60 * 24))
}
return {
totalUsage,
totalDuration,
favoriteApps,
daysJoined: Math.max(0, daysJoined)
}
}
const stats = calculateUserStats()
// Load recent apps from user's recent apps
useEffect(() => {
if (user?.recentApps) {
// Convert recent app IDs to app objects (simplified)
const recentAppsData = user.recentApps.slice(0, 10).map((appId, index) => ({
id: appId,
name: `應用 ${appId}`,
author: "系統",
category: "AI應用",
usageCount: getViewCount(appId),
timeSpent: "5分鐘",
lastUsed: `${index + 1}天前`,
icon: MessageSquare,
color: "bg-blue-500"
}))
setRecentApps(recentAppsData)
} else {
setRecentApps([])
}
}, [user, getViewCount])
// Load category data (simplified)
useEffect(() => {
// This would normally be calculated from actual usage data
setCategoryData([])
}, [user])
// Reset user activity data
const resetActivityData = async () => {
setIsResetting(true)
try {
// Clear localStorage data
if (typeof window !== "undefined") {
localStorage.removeItem("appViews")
localStorage.removeItem("appLikes")
localStorage.removeItem("userLikes")
localStorage.removeItem("appLikesOld")
localStorage.removeItem("appRatings")
}
// Reset user's recent apps and favorites
if (user) {
const updatedUser = {
...user,
recentApps: [],
favoriteApps: [],
totalLikes: 0,
totalViews: 0
}
localStorage.setItem("user", JSON.stringify(updatedUser))
// Reload the page to refresh all data
window.location.reload()
}
} catch (error) {
console.error("Error resetting activity data:", error)
} finally {
setIsResetting(false)
}
}
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-5xl max-h-[85vh] overflow-hidden">
<DialogHeader>
<DialogTitle className="text-2xl font-bold flex items-center gap-2">
<BarChart3 className="w-6 h-6" />
</DialogTitle>
</DialogHeader>
<Tabs defaultValue="recent" className="w-full">
<TabsList className="grid w-full grid-cols-2">
<TabsTrigger value="recent">使</TabsTrigger>
<TabsTrigger value="statistics"></TabsTrigger>
</TabsList>
<TabsContent value="recent" className="space-y-4 max-h-[60vh] overflow-y-auto">
<div>
<h3 className="text-lg font-semibold mb-2">使</h3>
<p className="text-sm text-muted-foreground mb-4"> AI </p>
{recentApps.length > 0 ? (
<div className="grid gap-4">
{recentApps.map((app) => {
const IconComponent = app.icon
return (
<Card key={app.id} className="hover:shadow-md transition-shadow">
<CardContent className="flex items-center justify-between p-4">
<div className="flex items-center space-x-4">
<div className={`p-3 rounded-lg ${app.color}`}>
<IconComponent className="w-6 h-6 text-white" />
</div>
<div>
<h4 className="font-semibold">{app.name}</h4>
<p className="text-sm text-muted-foreground">by {app.author}</p>
<div className="flex items-center gap-4 mt-1">
<Badge variant="secondary" className="text-xs">
{app.category}
</Badge>
<span className="text-xs text-muted-foreground flex items-center gap-1">
<BarChart3 className="w-3 h-3" />
使 {app.usageCount}
</span>
<span className="text-xs text-muted-foreground flex items-center gap-1">
<Clock className="w-3 h-3" />
{app.timeSpent}
</span>
</div>
</div>
</div>
<div className="text-right">
<p className="text-xs text-muted-foreground mb-2">{app.lastUsed}</p>
<Button size="sm" variant="outline">
</Button>
</div>
</CardContent>
</Card>
)
})}
</div>
) : (
<Card>
<CardContent className="text-center py-12">
<MessageSquare className="w-16 h-16 text-gray-400 mx-auto mb-4" />
<h3 className="text-xl font-semibold text-gray-600 mb-2">使</h3>
<p className="text-gray-500 mb-4"> AI 使</p>
<Button
variant="outline"
onClick={() => onOpenChange(false)}
>
</Button>
</CardContent>
</Card>
)}
</div>
</TabsContent>
<TabsContent value="statistics" className="space-y-6 max-h-[60vh] overflow-y-auto">
<div>
<div className="flex items-center justify-between mb-4">
<div>
<h3 className="text-lg font-semibold mb-2"></h3>
<p className="text-sm text-muted-foreground"></p>
</div>
<Button
variant="outline"
size="sm"
onClick={resetActivityData}
disabled={isResetting}
className="text-red-600 hover:text-red-700 hover:bg-red-50"
>
{isResetting ? (
<RefreshCw className="w-4 h-4 mr-2 animate-spin" />
) : (
<Trash2 className="w-4 h-4 mr-2" />
)}
{isResetting ? "重置中..." : "清空數據"}
</Button>
</div>
{/* Statistics Cards */}
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">使</CardTitle>
<TrendingUp className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{isNaN(stats.totalUsage) ? 0 : stats.totalUsage}</div>
<p className="text-xs text-muted-foreground">
{(isNaN(stats.totalUsage) ? 0 : stats.totalUsage) > 0 ? "累計使用" : "尚未使用任何應用"}
</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">使</CardTitle>
<Clock className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">
{isNaN(stats.totalDuration) ? "0分鐘" : (
stats.totalDuration >= 60
? `${(stats.totalDuration / 60).toFixed(1)}小時`
: `${stats.totalDuration}分鐘`
)}
</div>
<p className="text-xs text-muted-foreground">
{(isNaN(stats.totalDuration) ? 0 : stats.totalDuration) > 0 ? "累計時長" : "尚未開始使用"}
</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium"></CardTitle>
<Heart className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{isNaN(stats.favoriteApps) ? 0 : stats.favoriteApps}</div>
<p className="text-xs text-muted-foreground">
{(isNaN(stats.favoriteApps) ? 0 : stats.favoriteApps) > 0 ? "個人收藏" : "尚未收藏任何應用"}
</p>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle className="text-base"></CardTitle>
<CardDescription></CardDescription>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{isNaN(stats.daysJoined) ? 0 : stats.daysJoined}</div>
<p className="text-xs text-muted-foreground">
{(isNaN(stats.daysJoined) ? 0 : stats.daysJoined) > 0 ? "已加入平台" : "今天剛加入"}
</p>
</CardContent>
</Card>
</div>
{/* Category Usage */}
<Card>
<CardHeader>
<CardTitle className="text-base">使</CardTitle>
<CardDescription>使</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
{categoryData.length > 0 ? (
categoryData.map((category, index) => (
<div key={index} className="space-y-2">
<div className="flex items-center justify-between text-sm">
<div className="flex items-center gap-2">
<div className={`w-3 h-3 rounded-full ${category.color}`} />
<span className="font-medium">{category.name}</span>
</div>
<span className="text-muted-foreground">{category.usage}%</span>
</div>
<Progress value={category.usage} className="h-2" />
</div>
))
) : (
<div className="text-center py-8">
<BarChart3 className="w-12 h-12 text-gray-400 mx-auto mb-3" />
<p className="text-gray-500 text-sm">使</p>
<p className="text-gray-400 text-xs mt-1">使</p>
</div>
)}
</CardContent>
</Card>
</div>
</TabsContent>
</Tabs>
</DialogContent>
</Dialog>
)
}