/Users/khalidbinkalban/my-workspace/client/src/components/RightPanel.jsx:152:                        {over ? '⚠ Overdue · ' : ''}{formatDate(t.due_date)}
/Users/khalidbinkalban/my-workspace/client/src/components/Today.jsx:68:              {overdue ? '⚠ ' : ''}{formatDate(task.due_date)}
/Users/khalidbinkalban/my-workspace/client/src/components/Today.jsx:212:              { label: 'Active Projects', value: stats?.activeProjects ?? '—', icon: '🏗' },
/Users/khalidbinkalban/my-workspace/client/src/components/Today.jsx:213:              { label: 'Open Tasks',      value: stats?.openTasks ?? '—',      icon: '✅' },
/Users/khalidbinkalban/my-workspace/client/src/components/Today.jsx:214:              { label: 'Follow-ups',      value: stats?.openFollowUps ?? '—',  icon: '🔔' },
/Users/khalidbinkalban/my-workspace/client/src/components/Today.jsx:215:              { label: "Today's Focus",   value: stats?.todayFocus ?? '—',     icon: '🎯' },
/Users/khalidbinkalban/my-workspace/client/src/components/TaskCard.jsx:73:                  {overdue && '⚠ '}{formatDate(task.due_date)}
/Users/khalidbinkalban/my-workspace/client/src/components/Inbox.jsx:222:                💡 Suggested project: {editParsed.projectHint}
/Users/khalidbinkalban/my-workspace/client/index.html:10:    <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🏢</text></svg>" />
/Users/khalidbinkalban/my-workspace/client/src/components/RightPanel.jsx:152:                        {over ? '⚠ Overdue · ' : ''}{formatDate(t.due_date)}
/Users/khalidbinkalban/my-workspace/client/src/components/Today.jsx:68:              {overdue ? '⚠ ' : ''}{formatDate(task.due_date)}
/Users/khalidbinkalban/my-workspace/client/src/components/Today.jsx:212:              { label: 'Active Projects', value: stats?.activeProjects ?? '—', icon: '🏗' },
/Users/khalidbinkalban/my-workspace/client/src/components/Today.jsx:213:              { label: 'Open Tasks',      value: stats?.openTasks ?? '—',      icon: '✅' },
/Users/khalidbinkalban/my-workspace/client/src/components/Today.jsx:214:              { label: 'Follow-ups',      value: stats?.openFollowUps ?? '—',  icon: '🔔' },
/Users/khalidbinkalban/my-workspace/client/src/components/Today.jsx:215:              { label: "Today's Focus",   value: stats?.todayFocus ?? '—',     icon: '🎯' },
/Users/khalidbinkalban/my-workspace/client/src/components/TaskCard.jsx:73:                  {overdue && '⚠ '}{formatDate(task.due_date)}
/Users/khalidbinkalban/my-workspace/client/src/components/Inbox.jsx:222:                💡 Suggested project: {editParsed.projectHint}


200	                <Zap size={18} className="text-violet-600" />
201

202

203
DEWA AI Workspace

204
{dateLabel}

205

206

207

208
209	          {/* Stats row */}
210

211	            {[
212	              { label: 'Active Projects', value: stats?.activeProjects ?? '—', icon: '🏗' },
213	              { label: 'Open Tasks',      value: stats?.openTasks ?? '—',      icon: '✅' },
214	              { label: 'Follow-ups',      value: stats?.openFollowUps ?? '—',  icon: '🔔' },
215	              { label: "Today's Focus",   value: stats?.todayFocus ?? '—',     icon: '🎯' },
216	            ].map(({ label, value, icon }) => (
217

218
{value}

219
{icon} {label}

220

221	            ))}
222

223

224

225
226	      {/* ── Tabs ────────────────────────────────────────────────────── */}
227

228	        {TABS.map(t => (
229	          <button

<Zap size={18} className="text-violet-600" />

DEWA AI Workspace

{dateLabel}

          {/* Stats row */}

            {[
              { label: 'Active Projects', value: stats?.activeProjects ?? '—', icon: '🏗' },
              { label: 'Open Tasks',      value: stats?.openTasks ?? '—',      icon: '✅' },
              { label: 'Follow-ups',      value: stats?.openFollowUps ?? '—',  icon: '🔔' },
              { label: "Today's Focus",   value: stats?.todayFocus ?? '—',     icon: '🎯' },
            ].map(({ label, value, icon }) => (

{value}

{icon} {label}

            ))}

      {/* ── Tabs ────────────────────────────────────────────────────── */}

        {TABS.map(t => (
          <button


60	          )}
61	          {task.assignee && {task.assignee}}
62

63
64

65	          {task.due_date && (
66	            <span className={`flex items-center gap-1 text-[10px] ${overdue ? 'text-red-500 font-semibold' : 'text-gray-400'}`}>
67	              <Calendar size={10} />
68	              {overdue ? '⚠ ' : ''}{formatDate(task.due_date)}
69
70	          )}
71	          {task.status !== 'Done' && (
72	            <button
73	              onClick={() => onMarkDone(task)}
74	              className="opacity-0 group-hover:opacity-100 text-[10px] px-2 py-0.5 bg-green-100 text-green-700 rounded-full hover:bg-green-200 transition-all font-medium"

)}
          {task.assignee && {task.assignee}}

          {task.due_date && (
            <span className={`flex items-center gap-1 text-[10px] ${overdue ? 'text-red-500 font-semibold' : 'text-gray-400'}`}>
              <Calendar size={10} />
              {overdue ? '⚠ ' : ''}{formatDate(task.due_date)}

          )}
          {task.status !== 'Done' && (
            <button
              onClick={() => onMarkDone(task)}
              className="opacity-0 group-hover:opacity-100 text-[10px] px-2 py-0.5 bg-green-100 text-green-700 rounded-full hover:bg-green-200 transition-all font-medium"


All emojis found. Now fix them all in parallel:


Edit

import { Plus, MoreHorizontal, MessageSquare, Paperclip, User, Calendar, Zap, Target, ArrowRight } from 'lucide-react';

import { Plus, MoreHorizontal, User, Calendar, Zap, ArrowRight, FolderKanban, CheckSquare, Bell, Target, AlertTriangle } from 'lucide-react';


The file /Users/khalidbinkalban/my-workspace/client/src/components/Today.jsx has been updated successfully.

import { useState, useEffect, useCallback } from 'react';
import { Plus, MoreHorizontal, MessageSquare, Paperclip, User, Calendar, Zap, Target, ArrowRight } from 'lucide-react';
import { Link, useNavigate } from 'react-router-dom';
import toast from 'react-hot-toast';
import api from '../api';
import TaskModal from './TaskModal';
import ConfirmDialog from './ConfirmDialog';
import { getCategoryClass, getPriorityClass, CATEGORIES, formatDate, isOverdue } from '../utils';

// ─── Kanban Task Card ───────────────────────────────────────────────────────
function KanbanCard({ task, onEdit, onDelete, onToggleFocus, onMarkDone }) {
  const overdue = isOverdue(task.due_date) && task.status !== 'Done';
  const priorityBorder = {
    Urgent: 'border-l-red-500',
    High:   'border-l-amber-400',
    Medium: 'border-l-blue-400',
    Low:    'border-l-green-400',
  }[task.priority] || 'border-l-gray-200';

  return (
    <div className={`kanban-card border-l-4 ${priorityBorder} group`}>
      {/* Top row */}

{task.title}

        <button
          onClick={() => onEdit(task)}
          className="shrink-0 opacity-0 group-hover:opacity-100 p-1 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-400 transition-all"
        >
          <MoreHorizontal size={14} />
        </button>

      {/* Notes preview */}
      {task.notes && (

{task.notes}

      )}

      {/* Tags */}

        <span className={`badge text-[10px] py-0.5 ${getCategoryClass(task.category)}`}>
          {CATEGORIES[task.category]?.label?.split(' ')[0] || task.category}

        <span className={`badge text-[10px] py-0.5 ${getPriorityClass(task.priority)}`}>{task.priority}
        {task.is_follow_up === 1 && (
          Follow-up
        )}

      {/* Footer */}

          {task.assignee ? (

              {task.assignee[0]?.toUpperCase()}

          ) : (

              <User size={10} className="text-gray-400" />

          )}
          {task.assignee && {task.assignee}}

          {task.due_date && (
            <span className={`flex items-center gap-1 text-[10px] ${overdue ? 'text-red-500 font-semibold' : 'text-gray-400'}`}>
              <Calendar size={10} />
              {overdue ? '⚠ ' : ''}{formatDate(task.due_date)}

          )}
          {task.status !== 'Done' && (
            <button
              onClick={() => onMarkDone(task)}
              className="opacity-0 group-hover:opacity-100 text-[10px] px-2 py-0.5 bg-green-100 text-green-700 rounded-full hover:bg-green-200 transition-all font-medium"
            >
              Done
            </button>
          )}

  );
}

// ─── Kanban Column ──────────────────────────────────────────────────────────
function KanbanColumn({ title, count, tasks, color, onAddTask, onEdit, onDelete, onToggleFocus, onMarkDone, emptyText }) {
  return (

      {/* Column header */}

{title}

          <span className={`text-xs font-bold px-2 py-0.5 rounded-full ${color}`}>{count}

        <button onClick={onAddTask} className="w-6 h-6 rounded-lg bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 flex items-center justify-center text-gray-400 hover:text-primary hover:border-primary transition-all shadow-sm">
          <Plus size={12} />
        </button>

      {/* Cards */}

        {tasks.length === 0 ? (

{emptyText}

        ) : (
          tasks.map(task => (
            <KanbanCard
              key={task.id}
              task={task}
              onEdit={onEdit}
              onDelete={onDelete}
              onToggleFocus={onToggleFocus}
              onMarkDone={onMarkDone}
            />
          ))
        )}

  );
}

// ─── Main Component ─────────────────────────────────────────────────────────
export default function Today() {
  const [allTasks, setAllTasks] = useState([]);
  const [stats, setStats] = useState(null);
  const [projects, setProjects] = useState([]);
  const [loading, setLoading] = useState(true);
  const [editTask, setEditTask] = useState(null);
  const [deleteTask, setDeleteTask] = useState(null);
  const [showNewTask, setShowNewTask] = useState(false);
  const [newTaskDefaults, setNewTaskDefaults] = useState({});
  const [activeTab, setActiveTab] = useState('dashboard');
  const navigate = useNavigate();

  const today = new Date();
  const dateLabel = today.toLocaleDateString('en-GB', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' });

  const load = useCallback(async () => {
    try {
      const [tasks, st, pr] = await Promise.all([
        api.get('/tasks'),
        api.get('/tasks/stats'),
        api.get('/projects'),
      ]);
      setAllTasks(tasks);
      setStats(st);
      setProjects(pr);
    } finally { setLoading(false); }
  }, []);

  useEffect(() => { load(); }, [load]);

  // ── Kanban buckets ──────────────────────────────────────────────────────
  const focusTasks     = allTasks.filter(t => t.is_today_focus && t.status !== 'Done');
  const inProgressTasks = allTasks.filter(t => !t.is_today_focus && t.status === 'In Progress');
  const followUpTasks  = allTasks.filter(t => t.is_follow_up && t.status !== 'Done' && !t.is_today_focus);

  // ── Handlers ────────────────────────────────────────────────────────────
  const toggleFocus = async (task) => { await api.patch(`/tasks/${task.id}/focus`); load(); };
  const markDone    = async (task) => {
    await api.patch(`/tasks/${task.id}/status`, { status: 'Done' });
    toast.success('✓ Marked as done');
    load();
  };
  const openNew = (defaults = {}) => { setNewTaskDefaults(defaults); setShowNewTask(true); };
  const handleSave = async (form) => {
    try {
      if (editTask?.id) { await api.put(`/tasks/${editTask.id}`, form); toast.success('Task updated'); }
      else { await api.post('/tasks', { ...form, ...newTaskDefaults }); toast.success('Task added'); }
      setEditTask(null); setShowNewTask(false); load();
    } catch (e) { toast.error(e.message); }
  };
  const handleDelete = async () => {
    await api.delete(`/tasks/${deleteTask.id}`); toast.success('Deleted');
    setDeleteTask(null); load();
  };

  const TABS = [
    { id: 'dashboard', label: 'Dashboard' },
    { id: 'focus',     label: 'Today\'s Focus' },
    { id: 'all',       label: 'All Tasks' },
    { id: 'projects',  label: 'Projects' },
  ];

  return (

      {/* ── Hero Banner ─────────────────────────────────────────────── */}

        {/* Blobs */}

                <Zap size={18} className="text-violet-600" />

DEWA AI Workspace

{dateLabel}

          {/* Stats row */}

            {[
              { label: 'Active Projects', value: stats?.activeProjects ?? '—', icon: '🏗' },
              { label: 'Open Tasks',      value: stats?.openTasks ?? '—',      icon: '✅' },
              { label: 'Follow-ups',      value: stats?.openFollowUps ?? '—',  icon: '🔔' },
              { label: "Today's Focus",   value: stats?.todayFocus ?? '—',     icon: '🎯' },
            ].map(({ label, value, icon }) => (

{value}

{icon} {label}

            ))}

      {/* ── Tabs ────────────────────────────────────────────────────── */}

        {TABS.map(t => (
          <button
            key={t.id}
            onClick={() => setActiveTab(t.id)}
            className={`px-4 py-2 rounded-xl text-sm font-medium transition-all duration-150 ${
              activeTab === t.id
                ? 'bg-primary text-white shadow-sm'
                : 'text-gray-500 dark:text-gray-400 hover:bg-white dark:hover:bg-gray-800 hover:text-gray-800 dark:hover:text-white'
            }`}
          >
            {t.label}
          </button>
        ))}

        <button onClick={() => openNew({ is_today_focus: 1 })} className="btn-primary flex items-center gap-1.5 py-2 text-xs">
          <Plus size={13} /> New Task
        </button>

      {/* ── Tab Content ─────────────────────────────────────────────── */}
      {loading ? (

          {[1,2,3].map(i =>
)}

      ) : (
        <>
          {/* DASHBOARD — Kanban */}
          {(activeTab === 'dashboard' || activeTab === 'focus') && (

              <KanbanColumn
                title="Today's Focus"
                count={focusTasks.length}
                tasks={activeTab === 'focus' ? focusTasks : focusTasks}
                color="bg-primary/15 text-primary"
                onAddTask={() => openNew({ is_today_focus: 1 })}
                onEdit={setEditTask}
                onDelete={setDeleteTask}
                onToggleFocus={toggleFocus}
                onMarkDone={markDone}
                emptyText="No tasks pinned for today. Pin urgent tasks!"
              />
              <KanbanColumn
                title="In Progress"
                count={inProgressTasks.length}
                tasks={inProgressTasks}
                color="bg-blue-100 text-blue-600"
                onAddTask={() => openNew({ status: 'In Progress' })}
                onEdit={setEditTask}
                onDelete={setDeleteTask}
                onToggleFocus={toggleFocus}
                onMarkDone={markDone}
                emptyText="No tasks in progress"
              />
              <KanbanColumn
                title="Follow-ups"
                count={followUpTasks.length}
                tasks={followUpTasks}
                color="bg-amber-100 text-amber-600"
                onAddTask={() => openNew({ is_follow_up: 1 })}
                onEdit={setEditTask}
                onDelete={setDeleteTask}
                onToggleFocus={toggleFocus}
                onMarkDone={markDone}
                emptyText="No open follow-ups"
              />

          )}

          {/* ALL TASKS — flat list */}
          {activeTab === 'all' && (

                {allTasks.filter(t => t.status !== 'Done').map(task => (

 setEditTask(task)}
                  >

                      <button onClick={e => { e.stopPropagation(); toggleFocus(task); }}
                        className={`shrink-0 w-5 h-5 rounded-full border-2 transition-all ${task.is_today_focus ? 'bg-primary border-primary' : 'border-gray-300 hover:border-primary'}`} />

{task.title}

                        <span className={`badge text-[10px] ${getPriorityClass(task.priority)}`}>{task.priority}
                        {task.assignee && {task.assignee}}

                ))}

          )}

          {/* PROJECTS — grid */}
          {activeTab === 'projects' && (

                {projects.filter(p => p.status !== 'Done').map(p => (
                  <button
                    key={p.id}
                    onClick={() => navigate(`/projects/${p.id}`)}
                    className="card-hover text-left p-4 group"
                  >

                      <span className={`badge text-[10px] ${getCategoryClass(p.category)}`}>{CATEGORIES[p.category]?.label || p.category}
                      <ArrowRight size={13} className="text-gray-300 group-hover:text-primary transition-colors" />

{p.name}

                      <span className={`font-medium ${p.priority === 'Urgent' ? 'text-red-500' : p.priority === 'High' ? 'text-amber-500' : ''}`}>{p.priority}
                      {p.open_task_count || 0} tasks

                  </button>
                ))}

          )}
        </>
      )}

      {/* Modals */}
      {(showNewTask || editTask) && (
        <TaskModal task={editTask} projects={projects} onSave={handleSave} onClose={() => { setShowNewTask(false); setEditTask(null); }} />
      )}
      {deleteTask && (
        <ConfirmDialog title="Delete task?" message={`"${deleteTask.title}"`} onConfirm={handleDelete} onCancel={() => setDeleteTask(null)} />
      )}

  );
}

-import { Plus, MoreHorizontal, MessageSquare, Paperclip, User, Calendar, Zap, Target, ArrowRight } from 'lucide-react';

+import { Plus, MoreHorizontal, User, Calendar, Zap, ArrowRight, FolderKanban, CheckSquare, Bell, Target, AlertTriangle } from 'lucide-react';


{overdue ? '⚠ ' : ''}{formatDate(task.due_date)}

{overdue && <AlertTriangle size={10} className="text-red-500" />}{formatDate(task.due_date)}


import { useState, useEffect, useCallback } from 'react';
import { Plus, MoreHorizontal, User, Calendar, Zap, ArrowRight, FolderKanban, CheckSquare, Bell, Target, AlertTriangle } from 'lucide-react';
import { Link, useNavigate } from 'react-router-dom';
import toast from 'react-hot-toast';
import api from '../api';
import TaskModal from './TaskModal';
import ConfirmDialog from './ConfirmDialog';
import { getCategoryClass, getPriorityClass, CATEGORIES, formatDate, isOverdue } from '../utils';

// ─── Kanban Task Card ───────────────────────────────────────────────────────
function KanbanCard({ task, onEdit, onDelete, onToggleFocus, onMarkDone }) {
  const overdue = isOverdue(task.due_date) && task.status !== 'Done';
  const priorityBorder = {
    Urgent: 'border-l-red-500',
    High:   'border-l-amber-400',
    Medium: 'border-l-blue-400',
    Low:    'border-l-green-400',
  }[task.priority] || 'border-l-gray-200';

  return (
    <div className={`kanban-card border-l-4 ${priorityBorder} group`}>
      {/* Top row */}

{task.title}

        <button
          onClick={() => onEdit(task)}
          className="shrink-0 opacity-0 group-hover:opacity-100 p-1 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-400 transition-all"
        >
          <MoreHorizontal size={14} />
        </button>

      {/* Notes preview */}
      {task.notes && (

{task.notes}

      )}

      {/* Tags */}

        <span className={`badge text-[10px] py-0.5 ${getCategoryClass(task.category)}`}>
          {CATEGORIES[task.category]?.label?.split(' ')[0] || task.category}

        <span className={`badge text-[10px] py-0.5 ${getPriorityClass(task.priority)}`}>{task.priority}
        {task.is_follow_up === 1 && (
          Follow-up
        )}

      {/* Footer */}

          {task.assignee ? (

              {task.assignee[0]?.toUpperCase()}

          ) : (

              <User size={10} className="text-gray-400" />

          )}
          {task.assignee && {task.assignee}}

          {task.due_date && (
            <span className={`flex items-center gap-1 text-[10px] ${overdue ? 'text-red-500 font-semibold' : 'text-gray-400'}`}>
              <Calendar size={10} />
              {overdue ? '⚠ ' : ''}{formatDate(task.due_date)}

          )}
          {task.status !== 'Done' && (
            <button
              onClick={() => onMarkDone(task)}
              className="opacity-0 group-hover:opacity-100 text-[10px] px-2 py-0.5 bg-green-100 text-green-700 rounded-full hover:bg-green-200 transition-all font-medium"
            >
              Done
            </button>
          )}

  );
}

// ─── Kanban Column ──────────────────────────────────────────────────────────
function KanbanColumn({ title, count, tasks, color, onAddTask, onEdit, onDelete, onToggleFocus, onMarkDone, emptyText }) {
  return (

      {/* Column header */}

{title}

          <span className={`text-xs font-bold px-2 py-0.5 rounded-full ${color}`}>{count}

        <button onClick={onAddTask} className="w-6 h-6 rounded-lg bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 flex items-center justify-center text-gray-400 hover:text-primary hover:border-primary transition-all shadow-sm">
          <Plus size={12} />
        </button>

      {/* Cards */}

        {tasks.length === 0 ? (

{emptyText}

        ) : (
          tasks.map(task => (
            <KanbanCard
              key={task.id}
              task={task}
              onEdit={onEdit}
              onDelete={onDelete}
              onToggleFocus={onToggleFocus}
              onMarkDone={onMarkDone}
            />
          ))
        )}

  );
}

// ─── Main Component ─────────────────────────────────────────────────────────
export default function Today() {
  const [allTasks, setAllTasks] = useState([]);
  const [stats, setStats] = useState(null);
  const [projects, setProjects] = useState([]);
  const [loading, setLoading] = useState(true);
  const [editTask, setEditTask] = useState(null);
  const [deleteTask, setDeleteTask] = useState(null);
  const [showNewTask, setShowNewTask] = useState(false);
  const [newTaskDefaults, setNewTaskDefaults] = useState({});
  const [activeTab, setActiveTab] = useState('dashboard');
  const navigate = useNavigate();

  const today = new Date();
  const dateLabel = today.toLocaleDateString('en-GB', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' });

  const load = useCallback(async () => {
    try {
      const [tasks, st, pr] = await Promise.all([
        api.get('/tasks'),
        api.get('/tasks/stats'),
        api.get('/projects'),
      ]);
      setAllTasks(tasks);
      setStats(st);
      setProjects(pr);
    } finally { setLoading(false); }
  }, []);

  useEffect(() => { load(); }, [load]);

  // ── Kanban buckets ──────────────────────────────────────────────────────
  const focusTasks     = allTasks.filter(t => t.is_today_focus && t.status !== 'Done');
  const inProgressTasks = allTasks.filter(t => !t.is_today_focus && t.status === 'In Progress');
  const followUpTasks  = allTasks.filter(t => t.is_follow_up && t.status !== 'Done' && !t.is_today_focus);

  // ── Handlers ────────────────────────────────────────────────────────────
  const toggleFocus = async (task) => { await api.patch(`/tasks/${task.id}/focus`); load(); };
  const markDone    = async (task) => {
    await api.patch(`/tasks/${task.id}/status`, { status: 'Done' });
    toast.success('✓ Marked as done');
    load();
  };
  const openNew = (defaults = {}) => { setNewTaskDefaults(defaults); setShowNewTask(true); };
  const handleSave = async (form) => {
    try {
      if (editTask?.id) { await api.put(`/tasks/${editTask.id}`, form); toast.success('Task updated'); }
      else { await api.post('/tasks', { ...form, ...newTaskDefaults }); toast.success('Task added'); }
      setEditTask(null); setShowNewTask(false); load();
    } catch (e) { toast.error(e.message); }
  };
  const handleDelete = async () => {
    await api.delete(`/tasks/${deleteTask.id}`); toast.success('Deleted');
    setDeleteTask(null); load();
  };

  const TABS = [
    { id: 'dashboard', label: 'Dashboard' },
    { id: 'focus',     label: 'Today\'s Focus' },
    { id: 'all',       label: 'All Tasks' },
    { id: 'projects',  label: 'Projects' },
  ];

  return (

      {/* ── Hero Banner ─────────────────────────────────────────────── */}

        {/* Blobs */}

                <Zap size={18} className="text-violet-600" />

DEWA AI Workspace

{dateLabel}

          {/* Stats row */}

            {[
              { label: 'Active Projects', value: stats?.activeProjects ?? '—', icon: '🏗' },
              { label: 'Open Tasks',      value: stats?.openTasks ?? '—',      icon: '✅' },
              { label: 'Follow-ups',      value: stats?.openFollowUps ?? '—',  icon: '🔔' },
              { label: "Today's Focus",   value: stats?.todayFocus ?? '—',     icon: '🎯' },
            ].map(({ label, value, icon }) => (

{value}

{icon} {label}

            ))}

      {/* ── Tabs ────────────────────────────────────────────────────── */}

        {TABS.map(t => (
          <button
            key={t.id}
            onClick={() => setActiveTab(t.id)}
            className={`px-4 py-2 rounded-xl text-sm font-medium transition-all duration-150 ${
              activeTab === t.id
                ? 'bg-primary text-white shadow-sm'
                : 'text-gray-500 dark:text-gray-400 hover:bg-white dark:hover:bg-gray-800 hover:text-gray-800 dark:hover:text-white'
            }`}
          >
            {t.label}
          </button>
        ))}

        <button onClick={() => openNew({ is_today_focus: 1 })} className="btn-primary flex items-center gap-1.5 py-2 text-xs">
          <Plus size={13} /> New Task
        </button>

      {/* ── Tab Content ─────────────────────────────────────────────── */}
      {loading ? (

          {[1,2,3].map(i =>
)}

      ) : (
        <>
          {/* DASHBOARD — Kanban */}
          {(activeTab === 'dashboard' || activeTab === 'focus') && (

              <KanbanColumn
                title="Today's Focus"
                count={focusTasks.length}
                tasks={activeTab === 'focus' ? focusTasks : focusTasks}
                color="bg-primary/15 text-primary"
                onAddTask={() => openNew({ is_today_focus: 1 })}
                onEdit={setEditTask}
                onDelete={setDeleteTask}
                onToggleFocus={toggleFocus}
                onMarkDone={markDone}
                emptyText="No tasks pinned for today. Pin urgent tasks!"
              />
              <KanbanColumn
                title="In Progress"
                count={inProgressTasks.length}
                tasks={inProgressTasks}
                color="bg-blue-100 text-blue-600"
                onAddTask={() => openNew({ status: 'In Progress' })}
                onEdit={setEditTask}
                onDelete={setDeleteTask}
                onToggleFocus={toggleFocus}
                onMarkDone={markDone}
                emptyText="No tasks in progress"
              />
              <KanbanColumn
                title="Follow-ups"
                count={followUpTasks.length}
                tasks={followUpTasks}
                color="bg-amber-100 text-amber-600"
                onAddTask={() => openNew({ is_follow_up: 1 })}
                onEdit={setEditTask}
                onDelete={setDeleteTask}
                onToggleFocus={toggleFocus}
                onMarkDone={markDone}
                emptyText="No open follow-ups"
              />

          )}

          {/* ALL TASKS — flat list */}
          {activeTab === 'all' && (

                {allTasks.filter(t => t.status !== 'Done').map(task => (

 setEditTask(task)}
                  >

                      <button onClick={e => { e.stopPropagation(); toggleFocus(task); }}
                        className={`shrink-0 w-5 h-5 rounded-full border-2 transition-all ${task.is_today_focus ? 'bg-primary border-primary' : 'border-gray-300 hover:border-primary'}`} />

{task.title}

                        <span className={`badge text-[10px] ${getPriorityClass(task.priority)}`}>{task.priority}
                        {task.assignee && {task.assignee}}

                ))}

          )}

          {/* PROJECTS — grid */}
          {activeTab === 'projects' && (

                {projects.filter(p => p.status !== 'Done').map(p => (
                  <button
                    key={p.id}
                    onClick={() => navigate(`/projects/${p.id}`)}
                    className="card-hover text-left p-4 group"
                  >

                      <span className={`badge text-[10px] ${getCategoryClass(p.category)}`}>{CATEGORIES[p.category]?.label || p.category}
                      <ArrowRight size={13} className="text-gray-300 group-hover:text-primary transition-colors" />

{p.name}

                      <span className={`font-medium ${p.priority === 'Urgent' ? 'text-red-500' : p.priority === 'High' ? 'text-amber-500' : ''}`}>{p.priority}
                      {p.open_task_count || 0} tasks

                  </button>
                ))}

          )}
        </>
      )}

      {/* Modals */}
      {(showNewTask || editTask) && (
        <TaskModal task={editTask} projects={projects} onSave={handleSave} onClose={() => { setShowNewTask(false); setEditTask(null); }} />
      )}
      {deleteTask && (
        <ConfirmDialog title="Delete task?" message={`"${deleteTask.title}"`} onConfirm={handleDelete} onCancel={() => setDeleteTask(null)} />
      )}

  );
}

-              {overdue ? '⚠ ' : ''}{formatDate(task.due_date)}

+              {overdue && <AlertTriangle size={10} className="text-red-500" />}{formatDate(task.due_date)}


{[
              { label: 'Active Projects', value: stats?.activeProjects ?? '—', icon: '🏗' },
              { label: 'Open Tasks',      value: stats?.openTasks ?? '—',      icon: '✅' },
              { label: 'Follow-ups',      value: stats?.openFollowUps ?? '—',  icon: '🔔' },
              { label: "Today's Focus",   value: stats?.todayFocus ?? '—',     icon: '🎯' },
            ].map(({ label, value, icon }) => (

{value}

{icon} {label}

            ))}

{[
              { label: 'Active Projects', value: stats?.activeProjects ?? '—', Icon: FolderKanban },
              { label: 'Open Tasks',      value: stats?.openTasks ?? '—',      Icon: CheckSquare  },
              { label: 'Follow-ups',      value: stats?.openFollowUps ?? '—',  Icon: Bell         },
              { label: "Today's Focus",   value: stats?.todayFocus ?? '—',     Icon: Target       },
            ].map(({ label, value, Icon }) => (

{value}

                  <Icon size={10} />{label}

            ))}


{[
              { label: 'Active Projects', value: stats?.activeProjects ?? '—', Icon: FolderKanban },
              { label: 'Open Tasks',      value: stats?.openTasks ?? '—',      Icon: CheckSquare  },
              { label: 'Follow-ups',      value: stats?.openFollowUps ?? '—',  Icon: Bell         },
              { label: "Today's Focus",   value: stats?.todayFocus ?? '—',     Icon: Target       },
            ].map(({ label, value, Icon }) => (

{value}

                  <Icon size={10} />{label}

            ))}

import { useState, useEffect, useCallback } from 'react';
import { Plus, MoreHorizontal, User, Calendar, Zap, ArrowRight, FolderKanban, CheckSquare, Bell, Target, AlertTriangle } from 'lucide-react';
import { Link, useNavigate } from 'react-router-dom';
import toast from 'react-hot-toast';
import api from '../api';
import TaskModal from './TaskModal';
import ConfirmDialog from './ConfirmDialog';
import { getCategoryClass, getPriorityClass, CATEGORIES, formatDate, isOverdue } from '../utils';

// ─── Kanban Task Card ───────────────────────────────────────────────────────
function KanbanCard({ task, onEdit, onDelete, onToggleFocus, onMarkDone }) {
  const overdue = isOverdue(task.due_date) && task.status !== 'Done';
  const priorityBorder = {
    Urgent: 'border-l-red-500',
    High:   'border-l-amber-400',
    Medium: 'border-l-blue-400',
    Low:    'border-l-green-400',
  }[task.priority] || 'border-l-gray-200';

  return (
    <div className={`kanban-card border-l-4 ${priorityBorder} group`}>
      {/* Top row */}

{task.title}

        <button
          onClick={() => onEdit(task)}
          className="shrink-0 opacity-0 group-hover:opacity-100 p-1 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-400 transition-all"
        >
          <MoreHorizontal size={14} />
        </button>

      {/* Notes preview */}
      {task.notes && (

{task.notes}

      )}

      {/* Tags */}

        <span className={`badge text-[10px] py-0.5 ${getCategoryClass(task.category)}`}>
          {CATEGORIES[task.category]?.label?.split(' ')[0] || task.category}

        <span className={`badge text-[10px] py-0.5 ${getPriorityClass(task.priority)}`}>{task.priority}
        {task.is_follow_up === 1 && (
          Follow-up
        )}

      {/* Footer */}

          {task.assignee ? (

              {task.assignee[0]?.toUpperCase()}

          ) : (

              <User size={10} className="text-gray-400" />

          )}
          {task.assignee && {task.assignee}}

          {task.due_date && (
            <span className={`flex items-center gap-1 text-[10px] ${overdue ? 'text-red-500 font-semibold' : 'text-gray-400'}`}>
              <Calendar size={10} />
              {overdue && <AlertTriangle size={10} className="text-red-500" />}{formatDate(task.due_date)}

          )}
          {task.status !== 'Done' && (
            <button
              onClick={() => onMarkDone(task)}
              className="opacity-0 group-hover:opacity-100 text-[10px] px-2 py-0.5 bg-green-100 text-green-700 rounded-full hover:bg-green-200 transition-all font-medium"
            >
              Done
            </button>
          )}

  );
}

// ─── Kanban Column ──────────────────────────────────────────────────────────
function KanbanColumn({ title, count, tasks, color, onAddTask, onEdit, onDelete, onToggleFocus, onMarkDone, emptyText }) {
  return (

      {/* Column header */}

{title}

          <span className={`text-xs font-bold px-2 py-0.5 rounded-full ${color}`}>{count}

        <button onClick={onAddTask} className="w-6 h-6 rounded-lg bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 flex items-center justify-center text-gray-400 hover:text-primary hover:border-primary transition-all shadow-sm">
          <Plus size={12} />
        </button>

      {/* Cards */}

        {tasks.length === 0 ? (

{emptyText}

        ) : (
          tasks.map(task => (
            <KanbanCard
              key={task.id}
              task={task}
              onEdit={onEdit}
              onDelete={onDelete}
              onToggleFocus={onToggleFocus}
              onMarkDone={onMarkDone}
            />
          ))
        )}

  );
}

// ─── Main Component ─────────────────────────────────────────────────────────
export default function Today() {
  const [allTasks, setAllTasks] = useState([]);
  const [stats, setStats] = useState(null);
  const [projects, setProjects] = useState([]);
  const [loading, setLoading] = useState(true);
  const [editTask, setEditTask] = useState(null);
  const [deleteTask, setDeleteTask] = useState(null);
  const [showNewTask, setShowNewTask] = useState(false);
  const [newTaskDefaults, setNewTaskDefaults] = useState({});
  const [activeTab, setActiveTab] = useState('dashboard');
  const navigate = useNavigate();

  const today = new Date();
  const dateLabel = today.toLocaleDateString('en-GB', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' });

  const load = useCallback(async () => {
    try {
      const [tasks, st, pr] = await Promise.all([
        api.get('/tasks'),
        api.get('/tasks/stats'),
        api.get('/projects'),
      ]);
      setAllTasks(tasks);
      setStats(st);
      setProjects(pr);
    } finally { setLoading(false); }
  }, []);

  useEffect(() => { load(); }, [load]);

  // ── Kanban buckets ──────────────────────────────────────────────────────
  const focusTasks     = allTasks.filter(t => t.is_today_focus && t.status !== 'Done');
  const inProgressTasks = allTasks.filter(t => !t.is_today_focus && t.status === 'In Progress');
  const followUpTasks  = allTasks.filter(t => t.is_follow_up && t.status !== 'Done' && !t.is_today_focus);

  // ── Handlers ────────────────────────────────────────────────────────────
  const toggleFocus = async (task) => { await api.patch(`/tasks/${task.id}/focus`); load(); };
  const markDone    = async (task) => {
    await api.patch(`/tasks/${task.id}/status`, { status: 'Done' });
    toast.success('✓ Marked as done');
    load();
  };
  const openNew = (defaults = {}) => { setNewTaskDefaults(defaults); setShowNewTask(true); };
  const handleSave = async (form) => {
    try {
      if (editTask?.id) { await api.put(`/tasks/${editTask.id}`, form); toast.success('Task updated'); }
      else { await api.post('/tasks', { ...form, ...newTaskDefaults }); toast.success('Task added'); }
      setEditTask(null); setShowNewTask(false); load();
    } catch (e) { toast.error(e.message); }
  };
  const handleDelete = async () => {
    await api.delete(`/tasks/${deleteTask.id}`); toast.success('Deleted');
    setDeleteTask(null); load();
  };

  const TABS = [
    { id: 'dashboard', label: 'Dashboard' },
    { id: 'focus',     label: 'Today\'s Focus' },
    { id: 'all',       label: 'All Tasks' },
    { id: 'projects',  label: 'Projects' },
  ];

  return (

      {/* ── Hero Banner ─────────────────────────────────────────────── */}

        {/* Blobs */}

                <Zap size={18} className="text-violet-600" />

DEWA AI Workspace

{dateLabel}

          {/* Stats row */}

            {[
              { label: 'Active Projects', value: stats?.activeProjects ?? '—', icon: '🏗' },
              { label: 'Open Tasks',      value: stats?.openTasks ?? '—',      icon: '✅' },
              { label: 'Follow-ups',      value: stats?.openFollowUps ?? '—',  icon: '🔔' },
              { label: "Today's Focus",   value: stats?.todayFocus ?? '—',     icon: '🎯' },
            ].map(({ label, value, icon }) => (

{value}

{icon} {label}

            ))}

      {/* ── Tabs ────────────────────────────────────────────────────── */}

        {TABS.map(t => (
          <button
            key={t.id}
            onClick={() => setActiveTab(t.id)}
            className={`px-4 py-2 rounded-xl text-sm font-medium transition-all duration-150 ${
              activeTab === t.id
                ? 'bg-primary text-white shadow-sm'
                : 'text-gray-500 dark:text-gray-400 hover:bg-white dark:hover:bg-gray-800 hover:text-gray-800 dark:hover:text-white'
            }`}
          >
            {t.label}
          </button>
        ))}

        <button onClick={() => openNew({ is_today_focus: 1 })} className="btn-primary flex items-center gap-1.5 py-2 text-xs">
          <Plus size={13} /> New Task
        </button>

      {/* ── Tab Content ─────────────────────────────────────────────── */}
      {loading ? (

          {[1,2,3].map(i =>
)}

      ) : (
        <>
          {/* DASHBOARD — Kanban */}
          {(activeTab === 'dashboard' || activeTab === 'focus') && (

              <KanbanColumn
                title="Today's Focus"
                count={focusTasks.length}
                tasks={activeTab === 'focus' ? focusTasks : focusTasks}
                color="bg-primary/15 text-primary"
                onAddTask={() => openNew({ is_today_focus: 1 })}
                onEdit={setEditTask}
                onDelete={setDeleteTask}
                onToggleFocus={toggleFocus}
                onMarkDone={markDone}
                emptyText="No tasks pinned for today. Pin urgent tasks!"
              />
              <KanbanColumn
                title="In Progress"
                count={inProgressTasks.length}
                tasks={inProgressTasks}
                color="bg-blue-100 text-blue-600"
                onAddTask={() => openNew({ status: 'In Progress' })}
                onEdit={setEditTask}
                onDelete={setDeleteTask}
                onToggleFocus={toggleFocus}
                onMarkDone={markDone}
                emptyText="No tasks in progress"
              />
              <KanbanColumn
                title="Follow-ups"
                count={followUpTasks.length}
                tasks={followUpTasks}
                color="bg-amber-100 text-amber-600"
                onAddTask={() => openNew({ is_follow_up: 1 })}
                onEdit={setEditTask}
                onDelete={setDeleteTask}
                onToggleFocus={toggleFocus}
                onMarkDone={markDone}
                emptyText="No open follow-ups"
              />

          )}

          {/* ALL TASKS — flat list */}
          {activeTab === 'all' && (

                {allTasks.filter(t => t.status !== 'Done').map(task => (

 setEditTask(task)}
                  >

                      <button onClick={e => { e.stopPropagation(); toggleFocus(task); }}
                        className={`shrink-0 w-5 h-5 rounded-full border-2 transition-all ${task.is_today_focus ? 'bg-primary border-primary' : 'border-gray-300 hover:border-primary'}`} />

{task.title}

                        <span className={`badge text-[10px] ${getPriorityClass(task.priority)}`}>{task.priority}
                        {task.assignee && {task.assignee}}

                ))}

          )}

          {/* PROJECTS — grid */}
          {activeTab === 'projects' && (

                {projects.filter(p => p.status !== 'Done').map(p => (
                  <button
                    key={p.id}
                    onClick={() => navigate(`/projects/${p.id}`)}
                    className="card-hover text-left p-4 group"
                  >

                      <span className={`badge text-[10px] ${getCategoryClass(p.category)}`}>{CATEGORIES[p.category]?.label || p.category}
                      <ArrowRight size={13} className="text-gray-300 group-hover:text-primary transition-colors" />

{p.name}

                      <span className={`font-medium ${p.priority === 'Urgent' ? 'text-red-500' : p.priority === 'High' ? 'text-amber-500' : ''}`}>{p.priority}
                      {p.open_task_count || 0} tasks

                  </button>
                ))}

          )}
        </>
      )}

      {/* Modals */}
      {(showNewTask || editTask) && (
        <TaskModal task={editTask} projects={projects} onSave={handleSave} onClose={() => { setShowNewTask(false); setEditTask(null); }} />
      )}
      {deleteTask && (
        <ConfirmDialog title="Delete task?" message={`"${deleteTask.title}"`} onConfirm={handleDelete} onCancel={() => setDeleteTask(null)} />
      )}

  );
}

<div className="flex items-center gap-4 sm:gap-6">

-              { label: 'Active Projects', value: stats?.activeProjects ?? '—', icon: '🏗' },

-              { label: 'Open Tasks',      value: stats?.openTasks ?? '—',      icon: '✅' },

-              { label: 'Follow-ups',      value: stats?.openFollowUps ?? '—',  icon: '🔔' },

-              { label: "Today's Focus",   value: stats?.todayFocus ?? '—',     icon: '🎯' },

-            ].map(({ label, value, icon }) => (

+              { label: 'Active Projects', value: stats?.activeProjects ?? '—', Icon: FolderKanban },

+              { label: 'Open Tasks',      value: stats?.openTasks ?? '—',      Icon: CheckSquare  },

+              { label: 'Follow-ups',      value: stats?.openFollowUps ?? '—',  Icon: Bell         },

+              { label: "Today's Focus",   value: stats?.todayFocus ?? '—',     Icon: Target       },

+            ].map(({ label, value, Icon }) => (

+                <p className="text-[10px] text-gray-600 mt-0.5 whitespace-nowrap flex items-center justify-center gap-1">

+                  <Icon size={10} />{label}


import { Pencil, Trash2, User, Calendar, MoreHorizontal } from 'lucide-react';

import { Pencil, Trash2, User, Calendar, AlertTriangle } from 'lucide-react';


The file /Users/khalidbinkalban/my-workspace/client/src/components/TaskCard.jsx has been updated successfully.

import { Pencil, Trash2, User, Calendar, MoreHorizontal } from 'lucide-react';
import { getCategoryClass, getPriorityClass, getStatusClass, isOverdue, formatDate, CATEGORIES } from '../utils';

const PRIORITY_BORDER = {
  Urgent: 'border-l-red-500',
  High:   'border-l-amber-400',
  Medium: 'border-l-blue-400',
  Low:    'border-l-green-400',
};

export default function TaskCard({ task, onEdit, onDelete, onToggleFocus, showFocus = true, compact = false }) {
  const overdue = isOverdue(task.due_date) && task.status !== 'Done';

  return (
    <div className={`kanban-card border-l-4 ${PRIORITY_BORDER[task.priority] || 'border-l-gray-200'} group ${task.status === 'Done' ? 'opacity-50' : ''}`}>

        {/* Focus toggle */}
        {showFocus && (
          <button
            onClick={() => onToggleFocus?.(task)}
            title={task.is_today_focus ? 'Remove from today' : 'Pin to today'}
            className="shrink-0 mt-0.5"
          >

          </button>
        )}

          {/* Title */}

            {task.title}

          {/* Notes */}
          {task.notes && !compact && (

{task.notes}

          )}

          {/* Badges */}

            <span className={`badge text-[10px] py-0.5 ${getPriorityClass(task.priority)}`}>{task.priority}
            <span className={`badge text-[10px] py-0.5 ${getCategoryClass(task.category)}`}>
              {CATEGORIES[task.category]?.label?.split(' ')[0] || task.category}

            <span className={`badge text-[10px] py-0.5 ${getStatusClass(task.status)}`}>{task.status}
            {task.is_follow_up === 1 && (
              Follow-up
            )}

          {/* Meta */}
          {(task.assignee || task.due_date || task.project_name) && (

              {task.assignee && (

                    {task.assignee[0]?.toUpperCase()}

                  {task.assignee}

              )}
              {task.due_date && (
                <span className={`flex items-center gap-1 text-xs ${overdue ? 'text-red-600 dark:text-red-400 font-medium' : 'text-gray-400'}`}>
                  <Calendar size={10} />
                  {overdue && '⚠ '}{formatDate(task.due_date)}

              )}
              {task.project_name && (
                · {task.project_name}
              )}

          )}

        {/* Actions */}

          {onEdit && (
            <button onClick={() => onEdit(task)} className="p-1.5 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-400 hover:text-primary transition-colors">
              <Pencil size={12} />
            </button>
          )}
          {onDelete && (
            <button onClick={() => onDelete(task)} className="p-1.5 rounded-lg hover:bg-red-50 dark:hover:bg-red-900/30 text-gray-400 hover:text-red-500 transition-colors">
              <Trash2 size={12} />
            </button>
          )}

  );
}

-import { Pencil, Trash2, User, Calendar, MoreHorizontal } from 'lucide-react';

+import { Pencil, Trash2, User, Calendar, AlertTriangle } from 'lucide-react';


{overdue && '⚠ '}{formatDate(task.due_date)}

{overdue && <AlertTriangle size={10} className="text-red-500 shrink-0" />}{formatDate(task.due_date)}


import { Pencil, Trash2, User, Calendar, AlertTriangle } from 'lucide-react';
import { getCategoryClass, getPriorityClass, getStatusClass, isOverdue, formatDate, CATEGORIES } from '../utils';

const PRIORITY_BORDER = {
  Urgent: 'border-l-red-500',
  High:   'border-l-amber-400',
  Medium: 'border-l-blue-400',
  Low:    'border-l-green-400',
};

export default function TaskCard({ task, onEdit, onDelete, onToggleFocus, showFocus = true, compact = false }) {
  const overdue = isOverdue(task.due_date) && task.status !== 'Done';

  return (
    <div className={`kanban-card border-l-4 ${PRIORITY_BORDER[task.priority] || 'border-l-gray-200'} group ${task.status === 'Done' ? 'opacity-50' : ''}`}>

        {/* Focus toggle */}
        {showFocus && (
          <button
            onClick={() => onToggleFocus?.(task)}
            title={task.is_today_focus ? 'Remove from today' : 'Pin to today'}
            className="shrink-0 mt-0.5"
          >

          </button>
        )}

          {/* Title */}

            {task.title}

          {/* Notes */}
          {task.notes && !compact && (

{task.notes}

          )}

          {/* Badges */}

            <span className={`badge text-[10px] py-0.5 ${getPriorityClass(task.priority)}`}>{task.priority}
            <span className={`badge text-[10px] py-0.5 ${getCategoryClass(task.category)}`}>
              {CATEGORIES[task.category]?.label?.split(' ')[0] || task.category}

            <span className={`badge text-[10px] py-0.5 ${getStatusClass(task.status)}`}>{task.status}
            {task.is_follow_up === 1 && (
              Follow-up
            )}

          {/* Meta */}
          {(task.assignee || task.due_date || task.project_name) && (

              {task.assignee && (

                    {task.assignee[0]?.toUpperCase()}

                  {task.assignee}

              )}
              {task.due_date && (
                <span className={`flex items-center gap-1 text-xs ${overdue ? 'text-red-600 dark:text-red-400 font-medium' : 'text-gray-400'}`}>
                  <Calendar size={10} />
                  {overdue && '⚠ '}{formatDate(task.due_date)}

              )}
              {task.project_name && (
                · {task.project_name}
              )}

          )}

        {/* Actions */}

          {onEdit && (
            <button onClick={() => onEdit(task)} className="p-1.5 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-400 hover:text-primary transition-colors">
              <Pencil size={12} />
            </button>
          )}
          {onDelete && (
            <button onClick={() => onDelete(task)} className="p-1.5 rounded-lg hover:bg-red-50 dark:hover:bg-red-900/30 text-gray-400 hover:text-red-500 transition-colors">
              <Trash2 size={12} />
            </button>
          )}

  );
}

-                  {overdue && '⚠ '}{formatDate(task.due_date)}

+                  {overdue && <AlertTriangle size={10} className="text-red-500 shrink-0" />}{formatDate(task.due_date)}


import { TrendingUp, Clock, AlertCircle, CheckCircle2, ChevronRight } from 'lucide-react';

import { TrendingUp, Clock, AlertCircle, CheckCircle2, ChevronRight, AlertTriangle } from 'lucide-react';


The file /Users/khalidbinkalban/my-workspace/client/src/components/RightPanel.jsx has been updated successfully.

import { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { TrendingUp, Clock, AlertCircle, CheckCircle2, ChevronRight } from 'lucide-react';
import api from '../api';
import { getPriorityClass, getCategoryClass, CATEGORIES, formatDate, isOverdue } from '../utils';

function MiniBar({ value, max, color = 'bg-primary' }) {
  const pct = max > 0 ? Math.min((value / max) * 100, 100) : 0;
  return (

      <div className={`h-full ${color} rounded-full transition-all duration-700`} style={{ width: `${pct}%` }} />

  );
}

const CAT_COLORS = {
  ai: 'bg-blue-500', vendor: 'bg-purple-500', gov: 'bg-amber-500',
  people: 'bg-teal-500', events: 'bg-orange-500', strategic: 'bg-green-500', adhoc: 'bg-red-500',
};

export default function RightPanel() {
  const [stats, setStats] = useState(null);
  const [weekly, setWeekly] = useState(null);
  const [projects, setProjects] = useState([]);
  const [upcoming, setUpcoming] = useState([]);
  const navigate = useNavigate();

  useEffect(() => {
    Promise.all([
      api.get('/tasks/stats'),
      api.get('/weekly-review'),
      api.get('/projects'),
      api.get('/tasks'),
    ]).then(([s, w, pr, tasks]) => {
      setStats(s);
      setWeekly(w);
      // Top 4 active projects by category diversity
      const active = pr.filter(p => p.status !== 'Done').slice(0, 4);
      setProjects(active);
      // Upcoming tasks with due dates
      const now = new Date().toISOString().split('T')[0];
      const soon = tasks
        .filter(t => t.due_date && t.status !== 'Done')
        .sort((a, b) => a.due_date.localeCompare(b.due_date))
        .slice(0, 4);
      setUpcoming(soon);
    }).catch(() => {});
  }, []);

  // Category breakdown
  const catCounts = projects.reduce((acc, p) => {
    acc[p.category] = (acc[p.category] || 0) + 1;
    return acc;
  }, {});

  return (

        {/* Executive Summary */}

Executive Summary

            {[
              { label: 'Active Projects', value: stats?.activeProjects ?? '—', color: 'text-primary', bg: 'bg-primary/10' },
              { label: 'Open Tasks',      value: stats?.openTasks ?? '—',      color: 'text-amber-600', bg: 'bg-amber-50 dark:bg-amber-900/20' },
              { label: 'Follow-ups',      value: stats?.openFollowUps ?? '—',  color: 'text-violet-600', bg: 'bg-violet-50 dark:bg-violet-900/20' },
              { label: 'Today\'s Focus',  value: stats?.todayFocus ?? '—',     color: 'text-teal-600', bg: 'bg-teal-50 dark:bg-teal-900/20' },
            ].map(({ label, value, color, bg }) => (
              <div key={label} className={`${bg} rounded-xl p-3`}>
                <p className={`text-xl font-bold ${color}`}>{value}

{label}

            ))}

        {/* This Week */}
        {weekly && (

This Week

                  <CheckCircle2 size={13} className="text-green-500" />
                  Completed

                {weekly.completedThisWeek.length}

              <MiniBar value={weekly.completedThisWeek.length} max={Math.max(weekly.completedThisWeek.length + weekly.addedThisWeek.length, 1)} color="bg-green-500" />

                  <TrendingUp size={13} className="text-blue-500" />
                  Added

                {weekly.addedThisWeek.length}

                  <AlertCircle size={13} className="text-red-500" />
                  Overdue

                {weekly.overdue.length}

        )}

        {/* Project health */}

Active Projects

            <button onClick={() => navigate('/projects')} className="text-[10px] text-primary hover:underline">View all</button>

            {projects.map(p => (
              <button
                key={p.id}
                onClick={() => navigate(`/projects/${p.id}`)}
                className="w-full text-left card p-3 hover:shadow-hover transition-all duration-200 hover:-translate-y-0.5"
              >

                  <div className={`w-2 h-2 rounded-full shrink-0 mt-1.5 ${CAT_COLORS[p.category]}`} />

{p.name}

                  <ChevronRight size={11} className="text-gray-300 shrink-0 mt-1" />

                  {p.priority}
                  {p.open_task_count} tasks

              </button>
            ))}

        {/* Upcoming due dates */}
        {upcoming.length > 0 && (

Upcoming Deadlines

              {upcoming.map(t => {
                const over = isOverdue(t.due_date);
                return (

                    <Clock size={12} className={`shrink-0 mt-0.5 ${over ? 'text-red-500' : 'text-gray-400'}`} />

{t.title}

                      <p className={`text-[10px] mt-0.5 ${over ? 'text-red-500 font-medium' : 'text-gray-400'}`}>
                        {over ? '⚠ Overdue · ' : ''}{formatDate(t.due_date)}

                );
              })}

        )}

  );
}

-import { TrendingUp, Clock, AlertCircle, CheckCircle2, ChevronRight } from 'lucide-react';

+import { TrendingUp, Clock, AlertCircle, CheckCircle2, ChevronRight, AlertTriangle } from 'lucide-react';


{over ? '⚠ Overdue · ' : ''}{formatDate(t.due_date)}

                        {over && <AlertTriangle size={9} className="text-red-500 shrink-0" />}
                        {over ? 'Overdue · ' : ''}{formatDate(t.due_date)}


                        {over && <AlertTriangle size={9} className="text-red-500 shrink-0" />}
                        {over ? 'Overdue · ' : ''}{formatDate(t.due_date)}

import { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { TrendingUp, Clock, AlertCircle, CheckCircle2, ChevronRight, AlertTriangle } from 'lucide-react';
import api from '../api';
import { getPriorityClass, getCategoryClass, CATEGORIES, formatDate, isOverdue } from '../utils';

function MiniBar({ value, max, color = 'bg-primary' }) {
  const pct = max > 0 ? Math.min((value / max) * 100, 100) : 0;
  return (

      <div className={`h-full ${color} rounded-full transition-all duration-700`} style={{ width: `${pct}%` }} />

  );
}

const CAT_COLORS = {
  ai: 'bg-blue-500', vendor: 'bg-purple-500', gov: 'bg-amber-500',
  people: 'bg-teal-500', events: 'bg-orange-500', strategic: 'bg-green-500', adhoc: 'bg-red-500',
};

export default function RightPanel() {
  const [stats, setStats] = useState(null);
  const [weekly, setWeekly] = useState(null);
  const [projects, setProjects] = useState([]);
  const [upcoming, setUpcoming] = useState([]);
  const navigate = useNavigate();

  useEffect(() => {
    Promise.all([
      api.get('/tasks/stats'),
      api.get('/weekly-review'),
      api.get('/projects'),
      api.get('/tasks'),
    ]).then(([s, w, pr, tasks]) => {
      setStats(s);
      setWeekly(w);
      // Top 4 active projects by category diversity
      const active = pr.filter(p => p.status !== 'Done').slice(0, 4);
      setProjects(active);
      // Upcoming tasks with due dates
      const now = new Date().toISOString().split('T')[0];
      const soon = tasks
        .filter(t => t.due_date && t.status !== 'Done')
        .sort((a, b) => a.due_date.localeCompare(b.due_date))
        .slice(0, 4);
      setUpcoming(soon);
    }).catch(() => {});
  }, []);

  // Category breakdown
  const catCounts = projects.reduce((acc, p) => {
    acc[p.category] = (acc[p.category] || 0) + 1;
    return acc;
  }, {});

  return (

        {/* Executive Summary */}

Executive Summary

            {[
              { label: 'Active Projects', value: stats?.activeProjects ?? '—', color: 'text-primary', bg: 'bg-primary/10' },
              { label: 'Open Tasks',      value: stats?.openTasks ?? '—',      color: 'text-amber-600', bg: 'bg-amber-50 dark:bg-amber-900/20' },
              { label: 'Follow-ups',      value: stats?.openFollowUps ?? '—',  color: 'text-violet-600', bg: 'bg-violet-50 dark:bg-violet-900/20' },
              { label: 'Today\'s Focus',  value: stats?.todayFocus ?? '—',     color: 'text-teal-600', bg: 'bg-teal-50 dark:bg-teal-900/20' },
            ].map(({ label, value, color, bg }) => (
              <div key={label} className={`${bg} rounded-xl p-3`}>
                <p className={`text-xl font-bold ${color}`}>{value}

{label}

            ))}

        {/* This Week */}
        {weekly && (

This Week

                  <CheckCircle2 size={13} className="text-green-500" />
                  Completed

                {weekly.completedThisWeek.length}

              <MiniBar value={weekly.completedThisWeek.length} max={Math.max(weekly.completedThisWeek.length + weekly.addedThisWeek.length, 1)} color="bg-green-500" />

                  <TrendingUp size={13} className="text-blue-500" />
                  Added

                {weekly.addedThisWeek.length}

                  <AlertCircle size={13} className="text-red-500" />
                  Overdue

                {weekly.overdue.length}

        )}

        {/* Project health */}

Active Projects

            <button onClick={() => navigate('/projects')} className="text-[10px] text-primary hover:underline">View all</button>

            {projects.map(p => (
              <button
                key={p.id}
                onClick={() => navigate(`/projects/${p.id}`)}
                className="w-full text-left card p-3 hover:shadow-hover transition-all duration-200 hover:-translate-y-0.5"
              >

                  <div className={`w-2 h-2 rounded-full shrink-0 mt-1.5 ${CAT_COLORS[p.category]}`} />

{p.name}

                  <ChevronRight size={11} className="text-gray-300 shrink-0 mt-1" />

                  {p.priority}
                  {p.open_task_count} tasks

              </button>
            ))}

        {/* Upcoming due dates */}
        {upcoming.length > 0 && (

Upcoming Deadlines

              {upcoming.map(t => {
                const over = isOverdue(t.due_date);
                return (

                    <Clock size={12} className={`shrink-0 mt-0.5 ${over ? 'text-red-500' : 'text-gray-400'}`} />

{t.title}

                      <p className={`text-[10px] mt-0.5 ${over ? 'text-red-500 font-medium' : 'text-gray-400'}`}>
                        {over ? '⚠ Overdue · ' : ''}{formatDate(t.due_date)}

                );
              })}

        )}

  );
}

-                        {over ? '⚠ Overdue · ' : ''}{formatDate(t.due_date)}

+                        {over && <AlertTriangle size={9} className="text-red-500 shrink-0" />}

+                        {over ? 'Overdue · ' : ''}{formatDate(t.due_date)}


import { Mic, MicOff, Sparkles, Save, Trash2, ChevronDown } from 'lucide-react';

import { Mic, MicOff, Sparkles, Save, Trash2, Lightbulb } from 'lucide-react';


The file /Users/khalidbinkalban/my-workspace/client/src/components/Inbox.jsx has been updated successfully.

import { useState, useEffect, useRef } from 'react';
import { Mic, MicOff, Sparkles, Save, Trash2, ChevronDown } from 'lucide-react';
import toast from 'react-hot-toast';
import api from '../api';
import { CATEGORIES, PRIORITIES, getCategoryClass, getPriorityClass } from '../utils';

const HISTORY_KEY = 'inbox_history';

function loadHistory() {
  try { return JSON.parse(localStorage.getItem(HISTORY_KEY) || '[]'); } catch { return []; }
}
function saveHistory(item) {
  const h = loadHistory();
  h.unshift({ ...item, savedAt: new Date().toISOString() });
  localStorage.setItem(HISTORY_KEY, JSON.stringify(h.slice(0, 5)));
}

export default function Inbox() {
  const [text, setText] = useState('');
  const [listening, setListening] = useState(false);
  const [processing, setProcessing] = useState(false);
  const [parsed, setParsed] = useState(null);
  const [editParsed, setEditParsed] = useState(null);
  const [projects, setProjects] = useState([]);
  const [history, setHistory] = useState(loadHistory);
  const recognitionRef = useRef(null);

  useEffect(() => {
    api.get('/projects').then(setProjects).catch(() => {});
  }, []);

  // Voice setup
  const startVoice = () => {
    const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
    if (!SR) { toast.error('Voice not supported in this browser'); return; }
    const r = new SR();
    r.lang = 'en-US';
    r.interimResults = false;
    r.onresult = e => setText(e.results[0][0].transcript);
    r.onerror = () => { setListening(false); toast.error('Voice capture failed'); };
    r.onend = () => setListening(false);
    recognitionRef.current = r;
    r.start();
    setListening(true);
  };

  const stopVoice = () => {
    recognitionRef.current?.stop();
    setListening(false);
  };

  const process = async () => {
    if (!text.trim()) return;
    setProcessing(true);
    try {
      const result = await api.post('/ai/parse', { text });
      setParsed(result);
      setEditParsed({ ...result });
    } catch (e) {
      toast.error('AI parsing failed: ' + e.message);
    } finally {
      setProcessing(false);
    }
  };

  const setEdit = (k, v) => setEditParsed(p => ({ ...p, [k]: v }));

  const saveToWorkspace = async () => {
    if (!editParsed) return;
    try {
      const p = editParsed;
      if (p.type === 'task') {
        await api.post('/tasks', {
          title: p.title, notes: p.details, category: p.category, priority: p.priority,
          assignee: p.assignee, due_date: p.due || '', is_follow_up: p.isFollowUp ? 1 : 0,
          is_today_focus: p.suggestedTodayFocus ? 1 : 0,
        });
        toast.success('Task saved to workspace!');
      } else if (p.type === 'note') {
        await api.post('/notes', { title: p.title, body: p.details });
        toast.success('Note saved to workspace!');
      } else if (p.type === 'project') {
        await api.post('/projects', { name: p.title, category: p.category, description: p.details, priority: p.priority });
        toast.success('Project saved to workspace!');
      }
      saveHistory({ type: p.type, title: p.title, category: p.category, priority: p.priority });
      setHistory(loadHistory());
      setParsed(null);
      setEditParsed(null);
      setText('');
    } catch (e) {
      toast.error(e.message);
    }
  };

  return (

Inbox

        Speak or type anything — AI will parse it into a task, note, or project.

      {/* Input area */}

        <textarea
          className="w-full bg-transparent border-none outline-none text-sm text-gray-900 dark:text-white placeholder-gray-400 resize-none min-h-[120px]"
          placeholder="e.g. Follow up with Hamid about WEF Lighthouse document, urgent, needs to happen this week…"
          value={text}
          onChange={e => setText(e.target.value)}
          disabled={listening}
        />

          <button
            onClick={listening ? stopVoice : startVoice}
            className={`flex items-center gap-1.5 px-3 py-2 rounded-lg text-sm font-medium transition-all ${
              listening
                ? 'bg-red-100 text-red-600 dark:bg-red-900/30 dark:text-red-400 animate-pulse'
                : 'btn-secondary'
            }`}
          >
            {listening ? <><MicOff size={14} /> Listening…</> : <><Mic size={14} /> Voice</>}
          </button>

          {text.trim() && (
            <button onClick={() => { setText(''); setParsed(null); setEditParsed(null); }} className="btn-ghost text-xs">
              Clear
            </button>
          )}
          <button
            onClick={process}
            disabled={!text.trim() || processing}
            className="btn-primary flex items-center gap-1.5"
          >
            {processing
              ? <> Parsing…</>
              : <><Sparkles size={14} /> Process</>
            }
          </button>

      {/* Parsed result */}
      {editParsed && (

            <Sparkles size={15} className="text-primary" />
            AI parsed result — review before saving

            {/* Type + Title */}

                Type
                <select className="select" value={editParsed.type} onChange={e => setEdit('type', e.target.value)}>
                  <option value="task">Task</option>
                  <option value="note">Note</option>
                  <option value="project">Project</option>
                </select>

                Title
                <input className="input" value={editParsed.title} onChange={e => setEdit('title', e.target.value)} />

            {/* Category + Priority */}

                Category
                <select className="select" value={editParsed.category} onChange={e => setEdit('category', e.target.value)}>
                  {Object.entries(CATEGORIES).map(([k, v]) => <option key={k} value={k}>{v.label}</option>)}
                </select>

                Priority
                <select className="select" value={editParsed.priority} onChange={e => setEdit('priority', e.target.value)}>
                  {PRIORITIES.map(p => <option key={p}>{p}</option>)}
                </select>

            {/* Assignee + Due */}
            {editParsed.type === 'task' && (

                  Assignee
                  <input className="input" value={editParsed.assignee || ''} onChange={e => setEdit('assignee', e.target.value)} placeholder="Person name" />

                  Due Date
                  <input type="date" className="input" value={editParsed.due || ''} onChange={e => setEdit('due', e.target.value)} />

            )}

            {/* Details */}

              Details / Notes
              <textarea className="input resize-none" rows={2} value={editParsed.details || ''} onChange={e => setEdit('details', e.target.value)} />

            {/* Checkboxes */}
            {editParsed.type === 'task' && (

                  <input type="checkbox" className="accent-primary" checked={!!editParsed.isFollowUp} onChange={e => setEdit('isFollowUp', e.target.checked)} />
                  Follow-up needed

                  <input type="checkbox" className="accent-primary" checked={!!editParsed.suggestedTodayFocus} onChange={e => setEdit('suggestedTodayFocus', e.target.checked)} />
                  Today's focus

            )}

            {/* Project hint */}
            {editParsed.projectHint && (

                💡 Suggested project: {editParsed.projectHint}

            )}

            <button onClick={() => { setParsed(null); setEditParsed(null); }} className="btn-ghost flex items-center gap-1.5">
              <Trash2 size={13} /> Discard
            </button>

            <button onClick={saveToWorkspace} className="btn-primary flex items-center gap-1.5">
              <Save size={13} /> Save to workspace
            </button>

      )}

      {/* History */}
      {history.length > 0 && (

Recently added via Inbox

            {history.map((h, i) => (

                <span className={`badge ${h.type === 'task' ? 'bg-blue-100 text-blue-700' : h.type === 'note' ? 'bg-gray-100 text-gray-700' : 'bg-green-100 text-green-700'}`}>
                  {h.type}

                {h.title}
                {new Date(h.savedAt).toLocaleDateString()}

            ))}

      )}

  );
}

-import { Mic, MicOff, Sparkles, Save, Trash2, ChevronDown } from 'lucide-react';

+import { Mic, MicOff, Sparkles, Save, Trash2, Lightbulb } from 'lucide-react';


💡 Suggested project: {editParsed.projectHint}

<Lightbulb size={12} className="shrink-0" /> Suggested project: {editParsed.projectHint}


import { useState, useEffect, useRef } from 'react';
import { Mic, MicOff, Sparkles, Save, Trash2, Lightbulb } from 'lucide-react';
import toast from 'react-hot-toast';
import api from '../api';
import { CATEGORIES, PRIORITIES, getCategoryClass, getPriorityClass } from '../utils';

const HISTORY_KEY = 'inbox_history';

function loadHistory() {
  try { return JSON.parse(localStorage.getItem(HISTORY_KEY) || '[]'); } catch { return []; }
}
function saveHistory(item) {
  const h = loadHistory();
  h.unshift({ ...item, savedAt: new Date().toISOString() });
  localStorage.setItem(HISTORY_KEY, JSON.stringify(h.slice(0, 5)));
}

export default function Inbox() {
  const [text, setText] = useState('');
  const [listening, setListening] = useState(false);
  const [processing, setProcessing] = useState(false);
  const [parsed, setParsed] = useState(null);
  const [editParsed, setEditParsed] = useState(null);
  const [projects, setProjects] = useState([]);
  const [history, setHistory] = useState(loadHistory);
  const recognitionRef = useRef(null);

  useEffect(() => {
    api.get('/projects').then(setProjects).catch(() => {});
  }, []);

  // Voice setup
  const startVoice = () => {
    const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
    if (!SR) { toast.error('Voice not supported in this browser'); return; }
    const r = new SR();
    r.lang = 'en-US';
    r.interimResults = false;
    r.onresult = e => setText(e.results[0][0].transcript);
    r.onerror = () => { setListening(false); toast.error('Voice capture failed'); };
    r.onend = () => setListening(false);
    recognitionRef.current = r;
    r.start();
    setListening(true);
  };

  const stopVoice = () => {
    recognitionRef.current?.stop();
    setListening(false);
  };

  const process = async () => {
    if (!text.trim()) return;
    setProcessing(true);
    try {
      const result = await api.post('/ai/parse', { text });
      setParsed(result);
      setEditParsed({ ...result });
    } catch (e) {
      toast.error('AI parsing failed: ' + e.message);
    } finally {
      setProcessing(false);
    }
  };

  const setEdit = (k, v) => setEditParsed(p => ({ ...p, [k]: v }));

  const saveToWorkspace = async () => {
    if (!editParsed) return;
    try {
      const p = editParsed;
      if (p.type === 'task') {
        await api.post('/tasks', {
          title: p.title, notes: p.details, category: p.category, priority: p.priority,
          assignee: p.assignee, due_date: p.due || '', is_follow_up: p.isFollowUp ? 1 : 0,
          is_today_focus: p.suggestedTodayFocus ? 1 : 0,
        });
        toast.success('Task saved to workspace!');
      } else if (p.type === 'note') {
        await api.post('/notes', { title: p.title, body: p.details });
        toast.success('Note saved to workspace!');
      } else if (p.type === 'project') {
        await api.post('/projects', { name: p.title, category: p.category, description: p.details, priority: p.priority });
        toast.success('Project saved to workspace!');
      }
      saveHistory({ type: p.type, title: p.title, category: p.category, priority: p.priority });
      setHistory(loadHistory());
      setParsed(null);
      setEditParsed(null);
      setText('');
    } catch (e) {
      toast.error(e.message);
    }
  };

  return (

Inbox

        Speak or type anything — AI will parse it into a task, note, or project.

      {/* Input area */}

        <textarea
          className="w-full bg-transparent border-none outline-none text-sm text-gray-900 dark:text-white placeholder-gray-400 resize-none min-h-[120px]"
          placeholder="e.g. Follow up with Hamid about WEF Lighthouse document, urgent, needs to happen this week…"
          value={text}
          onChange={e => setText(e.target.value)}
          disabled={listening}
        />

          <button
            onClick={listening ? stopVoice : startVoice}
            className={`flex items-center gap-1.5 px-3 py-2 rounded-lg text-sm font-medium transition-all ${
              listening
                ? 'bg-red-100 text-red-600 dark:bg-red-900/30 dark:text-red-400 animate-pulse'
                : 'btn-secondary'
            }`}
          >
            {listening ? <><MicOff size={14} /> Listening…</> : <><Mic size={14} /> Voice</>}
          </button>

          {text.trim() && (
            <button onClick={() => { setText(''); setParsed(null); setEditParsed(null); }} className="btn-ghost text-xs">
              Clear
            </button>
          )}
          <button
            onClick={process}
            disabled={!text.trim() || processing}
            className="btn-primary flex items-center gap-1.5"
          >
            {processing
              ? <> Parsing…</>
              : <><Sparkles size={14} /> Process</>
            }
          </button>

      {/* Parsed result */}
      {editParsed && (

            <Sparkles size={15} className="text-primary" />
            AI parsed result — review before saving

            {/* Type + Title */}

                Type
                <select className="select" value={editParsed.type} onChange={e => setEdit('type', e.target.value)}>
                  <option value="task">Task</option>
                  <option value="note">Note</option>
                  <option value="project">Project</option>
                </select>

                Title
                <input className="input" value={editParsed.title} onChange={e => setEdit('title', e.target.value)} />

            {/* Category + Priority */}

                Category
                <select className="select" value={editParsed.category} onChange={e => setEdit('category', e.target.value)}>
                  {Object.entries(CATEGORIES).map(([k, v]) => <option key={k} value={k}>{v.label}</option>)}
                </select>

                Priority
                <select className="select" value={editParsed.priority} onChange={e => setEdit('priority', e.target.value)}>
                  {PRIORITIES.map(p => <option key={p}>{p}</option>)}
                </select>

            {/* Assignee + Due */}
            {editParsed.type === 'task' && (

                  Assignee
                  <input className="input" value={editParsed.assignee || ''} onChange={e => setEdit('assignee', e.target.value)} placeholder="Person name" />

                  Due Date
                  <input type="date" className="input" value={editParsed.due || ''} onChange={e => setEdit('due', e.target.value)} />

            )}

            {/* Details */}

              Details / Notes
              <textarea className="input resize-none" rows={2} value={editParsed.details || ''} onChange={e => setEdit('details', e.target.value)} />

            {/* Checkboxes */}
            {editParsed.type === 'task' && (

                  <input type="checkbox" className="accent-primary" checked={!!editParsed.isFollowUp} onChange={e => setEdit('isFollowUp', e.target.checked)} />
                  Follow-up needed

                  <input type="checkbox" className="accent-primary" checked={!!editParsed.suggestedTodayFocus} onChange={e => setEdit('suggestedTodayFocus', e.target.checked)} />
                  Today's focus

            )}

            {/* Project hint */}
            {editParsed.projectHint && (

                💡 Suggested project: {editParsed.projectHint}

            )}

            <button onClick={() => { setParsed(null); setEditParsed(null); }} className="btn-ghost flex items-center gap-1.5">
              <Trash2 size={13} /> Discard
            </button>

            <button onClick={saveToWorkspace} className="btn-primary flex items-center gap-1.5">
              <Save size={13} /> Save to workspace
            </button>

      )}

      {/* History */}
      {history.length > 0 && (

Recently added via Inbox

            {history.map((h, i) => (

                <span className={`badge ${h.type === 'task' ? 'bg-blue-100 text-blue-700' : h.type === 'note' ? 'bg-gray-100 text-gray-700' : 'bg-green-100 text-green-700'}`}>
                  {h.type}

                {h.title}
                {new Date(h.savedAt).toLocaleDateString()}

            ))}

      )}

  );
}

<p className="text-xs text-gray-400 dark:text-gray-500">

-                💡 Suggested project: {editParsed.projectHint}

+                <Lightbulb size={12} className="shrink-0" /> Suggested project: {editParsed.projectHint}


Fix the favicon in index.html — replace the emoji with a proper SVG:


<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🏢</text></svg>" />


The file /Users/khalidbinkalban/my-workspace/client/index.html has been updated successfully.

<!DOCTYPE html>

    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My Workspace</title>
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
    <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🏢</text></svg>" />

-    <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🏢</text></svg>" />


Now verify no emojis remain and do a clean build:


Bash

# Check for any remaining emojis (unicode ranges for common emoji blocks)
grep -rPn "[\x{1F300}-\x{1FFFF}]|[\x{2600}-\x{27BF}]|⚠|💡|🏗|✅|🔔|🎯|🏢" \
  /Users/khalidbinkalban/my-workspace/client/src/ \
  /Users/khalidbinkalban/my-workspace/client/index.html \
  2>/dev/null && echo "FOUND" || echo "No emojis remaining"

Verify all emojis are removed


No emojis remaining


Final build check


computing gzip size...
../dist/index.html                   0.94 kB │ gzip:  0.55 kB
../dist/assets/index-D09YZN8-.css   43.22 kB │ gzip:  7.08 kB
../dist/assets/index-C8O6Wiud.js   282.41 kB │ gzip: 79.86 kB
✓ built in 1.06s


Clean build. Every emoji has been replaced:

| Was | Now |
|---|---|
| `🏗` Active Projects | `<FolderKanban>` SVG icon |
| `✅` Open Tasks | `<CheckSquare>` SVG icon |
| `🔔` Follow-ups | `<Bell>` SVG icon |
| `🎯` Today's Focus | `<Target>` SVG icon |
| `⚠` overdue dates | `<AlertTriangle>` SVG icon |
| `💡` suggested project | `<Lightbulb>` SVG icon |
| `🏢` favicon | Purple star SVG favicon |


make it flixble in drag and drop
make all the pages look horizontally and not vertically
mobile friendly


npm install @dnd-kit/core @dnd-kit/utilities 2>&1 | tail -5

Install dnd-kit packages


59 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities


You're out of extra usage · resets 12pm (Asia/Dubai)


done?


Not yet — packages installed, now writing all the code:


Write

import { useState, useEffect, useCallback } from 'react';
import {
  DndContext, DragOverlay, useDroppable, useDraggable,
  PointerSensor, TouchSensor, useSensor, useSensors, closestCenter
} from '@dnd-kit/core';
import {
  Plus, User, Calendar, Zap, ArrowRight, FolderKanban,
  CheckSquare, Bell, Target, AlertTriangle, MoreHorizontal, GripVertical
} from 'lucide-react';
import { Link, useNavigate } from 'react-router-dom';
import toast from 'react-hot-toast';
import api from '../api';
import TaskModal from './TaskModal';
import ConfirmDialog from './ConfirmDialog';
import { getCategoryClass, getPriorityClass, CATEGORIES, formatDate, isOverdue } from '../utils';

// ── Column config ────────────────────────────────────────────────────────────
const COLUMNS = [
  { id: 'focus',      title: "Today's Focus", color: 'text-primary',    bg: 'bg-primary/10',  border: 'border-l-primary'  },
  { id: 'inprogress', title: 'In Progress',   color: 'text-blue-600',   bg: 'bg-blue-50 dark:bg-blue-900/20',   border: 'border-l-blue-400'   },
  { id: 'followups',  title: 'Follow-ups',    color: 'text-amber-600',  bg: 'bg-amber-50 dark:bg-amber-900/20', border: 'border-l-amber-400'  },
  { id: 'open',       title: 'Open',          color: 'text-gray-500',   bg: 'bg-gray-100 dark:bg-gray-800',     border: 'border-l-gray-300'   },
];

const PRIORITY_BORDER = { Urgent:'border-l-red-500', High:'border-l-amber-400', Medium:'border-l-blue-400', Low:'border-l-green-400' };

function getColumnId(task) {
  if (task.status === 'Done') return null;
  if (task.is_today_focus)    return 'focus';
  if (task.status === 'In Progress') return 'inprogress';
  if (task.is_follow_up)      return 'followups';
  return 'open';
}

function columnUpdates(col, task) {
  const base = { ...task };
  if (col === 'focus')      return { ...base, is_today_focus: 1 };
  if (col === 'inprogress') return { ...base, status: 'In Progress', is_today_focus: 0 };
  if (col === 'followups')  return { ...base, is_follow_up: 1,  is_today_focus: 0 };
  if (col === 'open')       return { ...base, is_today_focus: 0, status: 'Open' };
  return base;
}

// ── Draggable card ───────────────────────────────────────────────────────────
function DraggableCard({ task, onEdit, onDelete, onMarkDone }) {
  const { attributes, listeners, setNodeRef, isDragging } = useDraggable({ id: task.id });
  const overdue = isOverdue(task.due_date);

  return (

          {/* Drag handle */}
          <button {...listeners} {...attributes}
            className="shrink-0 mt-0.5 text-gray-300 hover:text-gray-500 cursor-grab active:cursor-grabbing touch-none">
            <GripVertical size={14} />
          </button>

{task.title}

              <button onClick={() => onEdit(task)}
                className="shrink-0 opacity-0 group-hover:opacity-100 p-1 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-400 transition-all">
                <MoreHorizontal size={13} />
              </button>

            {task.notes &&
{task.notes}
}

              <span className={`badge text-[10px] py-0.5 ${getCategoryClass(task.category)}`}>
                {CATEGORIES[task.category]?.label?.split(' ')[0] || task.category}

              <span className={`badge text-[10px] py-0.5 ${getPriorityClass(task.priority)}`}>{task.priority}
              {task.is_follow_up === 1 && Follow-up}

                {task.assignee ? (

                    {task.assignee[0].toUpperCase()}

                ) :
<User size={9} className="text-gray-400" />
}
                {task.assignee && {task.assignee}}

                {task.due_date && (
                  <span className={`flex items-center gap-0.5 text-[10px] ${overdue ? 'text-red-500 font-semibold' : 'text-gray-400'}`}>
                    {overdue && <AlertTriangle size={9} />}{formatDate(task.due_date)}

                )}
                <button onClick={() => onMarkDone(task)}
                  className="opacity-0 group-hover:opacity-100 text-[10px] px-2 py-0.5 bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400 rounded-full hover:bg-green-200 transition-all font-medium">
                  Done
                </button>

  );
}

// ── Drag overlay card (ghost while dragging) ─────────────────────────────────
function OverlayCard({ task }) {
  return (

{task.title}

        <span className={`badge text-[10px] py-0.5 ${getPriorityClass(task.priority)}`}>{task.priority}
        <span className={`badge text-[10px] py-0.5 ${getCategoryClass(task.category)}`}>
          {CATEGORIES[task.category]?.label?.split(' ')[0]}

  );
}

// ── Droppable column ─────────────────────────────────────────────────────────
function DroppableColumn({ col, tasks, stats, onAddTask, onEdit, onDelete, onMarkDone }) {
  const { setNodeRef, isOver } = useDroppable({ id: col.id });

  return (

      {/* Column header */}

{col.title}

          <span className={`text-xs font-bold px-2 py-0.5 rounded-full ${col.bg} ${col.color}`}>{tasks.length}

        <button onClick={onAddTask}
          className="w-6 h-6 rounded-lg bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 flex items-center justify-center text-gray-400 hover:text-primary hover:border-primary transition-all shadow-sm">
          <Plus size={12} />
        </button>

      {/* Cards */}

        {tasks.length === 0 ? (

Drop here

        ) : (
          tasks.map(task => (
            <DraggableCard key={task.id} task={task} onEdit={onEdit} onDelete={onDelete} onMarkDone={onMarkDone} />
          ))
        )}

  );
}

// ── Main Dashboard ───────────────────────────────────────────────────────────
export default function Today() {
  const [allTasks, setAllTasks]     = useState([]);
  const [stats, setStats]           = useState(null);
  const [projects, setProjects]     = useState([]);
  const [loading, setLoading]       = useState(true);
  const [editTask, setEditTask]     = useState(null);
  const [deleteTask, setDeleteTask] = useState(null);
  const [showNew, setShowNew]       = useState(false);
  const [newDefaults, setNewDefaults] = useState({});
  const [activeTask, setActiveTask] = useState(null);
  const [activeTab, setActiveTab]   = useState('dashboard');
  const navigate = useNavigate();

  const today = new Date();
  const dateLabel = today.toLocaleDateString('en-GB', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' });

  const load = useCallback(async () => {
    try {
      const [tasks, st, pr] = await Promise.all([api.get('/tasks'), api.get('/tasks/stats'), api.get('/projects')]);
      setAllTasks(tasks); setStats(st); setProjects(pr);
    } finally { setLoading(false); }
  }, []);

  useEffect(() => { load(); }, [load]);

  // Bucket tasks into columns
  const columns = COLUMNS.map(col => ({
    ...col,
    tasks: allTasks.filter(t => getColumnId(t) === col.id),
  }));

  // DnD sensors — support mouse, touch (mobile), delay to prevent accidental drags
  const sensors = useSensors(
    useSensor(PointerSensor, { activationConstraint: { distance: 8 } }),
    useSensor(TouchSensor,   { activationConstraint: { delay: 180, tolerance: 6 } })
  );

  const onDragStart = ({ active }) => {
    setActiveTask(allTasks.find(t => t.id === active.id) || null);
  };

  const onDragEnd = async ({ active, over }) => {
    setActiveTask(null);
    if (!over) return;
    const task = allTasks.find(t => t.id === active.id);
    if (!task) return;
    const targetCol = COLUMNS.find(c => c.id === over.id);
    if (!targetCol || getColumnId(task) === targetCol.id) return;

    // Optimistic update
    const updated = columnUpdates(targetCol.id, task);
    setAllTasks(prev => prev.map(t => t.id === task.id ? { ...t, ...updated } : t));
    try {
      await api.put(`/tasks/${task.id}`, updated);
      toast.success(`Moved to "${targetCol.title}"`);
    } catch (e) {
      toast.error('Failed to move task'); load();
    }
  };

  const markDone = async (task) => {
    setAllTasks(prev => prev.map(t => t.id === task.id ? { ...t, status: 'Done' } : t));
    await api.patch(`/tasks/${task.id}/status`, { status: 'Done' });
    toast.success('Marked as done');
  };

  const openNew = (defaults = {}) => { setNewDefaults(defaults); setShowNew(true); };

  const handleSave = async (form) => {
    try {
      if (editTask?.id) { await api.put(`/tasks/${editTask.id}`, form); toast.success('Task updated'); }
      else { await api.post('/tasks', { ...form, ...newDefaults }); toast.success('Task added'); }
      setEditTask(null); setShowNew(false); load();
    } catch (e) { toast.error(e.message); }
  };

  const handleDelete = async () => {
    await api.delete(`/tasks/${deleteTask.id}`);
    toast.success('Deleted'); setDeleteTask(null); load();
  };

  const TABS = [
    { id: 'dashboard', label: 'Dashboard' },
    { id: 'all',       label: 'All Tasks'      },
    { id: 'projects',  label: 'Projects'       },
  ];

  return (

      {/* Hero banner */}

              <Zap size={17} className="text-violet-600" />

DEWA AI Workspace

{dateLabel}

            {[
              { label: 'Projects',     value: stats?.activeProjects ?? '—', Icon: FolderKanban },
              { label: 'Open Tasks',   value: stats?.openTasks      ?? '—', Icon: CheckSquare  },
              { label: 'Follow-ups',   value: stats?.openFollowUps  ?? '—', Icon: Bell         },
              { label: "Today's Focus",value: stats?.todayFocus     ?? '—', Icon: Target       },
            ].map(({ label, value, Icon }) => (

{value}

                  <Icon size={9} />{label}

            ))}

      {/* Tabs */}

        {TABS.map(t => (
          <button key={t.id} onClick={() => setActiveTab(t.id)}
            className={`px-3.5 py-1.5 rounded-xl text-sm font-medium transition-all duration-150 ${
              activeTab === t.id
                ? 'bg-primary text-white shadow-sm'
                : 'text-gray-500 dark:text-gray-400 hover:bg-white dark:hover:bg-gray-800 hover:text-gray-800 dark:hover:text-white'
            }`}>
            {t.label}
          </button>
        ))}

        <button onClick={() => openNew({ is_today_focus: 1 })} className="btn-primary flex items-center gap-1 py-1.5 text-xs">
          <Plus size={12} /> New Task
        </button>

      {/* ── Kanban Board (drag & drop) ─────────────────────────────────── */}
      {loading ? (

          {[1,2,3,4].map(i =>
)}

      ) : (
        <>
          {activeTab === 'dashboard' && (
            <DndContext sensors={sensors} collisionDetection={closestCenter} onDragStart={onDragStart} onDragEnd={onDragEnd}>
              {/* Horizontal scrollable kanban — snaps on mobile */}

                {columns.map(col => (
                  <DroppableColumn
                    key={col.id} col={col} tasks={col.tasks}
                    onAddTask={() => openNew(
                      col.id === 'focus'      ? { is_today_focus: 1 } :
                      col.id === 'inprogress' ? { status: 'In Progress' } :
                      col.id === 'followups'  ? { is_follow_up: 1 } : {}
                    )}
                    onEdit={setEditTask}
                    onDelete={setDeleteTask}
                    onMarkDone={markDone}
                  />
                ))}

              {/* Drag overlay */}
              <DragOverlay dropAnimation={{ duration: 180, easing: 'cubic-bezier(0.18,0.67,0.6,1.22)' }}>
                {activeTask && <OverlayCard task={activeTask} />}
              </DragOverlay>
            </DndContext>
          )}

          {/* ALL TASKS — horizontal grid */}
          {activeTab === 'all' && (

                {allTasks.filter(t => t.status !== 'Done').map(task => (

 setEditTask(task)}>

{task.title}

                      <span className={`badge text-[10px] py-0.5 ${getPriorityClass(task.priority)}`}>{task.priority}
                      <span className={`badge text-[10px] py-0.5 ${getCategoryClass(task.category)}`}>
                        {CATEGORIES[task.category]?.label?.split(' ')[0]}

                    {task.assignee && (

                          {task.assignee[0].toUpperCase()}

                        {task.assignee}

                    )}

                ))}

          )}

          {/* PROJECTS — horizontal grid */}
          {activeTab === 'projects' && (

                {projects.filter(p => p.status !== 'Done').map(p => (
                  <button key={p.id} onClick={() => navigate(`/projects/${p.id}`)}
                    className="card-hover text-left p-4 group">

                      <span className={`badge text-[10px] ${getCategoryClass(p.category)}`}>
                        {CATEGORIES[p.category]?.label?.split(' ')[0] || p.category}

                      <ArrowRight size={12} className="text-gray-300 group-hover:text-primary transition-colors" />

{p.name}

                      <span className={`font-semibold ${p.priority === 'Urgent' ? 'text-red-500' : p.priority === 'High' ? 'text-amber-500' : ''}`}>{p.priority}
                      {p.open_task_count || 0} tasks

                  </button>
                ))}

          )}
        </>
      )}

      {/* Modals */}
      {(showNew || editTask) && (
        <TaskModal task={editTask} projects={projects} onSave={handleSave} onClose={() => { setShowNew(false); setEditTask(null); }} />
      )}
      {deleteTask && (
        <ConfirmDialog title="Delete task?" message={`"${deleteTask.title}"`} onConfirm={handleDelete} onCancel={() => setDeleteTask(null)} />
      )}

  );
}