From 34303744ee11a204b67ce5d304b5b66774116727 Mon Sep 17 00:00:00 2001 From: yu-3in Date: Fri, 19 Apr 2024 20:10:46 +0900 Subject: [PATCH] fix: event model date to timestamp --- .../CreateEventForm/CreateEventForm.tsx | 6 +- .../EventDataTable/EventDataTable.tsx | 309 ++++++++++++++++++ 2 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 src/components/EventDataTable/EventDataTable.tsx diff --git a/src/components/CreateEventForm/CreateEventForm.tsx b/src/components/CreateEventForm/CreateEventForm.tsx index e1ee8e7..38837ef 100644 --- a/src/components/CreateEventForm/CreateEventForm.tsx +++ b/src/components/CreateEventForm/CreateEventForm.tsx @@ -8,7 +8,7 @@ import { getDownloadURL, ref, uploadBytes } from "firebase/storage" import { zodResolver } from "@hookform/resolvers/zod" import { useCallback } from "react" import { CalendarIcon } from "lucide-react" -import { addDoc, collection } from "firebase/firestore" +import { addDoc, collection, serverTimestamp } from "firebase/firestore" import { toast } from "sonner" import { v4 as uuidv4 } from "uuid" import { useRouter } from "next/navigation" @@ -71,6 +71,8 @@ export const CreateEventForm = () => { const eventsCollection = collection(devDb, "events") + const serverTimeStamp = serverTimestamp() + const promise = addDoc(eventsCollection, { title: data.title, description: data.description ?? null, @@ -81,6 +83,8 @@ export const CreateEventForm = () => { externalLink: data.externalLink ?? null, isPublished: data.isPublished, // createdBy: null, // TODO: + createdAt: serverTimeStamp, + updatedAt: serverTimeStamp, }) toast.promise(promise, { diff --git a/src/components/EventDataTable/EventDataTable.tsx b/src/components/EventDataTable/EventDataTable.tsx new file mode 100644 index 0000000..6f40145 --- /dev/null +++ b/src/components/EventDataTable/EventDataTable.tsx @@ -0,0 +1,309 @@ +"use client" + +import { + ColumnDef, + ColumnFiltersState, + SortingState, + VisibilityState, + flexRender, + getCoreRowModel, + getFilteredRowModel, + getPaginationRowModel, + getSortedRowModel, + useReactTable, +} from "@tanstack/react-table" +import { useState } from "react" +import { ArrowUpDown, MoreHorizontal } from "lucide-react" +import { format } from "date-fns" + +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table" +import { Event } from "@/models/event" +import { Button } from "@/components/ui/button" +import { + DropdownMenu, + DropdownMenuCheckboxItem, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" + +import { Input } from "../ui/input" +import { Checkbox } from "../ui/checkbox" + +const columns: ColumnDef[] = [ + { + id: "select", + header: ({ table }) => ( + table.toggleAllPageRowsSelected(!!value)} + aria-label="Select all" + /> + ), + cell: ({ row }) => ( + row.toggleSelected(!!value)} + aria-label="Select row" + /> + ), + }, + { + accessorKey: "title", + header: ({ column }) => { + return ( + + ) + }, + }, + { + accessorKey: "description", + header: "説明", + }, + { + accessorKey: "thumbnailUrl", + header: "サムネイル", + }, + { + accessorKey: "color", + header: "テーマカラー", + }, + { + accessorKey: "startAt", + header: ({ column }) => { + return ( + + ) + }, + cell: ({ row }) => { + const date = format(new Date(row.original.startAt.seconds), "yyyy-MM-dd HH:mm:ss") + return {date} + }, + }, + { + accessorKey: "endAt", + header: ({ column }) => { + return ( + + ) + }, + }, + { + accessorKey: "externalLink", + header: "外部リンク", + }, + { + accessorKey: "isPublished", + header: ({ column }) => { + return ( + + ) + }, + }, + { + accessorKey: "createdBy", + header: "作成者", + }, + { + accessorKey: "participantIds", + header: "参加者", + }, + { + accessorKey: "createdAt", + header: "作成日時", + }, + { + accessorKey: "updatedAt", + header: "更新日時", + }, + { + id: "actions", + cell: ({ row }) => { + const payment = row.original + + return ( + + + + + + Actions + navigator.clipboard.writeText(payment.id)}> + Copy payment ID + + + View customer + View payment details + + + ) + }, + }, +] + +interface EventDataTableProps { + data: Event[] +} + +export function EventDataTable({ data }: EventDataTableProps) { + const [sorting, setSorting] = useState([]) + const [columnFilters, setColumnFilters] = useState([]) + const [columnVisibility, setColumnVisibility] = useState({}) + const [rowSelection, setRowSelection] = useState({}) + + const table = useReactTable({ + data, + columns, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + onSortingChange: setSorting, + getSortedRowModel: getSortedRowModel(), + onColumnFiltersChange: setColumnFilters, + getFilteredRowModel: getFilteredRowModel(), + onColumnVisibilityChange: setColumnVisibility, + onRowSelectionChange: setRowSelection, + state: { + sorting, + columnFilters, + columnVisibility, + rowSelection, + }, + }) + + return ( +
+
+ table.getColumn("email")?.setFilterValue(event.target.value)} + className="max-w-sm" + /> + + + + + + {table + .getAllColumns() + .filter((column) => column.getCanHide()) + .map((column) => { + return ( + column.toggleVisibility(!!value)} + > + {column.id} + + ) + })} + + +
+ +
+ {table.getFilteredSelectedRowModel().rows.length} of{" "} + {table.getFilteredRowModel().rows.length} row(s) selected. +
+ +
+ + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => { + return ( + + {header.isPlaceholder + ? null + : flexRender(header.column.columnDef.header, header.getContext())} + + ) + })} + + ))} + + + {table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender(cell.column.columnDef.cell, cell.getContext())} + + ))} + + )) + ) : ( + + + No results. + + + )} + +
+
+
+ + +
+
+ ) +}