diff --git a/app/(auth)/locations/page.tsx b/app/(auth)/locations/page.tsx new file mode 100644 index 0000000..da1f94b --- /dev/null +++ b/app/(auth)/locations/page.tsx @@ -0,0 +1,13 @@ +import LocationsTable from '@/components/tables/LocationsTable' +import { queries } from '@/lib/queries' +import React from 'react' + +export default async function LocationsPage() { + const eventLocations = await queries.fetchAllLocations() + + return ( +
+ +
+ ) +} diff --git a/components/GuestBookList.tsx b/components/GuestBookList.tsx index 3692148..3e07357 100644 --- a/components/GuestBookList.tsx +++ b/components/GuestBookList.tsx @@ -1,6 +1,7 @@ 'use client' import React, { useState } from 'react' import EditGuestBookEntryModal from './EditGuestBookEntryModal' +// import GuestBookTable from './tables/GuestBookTable' interface GuestBookEntry { id: string @@ -63,36 +64,39 @@ export default function GuestBookList({ entries, view }: { entries: GuestBookEnt return (
{view === 'TABLE' ? ( -
- - - - - - - - - - - - - {entries.map(entry => ( - setEditingEntry(entry)} - > - - - - - - + <> +
+
NameEmailPhoneAddressCongratulated EngagementNotes
{entry.fName + ' ' + entry.lName} (Side: {entry.side}){entry.email || 'N/A'}{entry.phone || 'N/A'}{entry.address || 'N/A'}{entry.congratulated == true ? 'Yes' : "No"}{entry.notes || 'N/A'}
+ + + + + + + + - ))} - -
NameEmailPhoneAddressCongratulated EngagementNotes
-
+ + + {entries.map(entry => ( + setEditingEntry(entry)} + > + {entry.fName + ' ' + entry.lName} (Side: {entry.side}) + {entry.email || 'N/A'} + {entry.phone || 'N/A'} + {entry.address || 'N/A'} + {entry.congratulated == true ? 'Yes' : "No"} + {entry.notes || 'N/A'} + + ))} + + +
+ {/* */} + ) : (
diff --git a/components/app-sidebar.tsx b/components/app-sidebar.tsx index 94e01dd..eb4ea2d 100644 --- a/components/app-sidebar.tsx +++ b/components/app-sidebar.tsx @@ -2,14 +2,10 @@ import * as React from "react" import { - IconCamera, - IconChartBar, + IconBuildingArch, IconDashboard, IconDatabase, - IconFileAi, - IconFileDescription, IconFileWord, - IconFolder, IconHelp, IconInnerShadowTop, IconListDetails, @@ -50,6 +46,11 @@ const data = { url: "/guest-book", icon: IconUsers, }, + { + title: "Locations", + url: "/locations", + icon: IconBuildingArch, + }, ], // navClouds: [ // { diff --git a/components/tables/DataTable.tsx b/components/tables/DataTable.tsx new file mode 100644 index 0000000..cad908b --- /dev/null +++ b/components/tables/DataTable.tsx @@ -0,0 +1,87 @@ +'use client' + +import { + ColumnDef, + flexRender, + getCoreRowModel, + useReactTable, + SortingState, + getSortedRowModel +} from '@tanstack/react-table' + +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow +} from '../ui/table' + +import { useState } from 'react' + +interface DataTableProps { + columns: ColumnDef[] + data: TData[] + className?: string +} + +export function DataTable({ + columns, + data, + className +}: DataTableProps) { + const [sorting, setSorting] = useState([]) + + const table = useReactTable({ + data, + columns, + state: { sorting }, + onSortingChange: setSorting, + getCoreRowModel: getCoreRowModel(), + getSortedRowModel: getSortedRowModel() + }) + + return ( +
+ + + {table.getHeaderGroups().map(headerGroup => ( + + {headerGroup.headers.map(header => ( + + {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 + + + )} + +
+
+ ) +} diff --git a/components/tables/GuestBookTable.tsx b/components/tables/GuestBookTable.tsx new file mode 100644 index 0000000..d2b89a4 --- /dev/null +++ b/components/tables/GuestBookTable.tsx @@ -0,0 +1,66 @@ +'use client' + +import { ColumnDef } from '@tanstack/react-table' +import { DataTable } from './DataTable' + +interface GuestBookEntryRow { + id: string + fName: string + lName: string + side: string + address: string + notes?: string | null + phone?: string | null + email?: string | null + congratulated?: boolean | null +} + +interface Props { + guestBookEntries: GuestBookEntryRow[] +} + +const columns: ColumnDef[] = [ + { + accessorKey: 'name', + header: 'Name', + cell: ({ row }) => row.original.fName + " " + row.original.lName + }, + { + accessorKey: 'side', + header: 'Side' + }, + { + accessorKey: 'email', + header: 'Email', + cell: ({ row }) => row.original.email || '—' + }, + { + accessorKey: 'phone', + header: 'Phone', + cell: ({ row }) => row.original.phone || '—' + }, + { + accessorKey: 'address', + header: 'Address', + cell: ({ row }) => row.original.address || '—' + }, + { + accessorKey: 'congratulated', + header: 'Congratulated Engagement', + cell: ({ row }) => row.original.congratulated == true ? "Yes" : 'No' + }, + { + accessorKey: 'notes', + header: 'Notes', + cell: ({ row }) => row.original.notes || '—' + }, + +] + +export default function GuestBookTable({ guestBookEntries }: Props) { + return ( +
+ +
+ ) +} diff --git a/components/tables/LocationsTable.tsx b/components/tables/LocationsTable.tsx new file mode 100644 index 0000000..36cf61a --- /dev/null +++ b/components/tables/LocationsTable.tsx @@ -0,0 +1,65 @@ +'use client' + +import { ColumnDef } from '@tanstack/react-table' +import { DataTable } from './DataTable' + +interface LocationRow { + id: string + name: string + address: string + city: string + state: string + postalCode: string + country: string + phone?: string | null + email?: string | null +} + +interface Props { + eventLocations: LocationRow[] +} + +const columns: ColumnDef[] = [ + { + accessorKey: 'name', + header: 'Name' + }, + { + accessorKey: 'address', + header: 'Address' + }, + { + accessorKey: 'city', + header: 'City' + }, + { + accessorKey: 'state', + header: 'State' + }, + { + accessorKey: 'postalCode', + header: 'Postal Code' + }, + { + accessorKey: 'country', + header: 'Country' + }, + { + accessorKey: 'phone', + header: 'Phone', + cell: ({ row }) => row.original.phone || '—' + }, + { + accessorKey: 'email', + header: 'Email', + cell: ({ row }) => row.original.email || '—' + } +] + +export default function LocationsTable({ eventLocations }: Props) { + return ( +
+ +
+ ) +} diff --git a/lib/mutations.ts b/lib/mutations.ts index a246b84..cf42bf5 100644 --- a/lib/mutations.ts +++ b/lib/mutations.ts @@ -192,5 +192,29 @@ export const mutations = { }); }, + async createEventLocation(data: { + name: string, + address: string, + city: string, + state: string, + postalCode: string, + country: string, + phone?: string, + email?: string, + }) { + return await prisma.location.create({ + data: { + name: data.name, + address: data.address, + city: data.city, + state: data.state, + postalCode: data.postalCode, + country: data.country || 'United States', + phone: data.phone, + email: data.email + } + }) + } + }; \ No newline at end of file diff --git a/lib/queries.ts b/lib/queries.ts index 5a852c4..d25c318 100644 --- a/lib/queries.ts +++ b/lib/queries.ts @@ -133,6 +133,10 @@ export const queries = { return await prisma.user.findUnique({ where: { id }, }) - } + }, + + async fetchAllLocations() { + return await prisma.location.findMany() + }, } \ No newline at end of file