Skip to content

Commit

Permalink
Merge pull request #27 from it-goats/feature/ITG-46
Browse files Browse the repository at this point in the history
[ITG-46] Dodanie listy zadań w relacji w widoku szczegółów zadania
  • Loading branch information
koszar91 committed Apr 27, 2022
2 parents 539a254 + 0bbecb3 commit 0f4e9ff
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 69 deletions.
16 changes: 15 additions & 1 deletion cabra/src/api/taskRelations.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { IRelatedTask, ITaskRelation } from "../types/taskRelation";
import {
DirectedRelationType,
IRelatedTask,
ITaskRelation,
} from "../types/taskRelation";

import axios from "axios";

Expand All @@ -8,6 +12,16 @@ export const getSubtasks = {
axios.get<IRelatedTask[]>(`/task-relations/${id}?relationType=subtask`),
};

export const getRelatedTasks = {
cacheKey: (taskId: string, type: DirectedRelationType) => [
"task-relations",
taskId,
type,
],
run: (taskId: string, type: DirectedRelationType) =>
axios.get<IRelatedTask[]>(`/task-relations/${taskId}?relationType=${type}`),
};

export const createRelation = (data: Omit<ITaskRelation, "id">) =>
axios.post<ITaskRelation>("/task-relations", data);

Expand Down
66 changes: 66 additions & 0 deletions cabra/src/pages/components/RelatedTask.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { getTask, getTasks, updateTask } from "../../api/tasks";
import tw, { styled } from "twin.macro";
import { useMutation, useQueryClient } from "react-query";

import Checkbox from "./CheckBox";
import { DirectedRelationType } from "../../types/taskRelation";
import { ITask } from "../../types/task";
import { getRelatedTasks } from "../../api/taskRelations";
import { useState } from "react";

interface Props {
task: ITask;
relationType: DirectedRelationType;
parentTaskId: string;
}

const Container = styled.div(
tw`rounded-xl bg-tertiary text-secondary m-1.5 p-1.5 grid`
);

export default function RelatedTask({
task,
relationType,
parentTaskId,
}: Props) {
const [errorMessage, setErrorMessage] = useState("");
const client = useQueryClient();
const editTask = useMutation((task: ITask) => updateTask(task.id, task), {
onSuccess: () => {
client.invalidateQueries(getTasks.cacheKey);
client.invalidateQueries(getTask.cacheKey(parentTaskId));
client.invalidateQueries(
getRelatedTasks.cacheKey(parentTaskId, relationType)
);
},
});
const handleIsDoneChange = async () => {
try {
const updatedTask = {
...task,
isDone: !task.isDone,
};
await editTask.mutateAsync(updatedTask);
} catch (error) {
setErrorMessage(
"Something went wrong :C, It's not possible to uncheck the task."
);
}
};

return (
<Container>
<p tw="font-bold text-base">{task.title}</p>
<p tw="place-self-end">
<Checkbox
id={task.id}
checked={task.isDone}
onChange={handleIsDoneChange}
/>
</p>
{errorMessage && (
<p tw="flex items-center text-orange-500 pt-1">&nbsp;{errorMessage}</p>
)}
</Container>
);
}
46 changes: 46 additions & 0 deletions cabra/src/pages/components/RelatedTaskList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import tw, { styled } from "twin.macro";

import { DirectedRelationType } from "../../types/taskRelation";
import RelatedTask from "./RelatedTask";
import { getRelatedTasks } from "../../api/taskRelations";
import { useQuery } from "react-query";

interface RelatedTasksListProps {
relationType: DirectedRelationType;
parentTaskId: string;
}

const Container = styled.div(tw``);

export default function RelatedTasksList({
relationType,
parentTaskId,
}: RelatedTasksListProps) {
const { data, isLoading, error } = useQuery(
getRelatedTasks.cacheKey(parentTaskId, relationType),
() => getRelatedTasks.run(parentTaskId, relationType)
);

if (isLoading) return <Container>Loading</Container>;
if (error) return <Container>Oops</Container>;
if (!data?.data) return <Container />;

const subtasks = data.data.slice().reverse();

if (subtasks.length == 0) {
return <Container>{"<No tasks>"}</Container>;
}

return (
<Container>
{subtasks.map((relatedTask) => (
<RelatedTask
key={relatedTask.relationId}
task={relatedTask.task}
relationType={relationType}
parentTaskId={parentTaskId}
/>
))}
</Container>
);
}
80 changes: 16 additions & 64 deletions cabra/src/pages/components/SubtasksList.tsx
Original file line number Diff line number Diff line change
@@ -1,69 +1,20 @@
import { getTask, getTasks, updateTask } from "../../api/tasks";
import tw, { styled } from "twin.macro";
import { useMutation, useQuery, useQueryClient } from "react-query";

import Checkbox from "./CheckBox";
import { ITask } from "../../types/task";
import { getSubtasks } from "../../api/taskRelations";
import { useState } from "react";
import { DirectedRelationType } from "../../types/taskRelation";
import RelatedTask from "./RelatedTask";
import { getRelatedTasks } from "../../api/taskRelations";
import { useQuery } from "react-query";

interface Props {
subtask: ITask;
parentId: string;
parentTaskId: string;
}

interface PropsList {
parentId: string;
}

const Container = styled.div(tw`grid grid-cols-4 gap-3`);

const Subtask = ({ subtask, parentId }: Props) => {
const [errorMessage, setErrorMessage] = useState("");
const client = useQueryClient();
const editTask = useMutation((task: ITask) => updateTask(task.id, task), {
onSuccess: () => {
client.invalidateQueries(getTasks.cacheKey);
client.invalidateQueries(getTask.cacheKey(parentId));
client.invalidateQueries(getSubtasks.cacheKey(parentId));
},
});
const handleIsDoneChange = async () => {
try {
const updatedTask = {
...subtask,
isDone: !subtask.isDone,
};
await editTask.mutateAsync(updatedTask);
} catch (error) {
setErrorMessage(
"Something went wrong :C, It's not possible to uncheck the task."
);
}
};

return (
<div tw="rounded-xl bg-tertiary text-secondary p-1.5 grid">
<p tw="font-medium text-xs">{subtask.title}</p>
<p tw="place-self-end">
<Checkbox
id={subtask.id}
checked={subtask.isDone}
onChange={handleIsDoneChange}
size="sm"
/>
</p>
{errorMessage && (
<p tw="flex items-center text-orange-500 pt-1">&nbsp;{errorMessage}</p>
)}
</div>
);
};
const Container = styled.div(tw`flex flex-row`);

export default function SubtasksList({ parentId }: PropsList) {
export default function SubtasksList({ parentTaskId }: Props) {
const { data, isLoading, error } = useQuery(
getSubtasks.cacheKey(parentId),
() => getSubtasks.run(parentId)
getRelatedTasks.cacheKey(parentTaskId, DirectedRelationType.Subtask),
() => getRelatedTasks.run(parentTaskId, DirectedRelationType.Subtask)
);

if (isLoading) return <Container>Loading</Container>;
Expand All @@ -73,16 +24,17 @@ export default function SubtasksList({ parentId }: PropsList) {
const subtasks = data.data.slice().reverse();

if (subtasks.length == 0) {
return <Container>{"<No tasks>"}</Container>;
return <div>{"<No tasks>"}</div>;
}

return (
<Container>
{subtasks.map((relation) => (
<Subtask
key={relation.relationId}
subtask={relation.task}
parentId={parentId}
{subtasks.map((relatedTask) => (
<RelatedTask
key={relatedTask.relationId}
task={relatedTask.task}
relationType={DirectedRelationType.Subtask}
parentTaskId={parentTaskId}
/>
))}
</Container>
Expand Down
19 changes: 15 additions & 4 deletions cabra/src/pages/components/TaskDetailsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import { PencilIcon, TrashIcon } from "@heroicons/react/solid";

import CardField from "./CardField";
import CheckBox from "./CheckBox";
import { DirectedRelationType } from "../../types/taskRelation";
import { Link } from "react-router-dom";
import NavigationButton from "./NavigationButton";
import RelatedTasksList from "./RelatedTaskList";
import SubtasksList from "./SubtasksList";
import { formatDateTime } from "../../utils/dates";
import { routeHelpers } from "../../routes";
Expand Down Expand Up @@ -68,16 +70,25 @@ export default function TaskDetails({ id }: Props) {
{task.description || "<No description>"}
</CardField>
<CardField title="Subtasks" span={3}>
<SubtasksList parentId={id} />
<SubtasksList parentTaskId={id} />
</CardField>
<CardField title="Is dependent on" span={1}>
{"<No tasks>"}
<RelatedTasksList
relationType={DirectedRelationType.IsDependentOn}
parentTaskId={id}
/>
</CardField>
<CardField title="Depends on" span={1}>
{"<No tasks>"}
<RelatedTasksList
relationType={DirectedRelationType.DependsOn}
parentTaskId={id}
/>
</CardField>
<CardField title="Interchangeable tasks" span={1}>
{"<No tasks>"}
<RelatedTasksList
relationType={DirectedRelationType.Interchangable}
parentTaskId={id}
/>
</CardField>
</Content>
</div>
Expand Down
8 changes: 8 additions & 0 deletions cabra/src/types/taskRelation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,11 @@ export interface IRelatedTask {
relationType: string;
relationId: string;
}

export enum DirectedRelationType {
IsDependentOn = "is_dependent_on",
DependsOn = "depends_on",
Subtask = "subtask",
Supertask = "supertask",
Interchangable = "interchangable",
}

0 comments on commit 0f4e9ff

Please sign in to comment.