events date range 7days

This commit is contained in:
2025-03-31 21:21:17 +08:00
parent 52969426a2
commit 727f0a9336
2 changed files with 73 additions and 89 deletions

View File

@@ -7,8 +7,8 @@ import { Event, EventType } from '@/lib/types';
export default function EventsPage() {
const [dateRange, setDateRange] = useState({
from: new Date('2024-02-01'),
to: new Date('2025-03-05')
from: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), // 7天前
to: new Date() // 今天
});
const [loading, setLoading] = useState(true);
@@ -227,6 +227,24 @@ export default function EventsPage() {
className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500"
/>
</div>
<div>
<select
value={filters.tags.length > 0 ? filters.tags[0] : ''}
onChange={(e) => {
const selectedTag = e.target.value;
setFilters(prev => ({
...prev,
tags: selectedTag ? [selectedTag] : []
}));
}}
className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500"
>
<option value=""></option>
{tags.map(tag => (
<option key={tag} value={tag}>{tag}</option>
))}
</select>
</div>
<div>
<select
value={filters.sortBy}
@@ -250,33 +268,6 @@ export default function EventsPage() {
</div>
</div>
{/* 标签选择 */}
<div className="mt-4">
<h3 className="text-sm font-medium mb-2"></h3>
<div className="flex flex-wrap gap-2">
{tags.map(tag => (
<button
key={tag}
onClick={() => {
setFilters(prev => ({
...prev,
tags: prev.tags.includes(tag)
? prev.tags.filter(t => t !== tag)
: [...prev.tags, tag]
}));
}}
className={`px-2 py-1 rounded-full text-sm font-medium ${
filters.tags.includes(tag)
? 'bg-blue-500 text-white'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
}`}
>
{tag}
</button>
))}
</div>
</div>
<div className="mt-4 flex justify-end">
<button
onClick={resetFilters}

View File

@@ -186,25 +186,19 @@ export default function LinkDetailsPage({
}
}, [dateRange, timeGranularity]);
// 获取并设置linkId
useEffect(() => {
const loadParams = async () => {
const resolvedParams = await params;
setLinkId(resolvedParams.id);
// 格式化时间(秒转为分钟和秒)
const formatTime = (seconds: number) => {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = Math.round(seconds % 60);
return `${minutes}m ${remainingSeconds}s`;
};
loadParams();
}, [params]);
// 获取链接详情数据
useEffect(() => {
if (!linkId) return;
const fetchLinkDetails = async () => {
// 将 fetchLinkDetails 移到 useEffect 外面
const fetchLinkDetails = useCallback(async (id: string) => {
setLoading(true);
try {
// 获取链接详情
const response = await fetch(`/api/links/${linkId}/details`);
const response = await fetch(`/api/links/${id}/details`);
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || "Failed to fetch link details");
@@ -215,7 +209,7 @@ export default function LinkDetailsPage({
// 将 API 返回的数据映射到组件需要的格式
setLinkDetails({
id: details.link_id || linkId,
id: details.link_id || id,
name: details.title || "Untitled Link",
shortUrl: details.short_url || window.location.hostname + "/" + details.link_id,
originalUrl: details.original_url || "",
@@ -234,24 +228,23 @@ export default function LinkDetailsPage({
});
setLoading(false);
// 获取分析数据
fetchAnalyticsData(linkId);
} catch (error) {
console.error("Failed to fetch link details:", error);
setLoading(false);
}
};
}, []);
fetchLinkDetails();
}, [linkId, fetchAnalyticsData]);
// 获取并设置linkId - 移除异步获取参数的逻辑因为params已经可用
useEffect(() => {
// 直接使用params.id
if (params.id) {
setLinkId(params.id);
fetchLinkDetails(params.id);
fetchAnalyticsData(params.id);
}
}, [params.id, fetchLinkDetails, fetchAnalyticsData]);
// 格式化时间(秒转为分钟和秒)
const formatTime = (seconds: number) => {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = Math.round(seconds % 60);
return `${minutes}m ${remainingSeconds}s`;
};
// 获取链接详情数据 - 这个 useEffect 可以删除,已合并到上面的 useEffect
// 更新时间粒度并重新获取趋势数据
const updateTimeGranularity = (granularity: TimeGranularity) => {