import { useCallback, useEffect, useState } from 'react' import { Link } from '../types/api' import { getAllLinks, deleteLink } from '../api/client' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table" import { Button } from "@/components/ui/button" import { useToast } from "@/hooks/use-toast" import { Copy, Trash2, BarChart2, Pencil } from "lucide-react" import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, } from "@/components/ui/dialog" import { StatisticsModal } from "./StatisticsModal" import { EditModal } from './EditModal' interface LinkListProps { refresh?: number; } export function LinkList({ refresh = 0 }: LinkListProps) { const [links, setLinks] = useState([]) const [loading, setLoading] = useState(true) const [deleteModal, setDeleteModal] = useState<{ isOpen: boolean; linkId: number | null }>({ isOpen: false, linkId: null, }) const [statsModal, setStatsModal] = useState<{ isOpen: boolean; linkId: number | null }>({ isOpen: false, linkId: null, }); const [editModal, setEditModal] = useState<{ isOpen: boolean; link: Link | null }>({ isOpen: false, link: null, }); const { toast } = useToast() const fetchLinks = useCallback(async () => { try { setLoading(true) const data = await getAllLinks() setLinks(data) } catch (err: unknown) { const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred'; toast({ title: "Error", description: `Failed to load links: ${errorMessage}`, variant: "destructive", }) } finally { setLoading(false) } }, [toast, setLinks, setLoading]) useEffect(() => { fetchLinks() }, [fetchLinks, refresh]) // Re-fetch when refresh counter changes const handleDelete = async () => { if (!deleteModal.linkId) return try { await deleteLink(deleteModal.linkId) await fetchLinks() setDeleteModal({ isOpen: false, linkId: null }) toast({ description: "Link deleted successfully", }) } catch (err: unknown) { const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred'; toast({ title: "Error", description: `Failed to delete link: ${errorMessage}`, variant: "destructive", }) } } const handleCopy = (shortCode: string) => { // Use import.meta.env.VITE_BASE_URL or fall back to window.location.origin const baseUrl = window.location.origin navigator.clipboard.writeText(`${baseUrl}/${shortCode}`) toast({ description: ( <> Link copied to clipboard
You can add ?source=TextHere to the end of the link to track the source of clicks ), }) } if (loading && !links.length) { return
Loading...
} return ( <> setDeleteModal({ isOpen: open, linkId: null })}> Delete Link Are you sure you want to delete this link? This action cannot be undone. Your Links Manage and track your shortened links
Short Code Original URL Clicks Created Actions {links.map((link) => ( {link.short_code} {link.original_url} {link.clicks} {new Date(link.created_at).toLocaleDateString()}
))}
setStatsModal({ isOpen: false, linkId: null })} linkId={statsModal.linkId!} /> {editModal.link && ( setEditModal({ isOpen: false, link: null })} link={editModal.link} onSuccess={fetchLinks} /> )} ) }