Skip to content

Commit

Permalink
update tasks and project view
Browse files Browse the repository at this point in the history
  • Loading branch information
hussaino03 committed Dec 28, 2024
1 parent 9af1300 commit bb4ce79
Show file tree
Hide file tree
Showing 12 changed files with 279 additions and 141 deletions.
10 changes: 5 additions & 5 deletions client/src/components/Modal Management/Layout/List.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const TaskList = ({
difficulty: 5,
importance: 5,
deadline: null,
collaborative: false,
urgent: false,
experience: 150
});
setQuickTaskInput('');
Expand Down Expand Up @@ -179,7 +179,7 @@ const TaskList = ({
<div className="inline-flex rounded-lg bg-gray-100 dark:bg-gray-700 p-0.5 sm:p-1">
<button
onClick={() => setActiveTab('tasks')}
className={`px-2 sm:px-4 py-1.5 sm:py-2 text-xs sm:text-sm rounded-md transition-all duration-200 ${
className={`px-3 sm:px-4 py-2 sm:py-2 text-sm sm:text-sm rounded-md transition-all duration-200 ${
activeTab === 'tasks'
? 'bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-sm'
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200'
Expand All @@ -189,7 +189,7 @@ const TaskList = ({
</button>
<button
onClick={() => setActiveTab('projects')}
className={`px-2 sm:px-4 py-1.5 sm:py-2 text-xs sm:text-sm rounded-md transition-all duration-200 ${
className={`px-3 sm:px-4 py-2 sm:py-2 text-sm sm:text-sm rounded-md transition-all duration-200 ${
activeTab === 'projects'
? 'bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-sm'
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200'
Expand All @@ -206,7 +206,7 @@ const TaskList = ({
onClick={() =>
setSortMethod(sortMethod === 'date' ? 'label' : 'date')
}
className="px-2 sm:px-4 py-1.5 sm:py-2 text-xs sm:text-sm rounded-md
className="px-3 sm:px-4 py-2 sm:py-2 text-sm sm:text-sm rounded-md
bg-gray-100 dark:bg-gray-700
text-gray-600 dark:text-gray-400
hover:text-gray-900 dark:hover:text-gray-200
Expand All @@ -223,7 +223,7 @@ const TaskList = ({
{/* Calendar/List View Toggle */}
<button
onClick={() => setIsCalendarView(!isCalendarView)}
className="px-2 sm:px-4 py-1.5 sm:py-2 text-xs sm:text-sm rounded-md
className="px-3 sm:px-4 py-2 sm:py-2 text-sm sm:text-sm rounded-md
bg-gray-100 dark:bg-gray-700
text-gray-600 dark:text-gray-400
hover:text-gray-900 dark:hover:text-gray-200
Expand Down
3 changes: 2 additions & 1 deletion client/src/components/Modal Management/Layout/View.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const View = ({ task, removeTask, completeTask, isCompleted, updateTask }) => {
deadline: task.deadline || '',
difficulty: task.difficulty,
importance: task.importance,
collaborative: task.collaborative,
urgent: task.urgent,
label: task.label || ''
});
const [showPomodoro, setShowPomodoro] = useState(false);
Expand Down Expand Up @@ -65,6 +65,7 @@ const View = ({ task, removeTask, completeTask, isCompleted, updateTask }) => {
<button
className="flex-shrink-0 w-8 h-8 flex items-center justify-center"
onClick={() => setShowDetails(!showDetails)}
aria-label="Toggle task details"
>
<svg
className="w-6 h-6 text-gray-400 transition-transform duration-300"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,19 @@ describe('Task Component Overdue Tests', () => {
/>
);

expect(screen.getByText('-10xp')).toBeInTheDocument();
// Click the expand button to show details
const expandButton = screen.getByRole('button', {
name: /toggle task details/i
});
fireEvent.click(expandButton);

// Now look for XP and penalty
expect(screen.getByText((content) => {
return content.includes('100') && content.includes('xp');
})).toBeInTheDocument();
expect(screen.getByText((content) => {
return content.includes('Due:') && content.includes('2024-01-13');
})).toBeInTheDocument();
});
});

Expand All @@ -151,7 +163,7 @@ describe('TaskView Integration Tests', () => {
difficulty: 50,
importance: 50,
experience: 100,
collaborative: false
urgent: false
};

const setup = (props = {}) => {
Expand All @@ -172,10 +184,8 @@ describe('TaskView Integration Tests', () => {
expect(screen.getByText('Test Task')).toBeInTheDocument();
});

test('shows description when details button is clicked', () => {
test('shows description when task has description', () => {
setup();
const detailsButton = screen.getByText('Details');
fireEvent.click(detailsButton);
expect(screen.getByText('Test description')).toBeInTheDocument();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const ProjectForm = ({ addTask }) => {
deadline: projectForm.deadline || null,
difficulty: 50,
importance: 50,
collaborative: false,
urgent: false,
experience: totalXP,
subtasks: subTasks
});
Expand Down
150 changes: 104 additions & 46 deletions client/src/components/Modal Management/Projects/ProjectView.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,117 @@ import React from 'react';
import { formatDeadline, isOverdue, calculateOverduePenalty } from '../../../utils/tasks/tasksUtils';

const ProjectView = ({ task, isCompleted, handleSubtaskToggle }) => {
const completedSubtasks = task.subtasks.filter(subtask => subtask.completed).length;
const progress = (completedSubtasks / task.subtasks.length) * 100;

return (
<>
<div className="space-y-2">
{task.subtasks.map((subtask, index) => (
<div key={index} className="flex items-center gap-2">
{!isCompleted && (
<div className="relative">
<input
type="checkbox"
className="peer h-4 w-4 appearance-none rounded border border-gray-300
dark:border-gray-600 bg-white dark:bg-gray-700
checked:bg-blue-500 dark:checked:bg-blue-400
focus:outline-none focus:ring-2 focus:ring-blue-500/20
transition-all duration-200"
checked={subtask.completed || false}
onChange={() => handleSubtaskToggle(index)}
/>
<div className="absolute inset-0 pointer-events-none">
<div
className="absolute top-1/2 w-full border-t
border-white dark:border-gray-900
opacity-0 peer-checked:opacity-100
transition-opacity duration-200"
/>
</div>
</div>
)}
<span
className={`${subtask.completed || isCompleted ? 'line-through text-gray-400 dark:text-gray-500' : ''}
transition-all duration-200`}
>
{subtask.name}
<div className="space-y-4">
{/* Progress Bar and Share Button */}
<div className="flex items-center justify-between mb-2">
<div className="flex items-center gap-3">
<span className="text-gray-600 dark:text-gray-400 text-sm">Progress</span>
<div className="flex items-center gap-2">
<div className="w-32 h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
<div
className="h-full bg-blue-500 dark:bg-blue-400 rounded-full transition-all duration-300"
style={{ width: `${progress}%` }}
/>
</div>
<span className="text-sm text-gray-600 dark:text-gray-400">
{completedSubtasks}/{task.subtasks.length}
</span>
</div>
))}
</div>
<button
onClick={() => {}} // Placeholder for future implementation
className="text-blue-500 hover:text-blue-600 dark:text-blue-400
dark:hover:text-blue-300 text-sm font-medium"
>
🤝 Share Project
</button>
</div>
{task.deadline && (
<p>Due date: {formatDeadline(task.deadline)}</p>

{/* Description Section */}
{task.desc && (
<div className="bg-gray-50/50 dark:bg-gray-800/30 rounded-lg p-4 mb-4">
<p className="text-sm text-gray-700 dark:text-gray-300 whitespace-pre-wrap leading-relaxed">
{task.desc}
</p>
</div>
)}
<p>
Total Experience: {task.experience}xp
{isCompleted && task.earlyBonus > 0 && (
<span className="text-green-600 dark:text-green-400">
{` + ${task.earlyBonus}xp early bonus!`}
</span>

{/* Subtasks List */}
<div className="border dark:border-gray-700 rounded-lg overflow-hidden">
<div className="divide-y divide-gray-200 dark:divide-gray-700">
{task.subtasks.map((subtask, index) => (
<div
key={index}
className={`p-3 transition-colors ${
subtask.completed
? 'bg-gray-50 dark:bg-gray-800/50'
: 'bg-white dark:bg-gray-800'
}`}
>
<div className="flex items-center gap-3">
{!isCompleted && (
<div className="relative">
<input
type="checkbox"
className="peer h-4 w-4 appearance-none rounded border border-gray-300
dark:border-gray-600 bg-white dark:bg-gray-700
checked:bg-blue-500 dark:checked:bg-blue-400
focus:outline-none focus:ring-2 focus:ring-blue-500/20
transition-all duration-200"
checked={subtask.completed || false}
onChange={() => handleSubtaskToggle(index)}
/>
<div className="absolute inset-0 pointer-events-none">
<div className="absolute top-1/2 w-full border-t border-white dark:border-gray-900
opacity-0 peer-checked:opacity-100 transition-opacity duration-200"/>
</div>
</div>
)}
<span className={`text-sm ${
subtask.completed || isCompleted
? 'text-gray-400 dark:text-gray-500 line-through'
: 'text-gray-900 dark:text-gray-100'
}`}>
{subtask.name}
</span>
</div>
</div>
))}
</div>
</div>

{/* Task Info Footer */}
<div className="flex flex-wrap gap-4 text-sm text-gray-600 dark:text-gray-400 pt-2">
{task.deadline && (
<div className="flex items-center gap-2">
<span>📅</span>
<span>
Due: {formatDeadline(task.deadline)}
{isOverdue(task.deadline) && !isCompleted && (
<span className="text-red-500 ml-1">
({calculateOverduePenalty(task.deadline)}xp)
</span>
)}
</span>
</div>
)}
{task.deadline && isOverdue(task.deadline) && (
<span className="text-red-500">
{` ${calculateOverduePenalty(task.deadline)}xp`}
<div className="flex items-center gap-2">
<span></span>
<span>
{task.experience}xp
{isCompleted && task.earlyBonus > 0 && (
<span className="text-green-600 dark:text-green-400">
{` + ${task.earlyBonus}xp early bonus!`}
</span>
)}
</span>
)}
</p>
</>
</div>
</div>
</div>
);
};

Expand Down
22 changes: 11 additions & 11 deletions client/src/components/Modal Management/Tasks/TaskForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const TaskForm = ({ addTask }) => {
difficulty: 50,
importance: 50,
deadline: '',
collaborative: false,
urgent: false,
label: ''
};

Expand All @@ -34,12 +34,12 @@ const TaskForm = ({ addTask }) => {
difficulty: formState.difficulty,
importance: formState.importance,
deadline: formState.deadline || null,
collaborative: formState.collaborative,
urgent: formState.urgent,
label: formState.label || null,
experience: calculateBaseXP(
formState.difficulty,
formState.importance,
formState.collaborative
formState.urgent
),
completion: false
};
Expand All @@ -64,8 +64,8 @@ const TaskForm = ({ addTask }) => {
setSelectedDeadline(null);
};

const toggleCollaborative = () => {
updateFormState('collaborative', !formState.collaborative);
const toggleUrgent = () => {
updateFormState('urgent', !formState.urgent);
};

const handleDeadlineClick = (days, buttonType) => {
Expand Down Expand Up @@ -260,19 +260,19 @@ const TaskForm = ({ addTask }) => {
<div className="flex items-center gap-4 pt-2">
<button
type="button"
onClick={toggleCollaborative}
onClick={toggleUrgent}
className={`flex-[1.2] px-3 py-2 rounded-lg border transition-all duration-200
${
formState.collaborative
? 'bg-blue-50 dark:bg-blue-500/10 border-blue-200 dark:border-blue-800'
formState.urgent
? 'bg-red-50 dark:bg-red-500/10 border-red-200 dark:border-red-800'
: 'bg-gray-50 dark:bg-gray-700/50 border-gray-200 dark:border-gray-600'
}`}
>
<div className="text-sm font-medium text-gray-800 dark:text-gray-200">
{formState.collaborative ? '👥 Team Task' : '👤 Solo Task'}
{formState.urgent ? '🚨 Urgent Task' : '⏱️ Regular Task'}
</div>
<div className="text-xs text-gray-500 dark:text-gray-400">
{formState.collaborative ? '+150 XP Bonus' : 'Base XP'}
{formState.urgent ? '+150 XP Bonus' : 'Base XP'}
</div>
</button>

Expand All @@ -284,7 +284,7 @@ const TaskForm = ({ addTask }) => {
{calculateBaseXP(
formState.difficulty,
formState.importance,
formState.collaborative
formState.urgent
)}
</div>
</div>
Expand Down
Loading

0 comments on commit bb4ce79

Please sign in to comment.