'use client';
import React, { createContext, useCallback, useContext, useEffect, useState } from 'react';
import { createClient } from '@/utils/supabase/client';
export type Task = {
id: string;
created_at: string;
name: string;
start_date: string;
interval: number;
difficulty: number;
time: string;
};
type Filters = {
intervalRange: [number, number];
difficultyRange: [number, number];
timeRange: [string, string];
};
type TasksContextType = {
tasks: Task[];
filters: Filters;
setFilters: (filters: Filters) => void;
fetchTasks: () => void;
updateTask: (id: string, updatedFields: Partial<Task>) => void;
createTask: () => Promise<string | null>;
deleteTask: (id: string) => void;
view: 'grid' | 'list';
setView: (view: 'grid' | 'list') => void;
isDialogOpen: boolean;
setIsDialogOpen: (isOpen: boolean) => void;
selectedTask: Task | undefined;
setSelectedTask: (task: Task | undefined) => void;
};
const TasksContext = createContext<TasksContextType | null>(null);
export function TasksProvider({ children }: { children: React.ReactNode }) {
const supabase = createClient();
const [tasks, setTasks] = useState<Task[]>([]);
const [filters, setFilters] = useState<Filters>({
intervalRange: [1, 30],
difficultyRange: [1, 5],
timeRange: ['00:00', '23:59']
});
const [view, setView] = useState<'grid' | 'list'>('grid');
const [isDialogOpen, setIsDialogOpen] = useState(false);
const [selectedTask, setSelectedTask] = useState<Task | undefined>();
const fetchTasks = useCallback(async () => {
const { data, error } = await supabase
.from('tasks' as any)
.select('*')
.gte('interval', filters.intervalRange[0])
.lte('interval', filters.intervalRange[1])
.gte('difficulty', filters.difficultyRange[0])
.lte('difficulty', filters.difficultyRange[1])
.gte('time', filters.timeRange[0])
.lte('time', filters.timeRange[1])
.order('start_date', { ascending: true });
if (error) {
console.error('Error fetching tasks:', error.message);
return;
}
// @ts-ignore
setTasks((data as Task[]) || []);
}, [filters, supabase]);
useEffect(() => {
fetchTasks();
}, [fetchTasks]);
const updateTask = async (id: string, updatedFields: Partial<Task>) => {
const { error } = await supabase
.from('tasks' as any)
.update(updatedFields)
.eq('id', id);
if (error) {
console.error('Error updating task:', error.message);
return;
}
setTasks((prev: Task[]) =>
prev.map((task) => (task.id === id ? { ...task, ...updatedFields } : task))
);
};
const createTask = async (): Promise<string | null> => {
const newTask: Partial<Task> = {
name: 'Нова задача',
start_date: new Date().toISOString(),
interval: 7,
difficulty: 1,
time: '09:00'
};
const { data, error } = await supabase
.from('tasks' as any)
.insert([newTask])
.select();
if (error) {
console.error('Error creating task:', error.message);
return null;
}
const createdTask = data?.[0];
if (createdTask && typeof createdTask === 'object' && 'id' in createdTask) {
setTasks((prev: Task[]) => [...prev, createdTask as Task]);
return (createdTask as Task).id || null;
}
return null;
};
const deleteTask = async (id: string) => {
const { error } = await supabase.from('tasks' as any).delete().eq('id', id);
if (error) {
console.error('Error deleting task:', error.message);
return;
}
setTasks((prev: Task[]) => prev.filter((task) => task.id !== id));
};
return (
<TasksContext.Provider
value={{
tasks,
filters,
setFilters,
fetchTasks,
updateTask,
createTask,
deleteTask,
view,
setView,
isDialogOpen,
setIsDialogOpen,
selectedTask,
setSelectedTask
}}
>
{children}
</TasksContext.Provider>
);
}
export function useTasks() {
const context = useContext(TasksContext);
if (!context) {
throw new Error('useTasks must be used within a TasksProvider');
}
return context;
}