-
Notifications
You must be signed in to change notification settings - Fork 0
Table Backend Integration #98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 5 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
148b818
student table backend integration
calebyhan cb312c4
mockclient fix and etc
calebyhan e31061d
client side sort and delete dialog fix
calebyhan 19dade3
extended table backend integration
calebyhan b8d7fe6
Merge branch 'main' into calebyhan/table-backend-integration
calebyhan 7e2468e
fixed type difference in location service
calebyhan c079772
party type difference
calebyhan 85cb4a7
accounts table default filter and table template remove actions header
calebyhan 2427444
optimistic loading
calebyhan b0ae0ae
Merge branch 'main' of https://github.com/cssgunc/party-registration …
naasanov 274e7ca
fix: service merge fixes
naasanov 376ae1d
side bar refactor, info chips, etc
naasanov 4ba2eea
Merge branch 'main' of https://github.com/cssgunc/party-registration …
naasanov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| "use client"; | ||
|
|
||
| import { AccountTable } from "@/components/AccountTable"; | ||
|
|
||
| export default function AccountDemoPage() { | ||
| return ( | ||
| <div className="container mx-auto p-6"> | ||
| <AccountTable /> | ||
| </div> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -25,8 +25,6 @@ const authOptions: NextAuthOptions = { | |||||||||
| id: "1", | ||||||||||
| name: "Admin User", | ||||||||||
| email: "[email protected]", | ||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reverting back to what it is in main
Suggested change
|
||||||||||
| accessToken: "fake-access-token-for-dev", | ||||||||||
| refreshToken: "fake-refresh-token-for-dev", | ||||||||||
| }; | ||||||||||
| } | ||||||||||
| return null; | ||||||||||
|
|
@@ -96,4 +94,4 @@ const authOptions: NextAuthOptions = { | |||||||||
|
|
||||||||||
| const handler = NextAuth(authOptions); | ||||||||||
|
|
||||||||||
| export { handler as GET, handler as POST, authOptions }; | ||||||||||
| export { authOptions, handler as GET, handler as POST }; | ||||||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| "use client"; | ||
|
|
||
| import { LocationTable } from "@/components/LocationTable"; | ||
|
|
||
| export default function LocationDemoPage() { | ||
| return ( | ||
| <div className="container mx-auto p-6"> | ||
| <LocationTable /> | ||
| </div> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| "use client"; | ||
|
|
||
| import { PartyTable } from "@/components/PartyTable"; | ||
|
|
||
| export default function PartyDemoPage() { | ||
| return ( | ||
| <div className="container mx-auto p-6"> | ||
| <PartyTable /> | ||
| </div> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| "use client"; | ||
|
|
||
| import { StudentTable } from "@/components/StudentTable"; | ||
|
|
||
| export default function StudentDemoPage() { | ||
| return ( | ||
| <div className="container mx-auto p-6"> | ||
| <StudentTable /> | ||
| </div> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,181 @@ | ||
| "use client"; | ||
|
|
||
| import { Button } from "@/components/ui/button"; | ||
| import { AccountService } from "@/services/accountService"; | ||
| import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; | ||
| import { ColumnDef } from "@tanstack/react-table"; | ||
| import { useState } from "react"; | ||
| import * as z from "zod"; | ||
| import AccountTableCreateEditForm, { | ||
| AccountCreateEditValues as AccountCreateEditSchema, | ||
| } from "./AccountTableCreateEdit"; | ||
| import { TableTemplate } from "./TableTemplate"; | ||
|
|
||
| import type { Account, AccountRole } from "@/services/accountService"; | ||
|
|
||
| type AccountCreateEditValues = z.infer<typeof AccountCreateEditSchema>; | ||
|
|
||
| const accountService = new AccountService(); | ||
|
|
||
| export const AccountTable = () => { | ||
| const queryClient = useQueryClient(); | ||
| const [sidebarOpen, setSidebarOpen] = useState(false); | ||
| const [sidebarMode, setSidebarMode] = useState<"create" | "edit">("create"); | ||
| const [editingAccount, setEditingAccount] = useState<Account | null>(null); | ||
|
|
||
| const accountsQuery = useQuery({ | ||
| queryKey: ["accounts"], | ||
| queryFn: () => accountService.listAccounts(), | ||
| retry: 1, | ||
| }); | ||
|
|
||
| const accounts = (accountsQuery.data ?? []).slice().sort((a, b) => | ||
| a.last_name.localeCompare(b.last_name) || | ||
| a.first_name.localeCompare(b.first_name) | ||
| ); | ||
|
|
||
| const createMutation = useMutation({ | ||
| mutationFn: (data: AccountCreateEditValues) => | ||
| accountService.createAccount({ | ||
| email: data.email, | ||
| first_name: data.firstName, | ||
| last_name: data.lastName, | ||
| pid: data.pid, | ||
| role: data.role as AccountRole, | ||
| }), | ||
| onSuccess: () => { | ||
| queryClient.invalidateQueries({ queryKey: ["accounts"] }); | ||
| setSidebarOpen(false); | ||
| setEditingAccount(null); | ||
| }, | ||
| onError: (error: Error) => { | ||
| console.error("Failed to create account:", error); | ||
| }, | ||
| }); | ||
|
|
||
| const updateMutation = useMutation({ | ||
| mutationFn: ({ id, data }: { id: number; data: AccountCreateEditValues }) => | ||
| accountService.updateAccount(id, { | ||
| email: data.email, | ||
| first_name: data.firstName, | ||
| last_name: data.lastName, | ||
| pid: data.pid, | ||
| role: data.role as AccountRole, | ||
| }), | ||
| onSuccess: () => { | ||
| queryClient.invalidateQueries({ queryKey: ["accounts"] }); | ||
| setSidebarOpen(false); | ||
| setEditingAccount(null); | ||
| }, | ||
| onError: (error: Error) => { | ||
| console.error("Failed to update account:", error); | ||
| }, | ||
| }); | ||
|
|
||
| const deleteMutation = useMutation({ | ||
| mutationFn: (id: number) => accountService.deleteAccount(id), | ||
| onSuccess: () => { | ||
| queryClient.invalidateQueries({ queryKey: ["accounts"] }); | ||
| }, | ||
| onError: (error: Error) => { | ||
| console.error("Failed to delete account:", error); | ||
| }, | ||
| }); | ||
|
|
||
| const handleEdit = (account: Account) => { | ||
| setEditingAccount(account); | ||
| setSidebarMode("edit"); | ||
| setSidebarOpen(true); | ||
| }; | ||
|
|
||
| const handleDelete = (account: Account) => { | ||
| deleteMutation.mutate(account.id); | ||
| }; | ||
|
|
||
| const handleCreate = () => { | ||
| setEditingAccount(null); | ||
| setSidebarMode("create"); | ||
| setSidebarOpen(true); | ||
| }; | ||
|
|
||
| const handleFormSubmit = async (data: AccountCreateEditValues) => { | ||
| if (sidebarMode === "edit" && editingAccount) { | ||
| updateMutation.mutate({ id: editingAccount.id, data }); | ||
| } else if (sidebarMode === "create") { | ||
| createMutation.mutate(data); | ||
| } | ||
| }; | ||
|
|
||
| const columns: ColumnDef<Account>[] = [ | ||
| { | ||
| accessorKey: "email", | ||
| header: "Email", | ||
| enableColumnFilter: true, | ||
| }, | ||
| { | ||
| accessorKey: "first_name", | ||
| header: "First Name", | ||
| enableColumnFilter: true, | ||
| }, | ||
| { | ||
| accessorKey: "last_name", | ||
| header: "Last Name", | ||
| enableColumnFilter: true, | ||
| }, | ||
| { | ||
| accessorKey: "role", | ||
| header: "Admin Type", | ||
| enableColumnFilter: true, | ||
| }, | ||
| ]; | ||
|
|
||
| return ( | ||
| <div className="space-y-4"> | ||
| <TableTemplate | ||
| data={accounts} | ||
| columns={columns} | ||
| resourceName="Account" | ||
| onEdit={handleEdit} | ||
| onDelete={handleDelete} | ||
| onCreateNew={handleCreate} | ||
| isLoading={accountsQuery.isLoading} | ||
| error={accountsQuery.error as Error | null} | ||
| getDeleteDescription={(account: Account) => | ||
| `Are you sure you want to delete account ${account.email}? This action cannot be undone.` | ||
| } | ||
| isDeleting={deleteMutation.isPending} | ||
| /> | ||
|
|
||
| {sidebarOpen && ( | ||
| <div className="fixed right-0 top-0 h-full w-96 bg-white shadow-lg p-6 overflow-y-auto z-50"> | ||
| <div className="flex justify-between items-center mb-4"> | ||
| <h3 className="text-lg font-semibold"> | ||
| {sidebarMode === "create" ? "New Account" : "Edit Account"} | ||
| </h3> | ||
| <Button | ||
| variant="ghost" | ||
| size="sm" | ||
| onClick={() => setSidebarOpen(false)} | ||
| > | ||
| Close | ||
| </Button> | ||
| </div> | ||
| <AccountTableCreateEditForm | ||
| onSubmit={handleFormSubmit} | ||
| editData={ | ||
| editingAccount | ||
| ? { | ||
| email: editingAccount.email, | ||
| firstName: editingAccount.first_name, | ||
| lastName: editingAccount.last_name, | ||
| role: editingAccount.role, | ||
| pid: editingAccount.pid ?? "", | ||
| } | ||
| : undefined | ||
| } | ||
| /> | ||
| </div> | ||
| )} | ||
| </div> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| "use client"; | ||
|
|
||
| import { Button } from "@/components/ui/button"; | ||
| import { | ||
| Dialog, | ||
| DialogContent, | ||
| DialogDescription, | ||
| DialogFooter, | ||
| DialogHeader, | ||
| DialogTitle, | ||
| } from "@/components/ui/dialog"; | ||
|
|
||
| interface DeleteConfirmDialogProps { | ||
| open: boolean; | ||
| onOpenChange: (open: boolean) => void; | ||
| onConfirm: () => void; | ||
| title?: string; | ||
| description?: string; | ||
| isDeleting?: boolean; | ||
| } | ||
|
|
||
| export function DeleteConfirmDialog({ | ||
| open, | ||
| onOpenChange, | ||
| onConfirm, | ||
| title = "Delete Item", | ||
| description = "Are you sure you want to delete this item? This action cannot be undone.", | ||
| isDeleting = false, | ||
| }: DeleteConfirmDialogProps) { | ||
| const handleConfirm = () => { | ||
| onConfirm(); | ||
| onOpenChange(false); | ||
| }; | ||
|
|
||
| return ( | ||
| <Dialog open={open} onOpenChange={onOpenChange}> | ||
| <DialogContent> | ||
| <DialogHeader> | ||
| <DialogTitle>{title}</DialogTitle> | ||
| <DialogDescription>{description}</DialogDescription> | ||
| </DialogHeader> | ||
| <DialogFooter> | ||
| <Button | ||
| variant="outline" | ||
| onClick={() => onOpenChange(false)} | ||
| disabled={isDeleting} | ||
| > | ||
| Cancel | ||
| </Button> | ||
| <Button | ||
| variant="destructive" | ||
| onClick={handleConfirm} | ||
| disabled={isDeleting} | ||
| > | ||
| {isDeleting ? "Deleting..." : "Delete"} | ||
| </Button> | ||
| </DialogFooter> | ||
| </DialogContent> | ||
| </Dialog> | ||
| ); | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.