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
+257
View File
@@ -0,0 +1,257 @@
import { useState } from 'react';
import { queryClient } from "./lib/queryClient";
import { QueryClientProvider } from "@tanstack/react-query";
import { Toaster } from "@/components/ui/toaster";
import { TooltipProvider } from "@/components/ui/tooltip";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
// Components
import BottomNavigation from './components/BottomNavigation';
import TaskCreationModal from './components/TaskCreationModal';
import TaskList from './components/TaskList';
import CalendarView from './components/CalendarView';
import KanbanBoard from './components/KanbanBoard';
import ProjectTemplate from './components/ProjectTemplate';
import ThemeToggle from './components/ThemeToggle';
import { Task } from './components/TaskCard';
import { addDays, subDays } from 'date-fns';
// Mock data for prototype
const initialTasks: Task[] = [
{
id: '1',
title: 'Review quarterly reports',
description: 'Analyze Q3 performance metrics and prepare summary',
status: 'todo',
priority: 'high',
dueDate: addDays(new Date(), 2),
timeTracked: 0,
isTracking: false,
projectId: 'project-1'
},
{
id: '2',
title: 'Update mobile app interface',
description: 'Implement new design system and improve user experience',
status: 'inProgress',
priority: 'high',
dueDate: addDays(new Date(), 1),
timeTracked: 120,
isTracking: true,
projectId: 'project-2'
},
{
id: '3',
title: 'Team standup meeting',
status: 'todo',
priority: 'low',
dueDate: new Date(),
timeTracked: 0,
isTracking: false
},
{
id: '4',
title: 'Fix critical login bug',
description: 'Users unable to login with special characters in password',
status: 'todo',
priority: 'high',
dueDate: subDays(new Date(), 1),
timeTracked: 30,
isTracking: false,
projectId: 'project-2'
},
{
id: '5',
title: 'Deploy new features',
status: 'done',
priority: 'medium',
dueDate: subDays(new Date(), 2),
timeTracked: 120,
isTracking: false,
projectId: 'project-1'
}
];
function App() {
const [currentTab, setCurrentTab] = useState('tasks');
const [tasks, setTasks] = useState<Task[]>(initialTasks);
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
const handleCreateTask = (newTask: Partial<Task>) => {
const task: Task = {
id: Date.now().toString(),
title: newTask.title || '',
description: newTask.description,
status: 'todo',
priority: newTask.priority || 'medium',
dueDate: newTask.dueDate,
timeTracked: 0,
isTracking: false,
projectId: newTask.projectId
};
setTasks(prev => [...prev, task]);
console.log('Task created:', task);
};
const handleTaskUpdate = (taskId: string, updates: Partial<Task>) => {
setTasks(prev => prev.map(task =>
task.id === taskId ? { ...task, ...updates } : task
));
console.log('Task updated:', taskId, updates);
};
const handleTaskStatusChange = (taskId: string, newStatus: Task['status']) => {
handleTaskUpdate(taskId, { status: newStatus });
};
const handleTaskDrop = (taskId: string, newDate: Date) => {
handleTaskUpdate(taskId, { dueDate: newDate });
};
const handleCreateFromTemplate = (templateId: string, startDate: Date, projectName: string) => {
console.log('Creating project from template:', { templateId, startDate, projectName });
// In a real app, this would create multiple tasks based on the template
};
const renderContent = () => {
switch (currentTab) {
case 'tasks':
return (
<TaskList
tasks={tasks}
onTaskUpdate={handleTaskUpdate}
onTaskEdit={(task) => console.log('Edit task:', task.title)}
/>
);
case 'calendar':
return (
<CalendarView
tasks={tasks}
onTaskDrop={handleTaskDrop}
onDateSelect={(date) => console.log('Date selected:', date.toLocaleDateString())}
/>
);
case 'kanban':
return (
<KanbanBoard
tasks={tasks}
onTaskStatusChange={handleTaskStatusChange}
onTaskUpdate={handleTaskUpdate}
/>
);
case 'templates':
return (
<ProjectTemplate
onCreateFromTemplate={handleCreateFromTemplate}
/>
);
case 'settings':
return (
<div className="space-y-6">
<div className="space-y-4">
<h2 className="text-lg font-semibold">Settings</h2>
<Card className="p-4">
<div className="flex items-center justify-between">
<div>
<h3 className="font-semibold">Dark Mode</h3>
<p className="text-sm text-muted-foreground">Toggle between light and dark themes</p>
</div>
<ThemeToggle />
</div>
</Card>
<Card className="p-4">
<div className="space-y-3">
<h3 className="font-semibold">About TaskFlow</h3>
<p className="text-sm text-muted-foreground">
A personal task management app with calendar scheduling, kanban boards, and project templates.
</p>
<div className="text-xs text-muted-foreground">
Version 1.0.0 Built with React and Tailwind CSS
</div>
</div>
</Card>
</div>
</div>
);
default:
return (
<div className="text-center py-8">
<p className="text-muted-foreground">Page not found</p>
</div>
);
}
};
return (
<QueryClientProvider client={queryClient}>
<TooltipProvider>
<div className="min-h-screen bg-background">
{/* Header */}
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="flex h-16 items-center justify-between px-4">
<div className="flex items-center gap-2">
<div className="w-8 h-8 bg-primary rounded-lg flex items-center justify-center">
<span className="text-primary-foreground font-bold text-sm">T</span>
</div>
<h1 className="text-lg font-semibold" data-testid="text-app-title">
TaskFlow
</h1>
</div>
<div className="flex items-center gap-2">
{currentTab === 'templates' && (
<Button
variant="outline"
size="sm"
onClick={() => setCurrentTab('tasks')}
data-testid="button-back-to-tasks"
>
Back to Tasks
</Button>
)}
<ThemeToggle />
</div>
</div>
</header>
{/* Main Content */}
<main className="pb-20 px-4 py-6">
{renderContent()}
</main>
{/* Bottom Navigation */}
<BottomNavigation
activeTab={currentTab}
onTabChange={(tab) => {
if (tab === 'templates') {
setCurrentTab('templates');
} else {
setCurrentTab(tab);
}
}}
onCreateTask={() => setIsCreateModalOpen(true)}
/>
{/* Task Creation Modal */}
<TaskCreationModal
isOpen={isCreateModalOpen}
onClose={() => setIsCreateModalOpen(false)}
onSave={handleCreateTask}
/>
</div>
<Toaster />
</TooltipProvider>
</QueryClientProvider>
);
}
export default App;