vkashti / app / admin / tasks / TasksProvider.tsx
TasksProvider.tsx
Raw
'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;
}