Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions frontend/src/components/EditProjectModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React, { useState, useEffect } from 'react';
import * as projectService from '../services/projectService';

const EditProjectModal = ({
isOpen,
onClose,
project,
onProjectUpdated
}) => {
const [title, setTitle] = useState('');
const [description, setDescription] = useState('');

// Pre-fill fields when modal opens or project changes
useEffect(() => {
if (project) {
setTitle(project.title || '');
setDescription(project.description || '');
}
}, [project]);

const handleSubmit = async (e) => {
e.preventDefault();
try {
const updatedProject = await projectService.updateProject(project._id, {
title,
description,
});
onProjectUpdated(updatedProject);
onClose();
} catch (error) {
console.error('Failed to update project:', error);
}
};

if (!isOpen) return null;

return (
<div className="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50">
<div className="bg-gray-800 rounded-lg shadow-xl p-6 w-full max-w-lg">
<h2 className="text-2xl font-bold mb-4">Edit Project</h2>
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label htmlFor="title" className="block text-sm font-medium text-gray-400">Title</label>
<input
id="title"
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
required
className="w-full px-3 py-2 mt-1 text-white bg-gray-700 border border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
</div>

<div>
<label htmlFor="description" className="block text-sm font-medium text-gray-400">Description</label>
<textarea
id="description"
value={description}
onChange={(e) => setDescription(e.target.value)}
rows="3"
className="w-full px-3 py-2 mt-1 text-white bg-gray-700 border border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
</div>

<div className="flex justify-end space-x-4 pt-4">
<button
type="button"
onClick={onClose}
className="px-4 py-2 font-semibold bg-gray-600 rounded-md hover:bg-gray-700"
>
Cancel
</button>
<button
type="submit"
className="px-4 py-2 font-semibold bg-blue-600 rounded-md hover:bg-blue-700"
>
Save Changes
</button>
</div>
</form>
</div>
</div>
);
};

export default EditProjectModal;
67 changes: 44 additions & 23 deletions frontend/src/pages/ProjectPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import * as taskService from '../services/taskService';
import TaskColumn from '../components/TaskColumn';
import TaskModal from '../components/TaskModal';
import socket from '../services/socketService';

import EditProjectModal from '../components/EditProjectModal';
const ProjectPage = () => {
// State for Edit modal
const [isEditModalOpen, setIsEditModalOpen] = useState(false);

const { projectId } = useParams();
const navigate = useNavigate(); // Get the navigate function
const { user } = useAuth();
Expand All @@ -34,20 +37,24 @@ const ProjectPage = () => {
socket.emit('joinProject', projectId);

const handleTaskUpdate = (updatedTask) => {
setTasks(currentTasks =>
currentTasks.map(task =>
setTasks(currentTasks =>
currentTasks.map(task =>
task._id === updatedTask._id ? updatedTask : task
)
);
};

socket.on('taskUpdated', handleTaskUpdate);

return () => {
socket.off('taskUpdated', handleTaskUpdate);
};
}, [projectId], fetchProjectData);

const handleProjectUpdated = (updated) => {
setProject(updated); // instantly refresh UI
};

const handleInviteMember = async (e) => {
e.preventDefault();
if (!inviteEmail) return;
Expand Down Expand Up @@ -110,27 +117,35 @@ const ProjectPage = () => {
}
};

return (
return (
<div className="container mx-auto p-4 md:p-8">
<header className="mb-6">
<Link to="/dashboard" className="text-blue-400 hover:underline">← Back to Dashboard</Link>
<div className="flex justify-between items-center mt-2">
<div>
<h1 className="text-4xl font-bold">{project.title}</h1>
<p className="text-gray-400 mt-1">{project.description}</p>
</div>
<div className="flex gap-2">
{/* Conditionally rendered Delete Project button */}
{project.isOwner && (
<button onClick={handleDeleteProject} className="px-4 py-2 font-semibold bg-red-600 rounded-md hover:bg-red-700">
Delete Project
</button>
)}
{/* Single Add Task button */}
<button onClick={openAddModal} className="px-4 py-2 font-semibold bg-blue-600 rounded-md hover:bg-blue-700">
+ Add Task
<div>
<h1 className="text-4xl font-bold">{project.title}</h1>
<p className="text-gray-400 mt-1">{project.description}</p>
</div>
<div className="flex gap-2">
{/* Conditionally rendered Delete Project button */}
{project.isOwner && (
<>
<button
onClick={() => setIsEditModalOpen(true)}
className="px-4 py-2 font-semibold bg-yellow-600 rounded-md hover:bg-yellow-700"
>
Edit Project
</button>
<button onClick={handleDeleteProject} className="px-4 py-2 font-semibold bg-red-600 rounded-md hover:bg-red-700">
Delete Project
</button>
</div>
</>
)}
{/* Single Add Task button */}
<button onClick={openAddModal} className="px-4 py-2 font-semibold bg-blue-600 rounded-md hover:bg-blue-700">
+ Add Task
</button>
</div>
</div>
</header>

Expand All @@ -151,8 +166,8 @@ return (

{user && project.owner && user._id === project.owner._id && (
<form onSubmit={handleInviteMember} className="mt-4 flex gap-2">
<input
type="email"
<input
type="email"
value={inviteEmail}
onChange={(e) => setInviteEmail(e.target.value)}
placeholder="Invite user by email"
Expand All @@ -164,13 +179,19 @@ return (
)}
</div>

<TaskModal
<TaskModal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
onTaskSaved={fetchProjectData}
projectId={projectId}
taskToEdit={taskToEdit}
/>
<EditProjectModal
isOpen={isEditModalOpen}
onClose={() => setIsEditModalOpen(false)}
project={project}
onProjectUpdated={handleProjectUpdated}
/>
</div>
);
};
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/services/projectService.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,9 @@ export const addMemberToProject = async (projectId, email) => {
export const deleteProject = async (projectId) => {
const response = await api.delete(`/projects/${projectId}`);
return response.data;
};

export const updateProject = async (projectId, projectData) => {
const response = await api.put(`/projects/${projectId}`, projectData);
return response.data;
};
Loading