Skip to content

Commit 4926e1e

Browse files
authored
Merge pull request #379 from CodebilityDev/miguel/fix-sidebar-revalidation
miguel/fix sidebar revalidation
2 parents 484d5a8 + 63b480b commit 4926e1e

10 files changed

Lines changed: 241 additions & 155 deletions

File tree

‎apps/codebility/app/home/kanban/[projectId]/[id]/_components/KanbanBoardColumnContainer.tsx‎

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { useCallback, useEffect, useMemo, useState } from "react";
44
import { useRouter } from "next/navigation";
5+
import { useKanbanStore } from "@/store/kanban-store";
56
import { KanbanColumnType, Task } from "@/types/home/codev";
67
import { debounce } from "@/utils/debounce";
78
import {
@@ -88,7 +89,7 @@ export default function KanbanBoardColumnContainer({
8889
const [pendingUpdates, setPendingUpdates] = useState<
8990
Array<{ taskId: string; newColumnId: string }>
9091
>([]);
91-
92+
9293
// Track dragging state for immediate feedback
9394
const [isDragging, setIsDragging] = useState(false);
9495

@@ -163,7 +164,6 @@ export default function KanbanBoardColumnContainer({
163164
);
164165
}, [orderedColumns, activeFilter, filterAndSortTasks]);
165166

166-
167167
const handleDragStart = useCallback((event: DragStartEvent) => {
168168
// Optional: set active item state for custom drag overlays.
169169
}, []);
@@ -264,8 +264,13 @@ export default function KanbanBoardColumnContainer({
264264
// Add to pending updates for debounced batch processing
265265
setPendingUpdates((prev) => {
266266
// Remove any existing update for this task to avoid duplicates
267-
const filtered = prev.filter(update => update.taskId !== movedTask.id);
268-
return [...filtered, { taskId: movedTask.id, newColumnId: overColId }];
267+
const filtered = prev.filter(
268+
(update) => update.taskId !== movedTask.id,
269+
);
270+
return [
271+
...filtered,
272+
{ taskId: movedTask.id, newColumnId: overColId },
273+
];
269274
});
270275
}
271276
},

‎apps/codebility/app/home/kanban/[projectId]/[id]/_components/KanbanColumn.tsx‎

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
"use client";
22

33
import { useMemo, useState } from "react";
4-
import { useRouter } from "next/navigation";
54
import { Button } from "@/components/ui/button";
65
import { useModal } from "@/hooks/use-modal";
76
import { useUserStore } from "@/store/codev-store";
7+
import { useKanbanStore } from "@/store/kanban-store";
88
import { ExtendedTask } from "@/types/home/codev";
99
import { useDroppable } from "@dnd-kit/core";
1010
import {
@@ -52,13 +52,18 @@ export default function KanbanColumn({
5252
tasks,
5353
onTaskComplete,
5454
}: Props) {
55-
const router = useRouter();
5655
const { user } = useUserStore();
5756
const canModifyColumn = user?.role_id === 1 || user?.role_id === 5;
58-
const canAddTask = user?.role_id === 1 || user?.role_id === 5 || user?.role_id === 4 || user?.role_id === 10;
57+
const canAddTask =
58+
user?.role_id === 1 ||
59+
user?.role_id === 5 ||
60+
user?.role_id === 4 ||
61+
user?.role_id === 10;
5962
const [isEditing, setIsEditing] = useState(false);
6063
const [newName, setNewName] = useState(column.name);
6164

65+
const { fetchBoardData } = useKanbanStore();
66+
6267
const safeTasks = tasks ?? [];
6368

6469
// 1) Make the whole column "sortable" so we can reorder columns horizontally
@@ -115,7 +120,8 @@ export default function KanbanColumn({
115120
const response = await deleteColumn(column.id);
116121
if (response.success) {
117122
toast.success("Column deleted successfully");
118-
window.location.reload();
123+
// Refetch the board data
124+
await fetchBoardData();
119125
} else {
120126
toast.error(response.error || "Failed to delete column");
121127
}
@@ -126,15 +132,14 @@ export default function KanbanColumn({
126132
toast.error("You don't have permission to delete columns");
127133
return;
128134
}
129-
135+
130136
if (safeTasks.length > 0) {
131137
toast.error("Cannot delete column with tasks");
132138
return;
133139
}
134-
140+
135141
onOpen("deleteWarningModal", {}, {}, () => confirmDelete());
136142
};
137-
138143

139144
// Handle column rename
140145
const handleUpdateName = async () => {
@@ -152,7 +157,8 @@ export default function KanbanColumn({
152157
if (response.success) {
153158
toast.success("Column name updated");
154159
setIsEditing(false);
155-
router.refresh();
160+
// Refetch the board data
161+
await fetchBoardData();
156162
} else {
157163
toast.error(response.error || "Failed to update column name");
158164
}
@@ -171,18 +177,18 @@ export default function KanbanColumn({
171177
lg:w-[400px] lg:min-w-[400px]
172178
${
173179
isColumnDragging
174-
? "border-customBlue-500 opacity-95 shadow-lg shadow-customBlue-500/15 scale-[1.02]"
180+
? "border-customBlue-500 shadow-customBlue-500/15 scale-[1.02] opacity-95 shadow-lg"
175181
: isOver
176182
? "border-customBlue-400 bg-customBlue-50/50 dark:border-customBlue-500 dark:bg-customBlue-950/20"
177-
: "border-gray-300 dark:border-gray-600 shadow-sm hover:shadow-md"
183+
: "border-gray-300 shadow-sm hover:shadow-md dark:border-gray-600"
178184
}
179185
bg-gray-50/90 backdrop-blur-sm transition-all duration-200 ease-out dark:bg-gray-800/90
180186
`}
181187
{...attributes}
182188
>
183189
{/* Column Header */}
184190
<div
185-
className="flex items-center justify-between bg-gradient-to-r from-gray-100 to-gray-200 dark:from-gray-700 dark:to-gray-800 p-3 md:p-4 border-b border-gray-300 dark:border-gray-600"
191+
className="flex items-center justify-between border-b border-gray-300 bg-gradient-to-r from-gray-100 to-gray-200 p-3 dark:border-gray-600 dark:from-gray-700 dark:to-gray-800 md:p-4"
186192
{...listeners}
187193
>
188194
<div className="flex items-center gap-2 text-gray-800 dark:text-gray-200 md:gap-3">
@@ -213,9 +219,11 @@ export default function KanbanColumn({
213219
</div>
214220
) : (
215221
<>
216-
<GripVertical className="hidden h-5 w-5 text-gray-400 cursor-grab hover:text-gray-600 dark:hover:text-gray-300 md:block transition-colors" />
217-
<span className="text-base font-semibold text-gray-900 dark:text-white md:text-lg">{column.name}</span>
218-
<div className="flex items-center justify-center rounded-full bg-customBlue-100 dark:bg-customBlue-900/30 px-3 py-1 text-sm font-medium text-blue-100 dark:text-customBlue-100">
222+
<GripVertical className="hidden h-5 w-5 cursor-grab text-gray-400 transition-colors hover:text-gray-600 dark:hover:text-gray-300 md:block" />
223+
<span className="text-base font-semibold text-gray-900 dark:text-white md:text-lg">
224+
{column.name}
225+
</span>
226+
<div className="bg-customBlue-100 dark:bg-customBlue-900/30 dark:text-customBlue-100 flex items-center justify-center rounded-full px-3 py-1 text-sm font-medium text-blue-100">
219227
{safeTasks.length}
220228
</div>
221229
</>
@@ -261,7 +269,7 @@ export default function KanbanColumn({
261269
className={`
262270
flex min-h-[100px] flex-col gap-2 rounded-md p-1 transition-colors duration-200
263271
md:gap-4 md:p-2
264-
${isOver ? "border-2 border-customBlue-200 bg-customBlue-50 dark:bg-customBlue-900/20" : ""}
272+
${isOver ? "border-customBlue-200 bg-customBlue-50 dark:bg-customBlue-900/20 border-2" : ""}
265273
`}
266274
>
267275
<SortableContext

‎apps/codebility/app/home/kanban/[projectId]/[id]/_components/kanban_modals/KanbanColumnAddModal.tsx‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
DialogTitle,
1313
} from "@/components/ui/dialog";
1414
import { useModal } from "@/hooks/use-modal";
15+
import { useKanbanStore } from "@/store/kanban-store";
1516
import toast from "react-hot-toast";
1617

1718
import { Input } from "@codevs/ui/input";
@@ -22,6 +23,7 @@ export default function KanbanColumnAddModal() {
2223
const [isLoading, setIsLoading] = useState(false);
2324
const router = useRouter();
2425
const isModalOpen = isOpen && type === "ColumnAddModal";
26+
const { fetchBoardData } = useKanbanStore();
2527

2628
const validateColumnName = (name: string): boolean => {
2729
// Add validation rules based on your database constraints
@@ -46,7 +48,9 @@ export default function KanbanColumnAddModal() {
4648
const response = await createNewColumn(columnName, boardId);
4749
if (response.success) {
4850
toast.success("Column created successfully!");
49-
window.location.reload();
51+
// Refetch the board data
52+
await fetchBoardData();
53+
// window.location.reload();
5054
onClose();
5155
setColumnName("");
5256
} else {

‎apps/codebility/app/home/kanban/[projectId]/[id]/_components/tasks/TaskAddModal.tsx‎

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import type { SkillCategory } from "@/types/home/codev";
44
import { useEffect, useState, useTransition } from "react";
5-
import { useRouter } from "next/navigation";
65
import { Button } from "@/components/ui/button";
76
import {
87
Dialog,
@@ -21,6 +20,7 @@ import {
2120
} from "@/components/ui/select";
2221
import { useModal } from "@/hooks/use-modal";
2322
import { useUserStore } from "@/store/codev-store";
23+
import { useKanbanStore } from "@/store/kanban-store";
2424
import { createClientClientComponent } from "@/utils/supabase/client";
2525
import { Loader2Icon } from "lucide-react";
2626
import toast from "react-hot-toast";
@@ -30,7 +30,10 @@ import { Label } from "@codevs/ui/label";
3030
import { Textarea } from "@codevs/ui/textarea";
3131

3232
import { createNewTask } from "../../actions";
33-
import DifficultyPointsTooltip, { DIFFICULTY_LEVELS, DIFFICULTY_POINTS } from "../DifficultyPointsTooltip";
33+
import DifficultyPointsTooltip, {
34+
DIFFICULTY_LEVELS,
35+
DIFFICULTY_POINTS,
36+
} from "../DifficultyPointsTooltip";
3437
import KanbanAddModalMembers from "../kanban_modals/KanbanAddModalMembers";
3538
import KanbanRichTextEditor from "../kanban_modals/KanbanRichTextEditor";
3639

@@ -50,7 +53,7 @@ const TaskAddModal = () => {
5053
const user = useUserStore((state) => state.user);
5154
const [supabase, setSupabase] = useState<any>(null);
5255

53-
const router = useRouter();
56+
const { fetchBoardData } = useKanbanStore();
5457

5558
const onChange = (value: string) => {
5659
setDescription(value);
@@ -134,7 +137,8 @@ const TaskAddModal = () => {
134137
toast.success("Task created successfully");
135138
handleClose();
136139

137-
router.refresh();
140+
// Refetch the board data
141+
await fetchBoardData();
138142
} else {
139143
toast.error(response.error || "Failed to create task");
140144
}
@@ -167,8 +171,8 @@ const TaskAddModal = () => {
167171
</DialogHeader>
168172

169173
{data?.listName && (
170-
<div className="rounded-md bg-customBlue-50 p-2 dark:bg-customBlue-900/20">
171-
<Label className="text-sm text-customBlue-700 dark:text-customBlue-100">
174+
<div className="bg-customBlue-50 dark:bg-customBlue-900/20 rounded-md p-2">
175+
<Label className="text-customBlue-700 dark:text-customBlue-100 text-sm">
172176
Adding to: {data.listName}
173177
</Label>
174178
</div>
@@ -185,7 +189,7 @@ const TaskAddModal = () => {
185189
id="title"
186190
name="title"
187191
placeholder="Enter task title"
188-
className="bg-light-900 dark:bg-dark-200 dark:text-light-900 border border-gray-300 focus:border-customBlue-500 "
192+
className="bg-light-900 dark:bg-dark-200 dark:text-light-900 focus:border-customBlue-500 border border-gray-300 "
189193
required
190194
/>
191195
</div>
@@ -211,7 +215,7 @@ const TaskAddModal = () => {
211215
<div className="space-y-2">
212216
<Label className="text-sm font-medium">Priority</Label>
213217
<Select name="priority">
214-
<SelectTrigger className="bg-light-900 border border-gray-300 focus:border-customBlue-500 dark:border-gray-700">
218+
<SelectTrigger className="bg-light-900 focus:border-customBlue-500 border border-gray-300 dark:border-gray-700">
215219
<SelectValue placeholder="Select priority" />
216220
</SelectTrigger>
217221
<SelectContent>
@@ -240,7 +244,7 @@ const TaskAddModal = () => {
240244
value={selectedDifficulty}
241245
onValueChange={handleDifficultyChange}
242246
>
243-
<SelectTrigger className="bg-light-900 border border-gray-300 focus:border-customBlue-500 dark:border-gray-700">
247+
<SelectTrigger className="bg-light-900 focus:border-customBlue-500 border border-gray-300 dark:border-gray-700">
244248
<SelectValue placeholder="Select difficulty" />
245249
</SelectTrigger>
246250
<SelectContent>
@@ -268,7 +272,7 @@ const TaskAddModal = () => {
268272
<div className="space-y-2">
269273
<Label className="text-sm font-medium">Task Type</Label>
270274
<Select name="type">
271-
<SelectTrigger className="bg-light-900 border border-gray-300 focus:border-customBlue-500 dark:border-gray-700">
275+
<SelectTrigger className="bg-light-900 focus:border-customBlue-500 border border-gray-300 dark:border-gray-700">
272276
<SelectValue placeholder="Select type" />
273277
</SelectTrigger>
274278
<SelectContent>
@@ -291,7 +295,7 @@ const TaskAddModal = () => {
291295
<div className="space-y-2">
292296
<Label className="text-sm font-medium">Skill Category</Label>
293297
<Select name="skill_category_id" required>
294-
<SelectTrigger className="bg-light-900 border border-gray-300 focus:border-customBlue-500 dark:border-gray-700">
298+
<SelectTrigger className="bg-light-900 focus:border-customBlue-500 border border-gray-300 dark:border-gray-700">
295299
<SelectValue placeholder="Select skill category" />
296300
</SelectTrigger>
297301
<SelectContent>
@@ -347,14 +351,14 @@ const TaskAddModal = () => {
347351
type="button"
348352
variant="outline"
349353
onClick={handleClose}
350-
className="text-md flex h-10 w-full items-center justify-center gap-2 whitespace-nowrap rounded-md bg-customBlue-100 px-6 py-3 text-white ring-offset-background transition-colors duration-300 hover:bg-customBlue-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-customBlue-100 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 sm:w-auto lg:text-lg"
354+
className="text-md bg-customBlue-100 hover:bg-customBlue-200 focus-visible:ring-customBlue-100 flex h-10 w-full items-center justify-center gap-2 whitespace-nowrap rounded-md px-6 py-3 text-white ring-offset-background transition-colors duration-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 sm:w-auto lg:text-lg"
351355
disabled={loading || isPending}
352356
>
353357
Cancel
354358
</Button>
355359
<Button
356360
type="submit"
357-
className="text-md flex h-10 w-full items-center justify-center gap-2 whitespace-nowrap rounded-md bg-customBlue-100 px-6 py-1 text-white ring-offset-background transition-colors duration-300 hover:bg-customBlue-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-customBlue-100 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 sm:w-auto lg:text-lg"
361+
className="text-md bg-customBlue-100 hover:bg-customBlue-200 focus-visible:ring-customBlue-100 flex h-10 w-full items-center justify-center gap-2 whitespace-nowrap rounded-md px-6 py-1 text-white ring-offset-background transition-colors duration-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 sm:w-auto lg:text-lg"
358362
disabled={loading || isPending}
359363
>
360364
{loading && <Loader2Icon className="mr-2 h-4 w-4 animate-spin" />}

‎apps/codebility/app/home/kanban/[projectId]/[id]/_components/tasks/TaskDeleteModal.tsx‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"use client";
22

33
import React from "react";
4-
import { useRouter } from "next/navigation";
54
import { Button } from "@/components/ui/button";
65
import {
76
Dialog,
@@ -10,6 +9,7 @@ import {
109
DialogTitle,
1110
} from "@/components/ui/dialog";
1211
import { useModal } from "@/hooks/use-modal";
12+
import { useKanbanStore } from "@/store/kanban-store";
1313
import { Task } from "@/types/home/codev";
1414
import { Loader2Icon } from "lucide-react";
1515
import toast from "react-hot-toast";
@@ -19,9 +19,10 @@ import { deleteTask } from "../../actions";
1919
const TaskDeleteModal = () => {
2020
const { isOpen, onClose, type, data } = useModal();
2121
const isModalOpen = isOpen && type === "taskDeleteModal";
22-
const router = useRouter();
2322
const [isLoading, setIsLoading] = React.useState(false);
2423

24+
const { fetchBoardData } = useKanbanStore();
25+
2526
const task = data as Task;
2627

2728
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
@@ -39,7 +40,8 @@ const TaskDeleteModal = () => {
3940

4041
if (response.success) {
4142
toast.success("Task deleted successfully");
42-
router.refresh();
43+
// Refetch the board data
44+
await fetchBoardData();
4345
onClose();
4446
} else {
4547
toast.error(response.error || "Failed to delete task");

0 commit comments

Comments
 (0)