Skip to content
Snippets Groups Projects
Commit 4cb7c8d3 authored by Kevin Portable's avatar Kevin Portable
Browse files

Merge branch 'main' of etulab.univ-amu.fr:ihm-web/todolist

parents 8ea1eaed a8c22cd0
No related branches found
No related tags found
No related merge requests found
...@@ -2,47 +2,86 @@ import { useState } from "react"; ...@@ -2,47 +2,86 @@ import { useState } from "react";
import DatePicker from "react-datepicker"; import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css"; import "react-datepicker/dist/react-datepicker.css";
export default function Modal({ isOpen, closeModal, saveTask }) { export default function Modal({task, isOpen, closeModal, saveTask }) {
if (!isOpen) return null; if (!isOpen) return null;
const [taskName, setTaskName] = useState(""); const [editedTask, setEditedTask] = useState({...task});
const [dueDate, setDueDate] = useState(new Date());
const createTask = () => { const handleSave = () => {
return { saveTask(editedTask)
id: crypto.randomUUID(), closeModal()
name: taskName,
isCompleted: false,
dueDate: dueDate
}
} }
const handleSaveTask = () => { const handleChange = (e) => {
const task = createTask(); const { name, value, type, checked } = e.target;
saveTask(task); setEditedTask({
closeModal(); ...editedTask,
[name]: type === 'checkbox' ? checked : value
});
}; };
return (
<div className="absolute top-0 left-0 right-0 bottom-0 flex justify-center items-center z-50">
<div className="absolute inset-0 bg-gray-500 dark:bg-gray-900 bg-opacity-50"></div>
<div className="relative bg-white dark:bg-gray-800 p-6 rounded-lg shadow-lg w-1/3 z-10"> return (
<h2 className="text-xl mb-4 dark:text-white">Add a New Task</h2> <div className="fixed inset-0 bg-black bg-opacity-25 flex items-center justify-center z-50">
<div
className="bg-white rounded-lg shadow-xl p-6 w-full max-w-md mx-4"
>
<div className="flex justify-between items-center mb-4">
<h3 className="text-lg font-medium">Edit Task</h3>
<button
onClick={closeModal}
className="text-gray-400 hover:text-gray-500"
>
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div className="space-y-4">
<div>
<label htmlFor="name" className="block text-sm font-medium text-gray-700 mb-1">
Task Name
</label>
<input <input
type="text" id="name"
className="w-full p-2 mb-4 border border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-700 text-gray-900 dark:text-white rounded-md" name="name"
placeholder="Task Name" className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500"
value={taskName} value={editedTask.name}
onChange={(e) => setTaskName(e.target.value)} onChange={handleChange}
/> />
</div>
<DatePicker className="dark:text-white" selected={dueDate} onChange={(date) => setDueDate(date)} /> <div>
<label htmlFor="dueDate" className="block text-sm font-medium text-gray-700 mb-1">
Due Date
</label>
<input
id="dueDate"
name="dueDate"
type="date"
className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500"
value={editedTask.dueDate}
onChange={handleChange}
/>
</div>
</div>
<div className="flex justify-between mt-4"> <div className="mt-6 flex justify-end space-x-3">
<button onClick={closeModal} className="px-4 py-2 bg-red-500 dark:bg-red-700 text-white rounded-md">Close</button> <button
<button onClick={handleSaveTask} className="px-4 py-2 bg-blue-500 dark:bg-blue-700 text-white rounded-md">Save Task</button> type="button"
className="px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
onClick={closeModal}
>
Cancel
</button>
<button
type="button"
className="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
onClick={handleSave}
>
Save
</button>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -22,6 +22,28 @@ export default function TaskItem({ task }) { ...@@ -22,6 +22,28 @@ export default function TaskItem({ task }) {
? new Date(task.dueDate).toLocaleDateString() ? new Date(task.dueDate).toLocaleDateString()
: "No due date"; : "No due date";
const getDateTextColor = (task) => {
if (task.isCompleted) {
return 'text-gray-400';
}
const now = new Date();
const due = new Date(task.dueDate);
const diffTime = due - now;
const diffDays = diffTime / (1000 * 60 * 60 * 24);
if (diffDays >= 0 && diffDays < 1) {
return 'text-orange-500';
}
if (now > due) {
return 'text-red-500';
}
return 'text-gray-500';
};
return ( return (
<li> <li>
<div className="flex items-start p-4 border rounded-lg shadow-sm bg-white dark:bg-gray-700 dark:border-gray-600 my-2 hover:shadow-md transition-shadow"> <div className="flex items-start p-4 border rounded-lg shadow-sm bg-white dark:bg-gray-700 dark:border-gray-600 my-2 hover:shadow-md transition-shadow">
...@@ -39,8 +61,14 @@ export default function TaskItem({ task }) { ...@@ -39,8 +61,14 @@ export default function TaskItem({ task }) {
<h3 className={`text-base font-medium ${task.isCompleted ? 'text-gray-400 line-through' : 'text-gray-900 dark:text-white'}`}> <h3 className={`text-base font-medium ${task.isCompleted ? 'text-gray-400 line-through' : 'text-gray-900 dark:text-white'}`}>
{task.name} {task.name}
</h3> </h3>
<p className={`text-sm mt-1 ${task.isCompleted ? 'text-gray-400' : 'text-gray-500 dark:text-gray-300'}`}> <p className={`text-sm mt-1 flex items-center gap-1 ${getDateTextColor(task)}`}>
Due: {formattedDate} <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect>
<line x1="16" y1="2" x2="16" y2="6"></line>
<line x1="8" y1="2" x2="8" y2="6"></line>
<line x1="3" y1="10" x2="21" y2="10"></line>
</svg>
{formattedDate}
</p> </p>
</div> </div>
<button <button
......
...@@ -15,6 +15,15 @@ const Home = () => { ...@@ -15,6 +15,15 @@ const Home = () => {
const openModal = () => setIsModalOpen(true); const openModal = () => setIsModalOpen(true);
const closeModal = () => setIsModalOpen(false); const closeModal = () => setIsModalOpen(false);
const newTask = () => {
return {
id: crypto.randomUUID(),
name: "",
isCompleted: false,
dueDate: ""
}
}
// Fonction pour ajouter une nouvelle tâche // Fonction pour ajouter une nouvelle tâche
const saveTask = (task) => { const saveTask = (task) => {
const newTask = { const newTask = {
...@@ -66,7 +75,7 @@ const Home = () => { ...@@ -66,7 +75,7 @@ const Home = () => {
</div> </div>
<Modal isOpen={isModalOpen} closeModal={closeModal} saveTask={saveTask} /> <Modal task={newTask()} isOpen={isModalOpen} closeModal={closeModal} saveTask={saveTask} />
</div> </div>
); );
}; };
......
...@@ -6,6 +6,16 @@ import { useTasks } from "@context/TasksContext"; ...@@ -6,6 +6,16 @@ import { useTasks } from "@context/TasksContext";
export default function Todolist() { export default function Todolist() {
const { tasks, setTasks } = useTasks() const { tasks, setTasks } = useTasks()
const newTask = () => {
return {
id: crypto.randomUUID(),
name: "",
isCompleted: false,
dueDate: ""
}
}
const saveTask = (task) => { const saveTask = (task) => {
const newTask = { const newTask = {
...task, ...task,
...@@ -38,7 +48,7 @@ export default function Todolist() { ...@@ -38,7 +48,7 @@ export default function Todolist() {
</div> </div>
</div> </div>
<Modal isOpen={isModalOpen} closeModal={closeModal} saveTask={saveTask} /> <Modal task={newTask()} isOpen={isModalOpen} closeModal={closeModal} saveTask={saveTask}/>
</div> </div>
); )
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment