fix: parse ISO dueDate to YYYY-MM-DD for date input display
This commit is contained in:
2
dist/index.html
vendored
2
dist/index.html
vendored
@@ -6,7 +6,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="Todo App - Task management made simple" />
|
||||
<title>Todo App</title>
|
||||
<script type="module" crossorigin src="/assets/index-WUccXayL.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-BF_dh0x-.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-CR9gBHOO.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -17,7 +17,7 @@ export function TaskDetail({ task, onClose }: TaskDetailProps) {
|
||||
const { updateTask, deleteTask, toggleComplete, projects, users, fetchUsers } = useTasksStore();
|
||||
const [title, setTitle] = useState(task.title);
|
||||
const [description, setDescription] = useState(task.description || '');
|
||||
const [dueDate, setDueDate] = useState(task.dueDate || '');
|
||||
const [dueDate, setDueDate] = useState(task.dueDate ? task.dueDate.slice(0, 10) : '');
|
||||
const [priority, setPriority] = useState<Priority>(task.priority);
|
||||
const [assigneeId, setAssigneeId] = useState(task.assigneeId || '');
|
||||
const [projectId, setProjectId] = useState(task.projectId || '');
|
||||
@@ -30,7 +30,7 @@ export function TaskDetail({ task, onClose }: TaskDetailProps) {
|
||||
useEffect(() => {
|
||||
setTitle(task.title);
|
||||
setDescription(task.description || '');
|
||||
setDueDate(task.dueDate || '');
|
||||
setDueDate(task.dueDate ? task.dueDate.slice(0, 10) : '');
|
||||
setPriority(task.priority);
|
||||
setAssigneeId(task.assigneeId || '');
|
||||
setProjectId(task.projectId || '');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEffect, useState, useRef } from 'react';
|
||||
import { useParams, useNavigate, useLocation } from 'react-router-dom';
|
||||
import { LayoutList, LayoutGrid, Plus } from 'lucide-react';
|
||||
import { LayoutList, LayoutGrid, Plus, Pencil, Trash2, AlertCircle } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useTasksStore } from '@/stores/tasks';
|
||||
import { TaskItem } from '@/components/TaskItem';
|
||||
@@ -14,9 +14,14 @@ export function ProjectPage() {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const { tasks, completedTasks, isLoading, fetchTasks, fetchCompletedTasks, setSelectedTask } = useTasksStore();
|
||||
const { tasks, completedTasks, isLoading, fetchTasks, fetchCompletedTasks, setSelectedTask, updateProject, deleteProject, fetchProjects } = useTasksStore();
|
||||
const [project, setProject] = useState<ProjectType | null>(null);
|
||||
const [sections, setSections] = useState<Section[]>([]);
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [editName, setEditName] = useState('');
|
||||
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
|
||||
const [isDeleting, setIsDeleting] = useState(false);
|
||||
const nameInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const isBoardView = location.pathname.endsWith('/board');
|
||||
|
||||
@@ -30,6 +35,43 @@ export function ProjectPage() {
|
||||
}).catch(console.error);
|
||||
}, [id]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isEditing && nameInputRef.current) {
|
||||
nameInputRef.current.focus();
|
||||
nameInputRef.current.select();
|
||||
}
|
||||
}, [isEditing]);
|
||||
|
||||
const handleStartRename = () => {
|
||||
if (!project) return;
|
||||
setEditName(project.name);
|
||||
setIsEditing(true);
|
||||
};
|
||||
|
||||
const handleSaveRename = async () => {
|
||||
if (!project || !id) return;
|
||||
const trimmed = editName.trim();
|
||||
if (trimmed && trimmed !== project.name) {
|
||||
await updateProject(id, { name: trimmed });
|
||||
setProject({ ...project, name: trimmed });
|
||||
}
|
||||
setIsEditing(false);
|
||||
};
|
||||
|
||||
const handleDeleteProject = async () => {
|
||||
if (!id) return;
|
||||
setIsDeleting(true);
|
||||
try {
|
||||
await deleteProject(id);
|
||||
await fetchProjects();
|
||||
navigate('/inbox');
|
||||
} catch (error) {
|
||||
console.error('Failed to delete project:', error);
|
||||
setIsDeleting(false);
|
||||
setShowDeleteConfirm(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (!project) {
|
||||
return (
|
||||
<div className="flex items-center justify-center py-12 text-gray-500">
|
||||
|
||||
@@ -27,6 +27,8 @@ interface TasksState {
|
||||
deleteTask: (id: string) => Promise<void>;
|
||||
toggleComplete: (id: string) => Promise<void>;
|
||||
createProject: (data: { name: string; color?: string; icon?: string }) => Promise<Project>;
|
||||
updateProject: (id: string, data: Partial<Project>) => Promise<void>;
|
||||
deleteProject: (id: string) => Promise<void>;
|
||||
|
||||
setSelectedTask: (task: Task | null) => void;
|
||||
setActiveProject: (projectId: string | null) => void;
|
||||
@@ -121,6 +123,20 @@ export const useTasksStore = create<TasksState>((set, get) => ({
|
||||
return project;
|
||||
},
|
||||
|
||||
updateProject: async (id, data) => {
|
||||
const updated = await api.updateProject(id, data);
|
||||
set((state) => ({
|
||||
projects: state.projects.map((p) => (p.id === id ? { ...p, ...updated } : p)),
|
||||
}));
|
||||
},
|
||||
|
||||
deleteProject: async (id) => {
|
||||
await api.deleteProject(id);
|
||||
set((state) => ({
|
||||
projects: state.projects.filter((p) => p.id !== id),
|
||||
}));
|
||||
},
|
||||
|
||||
toggleComplete: async (id) => {
|
||||
const task = get().tasks.find((t) => t.id === id) || get().completedTasks.find((t) => t.id === id);
|
||||
if (!task) return;
|
||||
|
||||
Reference in New Issue
Block a user