Updated list component

This commit is contained in:
2025-06-26 14:55:04 +02:00
parent 4381d81710
commit 7390964d56
2 changed files with 74 additions and 23 deletions

View File

@@ -12,7 +12,7 @@ import {
useReactTable, useReactTable,
VisibilityState VisibilityState
} from "@tanstack/react-table" } from "@tanstack/react-table"
import { ArrowUpDown, Check, Copy, ExternalLink, MoreHorizontal, Trash2, X } from "lucide-react" import { ArrowUpDown, Check, Copy, MoreHorizontal, Trash2, X } from "lucide-react"
import * as React from "react" import * as React from "react"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
@@ -27,19 +27,13 @@ import {
} from "@/components/ui/dropdown-menu" } from "@/components/ui/dropdown-menu"
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input"
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import { deleteUrl } from "@/lib/actions/url"
import { urls } from "@/lib/drizzle/schema" import { urls } from "@/lib/drizzle/schema"
import { useRouter } from "next/navigation"
import { toast } from "sonner" import { toast } from "sonner"
type UrlRecord = typeof urls.$inferSelect type UrlRecord = typeof urls.$inferSelect
function handleCopy(string: string) {
navigator.clipboard.writeText(string).then(() => {
toast.success("URL copied to clipboard")
}).catch(() => {
toast.error("Failed to copy URL")
})
}
export const columns: ColumnDef<UrlRecord>[] = [ export const columns: ColumnDef<UrlRecord>[] = [
{ {
accessorKey: "slug", accessorKey: "slug",
@@ -202,8 +196,39 @@ export const columns: ColumnDef<UrlRecord>[] = [
</div> </div>
) )
} }
}, }
{ ]
interface UrlsDataTableProps {
data: UrlRecord[]
}
export function UrlsDataTable({ data }: UrlsDataTableProps) {
const [sorting, setSorting] = React.useState<SortingState>([])
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([])
const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({})
const router = useRouter()
function handleCopy(string: string) {
navigator.clipboard.writeText(string).then(() => {
toast.success("URL copied to clipboard")
}).catch(() => {
toast.error("Failed to copy URL")
})
}
async function handleDelete(id: string) {
const res = await deleteUrl(id)
if (res.error) {
toast.error("Failed to delete URL")
} else {
toast.success("URL deleted successfully")
router.refresh()
}
}
const actionRow: ColumnDef<UrlRecord> = {
id: "actions", id: "actions",
enableHiding: false, enableHiding: false,
cell: ({ row }) => { cell: ({ row }) => {
@@ -228,7 +253,12 @@ export const columns: ColumnDef<UrlRecord>[] = [
Copy URL Copy URL
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuSeparator /> <DropdownMenuSeparator />
<DropdownMenuItem className="text-red-600"> <DropdownMenuItem
className="text-red-600"
onClick={() => {
handleDelete(urlRecord.id)
}}
>
<Trash2 className="mr-2 h-4 w-4" /> <Trash2 className="mr-2 h-4 w-4" />
Delete Delete
</DropdownMenuItem> </DropdownMenuItem>
@@ -237,20 +267,12 @@ export const columns: ColumnDef<UrlRecord>[] = [
) )
} }
} }
]
interface UrlsDataTableProps { const tableColumns = React.useMemo(() => [...columns, actionRow], [])
data: UrlRecord[]
}
export function UrlsDataTable({ data }: UrlsDataTableProps) {
const [sorting, setSorting] = React.useState<SortingState>([])
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([])
const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({})
const table = useReactTable({ const table = useReactTable({
data, data,
columns, columns: tableColumns,
onSortingChange: setSorting, onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters, onColumnFiltersChange: setColumnFilters,
getCoreRowModel: getCoreRowModel(), getCoreRowModel: getCoreRowModel(),
@@ -341,7 +363,7 @@ export function UrlsDataTable({ data }: UrlsDataTableProps) {
( (
<TableRow> <TableRow>
<TableCell <TableCell
colSpan={columns.length} colSpan={tableColumns.length}
className="h-24 text-center" className="h-24 text-center"
> >
No results. No results.

View File

@@ -1,8 +1,10 @@
"use server" "use server"
import { z } from "zod"
import { getSession } from "../auth/session" import { getSession } from "../auth/session"
import { insertUrl } from "../db/urls" import { insertUrl } from "../db/urls"
import { urlFormSchema } from "../schema/url" import { urlFormSchema } from "../schema/url"
import { deleteUrl as deleteUrlDb } from "../db/urls"
type Response = { type Response = {
error: boolean error: boolean
@@ -34,4 +36,31 @@ export async function addUrl(unsafeData: unknown): Promise<Response> {
error: false, error: false,
message: "Short link created successfully!" message: "Short link created successfully!"
} }
}
export async function deleteUrl(unsafe: unknown): Promise<Response> {
const { session } = await getSession()
if (!session) {
return {
error: true,
message: "You must be logged in to create a short link."
}
}
const { error, data: id } = z.string().safeParse(unsafe)
if (error) {
return {
error: true,
message: "Error parsing form data."
}
}
await deleteUrlDb(id)
return {
error: false,
message: "Short link deleted successfully!"
}
} }