|
7 | 7 | getCoreRowModel,
|
8 | 8 | getPaginationRowModel,
|
9 | 9 | PaginationState,
|
| 10 | + Row, |
10 | 11 | useReactTable,
|
11 | 12 | } from "@tanstack/react-table";
|
12 | 13 |
|
@@ -49,15 +50,114 @@ const Cell = ({
|
49 | 50 | return <div className={cn("text-center", className)}>{children}</div>;
|
50 | 51 | };
|
51 | 52 |
|
| 53 | +interface CellProps { |
| 54 | + row: Row<QuestionMinified>; |
| 55 | +} |
| 56 | + |
| 57 | +interface ActionCellProps { |
| 58 | + row: Row<QuestionMinified>; |
| 59 | + openModal(questionId: string): void; |
| 60 | + editingQuestionId: string | null; |
| 61 | + closeModal(): void; |
| 62 | + modalAnimation: { |
| 63 | + hidden: { |
| 64 | + opacity: number; |
| 65 | + scale: number; |
| 66 | + }; |
| 67 | + visible: { |
| 68 | + opacity: number; |
| 69 | + scale: number; |
| 70 | + }; |
| 71 | + exit: { |
| 72 | + opacity: number; |
| 73 | + scale: number; |
| 74 | + }; |
| 75 | + }; |
| 76 | + setRefreshKey: React.Dispatch<React.SetStateAction<number>>; |
| 77 | + handleDelete(questionId: string): void; |
| 78 | +} |
| 79 | + |
52 | 80 | interface LeetcodeDashboardTableProps {
|
53 | 81 | refreshKey: number;
|
54 | 82 | setRefreshKey: React.Dispatch<React.SetStateAction<number>>;
|
55 | 83 | }
|
56 | 84 |
|
| 85 | +const QuestionIdHeader = () => <Cell>ID</Cell>; |
| 86 | +const QuestionIdCell: React.FC<CellProps> = ({ row }) => ( |
| 87 | + <Cell className="capitalize">{row.getValue("questionid")}</Cell> |
| 88 | +); |
| 89 | + |
| 90 | +const TitleHeader = () => <Cell>Question Title</Cell>; |
| 91 | +const TitleCell: React.FC<CellProps> = ({ row }) => ( |
| 92 | + <Cell>{row.getValue("title")}</Cell> |
| 93 | +); |
| 94 | + |
| 95 | +const ComplexityHeader = () => <Cell>Difficulty</Cell>; |
| 96 | +const ComplexityCell: React.FC<CellProps> = ({ row }) => { |
| 97 | + return <Cell>{row.getValue("complexity")}</Cell>; |
| 98 | +}; |
| 99 | + |
| 100 | +const CategoryHeader = () => <Cell>Topics</Cell>; |
| 101 | +const CategoryCell: React.FC<CellProps> = ({ row }) => { |
| 102 | + const categoryValue = row.getValue("category"); |
| 103 | + const result: string = Array.isArray(categoryValue) |
| 104 | + ? categoryValue.join(", ") |
| 105 | + : String(categoryValue); |
| 106 | + return <Cell>{result}</Cell>; |
| 107 | +}; |
| 108 | + |
| 109 | +const ActionsHeader = () => <Cell>Actions</Cell>; |
| 110 | +const ActionsCell: React.FC<ActionCellProps> = ({ |
| 111 | + row, |
| 112 | + openModal, |
| 113 | + editingQuestionId, |
| 114 | + closeModal, |
| 115 | + modalAnimation, |
| 116 | + setRefreshKey, |
| 117 | + handleDelete, |
| 118 | +}) => { |
| 119 | + const questionId: string = row.getValue("questionid"); |
| 120 | + return ( |
| 121 | + <Cell> |
| 122 | + <Button onClick={() => openModal(questionId)} variant={"ghost"}> |
| 123 | + <HiOutlinePencil /> |
| 124 | + </Button> |
| 125 | + <Modal |
| 126 | + isOpen={editingQuestionId === questionId} |
| 127 | + onRequestClose={closeModal} |
| 128 | + ariaHideApp={false} |
| 129 | + className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-none" |
| 130 | + style={{ |
| 131 | + overlay: { |
| 132 | + backgroundColor: "rgba(29, 36, 51, 0.8)", |
| 133 | + }, |
| 134 | + }} |
| 135 | + > |
| 136 | + <motion.div |
| 137 | + initial="hidden" |
| 138 | + animate="visible" |
| 139 | + exit="exit" |
| 140 | + variants={modalAnimation} |
| 141 | + transition={{ duration: 0.3 }} |
| 142 | + > |
| 143 | + <EditQuestionDialog |
| 144 | + questionId={questionId} |
| 145 | + handleClose={closeModal} |
| 146 | + setRefreshKey={setRefreshKey} |
| 147 | + /> |
| 148 | + </motion.div> |
| 149 | + </Modal> |
| 150 | + <Button variant={"ghost"} onClick={() => handleDelete(questionId)}> |
| 151 | + <FaRegTrashAlt /> |
| 152 | + </Button> |
| 153 | + </Cell> |
| 154 | + ); |
| 155 | +}; |
| 156 | + |
57 | 157 | export function LeetcodeDashboardTable({
|
58 | 158 | refreshKey,
|
59 | 159 | setRefreshKey,
|
60 |
| -}: LeetcodeDashboardTableProps) { |
| 160 | +}: Readonly<LeetcodeDashboardTableProps>) { |
61 | 161 | const [data, setData] = useState<QuestionMinified[]>([]);
|
62 | 162 | const [editingQuestionId, setEditingQuestionId] = React.useState<
|
63 | 163 | string | null
|
@@ -130,75 +230,37 @@ export function LeetcodeDashboardTable({
|
130 | 230 | const columns: ColumnDef<QuestionMinified>[] = [
|
131 | 231 | {
|
132 | 232 | accessorKey: "questionid",
|
133 |
| - header: () => <Cell>ID</Cell>, |
134 |
| - cell: ({ row }) => ( |
135 |
| - <Cell className="capitalize">{row.getValue("questionid")}</Cell> |
136 |
| - ), |
| 233 | + header: QuestionIdHeader, |
| 234 | + cell: ({ row }) => QuestionIdCell({ row }), |
137 | 235 | },
|
138 | 236 | {
|
139 | 237 | accessorKey: "title",
|
140 |
| - header: () => <Cell>Question Title</Cell>, |
141 |
| - cell: ({ row }) => <Cell>{row.getValue("title")}</Cell>, |
| 238 | + header: TitleHeader, |
| 239 | + cell: ({ row }) => TitleCell({ row }), |
142 | 240 | },
|
143 | 241 | {
|
144 | 242 | accessorKey: "complexity",
|
145 |
| - header: () => <Cell>Difficulty</Cell>, |
146 |
| - cell: ({ row }) => { |
147 |
| - return <Cell>{row.getValue("complexity")}</Cell>; |
148 |
| - }, |
| 243 | + header: ComplexityHeader, |
| 244 | + cell: ({ row }) => ComplexityCell({ row }), |
149 | 245 | },
|
150 | 246 | {
|
151 | 247 | accessorKey: "category",
|
152 |
| - header: () => <Cell>Topics</Cell>, |
153 |
| - cell: ({ row }) => { |
154 |
| - const categoryValue = row.getValue("category"); |
155 |
| - const result: string = Array.isArray(categoryValue) |
156 |
| - ? categoryValue.join(", ") |
157 |
| - : String(categoryValue); |
158 |
| - return <Cell>{result}</Cell>; |
159 |
| - }, |
| 248 | + header: CategoryHeader, |
| 249 | + cell: ({ row }) => CategoryCell({ row }), |
160 | 250 | },
|
161 | 251 | {
|
162 | 252 | accessorKey: "actions",
|
163 |
| - header: () => <Cell>Actions</Cell>, |
164 |
| - cell: ({ row }) => { |
165 |
| - const questionId: string = row.getValue("questionid"); |
166 |
| - return ( |
167 |
| - <Cell> |
168 |
| - <Button onClick={() => openModal(questionId)} variant={"ghost"}> |
169 |
| - <HiOutlinePencil /> |
170 |
| - </Button> |
171 |
| - <Modal |
172 |
| - isOpen={editingQuestionId === questionId} |
173 |
| - onRequestClose={closeModal} |
174 |
| - ariaHideApp={false} |
175 |
| - className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-none" |
176 |
| - style={{ |
177 |
| - overlay: { |
178 |
| - backgroundColor: "rgba(29, 36, 51, 0.8)", |
179 |
| - }, |
180 |
| - }} |
181 |
| - > |
182 |
| - <motion.div |
183 |
| - initial="hidden" |
184 |
| - animate="visible" |
185 |
| - exit="exit" |
186 |
| - variants={modalAnimation} |
187 |
| - transition={{ duration: 0.3 }} |
188 |
| - > |
189 |
| - <EditQuestionDialog |
190 |
| - questionId={questionId} |
191 |
| - handleClose={closeModal} |
192 |
| - setRefreshKey={setRefreshKey} |
193 |
| - /> |
194 |
| - </motion.div> |
195 |
| - </Modal> |
196 |
| - <Button variant={"ghost"} onClick={() => handleDelete(questionId)}> |
197 |
| - <FaRegTrashAlt /> |
198 |
| - </Button> |
199 |
| - </Cell> |
200 |
| - ); |
201 |
| - }, |
| 253 | + header: ActionsHeader, |
| 254 | + cell: ({ row }) => |
| 255 | + ActionsCell({ |
| 256 | + row, |
| 257 | + openModal, |
| 258 | + editingQuestionId, |
| 259 | + closeModal, |
| 260 | + modalAnimation, |
| 261 | + setRefreshKey, |
| 262 | + handleDelete, |
| 263 | + }), |
202 | 264 | },
|
203 | 265 | ];
|
204 | 266 |
|
|
0 commit comments