Skip to content

Commit ea994bb

Browse files
committed
fix: applies fix on planning view
1 parent da6f4c4 commit ea994bb

1 file changed

Lines changed: 74 additions & 52 deletions

File tree

src/components/Projects/PlanningView.tsx

Lines changed: 74 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
5555
endDate: '',
5656
isActive: false,
5757
})
58+
const [availableSprints, setAvailableSprints] = useState<Sprint[]>([])
5859
const [sprintFilter, setSprintFilter] = useState<'all' | 'active' | 'upcoming'>('upcoming')
5960
const [isSprintSelectorOpen, setIsSprintSelectorOpen] = useState(false)
6061
const [heroHeight, setHeroHeight] = useState(0)
@@ -98,8 +99,9 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
9899
}
99100

100101
const getDisplayName = (name: string): string => {
101-
const parts = name.trim().split(' ')
102-
if (parts.length === 1) {
102+
if (!name || name?.length === 0) return ''
103+
const parts = name?.trim().split(' ')
104+
if (parts?.length === 1) {
103105
return parts[0] // Just first name if only one part
104106
}
105107
const firstName = parts[0]
@@ -127,7 +129,10 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
127129
}
128130

129131
// Filter and manage sprints
130-
const availableSprints = sprints.filter((sprint) => sprint.id !== 1 && sprint.id !== 2)
132+
// const availableSprints = sprints.filter((sprint) => sprint.id !== 1 && sprint.id !== 2)
133+
useEffect(() => {
134+
setAvailableSprints(sprints)
135+
}, [sprints])
131136

132137
const displayedSprints = availableSprints.filter((sprint) => {
133138
switch (sprintFilter) {
@@ -144,17 +149,15 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
144149
selectedSprintIds.includes(sprint.id.toString()),
145150
)
146151

147-
// const backlogTasks = tasks.filter(
148-
// (task) => !task.sprintId || task.sprintId === 'backlog' || task.sprintId === 'Backlog',
149-
// )
150-
// const backlogStoryPoints = backlogTasks.reduce((sum, task) => sum + (task.points || 0), 0)
152+
const backlogTasks = tasks.filter((task) => !task.sprint || task.status === 'backlog')
153+
const backlogStoryPoints = backlogTasks.reduce((sum, task) => sum + (task.storyPoints || 0), 0)
151154

152155
// Sprint management functions
153156
const toggleSprintView = (sprintId: string) => {
154157
setSelectedSprintIds((prev) => {
155158
if (prev.includes(sprintId)) {
156159
return prev.filter((id) => id !== sprintId)
157-
} else if (prev.length < 3) {
160+
} else if (prev?.length < 3) {
158161
return [...prev, sprintId]
159162
}
160163
return prev
@@ -202,6 +205,17 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
202205
endDate: sprintEditForm.endDate,
203206
// isActive: sprintEditForm.isActive,
204207
})
208+
setAvailableSprints((prev) =>
209+
prev.map((sprint) => {
210+
if (sprint.id === Number(editingSprintId)) {
211+
sprint.name = sprintEditForm.name
212+
sprint.description = sprintEditForm.description
213+
sprint.startDate = sprintEditForm.startDate
214+
sprint.endDate = sprintEditForm.endDate
215+
}
216+
return sprint
217+
}),
218+
)
205219
setEditingSprintId(null)
206220
}
207221
}
@@ -244,11 +258,10 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
244258

245259
// Normalize the sprint IDs for comparison
246260
const currentSprint = extractId(draggedTask.sprint) || undefined
247-
const targetSprint = targetSprintId === 'backlog' ? undefined : targetSprintId
248261

249262
// Only update if moving to a different sprint
250-
if (currentSprint !== targetSprint) {
251-
// onUpdateTask(draggedTask.id.toString(), { sprint: targetSprint as Sprint })
263+
if (currentSprint !== Number(targetSprintId)) {
264+
onUpdateTask(draggedTask.id.toString(), { sprint: Number(targetSprintId) })
252265
}
253266

254267
setDraggedTask(null)
@@ -342,15 +355,15 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
342355
<div className="flex items-center gap-3">
343356
<div>
344357
<h3 className="font-semibold text-foreground text-sm">Sprint Board</h3>
345-
{/* <p className="text-xs text-muted-foreground">
346-
{selectedSprintIds.length}/3 selected
347-
</p> */}
358+
<p className="text-xs text-muted-foreground">
359+
{selectedSprintIds?.length}/3 selected
360+
</p>
348361
</div>
349362

350363
{/* Current Selection - Always Visible */}
351-
{selectedSprintIds.length > 0 && (
364+
{selectedSprintIds?.length > 0 && (
352365
<div className="flex items-center gap-2">
353-
{/* <span className="text-xs text-muted-foreground">Viewing:</span> */}
366+
<span className="text-xs text-muted-foreground">Viewing:</span>
354367
<div className="flex flex-wrap gap-1">
355368
{visibleSprints.map((sprint) => (
356369
<div
@@ -558,7 +571,7 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
558571
>
559572
<Edit2 className="h-3 w-3" />
560573
</Button>
561-
{sprint.id !== 1 && sprint.id !== 2 && (
574+
{
562575
<Button
563576
size="sm"
564577
variant="ghost"
@@ -567,7 +580,7 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
567580
>
568581
<Trash2 className="h-3 w-3" />
569582
</Button>
570-
)}
583+
}
571584
</div>
572585
</div>
573586
<div className="flex items-center justify-between mt-2">
@@ -576,12 +589,12 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
576589
size="sm"
577590
className="text-xs w-full h-8 flex items-center justify-center cursor-pointer"
578591
onClick={() => toggleSprintView(sprint.id.toString())}
579-
disabled={!isSelected && selectedSprintIds.length >= 3}
592+
disabled={!isSelected && selectedSprintIds?.length >= 3}
580593
>
581594
<span className="pointer-events-none select-none">
582595
{isSelected
583596
? 'Deselect'
584-
: selectedSprintIds.length >= 3
597+
: selectedSprintIds?.length >= 3
585598
? 'Limit Reached'
586599
: 'Select'}
587600
</span>
@@ -608,7 +621,7 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
608621
)}
609622
</div>
610623

611-
{selectedSprintIds.length === 0 && (
624+
{selectedSprintIds?.length === 0 && (
612625
<div className="mt-4 p-4 bg-muted/50 rounded-lg border-2 border-dashed border-border">
613626
<div className="text-center">
614627
<Calendar className="h-6 w-6 mx-auto mb-2 text-muted-foreground" />
@@ -643,14 +656,14 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
643656
>
644657
<div className="flex items-center justify-between mb-4 flex-shrink-0">
645658
<h3 className="font-semibold text-foreground select-none text-lg">Backlog</h3>
646-
{/* <div className="flex items-center gap-2">
659+
<div className="flex items-center gap-2">
647660
<Badge variant="secondary" className="bg-muted text-muted-foreground">
648-
{backlogTasks.length} tasks
661+
{backlogTasks?.length} tasks
649662
</Badge>
650663
<Badge variant="outline" className="bg-gray-50 text-gray-700 border-gray-200">
651664
{backlogStoryPoints} pts
652665
</Badge>
653-
</div> */}
666+
</div>
654667
</div>
655668

656669
<div
@@ -659,12 +672,12 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
659672
}`}
660673
>
661674
{(() => {
662-
// const { tasksByEpic, unassignedTasks } = getTasksByEpic(backlogTasks)
675+
const { tasksByEpic, unassignedTasks } = getTasksByEpic(backlogTasks)
663676

664677
return (
665678
<>
666679
{/* Epic Groups */}
667-
{/* {Object.entries(tasksByEpic).map(([epicId, epicTasks]) => {
680+
{Object.entries(tasksByEpic).map(([epicId, epicTasks]) => {
668681
const epic = getEpicById(epicId)
669682
if (!epic) return null
670683
const isCollapsed = collapsedEpics.has(epicId)
@@ -679,7 +692,7 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
679692
<span className="font-medium text-muted-foreground">
680693
{epic.name}
681694
</span>
682-
<span className="text-muted-foreground">({epicTasks.length})</span>
695+
<span className="text-muted-foreground">({epicTasks?.length})</span>
683696
<div className="ml-auto">
684697
{isCollapsed ? (
685698
<ChevronDown className="h-3 w-3 text-muted-foreground" />
@@ -697,10 +710,10 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
697710
)}
698711
</div>
699712
)
700-
})} */}
713+
})}
701714

702715
{/* Unassigned Tasks */}
703-
{/* {unassignedTasks.length > 0 &&
716+
{unassignedTasks?.length > 0 &&
704717
(() => {
705718
const isCollapsed = collapsedEpics.has('no-epic')
706719
return (
@@ -712,7 +725,7 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
712725
<div className="w-3 h-3 rounded-full bg-gray-400" />
713726
<span className="font-medium text-muted-foreground">No Epic</span>
714727
<span className="text-muted-foreground">
715-
({unassignedTasks.length})
728+
({unassignedTasks?.length})
716729
</span>
717730
<div className="ml-auto">
718731
{isCollapsed ? (
@@ -724,34 +737,34 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
724737
</div>
725738
{!isCollapsed && (
726739
<div className="space-y-2 pl-2">
727-
{unassignedTasks.map((task) => (
740+
{unassignedTasks?.map((task) => (
728741
<CompactTaskCard key={task.id} task={task} />
729742
))}
730743
</div>
731744
)}
732745
</div>
733746
)
734-
})()} */}
747+
})()}
735748

736-
{/* {backlogTasks.length === 0 && (
749+
{backlogTasks?.length === 0 && (
737750
<div className="flex items-center justify-center h-32 text-muted-foreground text-sm select-none">
738751
Drop tasks here to move to backlog
739752
</div>
740-
)} */}
753+
)}
741754

742755
{/* Fallback: Show all backlog tasks if nothing else is showing */}
743-
{/* {backlogTasks.length > 0 &&
756+
{backlogTasks?.length > 0 &&
744757
Object.keys(tasksByEpic).length === 0 &&
745758
unassignedTasks.length === 0 && (
746759
<div className="space-y-2">
747760
<div className="text-xs text-muted-foreground mb-2">
748761
Direct backlog tasks:
749762
</div>
750-
{backlogTasks.map((task) => (
763+
{backlogTasks?.map((task) => (
751764
<CompactTaskCard key={task.id} task={task} />
752765
))}
753766
</div>
754-
)} */}
767+
)}
755768
</>
756769
)
757770
})()}
@@ -762,10 +775,10 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
762775
{/* Sprint Columns - Now at same level as backlog */}
763776
{visibleSprints.map((sprint) => {
764777
const sprintTasksFiltered = tasks.filter(
765-
(task) => extractId(task.sprint) === sprint.id,
778+
(task) => extractId(task?.sprint) === sprint.id,
766779
)
767780
const totalStoryPoints = sprintTasksFiltered.reduce(
768-
(sum, task) => sum + (task.storyPoints || 0),
781+
(sum, task) => sum + (task?.storyPoints || 0),
769782
0,
770783
)
771784

@@ -796,30 +809,39 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
796809
)} */}
797810
</div>
798811
<div className="flex items-center gap-2">
799-
<Badge variant="secondary" className="bg-muted text-muted-foreground">
800-
{sprintTasksFiltered.length} tasks
812+
<Badge
813+
variant="secondary"
814+
className="bg-muted flex items-center justify-center text-muted-foreground"
815+
>
816+
{sprintTasksFiltered?.length} tasks
801817
</Badge>
802-
<Badge variant="outline" className="bg-blue-50 text-blue-700 border-blue-200">
818+
<Badge
819+
variant="outline"
820+
className="bg-blue-50 flex items-center justify-center text-blue-700 border-blue-200"
821+
>
803822
{totalStoryPoints} pts
804823
</Badge>
805824
<Button
806825
size="sm"
807826
variant="ghost"
808-
onClick={() => handleSprintEditStart(sprint)}
827+
onClick={() => {
828+
setIsSprintSelectorOpen(true)
829+
handleSprintEditStart(sprint as Sprint)
830+
}}
809831
className="h-6 px-2"
810832
>
811833
<Edit2 className="h-3 w-3" />
812834
</Button>
813-
{/* {sprint.id !== 'backlog' && sprint.id !== 'all-tasks' && (
835+
{
814836
<Button
815837
size="sm"
816838
variant="ghost"
817-
onClick={() => onDeleteSprint(sprint.id)}
839+
onClick={() => onDeleteSprint(sprint.id.toString())}
818840
className="h-6 px-2 text-destructive hover:text-destructive"
819841
>
820842
<Trash2 className="h-3 w-3" />
821843
</Button>
822-
)} */}
844+
}
823845
</div>
824846
</div>
825847

@@ -846,7 +868,7 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
846868
{epic.name}
847869
</span>
848870
<span className="text-muted-foreground">
849-
({epicTasks.length})
871+
({epicTasks?.length})
850872
</span>
851873
<div className="ml-auto">
852874
{isCollapsed ? (
@@ -858,7 +880,7 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
858880
</div>
859881
{!isCollapsed && (
860882
<div className="space-y-2 pl-2">
861-
{epicTasks.map((task) => (
883+
{epicTasks?.map((task) => (
862884
<CompactTaskCard key={task.id} task={task} />
863885
))}
864886
</div>
@@ -868,7 +890,7 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
868890
})}
869891

870892
{/* Unassigned Tasks */}
871-
{unassignedTasks.length > 0 &&
893+
{unassignedTasks?.length > 0 &&
872894
(() => {
873895
const isCollapsed = collapsedEpics.has('no-epic')
874896
return (
@@ -882,7 +904,7 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
882904
No Epic
883905
</span>
884906
<span className="text-muted-foreground">
885-
({unassignedTasks.length})
907+
({unassignedTasks?.length})
886908
</span>
887909
<div className="ml-auto">
888910
{isCollapsed ? (
@@ -894,7 +916,7 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
894916
</div>
895917
{!isCollapsed && (
896918
<div className="space-y-2 pl-2">
897-
{unassignedTasks.map((task) => (
919+
{unassignedTasks?.map((task) => (
898920
<CompactTaskCard key={task.id} task={task} />
899921
))}
900922
</div>
@@ -903,7 +925,7 @@ export const PlanningView: React.FC<PlanningViewProps> = ({
903925
)
904926
})()}
905927

906-
{sprintTasksFiltered.length === 0 && (
928+
{sprintTasksFiltered?.length === 0 && (
907929
<div className="flex items-center justify-center h-32 text-muted-foreground text-sm select-none">
908930
Drop tasks here
909931
</div>

0 commit comments

Comments
 (0)