add edit task dialog
This commit is contained in:
@@ -8,7 +8,7 @@ import { ProjectProvider } from "../../../../providers/ProjectProvider";
|
|||||||
import { createSWRFetcher } from "../../../../utils/swrFetcher";
|
import { createSWRFetcher } from "../../../../utils/swrFetcher";
|
||||||
import { AddTask } from "./AddTask";
|
import { AddTask } from "./AddTask";
|
||||||
import { ProjectOptions } from "./ProjectOptions";
|
import { ProjectOptions } from "./ProjectOptions";
|
||||||
import { TaskListProps, TasksList } from "./TasksList";
|
import { TaskListProps, TasksList } from "./TaskList/TasksList";
|
||||||
|
|
||||||
export type APIProjectTasksList = {
|
export type APIProjectTasksList = {
|
||||||
data: TaskListProps["tasks"];
|
data: TaskListProps["tasks"];
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Dialog,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
DialogTitle,
|
||||||
|
TextField,
|
||||||
|
} from "@mui/material";
|
||||||
|
import { SetStateAction, useState } from "react";
|
||||||
|
import { SubmitHandler, useForm } from "react-hook-form";
|
||||||
|
import { useAuth } from "../../../../../hooks/useAuth";
|
||||||
|
import { useProject } from "../../../../../hooks/useProject";
|
||||||
|
import { Task } from "./TasksListItem";
|
||||||
|
|
||||||
|
type EditProjectForm = {
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type EditTaskDialogProps = {
|
||||||
|
open: boolean;
|
||||||
|
setOpen: (value: SetStateAction<boolean>) => void;
|
||||||
|
task: Task;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const EditTaskDialog = ({
|
||||||
|
task,
|
||||||
|
open,
|
||||||
|
setOpen,
|
||||||
|
}: EditTaskDialogProps) => {
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const { apiClient } = useAuth();
|
||||||
|
const { tasksMutate, project } = useProject();
|
||||||
|
const { register, handleSubmit, reset } = useForm<EditProjectForm>({
|
||||||
|
defaultValues: task,
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
reset();
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit: SubmitHandler<EditProjectForm> = (data) => {
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
|
apiClient(`projects/${project.id}/tasks/${task.id}`, {
|
||||||
|
method: "PUT",
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
}).then(() => {
|
||||||
|
tasksMutate();
|
||||||
|
setIsLoading(false);
|
||||||
|
handleClose();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onClose={handleClose}>
|
||||||
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<DialogTitle>Rename task</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<TextField
|
||||||
|
{...register("description")}
|
||||||
|
disabled={isLoading}
|
||||||
|
autoFocus
|
||||||
|
fullWidth
|
||||||
|
margin="dense"
|
||||||
|
variant="standard"
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button disabled={isLoading} onClick={handleClose}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button type="submit" disabled={isLoading}>
|
||||||
|
Rename
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</form>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { List, ListSubheader } from "@mui/material";
|
import { List, ListSubheader } from "@mui/material";
|
||||||
import { useAuth } from "../../../../hooks/useAuth";
|
import { useAuth } from "../../../../../hooks/useAuth";
|
||||||
import { useProject } from "../../../../hooks/useProject";
|
import { useProject } from "../../../../../hooks/useProject";
|
||||||
import { Task, TasksListItem } from "./TasksListItem";
|
import { Task, TasksListItem } from "./TasksListItem";
|
||||||
|
|
||||||
export type TaskListProps = {
|
export type TaskListProps = {
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
import DeleteIcon from "@mui/icons-material/Delete";
|
||||||
|
import EditIcon from "@mui/icons-material/Edit";
|
||||||
|
|
||||||
|
import {
|
||||||
|
Checkbox,
|
||||||
|
IconButton,
|
||||||
|
ListItem,
|
||||||
|
ListItemAvatar,
|
||||||
|
ListItemText,
|
||||||
|
Tooltip,
|
||||||
|
} from "@mui/material";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { formatDate } from "../../../../../utils/formatDate";
|
||||||
|
import { EditTaskDialog } from "./EditTaskDialog";
|
||||||
|
|
||||||
|
export type Task = {
|
||||||
|
id: number;
|
||||||
|
description: string;
|
||||||
|
createdAt: string;
|
||||||
|
finishedAt?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TasksListItemProps = {
|
||||||
|
task: Task;
|
||||||
|
onCheck: (taskId: number) => void;
|
||||||
|
onDelete: (taskId: number) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TasksListItem = ({
|
||||||
|
task,
|
||||||
|
onCheck,
|
||||||
|
onDelete,
|
||||||
|
}: TasksListItemProps) => {
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [openEditDialog, setOpenEditDialog] = useState(false);
|
||||||
|
const finished = !!task.finishedAt;
|
||||||
|
const blockInteration = finished || isLoading;
|
||||||
|
|
||||||
|
const handleCheck = () => {
|
||||||
|
setIsLoading(true);
|
||||||
|
onCheck(task.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
setIsLoading(true);
|
||||||
|
onDelete(task.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEdit = () => {
|
||||||
|
setOpenEditDialog(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const tooltipText = `
|
||||||
|
${task.finishedAt ? `Finished at: ${formatDate(task.finishedAt)} |` : ""}
|
||||||
|
${`Created at: ${formatDate(task.createdAt)}`}
|
||||||
|
`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<EditTaskDialog
|
||||||
|
task={task}
|
||||||
|
open={openEditDialog}
|
||||||
|
setOpen={setOpenEditDialog}
|
||||||
|
/>
|
||||||
|
<Tooltip title={tooltipText} placement="top-start">
|
||||||
|
<ListItem
|
||||||
|
secondaryAction={
|
||||||
|
finished ? null : (
|
||||||
|
<>
|
||||||
|
<IconButton
|
||||||
|
onClick={handleEdit}
|
||||||
|
disabled={blockInteration}
|
||||||
|
edge="end"
|
||||||
|
aria-label="edit"
|
||||||
|
>
|
||||||
|
<EditIcon />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
sx={{ ml: 2 }}
|
||||||
|
onClick={handleDelete}
|
||||||
|
disabled={blockInteration}
|
||||||
|
edge="end"
|
||||||
|
aria-label="delete"
|
||||||
|
>
|
||||||
|
<DeleteIcon />
|
||||||
|
</IconButton>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Checkbox
|
||||||
|
onChange={handleCheck}
|
||||||
|
disabled={blockInteration}
|
||||||
|
checked={blockInteration}
|
||||||
|
/>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText primary={task.description} />
|
||||||
|
</ListItem>
|
||||||
|
</Tooltip>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './TasksList'
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
import DeleteIcon from "@mui/icons-material/Delete";
|
|
||||||
import {
|
|
||||||
Checkbox,
|
|
||||||
IconButton,
|
|
||||||
ListItem,
|
|
||||||
ListItemAvatar,
|
|
||||||
ListItemText,
|
|
||||||
Tooltip,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { useState } from "react";
|
|
||||||
import { formatDate } from "../../../../utils/formatDate";
|
|
||||||
|
|
||||||
export type Task = {
|
|
||||||
id: number;
|
|
||||||
description: string;
|
|
||||||
createdAt: string;
|
|
||||||
finishedAt?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TasksListItemProps = {
|
|
||||||
task: Task;
|
|
||||||
onCheck: (taskId: number) => void;
|
|
||||||
onDelete: (taskId: number) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const TasksListItem = ({
|
|
||||||
task,
|
|
||||||
onCheck,
|
|
||||||
onDelete,
|
|
||||||
}: TasksListItemProps) => {
|
|
||||||
const finished = !!task.finishedAt;
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
|
||||||
|
|
||||||
const handleCheck = () => {
|
|
||||||
setIsLoading(true);
|
|
||||||
onCheck(task.id);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDelete = () => {
|
|
||||||
setIsLoading(true);
|
|
||||||
onDelete(task.id);
|
|
||||||
};
|
|
||||||
|
|
||||||
const blockInteration = finished || isLoading;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Tooltip
|
|
||||||
title={`
|
|
||||||
${
|
|
||||||
task.finishedAt ? `Finished at: ${formatDate(task.finishedAt)} |` : ""
|
|
||||||
}
|
|
||||||
${`Created at: ${formatDate(task.createdAt)}`}
|
|
||||||
`}
|
|
||||||
placement="top-start"
|
|
||||||
>
|
|
||||||
<ListItem
|
|
||||||
secondaryAction={
|
|
||||||
finished ? null : (
|
|
||||||
<IconButton
|
|
||||||
onClick={handleDelete}
|
|
||||||
disabled={blockInteration}
|
|
||||||
edge="end"
|
|
||||||
aria-label="delete"
|
|
||||||
>
|
|
||||||
<DeleteIcon />
|
|
||||||
</IconButton>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<ListItemAvatar>
|
|
||||||
<Checkbox
|
|
||||||
onChange={handleCheck}
|
|
||||||
disabled={blockInteration}
|
|
||||||
checked={blockInteration}
|
|
||||||
/>
|
|
||||||
</ListItemAvatar>
|
|
||||||
<ListItemText primary={task.description} />
|
|
||||||
</ListItem>
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user