33import { useState , useMemo , useRef , useEffect , useCallback , lazy , Suspense } from "react" ;
44import { Card , CardContent , CardHeader } from "@/components/ui/card" ;
55import { Input } from "@/components/ui/input" ;
6- import TaskForm from "@/app/app/to-do/TaskForm" ;
76import TaskList from "@/app/app/to-do/TaskList" ;
7+ import type { Task } from "@/app/app/to-do/types/Task" ;
88import PaginationDemo from "@/app/app/to-do/PaginationS" ;
99import { LazyBoundary } from "@/app/app/to-do/components/LazyBoundary" ;
1010
@@ -16,6 +16,7 @@ const TaskCommandPalette = lazy(() =>
1616 } ) )
1717) ;
1818const ManageStatusesDialog = lazy ( ( ) => import ( "@/app/app/to-do/ManageStatusesDialog" ) ) ;
19+ const TaskEditDialog = lazy ( ( ) => import ( "@/app/app/to-do/TaskEditDialog" ) ) ;
1920const ProjectManagerDialog = lazy ( ( ) =>
2021 import ( "@/app/app/to-do/components/ProjectManagerDialog" ) . then ( ( m ) => ( {
2122 default : m . ProjectManagerDialog ,
@@ -36,16 +37,6 @@ import { useStatuses } from "./hooks/useStatuses";
3637import { cn } from "@/lib/utils" ;
3738import { useIsMobile } from "@/components/hooks/use-mobile" ;
3839import { useTranslations } from "next-intl" ;
39- import {
40- Drawer ,
41- DrawerContent ,
42- DrawerHeader ,
43- DrawerTitle ,
44- DrawerDescription ,
45- DrawerFooter ,
46- DrawerClose ,
47- DrawerTrigger ,
48- } from "@/components/ui/drawer" ;
4940import { Badge } from "@/components/ui/badge" ;
5041import {
5142 Select ,
@@ -74,10 +65,10 @@ export const TaskContainer = () => {
7465 } , [ isMobile ] ) ;
7566
7667 const [ searchQuery , setSearchQuery ] = useState ( "" ) ;
77- const [ isDrawerOpen , setIsDrawerOpen ] = useState ( false ) ;
68+ const [ isAddTaskOpen , setIsAddTaskOpen ] = useState ( false ) ;
69+ const [ addTaskStatus , setAddTaskStatus ] = useState < string | null > ( null ) ;
7870 const [ isPaletteOpen , setIsPaletteOpen ] = useState ( false ) ;
7971 const searchInputRef = useRef < HTMLInputElement > ( null ) ;
80- const taskFormInputRef = useRef < HTMLInputElement > ( null ) ;
8172 const {
8273 tasks,
8374 isLoading,
@@ -150,13 +141,34 @@ export const TaskContainer = () => {
150141 // Calculate statistics using all tasks stats
151142 const completionRate = allTaskStats . total > 0 ? Math . round ( ( allTaskStats . completed / allTaskStats . total ) * 100 ) : 0 ;
152143
153- // New tasks land in the centrally selected project; "all" creates them unassigned.
154- const handleAddTask = useCallback (
155- ( taskText : string ) => {
156- addTask ( taskText , filterProject !== "all" ? filterProject : undefined ) ;
157- setIsDrawerOpen ( false ) ;
144+ // Template for the create dialog — preselects the centrally selected project
145+ // and, when opened from a status group's "+", that status.
146+ const blankTask = useMemo < Task > (
147+ ( ) => ( {
148+ id : "" ,
149+ text : "" ,
150+ status : addTaskStatus ?? "not-started" ,
151+ statusOrder : 0 ,
152+ createdAt : "" ,
153+ created_by : "" ,
154+ tags : [ ] ,
155+ subTasks : [ ] ,
156+ projectId : filterProject !== "all" ? filterProject : undefined ,
157+ } ) ,
158+ [ filterProject , addTaskStatus ]
159+ ) ;
160+
161+ const openAddTask = useCallback ( ( statusId ?: string ) => {
162+ setAddTaskStatus ( statusId ?? null ) ;
163+ setIsAddTaskOpen ( true ) ;
164+ } , [ ] ) ;
165+
166+ const handleCreateTask = useCallback (
167+ async ( updates : Partial < Task > ) => {
168+ const { text = "" , projectId, ...rest } = updates ;
169+ await addTask ( text , projectId , rest ) ;
158170 } ,
159- [ addTask , filterProject ]
171+ [ addTask ]
160172 ) ;
161173
162174 const [ isExportDialogOpen , setIsExportDialogOpen ] = useState ( false ) ;
@@ -213,7 +225,7 @@ export const TaskContainer = () => {
213225
214226 if ( ! isMobile && event . key ?. toLowerCase ( ) === "n" && ! isTypingInField ) {
215227 event . preventDefault ( ) ;
216- taskFormInputRef . current ?. focus ( ) ;
228+ openAddTask ( ) ;
217229 }
218230 } ;
219231
@@ -426,6 +438,16 @@ export const TaskContainer = () => {
426438 ) }
427439 </ div >
428440
441+ { /* Add Task */ }
442+ < Button
443+ size = "sm"
444+ onClick = { ( ) => openAddTask ( ) }
445+ className = "h-9 px-3 gap-2"
446+ >
447+ < Plus className = "h-3.5 w-3.5" />
448+ < span className = "text-xs font-medium" > { tDrawer ( "addTaskSrOnly" ) } </ span >
449+ </ Button >
450+
429451 { /* Project filter lives in the ToolSidebarLayout panel. */ }
430452
431453 { /* Assignee Filter — only meaningful in a shared workspace */ }
@@ -618,11 +640,6 @@ export const TaskContainer = () => {
618640 </ Card >
619641 ) }
620642
621- { /* Task Form - Hidden on mobile, visible on desktop */ }
622- < div className = "hidden md:block" >
623- < TaskForm onAddTask = { handleAddTask } inputRef = { taskFormInputRef } />
624- </ div >
625-
626643 { /* Task View */ }
627644 < div className = "flex-1 overflow-hidden flex flex-col" >
628645 { viewMode === "kanban" ? (
@@ -658,6 +675,7 @@ export const TaskContainer = () => {
658675 onUpdateStatus = { updateTaskStatus }
659676 onUpdateTask = { updateTask }
660677 onDeleteTask = { deleteTask }
678+ onAddInStatus = { openAddTask }
661679 />
662680 </ div >
663681 ) : (
@@ -670,6 +688,7 @@ export const TaskContainer = () => {
670688 onUpdateStatus = { updateTaskStatus }
671689 onUpdateTask = { updateTask }
672690 onDeleteTask = { deleteTask }
691+ onAddInStatus = { openAddTask }
673692 />
674693 </ CardContent >
675694 </ Card >
@@ -694,35 +713,30 @@ export const TaskContainer = () => {
694713
695714 { /* Floating Action Button (FAB) - Mobile Only */ }
696715 < div className = "md:hidden" >
697- < Drawer open = { isDrawerOpen } onOpenChange = { setIsDrawerOpen } >
698- < DrawerTrigger asChild >
699- < Button
700- size = "icon"
701- className = "fab fab-pulse h-14 w-14 bg-primary hover:bg-primary/90 text-primary-foreground transition-transform active:scale-95"
702- >
703- < Plus className = "h-6 w-6" />
704- < span className = "sr-only" > { tDrawer ( "addTaskSrOnly" ) } </ span >
705- </ Button >
706- </ DrawerTrigger >
707- < DrawerContent >
708- < div className = "mx-auto w-full max-w-sm" >
709- < DrawerHeader >
710- < DrawerTitle > { tDrawer ( "addNewTaskTitle" ) } </ DrawerTitle >
711- < DrawerDescription > { tDrawer ( "addNewTaskDescription" ) } </ DrawerDescription >
712- </ DrawerHeader >
713- < div className = "p-4 pb-0" >
714- < TaskForm onAddTask = { handleAddTask } />
715- </ div >
716- < DrawerFooter >
717- < DrawerClose asChild >
718- < Button variant = "outline" > { tDrawer ( "cancel" ) } </ Button >
719- </ DrawerClose >
720- </ DrawerFooter >
721- </ div >
722- </ DrawerContent >
723- </ Drawer >
716+ < Button
717+ size = "icon"
718+ onClick = { ( ) => openAddTask ( ) }
719+ className = "fab fab-pulse h-14 w-14 bg-primary hover:bg-primary/90 text-primary-foreground transition-transform active:scale-95"
720+ >
721+ < Plus className = "h-6 w-6" />
722+ < span className = "sr-only" > { tDrawer ( "addTaskSrOnly" ) } </ span >
723+ </ Button >
724724 </ div >
725725
726+ { isAddTaskOpen && (
727+ < LazyBoundary fallback = { null } >
728+ < Suspense fallback = { null } >
729+ < TaskEditDialog
730+ task = { blankTask }
731+ mode = "create"
732+ open = { isAddTaskOpen }
733+ onOpenChange = { setIsAddTaskOpen }
734+ onSave = { handleCreateTask }
735+ />
736+ </ Suspense >
737+ </ LazyBoundary >
738+ ) }
739+
726740 { isExportDialogOpen && (
727741 < LazyBoundary fallback = { null } >
728742 < Suspense fallback = { null } >
@@ -755,10 +769,7 @@ export const TaskContainer = () => {
755769 onOpenChange = { setIsPaletteOpen }
756770 viewMode = { viewMode }
757771 onViewModeChange = { setViewMode }
758- onNewTask = { ( ) => {
759- if ( isMobile ) setIsDrawerOpen ( true ) ;
760- else taskFormInputRef . current ?. focus ( ) ;
761- } }
772+ onNewTask = { ( ) => openAddTask ( ) }
762773 />
763774 </ Suspense >
764775 </ LazyBoundary >
0 commit comments