Add core components for task management and navigation

This commit introduces the foundational UI components and logic for the task management application, including task creation, calendar views, Kanban boards, and navigation elements.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: ceced2fc-aa46-458d-ba87-ddd4b7bb1518
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/659922a9-0087-461c-90dd-6d9a58b81d4d/ceced2fc-aa46-458d-ba87-ddd4b7bb1518/yy9YLEW
This commit is contained in:
paul-nothaft
2025-09-11 08:59:20 +00:00
parent 5d959e8ab3
commit 28ad3f1535
88 changed files with 17059 additions and 0 deletions
+152
View File
@@ -0,0 +1,152 @@
import { useState } from 'react';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Calendar } from '@/components/ui/calendar';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { CalendarIcon, Plus } from 'lucide-react';
import { Task } from './TaskCard';
interface TaskCreationModalProps {
isOpen: boolean;
onClose: () => void;
onSave: (task: Partial<Task>) => void;
}
export default function TaskCreationModal({ isOpen, onClose, onSave }: TaskCreationModalProps) {
const [title, setTitle] = useState('');
const [description, setDescription] = useState('');
const [priority, setPriority] = useState<'low' | 'medium' | 'high'>('medium');
const [dueDate, setDueDate] = useState<Date | undefined>();
const [isCalendarOpen, setIsCalendarOpen] = useState(false);
const handleSave = () => {
if (!title.trim()) return;
const newTask: Partial<Task> = {
title: title.trim(),
description: description.trim() || undefined,
priority,
dueDate,
status: 'todo',
timeTracked: 0,
isTracking: false
};
onSave(newTask);
console.log('New task created:', newTask);
// Reset form
setTitle('');
setDescription('');
setPriority('medium');
setDueDate(undefined);
onClose();
};
const handleClose = () => {
setTitle('');
setDescription('');
setPriority('medium');
setDueDate(undefined);
onClose();
};
return (
<Dialog open={isOpen} onOpenChange={handleClose}>
<DialogContent className="sm:max-w-md mx-4">
<DialogHeader>
<DialogTitle className="flex items-center gap-2">
<Plus className="w-4 h-4" />
New Task
</DialogTitle>
</DialogHeader>
<div className="space-y-4">
<div>
<Input
placeholder="What needs to be done?"
value={title}
onChange={(e) => setTitle(e.target.value)}
className="text-base"
data-testid="input-task-title"
autoFocus
/>
</div>
<div>
<Textarea
placeholder="Add a description (optional)"
value={description}
onChange={(e) => setDescription(e.target.value)}
className="resize-none text-sm"
rows={3}
data-testid="input-task-description"
/>
</div>
<div className="flex gap-3">
<div className="flex-1">
<Select value={priority} onValueChange={(value: 'low' | 'medium' | 'high') => setPriority(value)}>
<SelectTrigger data-testid="select-task-priority">
<SelectValue placeholder="Priority" />
</SelectTrigger>
<SelectContent>
<SelectItem value="low">Low</SelectItem>
<SelectItem value="medium">Medium</SelectItem>
<SelectItem value="high">High</SelectItem>
</SelectContent>
</Select>
</div>
<Popover open={isCalendarOpen} onOpenChange={setIsCalendarOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
className="flex items-center gap-2"
data-testid="button-due-date"
>
<CalendarIcon className="w-4 h-4" />
{dueDate ? dueDate.toLocaleDateString() : 'Due date'}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="end">
<Calendar
mode="single"
selected={dueDate}
onSelect={(date) => {
setDueDate(date);
setIsCalendarOpen(false);
}}
disabled={(date) => date < new Date()}
initialFocus
/>
</PopoverContent>
</Popover>
</div>
<div className="flex gap-3 pt-2">
<Button
variant="outline"
onClick={handleClose}
className="flex-1"
data-testid="button-cancel"
>
Cancel
</Button>
<Button
onClick={handleSave}
disabled={!title.trim()}
className="flex-1"
data-testid="button-save-task"
>
Create Task
</Button>
</div>
</div>
</DialogContent>
</Dialog>
);
}