Skip to content

Commit

Permalink
Merge pull request #105 from codersforcauses/issue-100-View_and_Delet…
Browse files Browse the repository at this point in the history
…e_Functionality_All_Table_List

Issue 100 view and delete functionality all table list
  • Loading branch information
loklokyx authored Jan 31, 2025
2 parents 95581ca + ee882f5 commit ea922de
Show file tree
Hide file tree
Showing 32 changed files with 1,004 additions and 290 deletions.
75 changes: 75 additions & 0 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@hookform/resolvers": "^3.9.1",
"@radix-ui/react-checkbox": "^1.1.3",
"@radix-ui/react-collapsible": "^1.1.2",
"@radix-ui/react-dialog": "^1.1.4",
"@radix-ui/react-label": "^2.1.0",
Expand Down
29 changes: 22 additions & 7 deletions client/src/components/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,28 @@ export default function Sidebar({ children, role }: LayoutProps) {
const pathSegments = router.pathname.split("/").filter(Boolean);

const breadcrumbItems = pathSegments.map((segment, index) => {
const formattedSegment = segment
.replace(/_/g, " ") // replace underscores with spaces
.replace(/\b\w/g, (char) => char.toUpperCase()); // capitalize first letter
return {
title: formattedSegment,
url: `/${pathSegments.slice(0, index + 1).join("/")}`,
};
// handle dynamic segments
const isDynamic = /^\[.*\]$/.test(segment);
const actualSegment = isDynamic
? router.query[segment.slice(1, -1)] || segment.slice(1, -1)
: segment;

const title = actualSegment
.toString()
.replace(/_/g, " ")
.replace(/\b\w/g, (letter) => letter.toUpperCase());

const url =
"/" +
pathSegments
.slice(0, index + 1)
.map((seg) => {
const isParam = /^\[.*\]$/.test(seg);
return isParam ? router.query[seg.slice(1, -1)] || seg : seg;
})
.join("/");

return { title, url };
});

return (
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/ui/Users/data-grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export function DataGrid({
<TableCell className="w-1/4">{item.id}</TableCell>
<TableCell className="w-1/4">{item.username}</TableCell>
<TableCell className="w-1/4">{item.role}</TableCell>
<TableCell className="w-1/4">{item.school}</TableCell>
<TableCell className="w-1/4">{item.school?.name}</TableCell>
<TableCell className="flex py-4">
<div className={cn("flex", { invisible: !item.username })}>
<Button className="me-2">View</Button>
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/ui/Users/login-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,10 @@ export function LoginModal({ children }: LoginFormProps) {
</span>
</div>
</FormControl>
<FormDescription className="text-xs">
{/* <FormDescription className="text-xs">
It must be a combination of minimum 8 letters, numbers,
and symbols
</FormDescription>
</FormDescription> */}
<FormMessage />
</div>
</FormItem>
Expand Down
34 changes: 32 additions & 2 deletions client/src/components/ui/Users/school-data-grid.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { useRouter } from "next/router";
import React, { useEffect, useState } from "react";
import { toast } from "sonner";

import { Button } from "@/components/ui/button";
import { Pagination } from "@/components/ui/pagination";
Expand All @@ -10,6 +12,7 @@ import {
TableHeader,
TableRow,
} from "@/components/ui/table";
import { useDynamicDeleteMutation } from "@/hooks/use-delete-data";
import { cn } from "@/lib/utils";
import { DatagridProps } from "@/types/data-grid";
import { School } from "@/types/user";
Expand All @@ -29,11 +32,28 @@ export function SchoolDataGrid({
onDataChange,
changePage,
}: DatagridProps<School>) {
const router = useRouter();
const [currentPage, setCurrentPage] = useState(1);
const [paddedData, setPaddedData] = useState<School[]>([]);
const itemsPerPage = 5;
const totalPages = Math.ceil(datacontext.length / itemsPerPage);

const { mutate: deleteSchool, isPending } = useDynamicDeleteMutation({
baseUrl: "/users/schools",
mutationKey: ["school_delete"],
onSuccess: () => {
router.reload();
toast.success("School has been deleted.");
},
});

const onDelete = (id: number) => {
if (!window.confirm("Are you sure you want to delete this school?")) {
return;
}
deleteSchool(id);
};

const handlePageChange = (page: number) => {
if (page >= 1 && page <= totalPages) {
setCurrentPage(page);
Expand Down Expand Up @@ -97,8 +117,18 @@ export function SchoolDataGrid({
</TableCell>
<TableCell className="flex py-4">
<div className={cn("flex", { invisible: !item.id })}>
<Button className="me-2">View</Button>
<Button variant={"destructive"}>Delete</Button>
<Button
className="me-2"
onClick={() => router.push(`/users/school/${item.id}`)}
>
View
</Button>
<Button
variant={"destructive"}
onClick={() => onDelete(item.id)}
>
{isPending ? "Deleting..." : "Delete"}
</Button>
</div>
</TableCell>
</TableRow>
Expand Down
90 changes: 88 additions & 2 deletions client/src/components/ui/Users/school-data-table-form.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { useRouter } from "next/router";
import { useFieldArray, useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";

import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
Expand All @@ -19,6 +23,8 @@ import {
TableHeader,
TableRow,
} from "@/components/ui/table";
import { SelectSchoolType } from "@/components/ui/Users/select-school";
import { usePostMutation } from "@/hooks/use-post-data";
import { cn } from "@/lib/utils";
import { createSchoolSchema } from "@/types/user";

Expand All @@ -38,6 +44,8 @@ type School = z.infer<typeof createSchoolSchema>;
export function SchoolDataTableForm() {
const defaultSchool = {
name: "",
is_country: true,
abbreviation: "",
} as School;

const createSchoolForm = useForm<{
Expand All @@ -52,8 +60,21 @@ export function SchoolDataTableForm() {
name: "schools",
});

const router = useRouter();
const { mutate: createSchool, isPending } = usePostMutation<School[]>(
["schools"],
"/users/schools/",
1000,
{
onSuccess: () => {
toast.success("Schools created successfully!");
router.push("/users/school/");
},
},
);

const onSubmit = (data: { schools: School[] }) => {
console.log("Submitted data:", data.schools);
createSchool({ ...data.schools });
};

const commonTableHeadClasses = "w-auto text-white text-nowrap";
Expand All @@ -74,6 +95,15 @@ export function SchoolDataTableForm() {
No.
</TableHead>
<TableHead className={commonTableHeadClasses}>Name*</TableHead>
<TableHead className={commonTableHeadClasses}>Type*</TableHead>
<TableHead
className={cn(commonTableHeadClasses, "text-center")}
>
Is Country
</TableHead>
<TableHead className={commonTableHeadClasses}>
Abbreviation*
</TableHead>
<TableHead
className={cn(commonTableHeadClasses, "rounded-tr-lg", "w-0")}
></TableHead>
Expand Down Expand Up @@ -102,6 +132,60 @@ export function SchoolDataTableForm() {
)}
/>
</TableCell>
<TableCell className="align-top">
<FormField
control={createSchoolForm.control}
name={`schools.${index}.type`}
render={({ field }) => (
<FormItem className="flex flex-col justify-between gap-1.5 space-y-0">
<FormControl>
<SelectSchoolType
selectedType={field.value}
onChange={field.onChange}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</TableCell>
<TableCell className="px-0 pt-6 align-top">
<FormField
control={createSchoolForm.control}
name={`schools.${index}.is_country`}
render={({ field }) => (
<FormItem>
<div className="flex justify-center space-x-2">
<FormControl>
<Checkbox
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
<FormLabel>{field.value ? "Yes" : "No"}</FormLabel>
</div>
<FormMessage />
</FormItem>
)}
/>
</TableCell>
<TableCell className="align-top">
<FormField
control={createSchoolForm.control}
name={`schools.${index}.abbreviation`}
render={({ field }) => (
<FormItem className="flex flex-col justify-between gap-1.5 space-y-0">
<FormControl>
<Input
{...field}
placeholder="Enter Abbreviation"
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</TableCell>
<TableCell className="w-24 text-right align-top">
<Button
type="button"
Expand All @@ -123,7 +207,9 @@ export function SchoolDataTableForm() {
>
Add Row
</Button>
<Button type="submit">Submit</Button>
<Button type="submit" disabled={isPending}>
Submit
</Button>
</div>
</form>
</Form>
Expand Down
Loading

0 comments on commit ea922de

Please sign in to comment.