Add src/components/AppProvider.tsx
This commit is contained in:
143
src/components/AppProvider.tsx
Normal file
143
src/components/AppProvider.tsx
Normal file
@@ -0,0 +1,143 @@
|
||||
'use client';
|
||||
|
||||
import { createContext, useContext, useState, useCallback, type ReactNode, type Dispatch, type SetStateAction } from 'react';
|
||||
|
||||
export type ViewType = 'list' | 'kanban' | 'calendar';
|
||||
|
||||
export interface Task {
|
||||
id: string;
|
||||
projectId: string | null;
|
||||
title: string;
|
||||
description: string;
|
||||
completed: boolean;
|
||||
priority: 'low' | 'medium' | 'high' | 'urgent';
|
||||
dueDate: string | null;
|
||||
status: 'todo' | 'in_progress' | 'done';
|
||||
parentTaskId: string | null;
|
||||
recurrenceRule: 'none' | 'daily' | 'weekly' | 'biweekly' | 'monthly' | 'yearly';
|
||||
recurrenceInterval: number;
|
||||
nextOccurrence: string | null;
|
||||
sortOrder: number;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface Project {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
color: string;
|
||||
sortOrder: number;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface AppState {
|
||||
view: ViewType;
|
||||
selectedProject: string | null;
|
||||
selectedTask: Task | null;
|
||||
searchQuery: string;
|
||||
sidebarOpen: boolean;
|
||||
showNewTaskModal: boolean;
|
||||
showEditTaskModal: boolean;
|
||||
showNewProjectModal: boolean;
|
||||
showRecurrenceModal: boolean;
|
||||
editingTask: Task | null;
|
||||
filterStatus: string;
|
||||
filterPriority: string;
|
||||
filterDueBefore: string;
|
||||
filterDueAfter: string;
|
||||
filterCompleted: string;
|
||||
tasks: Task[];
|
||||
projects: Project[];
|
||||
setView: (view: ViewType) => void;
|
||||
setSelectedProject: (project: string | null) => void;
|
||||
setSelectedTask: (task: Task | null) => void;
|
||||
setSearchQuery: (query: string) => void;
|
||||
setSidebarOpen: (open: boolean) => void;
|
||||
setShowNewTaskModal: (show: boolean) => void;
|
||||
setShowEditTaskModal: (show: boolean) => void;
|
||||
setShowNewProjectModal: (show: boolean) => void;
|
||||
setShowRecurrenceModal: (show: boolean) => void;
|
||||
setEditingTask: (task: Task | null) => void;
|
||||
setFilterStatus: (status: string) => void;
|
||||
setFilterPriority: (priority: string) => void;
|
||||
setFilterDueBefore: (date: string) => void;
|
||||
setFilterDueAfter: (date: string) => void;
|
||||
setFilterCompleted: (completed: string) => void;
|
||||
setTasks: Dispatch<SetStateAction<Task[]>>;
|
||||
setProjects: Dispatch<SetStateAction<Project[]>>;
|
||||
refreshTasks: () => Promise<void>;
|
||||
refreshProjects: () => Promise<void>;
|
||||
}
|
||||
|
||||
const AppContext = createContext<AppState | null>(null);
|
||||
|
||||
export function useApp() {
|
||||
const context = useContext(AppContext);
|
||||
if (!context) throw new Error('useApp must be used within AppProvider');
|
||||
return context;
|
||||
}
|
||||
|
||||
export default function AppProvider({ children }: { children: ReactNode }) {
|
||||
const [view, setView] = useState<ViewType>('list');
|
||||
const [selectedProject, setSelectedProject] = useState<string | null>(null);
|
||||
const [selectedTask, setSelectedTask] = useState<Task | null>(null);
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [sidebarOpen, setSidebarOpen] = useState(true);
|
||||
const [showNewTaskModal, setShowNewTaskModal] = useState(false);
|
||||
const [showEditTaskModal, setShowEditTaskModal] = useState(false);
|
||||
const [showNewProjectModal, setShowNewProjectModal] = useState(false);
|
||||
const [showRecurrenceModal, setShowRecurrenceModal] = useState(false);
|
||||
const [editingTask, setEditingTask] = useState<Task | null>(null);
|
||||
const [filterStatus, setFilterStatus] = useState('');
|
||||
const [filterPriority, setFilterPriority] = useState('');
|
||||
const [filterDueBefore, setFilterDueBefore] = useState('');
|
||||
const [filterDueAfter, setFilterDueAfter] = useState('');
|
||||
const [filterCompleted, setFilterCompleted] = useState('');
|
||||
const [tasks, setTasks] = useState<Task[]>([]);
|
||||
const [projects, setProjects] = useState<Project[]>([]);
|
||||
|
||||
const refreshTasks = useCallback(async () => {
|
||||
try {
|
||||
const params = new URLSearchParams();
|
||||
if (selectedProject) params.set('project', selectedProject);
|
||||
if (searchQuery) params.set('search', searchQuery);
|
||||
if (filterStatus) params.set('status', filterStatus);
|
||||
if (filterPriority) params.set('priority', filterPriority);
|
||||
if (filterDueBefore) params.set('due_before', filterDueBefore);
|
||||
if (filterDueAfter) params.set('due_after', filterDueAfter);
|
||||
if (filterCompleted) params.set('completed', filterCompleted);
|
||||
|
||||
const res = await fetch(`/api/tasks?${params}`);
|
||||
const data = await res.json();
|
||||
setTasks(data);
|
||||
} catch (error) {
|
||||
console.error('Failed to refresh tasks:', error);
|
||||
}
|
||||
}, [selectedProject, searchQuery, filterStatus, filterPriority, filterDueBefore, filterDueAfter, filterCompleted]);
|
||||
|
||||
const refreshProjects = useCallback(async () => {
|
||||
try {
|
||||
const res = await fetch('/api/projects');
|
||||
const data = await res.json();
|
||||
setProjects(data);
|
||||
} catch (error) {
|
||||
console.error('Failed to refresh projects:', error);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const value: AppState = {
|
||||
view, selectedProject, selectedTask, searchQuery, sidebarOpen,
|
||||
showNewTaskModal, showEditTaskModal, showNewProjectModal, showRecurrenceModal,
|
||||
editingTask, filterStatus, filterPriority, filterDueBefore, filterDueAfter, filterCompleted,
|
||||
tasks, projects,
|
||||
setView, setSelectedProject, setSelectedTask, setSearchQuery, setSidebarOpen,
|
||||
setShowNewTaskModal, setShowEditTaskModal, setShowNewProjectModal, setShowRecurrenceModal,
|
||||
setEditingTask, setFilterStatus, setFilterPriority, setFilterDueBefore, setFilterDueAfter,
|
||||
setFilterCompleted, setTasks, setProjects,
|
||||
refreshTasks, refreshProjects,
|
||||
};
|
||||
|
||||
return <AppContext.Provider value={value}>{children}</AppContext.Provider>;
|
||||
}
|
||||
Reference in New Issue
Block a user