diff --git a/src/app/(content)/terms/page.tsx b/src/app/(content)/terms/page.tsx index 3699924..709bbe9 100644 --- a/src/app/(content)/terms/page.tsx +++ b/src/app/(content)/terms/page.tsx @@ -6,18 +6,21 @@ import { cn } from "@/lib/utils"; import { legalInfo } from "../../../data/legal_Info"; import { Text } from "@/components/shared/text"; export default function Terms() { - - return ( - -
- Terms & Conditions - {legalInfo.terms.map((terms, index) => ( -
- {terms.title} -

-
- ))} -
-
- ); + return ( + +
+ + Terms & Conditions + + {legalInfo.terms.map((terms, index) => ( +
+ + {terms.title} + +

+
+ ))} +
+
+ ); } diff --git a/src/app/admin/_components/columnsPayments.tsx b/src/app/admin/_components/columnsPayments.tsx new file mode 100644 index 0000000..88e37da --- /dev/null +++ b/src/app/admin/_components/columnsPayments.tsx @@ -0,0 +1,96 @@ +"use client"; +import { ColumnDef } from "@tanstack/react-table"; +import { Payment } from "@prisma/client"; +import { ArrowUpDown } from "lucide-react"; +import { Button } from "@/components/ui/button"; + +export const columns: ColumnDef[] = [ + { + header: ({ column }) => { + return ( + + ); + }, + accessorKey: "user.name", + }, + { + header: ({ column }) => { + return ( + + ); + }, + accessorKey: "user.email", + }, + { + header: ({ column }) => { + return ( + + ); + }, + accessorKey: "user.events", + cell: ({ row }) => { + // @ts-ignore + return row.original.user.events.map((event, i) =>
{event}
); + }, + }, + { + header: ({ column }) => { + return ( + + ); + }, + accessorKey: "user.college", + }, + { + header: ({ column }) => { + return ( + + ); + }, + accessorKey: "status", + }, + { + header: ({ column }) => { + return ( + + ); + }, + accessorKey: "orderCreationId", + }, +]; diff --git a/src/app/admin/_components/columns.tsx b/src/app/admin/_components/columnsUsers.tsx similarity index 88% rename from src/app/admin/_components/columns.tsx rename to src/app/admin/_components/columnsUsers.tsx index cb367f8..731f044 100644 --- a/src/app/admin/_components/columns.tsx +++ b/src/app/admin/_components/columnsUsers.tsx @@ -4,8 +4,7 @@ import { User, Payment } from "@prisma/client"; import { ArrowUpDown } from "lucide-react"; import { Button } from "@/components/ui/button"; -// We concat the User and Payment types to create a new type, as the same will be returned by the API, fetched from the database. -export const columns: ColumnDef[] = [ +export const columns: ColumnDef[] = [ { header: ({ column }) => { return ( diff --git a/src/app/admin/_components/datatablepayments.tsx b/src/app/admin/_components/datatablepayments.tsx new file mode 100644 index 0000000..0082a6f --- /dev/null +++ b/src/app/admin/_components/datatablepayments.tsx @@ -0,0 +1,186 @@ +"use client"; + +import * as React from "react"; +import { + ColumnDef, + ColumnFiltersState, + SortingState, + flexRender, + getCoreRowModel, + getFilteredRowModel, + getPaginationRowModel, + VisibilityState, + getSortedRowModel, + useReactTable, +} from "@tanstack/react-table"; + +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { + DropdownMenu, + DropdownMenuCheckboxItem, + DropdownMenuContent, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +interface DataTableProps { + columns: ColumnDef[]; + data: TData[]; +} + +export function DataTable({ + columns, + data, +}: DataTableProps) { + const [sorting, setSorting] = React.useState([]); + const [columnFilters, setColumnFilters] = React.useState( + [] + ); + const [columnVisibility, setColumnVisibility] = + React.useState({}); + + const table = useReactTable({ + data, + columns, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + onSortingChange: setSorting, + getSortedRowModel: getSortedRowModel(), + onColumnFiltersChange: setColumnFilters, + getFilteredRowModel: getFilteredRowModel(), + onColumnVisibilityChange: setColumnVisibility, + state: { + sorting, + columnFilters, + columnVisibility, + }, + }); + + return ( + <> +
+ + table.getColumn("user_name")?.setFilterValue(event.target.value) + } + className="max-w-sm" + /> + + table.getColumn("user_email")?.setFilterValue(event.target.value) + } + className="max-w-sm" + /> + + + + + + {table + .getAllColumns() + .filter((column) => column.getCanHide()) + .map((column) => { + return ( + + column.toggleVisibility(!!value) + } + > + {column.id} + + ); + })} + + +
+
+ + + {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. + + + )} + +
+
+
+ + +
+ + ); +} diff --git a/src/app/admin/layout.tsx b/src/app/admin/layout.tsx index e80218f..16f22b6 100644 --- a/src/app/admin/layout.tsx +++ b/src/app/admin/layout.tsx @@ -1,12 +1,7 @@ "use client"; import Link from "next/link"; -import { - CircleUser, - Home, - Menu, - Users, -} from "lucide-react"; +import { CircleUser, Home, Menu, Users, CreditCard } from "lucide-react"; import { Button } from "@/components/ui/button"; import { @@ -42,15 +37,15 @@ export default function AdminDashboard({ href="/admin" className="flex items-center gap-3 rounded-lg px-3 py-2 text-muted-foreground transition-all hover:text-primary" > - - Dashboard + + Users - - Users + + Payments diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index 5cbaf7f..6fecb64 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -1,7 +1,30 @@ +"use client"; + import React from "react"; +import { Payment, User, UserRole } from "@prisma/client"; +import { DataTable } from "./_components/datatable"; +import { columns } from "./_components/columnsUsers"; +import { useSession } from "next-auth/react"; -function DashboardPage() { - return
DashboardPage
; +async function getData() { + const response = await fetch("/api/admin"); + return response.json(); } -export default DashboardPage; +export default function AdminPage() { + const { data: session } = useSession(); + const [data, setData] = React.useState<(User & { payment: Payment })[]>([]); + + React.useEffect(() => { + getData().then(setData); + }, []); + + if (!session) { + return
Unauthorized
; + } + + if (session.user.role !== UserRole.ADMIN) { + return
Forbidden
; + } + return ; +} diff --git a/src/app/admin/payments/page.tsx b/src/app/admin/payments/page.tsx new file mode 100644 index 0000000..84bbca3 --- /dev/null +++ b/src/app/admin/payments/page.tsx @@ -0,0 +1,36 @@ +"use client"; + +import React from "react"; +import { Payment, UserRole } from "@prisma/client"; +import { DataTable } from "../_components/datatablepayments"; +import { columns } from "../_components/columnsPayments"; +import { useSession } from "next-auth/react"; + +async function getData() { + const response = await fetch("/api/admin/payments"); + return response.json(); +} + +export default function AdminPage() { + const { data: session } = useSession(); + const [data, setData] = React.useState([]); + + React.useEffect(() => { + getData().then(setData); + }, []); + + if (!session) { + return
Unauthorized
; + } + + if (session.user.role !== UserRole.ADMIN) { + return
Forbidden
; + } + + return ( + <> +

Please note few inital payments, do not exists due to some issue with the database write.

+ + + ); +} diff --git a/src/app/admin/users/page.tsx b/src/app/admin/users/page.tsx deleted file mode 100644 index 3c03f4b..0000000 --- a/src/app/admin/users/page.tsx +++ /dev/null @@ -1,30 +0,0 @@ -"use client"; - -import React from "react"; -import { Payment, User, UserRole } from "@prisma/client"; -import { DataTable } from "../_components/datatable"; -import { columns } from "../_components/columns"; -import { useSession } from "next-auth/react"; - -async function getData() { - const response = await fetch("/api/users"); - return response.json(); -} - -export default function AdminPage() { - const { data: session } = useSession(); - const [data, setData] = React.useState<(User & { payment: Payment })[]>([]); - - React.useEffect(() => { - getData().then(setData); - }, []); - - if (!session) { - return
Unauthorized
; - } - - if (session.user.role !== UserRole.ADMIN) { - return
Forbidden
; - } - return ; -} diff --git a/src/app/api/users/route.ts b/src/app/api/admin/payments/route.ts similarity index 81% rename from src/app/api/users/route.ts rename to src/app/api/admin/payments/route.ts index f32a994..2bf4aab 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/admin/payments/route.ts @@ -17,10 +17,10 @@ export async function GET() { return NextResponse.json({ error: "Unauthorized" }, { status: 403 }); } - const users = await prisma.user.findMany({ + const payments = await prisma.payment.findMany({ include: { - payment: true, - }, + user: true, + } }); - return NextResponse.json(users); + return NextResponse.json(payments); } diff --git a/src/app/api/admin/route.ts b/src/app/api/admin/route.ts index 2cb17a5..f32a994 100644 --- a/src/app/api/admin/route.ts +++ b/src/app/api/admin/route.ts @@ -1,18 +1,26 @@ import { auth } from "@/auth"; -import { prisma } from "@/lib/prisma"; +import { NextRequest, NextResponse } from "next/server"; import { UserRole } from "@prisma/client"; -import { NextResponse } from "next/server"; +import { prisma } from "@/lib/prisma"; export async function GET() { const session = await auth(); + if (!session) { - return NextResponse.json({ message: "Unauthorized" }, { status: 401 }); + return NextResponse.json( + { message: "Unauthorized", isOk: false }, + { status: 401 } + ); } if (session.user.role !== UserRole.ADMIN) { return NextResponse.json({ error: "Unauthorized" }, { status: 403 }); } - const users = await prisma.user.count(); - const payments = await prisma.payment.count(); - return NextResponse.json({ users, payments }); + + const users = await prisma.user.findMany({ + include: { + payment: true, + }, + }); + return NextResponse.json(users); }