import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { PlayIcon, XMarkIcon, ArrowPathIcon, SparklesIcon, } from '@heroicons/react/24/outline'; import { FolderIcon } from '@heroicons/react/24/solid'; import { Task } from '../../entities/Task'; import { useToast } from '../Shared/ToastContext'; interface NextTaskSuggestionProps { metrics: { tasks_due_today: Task[]; suggested_tasks: Task[]; tasks_in_progress: Task[]; today_plan_tasks?: Task[]; }; projects: any[]; onTaskUpdate: (task: Task) => Promise; onClose?: () => void; } const NextTaskSuggestion: React.FC = ({ metrics, projects, onTaskUpdate, onClose, }) => { const { t } = useTranslation(); const { showSuccessToast } = useToast(); const [isUpdating, setIsUpdating] = useState(false); const [currentTaskIndex, setCurrentTaskIndex] = useState(0); // Check if there are any tasks in progress // If there are tasks in progress, don't show the suggestion if (metrics.tasks_in_progress.length > 0) { return null; } // Helper function to check if task is not started const isNotStarted = (task: Task) => { return task.status === 'not_started' || task.status === 0; }; // Get all available tasks in priority order: // 1. Today plan tasks (user's intentional selection for today) // 2. Due today tasks (time-based urgency) // 3. Suggested tasks from today page (algorithm recommendations) const todayPlanAvailable = (metrics.today_plan_tasks || []).filter( isNotStarted ); const dueTodayAvailable = metrics.tasks_due_today.filter(isNotStarted); const suggestedAvailable = metrics.suggested_tasks.filter(isNotStarted); // Combine all available tasks with priority (intelligent selection) const allAvailableTasks = [ ...todayPlanAvailable.map((task) => ({ task, source: 'today_plan' })), ...dueTodayAvailable.map((task) => ({ task, source: 'due_today' })), ...suggestedAvailable.map((task) => ({ task, source: 'suggested' })), ]; if (allAvailableTasks.length === 0) { return null; } // Get current task based on index, wrap around if needed const currentTaskData = allAvailableTasks[currentTaskIndex % allAvailableTasks.length]; const suggestedTask = currentTaskData.task; const suggestionSource = currentTaskData.source; // Helper function to get project name const getProjectName = (task: Task) => { if (task.Project) { return task.Project.name; } if (task.project_id) { const project = projects.find((p) => p.id === task.project_id); return project?.name; } return null; }; const handleStartTask = async () => { if (!suggestedTask || !suggestedTask.id) return; setIsUpdating(true); try { // Universal rule: when setting status to in_progress, also add to today const updatedTask = { ...suggestedTask, status: 'in_progress' as const, today: true, }; await onTaskUpdate(updatedTask); showSuccessToast( t('task.startedSuccessfully', 'Task started successfully!') ); } catch (error) { console.error('Error starting task:', error); } finally { setIsUpdating(false); } }; const handleGiveMeSomethingElse = () => { setCurrentTaskIndex((prev) => prev + 1); }; return (
{onClose && ( )}

{suggestionSource === 'today_plan' && t( 'nextTask.suggestionTodayPlan', 'Since there is nothing in progress, what about starting with this task from your today plan' )} {suggestionSource === 'due_today' && t( 'nextTask.suggestionDueToday', 'Since there is nothing in progress, what about starting with this task due today' )} {suggestionSource === 'suggested' && t( 'nextTask.suggestionSuggested', 'Since there is nothing in progress, what about starting with this suggested task' )}

{suggestedTask.name}

{getProjectName(suggestedTask) && (

{getProjectName(suggestedTask)}

)} {suggestedTask.due_date && (

{t('forms.task.labels.dueDate', 'Due')}:{' '} {new Date( suggestedTask.due_date ).toLocaleDateString()}

)}
{allAvailableTasks.length > 1 && ( )}
); }; export default NextTaskSuggestion;