Skip to content

Commit

Permalink
feat(data-grid): enhance table ID with index, improve loading state, …
Browse files Browse the repository at this point in the history
…add success callbacks, and clean up code

- Added "No." index to table rows for better identification
- Implemented loading state for table rows only (not the entire page)
- Added on delete success callback for better feedback handling
- Introduced `toQueryString` utility to streamline query string generation
- Fixed bug in categories fetch function
- Set default value for school select input
- Fixed pagination route path issue in `setAndPush` method
  • Loading branch information
loklokyx committed Feb 23, 2025
1 parent 1273309 commit 98d5486
Show file tree
Hide file tree
Showing 31 changed files with 324 additions and 268 deletions.
21 changes: 15 additions & 6 deletions client/src/components/ui/Question/category-data-grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as React from "react";
import { Button } from "@/components/ui/button";
import DeleteModal from "@/components/ui/delete-modal";
import { SortIcon } from "@/components/ui/icon";
import { WaitingLoader } from "@/components/ui/loading";
import {
Table,
TableBody,
Expand All @@ -19,7 +20,10 @@ import { Category } from "@/types/question";

export function CategoryDataGrid({
datacontext,
isLoading,
startIdx,
onOrderingChange = () => {},
onDeleteSuccess,
}: DatagridProps<Category>) {
const router = useRouter();

Expand All @@ -30,9 +34,7 @@ export function CategoryDataGrid({
<Table className="w-full border-collapse text-left shadow-md">
<TableHeader className="bg-black text-lg font-semibold">
<TableRow className="hover:bg-muted/0">
<TableHead className={commonTableHeadClasses}>
Category Id
</TableHead>
<TableHead className={commonTableHeadClasses}>No.</TableHead>
<TableHead
className={commonTableHeadClasses}
onClick={() => onOrderingChange("genre")}
Expand All @@ -51,15 +53,17 @@ export function CategoryDataGrid({
</TableRow>
</TableHeader>
<TableBody>
{datacontext.length > 0 ? (
{!isLoading && datacontext.length > 0 ? (
datacontext.map((item, index) => (
<TableRow
key={item.id}
className={
"divide-gray-200 border-gray-50 text-sm text-black"
}
>
<TableCell className="w-0">{item.id}</TableCell>
<TableCell className="w-0">
{startIdx ? startIdx + index : item.id}
</TableCell>
<TableCell className="w-1/4">{item.genre}</TableCell>
<TableCell className="w-3/4 max-w-80 truncate">
{item.info}
Expand All @@ -73,6 +77,7 @@ export function CategoryDataGrid({
baseUrl="/questions/categories"
entity="category"
id={item.id}
onSuccess={onDeleteSuccess}
>
<Button variant={"destructive"}>Delete</Button>
</DeleteModal>
Expand All @@ -86,7 +91,11 @@ export function CategoryDataGrid({
colSpan={4}
className="py-4 text-center text-gray-500"
>
No Results Found
{isLoading ? (
<WaitingLoader className="p-0" />
) : (
"No Results Found"
)}
</TableCell>
</TableRow>
)}
Expand Down
19 changes: 15 additions & 4 deletions client/src/components/ui/Question/data-grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Button } from "@/components/ui/button";
import DateTimeDisplay from "@/components/ui/date-format";
import DeleteModal from "@/components/ui/delete-modal";
import { SortIcon } from "@/components/ui/icon";
import { WaitingLoader } from "@/components/ui/loading";
import {
Table,
TableBody,
Expand All @@ -25,6 +26,9 @@ import { Question } from "@/types/question";
*/
export function Datagrid({
datacontext,
isLoading,
startIdx,
onDeleteSuccess,
onOrderingChange = () => {},
}: DatagridProps<Question>) {
const router = useRouter();
Expand All @@ -36,7 +40,7 @@ export function Datagrid({
<Table className="w-full border-collapse text-left shadow-md">
<TableHeader className="bg-black text-lg font-semibold">
<TableRow className="hover:bg-muted/0">
<TableHead className={commonTableHeadClasses}>Id</TableHead>
<TableHead className={commonTableHeadClasses}>No.</TableHead>
<TableHead className={commonTableHeadClasses}>Name</TableHead>
<TableHead
className={commonTableHeadClasses}
Expand Down Expand Up @@ -67,15 +71,17 @@ export function Datagrid({
</TableRow>
</TableHeader>
<TableBody>
{datacontext.length > 0 ? (
{!isLoading && datacontext.length > 0 ? (
datacontext.map((item, index) => (
<TableRow
key={item.id}
className={
"divide-gray-200 border-gray-50 text-sm text-black"
}
>
<TableCell className="w-0">{item.id}</TableCell>
<TableCell className="w-0">
{startIdx ? startIdx + index : item.id}
</TableCell>
<TableCell className="w-1/2 max-w-80 truncate">
{item.name}
</TableCell>
Expand All @@ -96,6 +102,7 @@ export function Datagrid({
baseUrl="/questions/question-bank"
entity="question"
id={item.id}
onSuccess={onDeleteSuccess}
>
<Button variant={"destructive"}>Delete</Button>
</DeleteModal>
Expand All @@ -109,7 +116,11 @@ export function Datagrid({
colSpan={7}
className="py-4 text-center text-gray-500"
>
No Results Found
{isLoading ? (
<WaitingLoader className="p-0" />
) : (
"No Results Found"
)}
</TableCell>
</TableRow>
)}
Expand Down
22 changes: 11 additions & 11 deletions client/src/components/ui/Question/select-category.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import MultipleSelector, { Option } from "@/components/ui/multiple-select";
import { useFetchData } from "@/hooks/use-fetch-data";
import { useFetchDataTable } from "@/hooks/use-fetch-data";
import { cn } from "@/lib/utils";
import { Category } from "@/types/question";

Expand All @@ -10,21 +10,21 @@ type Props = {
};

export function MultipleSelectCategory({ value, onChange, className }: Props) {
const {
data: categories,
isPending,
isError,
} = useFetchData<Category[]>({
queryKey: ["questions.categories"],
const { data, isLoading, isError } = useFetchDataTable<Category>({
queryKey: ["questions.categories.all"],
endpoint: "/questions/categories/",
searchParams: {
nrows: 999999, // to get all with some large number
page: 1,
},
});

if (isPending || isError) return;
if (isLoading || isError) return;

const categoryOptions =
isPending || isError
isLoading || isError
? []
: categories?.map((cat) => ({
: data?.map((cat) => ({
label: cat.genre,
value: cat.id.toString(),
}));
Expand All @@ -37,7 +37,7 @@ export function MultipleSelectCategory({ value, onChange, className }: Props) {
defaultOptions={categoryOptions}
placeholder="Select categories..."
emptyIndicator="No categories found."
disabled={isPending || isError}
disabled={isLoading || isError}
/>
);
}
19 changes: 15 additions & 4 deletions client/src/components/ui/Test/competition-data-grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Button } from "@/components/ui/button";
import DateTimeDisplay from "@/components/ui/date-format";
import DeleteModal from "@/components/ui/delete-modal";
import { SortIcon } from "@/components/ui/icon";
import { WaitingLoader } from "@/components/ui/loading";
import {
Table,
TableBody,
Expand Down Expand Up @@ -52,6 +53,9 @@ import { AdminQuiz } from "@/types/quiz";
*/
export function CompetitionDataGrid({
datacontext,
isLoading,
startIdx,
onDeleteSuccess,
onOrderingChange = () => {},
}: DatagridProps<AdminQuiz>) {
const router = useRouter();
Expand Down Expand Up @@ -80,7 +84,7 @@ export function CompetitionDataGrid({
<Table className="w-full border-collapse text-left shadow-md">
<TableHeader className="bg-black text-lg font-semibold">
<TableRow className="hover:bg-muted/0">
<TableHead className={commonTableHeadClasses}>Id</TableHead>
<TableHead className={commonTableHeadClasses}>No.</TableHead>
<TableHead
className={commonTableHeadClasses}
onClick={() => onOrderingChange("name")}
Expand Down Expand Up @@ -111,15 +115,17 @@ export function CompetitionDataGrid({
</TableRow>
</TableHeader>
<TableBody>
{datacontext.length > 0 ? (
{!isLoading && datacontext.length > 0 ? (
datacontext.map((item, index) => (
<TableRow
key={item.id}
className={
"divide-gray-200 border-gray-50 text-sm text-black"
}
>
<TableCell className="w-0">{item.id}</TableCell>
<TableCell className="w-0">
{startIdx ? startIdx + index : item.id}
</TableCell>
<TableCell className="w-1/4">{item.name}</TableCell>
<TableCell className="w-1/2 max-w-80 truncate">
{item.intro}
Expand Down Expand Up @@ -156,6 +162,7 @@ export function CompetitionDataGrid({
baseUrl="/quiz/admin-quizzes"
entity="competition"
id={item.id}
onSuccess={onDeleteSuccess}
>
<Button variant={"destructive"}>Delete</Button>
</DeleteModal>
Expand All @@ -169,7 +176,11 @@ export function CompetitionDataGrid({
colSpan={8}
className="py-4 text-center text-gray-500"
>
No Results Found
{isLoading ? (
<WaitingLoader className="p-0" />
) : (
"No Results Found"
)}
</TableCell>
</TableRow>
)}
Expand Down
10 changes: 8 additions & 2 deletions client/src/components/ui/Test/insight-data-grid.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from "react";

import { WaitingLoader } from "@/components/ui/loading";
import {
Table,
TableBody,
Expand Down Expand Up @@ -44,6 +45,7 @@ import { Insight } from "@/types/leaderboard";
*/
export function InsightDataGrid({
datacontext,
isLoading,
onOrderingChange = () => {},
}: DatagridProps<Insight>) {
const commonTableHeadClasses = "w-auto text-white text-nowrap";
Expand Down Expand Up @@ -76,7 +78,7 @@ export function InsightDataGrid({
</TableRow>
</TableHeader>
<TableBody>
{datacontext.length > 0 ? (
{!isLoading && datacontext.length > 0 ? (
datacontext.map((item, index) => (
<TableRow
key={index}
Expand All @@ -98,7 +100,11 @@ export function InsightDataGrid({
colSpan={4}
className="py-4 text-center text-gray-500"
>
No Results Found
{isLoading ? (
<WaitingLoader className="p-0" />
) : (
"No Results Found"
)}
</TableCell>
</TableRow>
)}
Expand Down
10 changes: 8 additions & 2 deletions client/src/components/ui/Test/leaderboard-data-grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useRouter } from "next/router";
import * as React from "react";

import { Button } from "@/components/ui/button";
import { WaitingLoader } from "@/components/ui/loading";
import {
Table,
TableBody,
Expand Down Expand Up @@ -38,6 +39,7 @@ import { Leaderboard } from "@/types/leaderboard";
*/
export function LeaderboardDataGrid({
datacontext,
isLoading,
onOrderingChange = () => {},
}: DatagridProps<Leaderboard>) {
const router = useRouter();
Expand Down Expand Up @@ -71,7 +73,7 @@ export function LeaderboardDataGrid({
</TableRow>
</TableHeader>
<TableBody>
{datacontext.length > 0 ? (
{!isLoading && datacontext.length > 0 ? (
datacontext.map((item, index) => (
<TableRow
key={index}
Expand Down Expand Up @@ -104,7 +106,11 @@ export function LeaderboardDataGrid({
colSpan={4}
className="py-4 text-center text-gray-500"
>
No Results Found
{isLoading ? (
<WaitingLoader className="p-0" />
) : (
"No Results Found"
)}
</TableCell>
</TableRow>
)}
Expand Down
19 changes: 15 additions & 4 deletions client/src/components/ui/Test/practice-data-grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import DeleteModal from "@/components/ui/delete-modal";
import { SortIcon } from "@/components/ui/icon";
import { WaitingLoader } from "@/components/ui/loading";
import {
Table,
TableBody,
Expand Down Expand Up @@ -42,6 +43,9 @@ import { AdminQuiz } from "@/types/quiz";
*/
export function PracticeDataGrid({
datacontext,
isLoading,
startIdx,
onDeleteSuccess,
onOrderingChange = () => {},
}: DatagridProps<AdminQuiz>) {
const router = useRouter();
Expand Down Expand Up @@ -70,7 +74,7 @@ export function PracticeDataGrid({
<Table className="w-full border-collapse text-left shadow-md">
<TableHeader className="bg-black text-lg font-semibold">
<TableRow className="hover:bg-muted/0">
<TableHead className={commonTableHeadClasses}>Id</TableHead>
<TableHead className={commonTableHeadClasses}>No.</TableHead>
<TableHead
className={commonTableHeadClasses}
onClick={() => onOrderingChange("name")}
Expand All @@ -95,15 +99,17 @@ export function PracticeDataGrid({
</TableRow>
</TableHeader>
<TableBody>
{datacontext.length > 0 ? (
{!isLoading && datacontext.length > 0 ? (
datacontext.map((item, index) => (
<TableRow
key={item.id}
className={
"divide-gray-200 border-gray-50 text-sm text-black"
}
>
<TableCell className="w-0">{item.id}</TableCell>
<TableCell className="w-0">
{startIdx ? startIdx + index : item.id}
</TableCell>
<TableCell className="w-1/4">{item.name}</TableCell>
<TableCell className="w-1/2 max-w-80 truncate">
{item.intro}
Expand Down Expand Up @@ -136,6 +142,7 @@ export function PracticeDataGrid({
baseUrl="/quiz/admin-quizzes"
entity="practice"
id={item.id}
onSuccess={onDeleteSuccess}
>
<Button variant={"destructive"}>Delete</Button>
</DeleteModal>
Expand All @@ -149,7 +156,11 @@ export function PracticeDataGrid({
colSpan={6}
className="py-4 text-center text-gray-500"
>
No Results Found
{isLoading ? (
<WaitingLoader className="p-0" />
) : (
"No Results Found"
)}
</TableCell>
</TableRow>
)}
Expand Down
Loading

0 comments on commit 98d5486

Please sign in to comment.