@@ -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