Skip to content

Commit

Permalink
feat: payments route
Browse files Browse the repository at this point in the history
  • Loading branch information
anishshobithps committed May 2, 2024
1 parent 73ca97d commit 04b7b71
Show file tree
Hide file tree
Showing 10 changed files with 386 additions and 70 deletions.
31 changes: 17 additions & 14 deletions src/app/(content)/terms/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<Container className="mx-auto">
<div className="py-4 mx-6 sm:mx-12 space-y-4 pt-32 text-white">
<Text variant="h1" className={cn("text-5xl", tiaraFont)}>Terms & Conditions</Text>
{legalInfo.terms.map((terms, index) => (
<div key={index}>
<Text variant="h2" className={cn("text-2xl", tiaraFont)}>{terms.title}</Text>
<p dangerouslySetInnerHTML={{ __html: terms.description }}></p>
</div>
))}
</div>
</Container>
);
return (
<Container className="mx-auto">
<div className="py-4 mx-6 sm:mx-12 space-y-4 pt-32 text-white">
<Text variant="h1" className={cn("text-5xl", tiaraFont)}>
Terms & Conditions
</Text>
{legalInfo.terms.map((terms, index) => (
<div key={index}>
<Text variant="h2" className={cn("text-2xl", tiaraFont)}>
{terms.title}
</Text>
<p dangerouslySetInnerHTML={{ __html: terms.description }}></p>
</div>
))}
</div>
</Container>
);
}
96 changes: 96 additions & 0 deletions src/app/admin/_components/columnsPayments.tsx
Original file line number Diff line number Diff line change
@@ -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<Payment>[] = [
{
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Name
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
},
accessorKey: "user.name",
},
{
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Email
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
},
accessorKey: "user.email",
},
{
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Events
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
},
accessorKey: "user.events",
cell: ({ row }) => {
// @ts-ignore
return row.original.user.events.map((event, i) => <div key={i}>{event}</div>);
},
},
{
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
College
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
},
accessorKey: "user.college",
},
{
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Status
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
},
accessorKey: "status",
},
{
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Order ID
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
},
accessorKey: "orderCreationId",
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -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<User & { payment: Payment }>[] = [
export const columns: ColumnDef<User>[] = [
{
header: ({ column }) => {
return (
Expand Down
186 changes: 186 additions & 0 deletions src/app/admin/_components/datatablepayments.tsx
Original file line number Diff line number Diff line change
@@ -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<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
data: TData[];
}

export function DataTable<TData, TValue>({
columns,
data,
}: DataTableProps<TData, TValue>) {
const [sorting, setSorting] = React.useState<SortingState>([]);
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
);
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({});

const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
onSortingChange: setSorting,
getSortedRowModel: getSortedRowModel(),
onColumnFiltersChange: setColumnFilters,
getFilteredRowModel: getFilteredRowModel(),
onColumnVisibilityChange: setColumnVisibility,
state: {
sorting,
columnFilters,
columnVisibility,
},
});

return (
<>
<div className="flex items-center gap-2">
<Input
placeholder="Filter names..."
value={
(table.getColumn("user_name")?.getFilterValue() as string) ?? ""
}
onChange={(event) =>
table.getColumn("user_name")?.setFilterValue(event.target.value)
}
className="max-w-sm"
/>
<Input
placeholder="Filter emails..."
value={
(table.getColumn("user_email")?.getFilterValue() as string) ?? ""
}
onChange={(event) =>
table.getColumn("user_email")?.setFilterValue(event.target.value)
}
className="max-w-sm"
/>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" className="ml-auto">
Columns
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
{table
.getAllColumns()
.filter((column) => column.getCanHide())
.map((column) => {
return (
<DropdownMenuCheckboxItem
key={column.id}
className="capitalize"
checked={column.getIsVisible()}
onCheckedChange={(value) =>
column.toggleVisibility(!!value)
}
>
{column.id}
</DropdownMenuCheckboxItem>
);
})}
</DropdownMenuContent>
</DropdownMenu>
</div>
<div className="rounded-md border">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
);
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
<div className="flex items-center justify-end space-x-2 py-4">
<Button
variant="outline"
size="sm"
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
>
Previous
</Button>
<Button
variant="outline"
size="sm"
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
>
Next
</Button>
</div>
</>
);
}
17 changes: 6 additions & 11 deletions src/app/admin/layout.tsx
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -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"
>
<Home className="h-4 w-4" />
Dashboard
<Users className="h-4 w-4" />
Users
</Link>
<Link
href="/admin/users"
href="/admin/payments"
className="flex items-center gap-3 rounded-lg px-3 py-2 text-muted-foreground transition-all hover:text-primary"
>
<Users className="h-4 w-4" />
Users
<CreditCard className="h-4 w-4" />
Payments
</Link>
</nav>
</div>
Expand Down
29 changes: 26 additions & 3 deletions src/app/admin/page.tsx
Original file line number Diff line number Diff line change
@@ -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 <div>DashboardPage</div>;
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 <div>Unauthorized</div>;
}

if (session.user.role !== UserRole.ADMIN) {
return <div>Forbidden</div>;
}
return <DataTable columns={columns} data={data} />;
}
Loading

0 comments on commit 04b7b71

Please sign in to comment.