"use client"; import { useState, useEffect, useRef } from 'react'; import { addDays, format } from 'date-fns'; import { DateRangePicker } from '../components/ui/DateRangePicker'; import { Event, EventFilters } from '../api/types'; export default function EventsPage() { const [dateRange, setDateRange] = useState({ from: addDays(new Date(), -7), to: new Date() }); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [events, setEvents] = useState([]); const [page, setPage] = useState(1); const [hasMore, setHasMore] = useState(true); const [filter, setFilter] = useState({ eventType: '', linkId: '', linkSlug: '' }); const [filters, setFilters] = useState({ startTime: format(new Date('2024-02-01'), "yyyy-MM-dd'T'HH:mm:ss'Z'"), endTime: format(new Date('2025-03-05'), "yyyy-MM-dd'T'HH:mm:ss'Z'"), page: 1, pageSize: 20 }); const [summary, setSummary] = useState(null); const observerRef = useRef(null); const lastEventRef = useRef(null); const fetchEvents = async (pageNum: number) => { try { const startTime = format(dateRange.from, "yyyy-MM-dd'T'HH:mm:ss'Z'"); const endTime = format(dateRange.to, "yyyy-MM-dd'T'HH:mm:ss'Z'"); const params = new URLSearchParams({ startTime, endTime, page: pageNum.toString(), pageSize: '50' }); if (filter.eventType) params.append('eventType', filter.eventType); if (filter.linkId) params.append('linkId', filter.linkId); if (filter.linkSlug) params.append('linkSlug', filter.linkSlug); const response = await fetch(`/api/events?${params.toString()}`); const data = await response.json(); if (!response.ok) { throw new Error(data.error || 'Failed to fetch events'); } if (pageNum === 1) { setEvents(data.events); } else { setEvents(prev => [...prev, ...data.events]); } setHasMore(data.events.length === 50); } catch (err) { setError(err instanceof Error ? err.message : 'An error occurred while fetching events'); } finally { setLoading(false); } }; useEffect(() => { setPage(1); setEvents([]); setLoading(true); fetchEvents(1); }, [dateRange, filter]); const loadMore = () => { if (!loading && hasMore) { const nextPage = page + 1; setPage(nextPage); fetchEvents(nextPage); } }; const formatDate = (dateString: string) => { const date = new Date(dateString); return date.toLocaleString(); }; if (error) { return (
{error}
); } return (

Events

setFilter(prev => ({ ...prev, linkId: e.target.value }))} placeholder="Enter Link ID" className="block w-full px-3 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-md text-sm text-gray-900 dark:text-gray-100" />
setFilter(prev => ({ ...prev, linkSlug: e.target.value }))} placeholder="Enter Link Slug" className="block w-full px-3 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-md text-sm text-gray-900 dark:text-gray-100" />
{events.map((event, index) => ( ))}
Time Type Link Visitor Location Referrer
{formatDate(event.time)} {event.type}
{event.linkInfo.shortUrl}
{event.linkInfo.originalUrl}
{event.visitor.browser}
{event.visitor.os} / {event.visitor.device}
{event.location.city}
{event.location.region}, {event.location.country}
{event.referrer || '-'}
{loading && (
)} {!loading && hasMore && (
)} {!loading && events.length === 0 && (
No events found
)}
); }