diff --git a/cool_todo_manager/src/api/RTKQuery.ts b/cool_todo_manager/src/api/RTKQuery.ts
index 7091df8..cd93886 100644
--- a/cool_todo_manager/src/api/RTKQuery.ts
+++ b/cool_todo_manager/src/api/RTKQuery.ts
@@ -1,7 +1,22 @@
-import { configureStore } from '@reduxjs/toolkit';
+import { configureStore, isRejectedWithValue, Middleware } from '@reduxjs/toolkit';
import { setupListeners } from '@reduxjs/toolkit/query';
import { authApi, mainApi } from '../services/mainApi';
+const loggerMiddleware: Middleware = (_store) => (next) => (action) => {
+ console.log('dispatching', action);
+ if(isRejectedWithValue(action)) {
+ // @ts-ignore
+ const statusCode = action.payload.status;
+ if(statusCode === 401) {
+ console.log('Unauthorized, redirecting to login page');
+ localStorage.removeItem('token');
+ window.location.href = '/login';
+ }
+ }
+ let result = next(action);
+ return result;
+};
+
export const store = configureStore({
reducer: {
[mainApi.reducerPath]: mainApi.reducer,
@@ -9,8 +24,10 @@ export const store = configureStore({
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware()
+ .prepend(loggerMiddleware)
.concat(mainApi.middleware)
.concat(authApi.middleware),
});
setupListeners(store.dispatch);
+
diff --git a/cool_todo_manager/src/components/AuthWrapper/AuthWrapper.tsx b/cool_todo_manager/src/components/AuthWrapper/AuthWrapper.tsx
index ebafd16..07d3bac 100644
--- a/cool_todo_manager/src/components/AuthWrapper/AuthWrapper.tsx
+++ b/cool_todo_manager/src/components/AuthWrapper/AuthWrapper.tsx
@@ -1,15 +1,12 @@
-import { useNavigate } from "react-router-dom"
+import { PropsWithChildren } from 'react';
+import { Navigate } from 'react-router-dom';
-export default function AuthWrapper() {
- const navigate = useNavigate()
+export default function AuthWrapper(props: PropsWithChildren) {
- if(!localStorage.getItem('token')) {
- navigate('/login')
- }
+ if (!localStorage.getItem('token')) {
+ console.log('No token found, redirecting to login');
+ return
+ }
- return (
-
-
-
- )
+ return {props.children}
;
}
diff --git a/cool_todo_manager/src/components/CardGroup/CardGroup.tsx b/cool_todo_manager/src/components/CardGroup/CardGroup.tsx
index f41d337..ce655b8 100644
--- a/cool_todo_manager/src/components/CardGroup/CardGroup.tsx
+++ b/cool_todo_manager/src/components/CardGroup/CardGroup.tsx
@@ -1,34 +1,69 @@
import { Droppable } from '@hello-pangea/dnd';
-import { Box } from '@radix-ui/themes';
-import { useState } from 'react';
+import { Box, Button, Flex, Text } from '@radix-ui/themes';
+import {
+ useCreateTaskMutation,
+ useDeleteProjectMutation,
+ useGetTasksForGroupQuery,
+} from '../../services/mainApi';
import TaskCard from '../TaskCard/TaskCard';
-
-const tasks = [
- { id: 1, title: 'Task 1', description: 'Description for Task 1' },
- { id: 2, title: 'Task 2', description: 'Description for Task 2' },
-];
+import CreateTaskDialog from './CreateTaskDialog/CreateTaskDialog';
+import DeleteProjectDialog from './DeleteProjectDialog/CreateTaskDialog';
type TCardGroup = {
id: string;
+ title: string;
};
export default function CardGroup(props: TCardGroup) {
- const [localTasks, setLocalTasks] = useState(tasks)
+ const { data, isLoading } = useGetTasksForGroupQuery(props.id);
+
+ const [createTaskForGroup] = useCreateTaskMutation();
+ const [deleteProject] = useDeleteProjectMutation();
+
+ const createTask = (taskText: string, date: string) => {
+ createTaskForGroup({
+ title: taskText,
+ projectId: props.id,
+ assignedUserId: 1,
+ deadline: date,
+ });
+ };
+
+ const deleteGroup = () => {
+ deleteProject(props.id);
+ };
return (
-
+
{(provided) => (
-
- {localTasks.map((task, i) => (
-
- ))}
- {provided.placeholder}
+
+ {props.title}
+
+ {data &&
+ data.map((task, i) => (
+
+ ))}
+
+
+
+
+
+
+
+
+
)}
diff --git a/cool_todo_manager/src/components/CardGroup/CreateTaskDialog/CreateTaskDialog.tsx b/cool_todo_manager/src/components/CardGroup/CreateTaskDialog/CreateTaskDialog.tsx
new file mode 100644
index 0000000..e9fa374
--- /dev/null
+++ b/cool_todo_manager/src/components/CardGroup/CreateTaskDialog/CreateTaskDialog.tsx
@@ -0,0 +1,63 @@
+import { Button, Dialog, Flex, Text, TextField } from '@radix-ui/themes';
+import { PropsWithChildren, useState } from 'react';
+
+type TCreateTaskDialog = {
+ onClose: (text: string, timeString: string) => void;
+} & PropsWithChildren;
+
+export default function CreateTaskDialog(props: TCreateTaskDialog) {
+ const [text, setText] = useState('');
+ const [deadline, setDeadline] = useState('');
+
+ return (
+
+ {props.children}
+
+
+ Task creation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/cool_todo_manager/src/components/CardGroup/DeleteProjectDialog/CreateTaskDialog.tsx b/cool_todo_manager/src/components/CardGroup/DeleteProjectDialog/CreateTaskDialog.tsx
new file mode 100644
index 0000000..7047c5c
--- /dev/null
+++ b/cool_todo_manager/src/components/CardGroup/DeleteProjectDialog/CreateTaskDialog.tsx
@@ -0,0 +1,36 @@
+import { Button, Dialog, Flex } from '@radix-ui/themes';
+import { PropsWithChildren } from 'react';
+
+type TCreateTaskDialog = {
+ onClose: () => void;
+} & PropsWithChildren;
+
+export default function DeleteProjectDialog(props: TCreateTaskDialog) {
+ return (
+
+ {props.children}
+
+
+ Delete project?
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/cool_todo_manager/src/components/MainBoard/MainBoard.tsx b/cool_todo_manager/src/components/MainBoard/MainBoard.tsx
index a3573b7..31c9c93 100644
--- a/cool_todo_manager/src/components/MainBoard/MainBoard.tsx
+++ b/cool_todo_manager/src/components/MainBoard/MainBoard.tsx
@@ -1,8 +1,9 @@
import { DragDropContext } from '@hello-pangea/dnd';
-import { Button } from '@radix-ui/themes';
+import { Button, Flex, ScrollArea } from '@radix-ui/themes';
import {
+ useCreateProjectMutation,
useCreateTaskMutation,
- useGetTasksQuery,
+ useGetProjectsQuery,
} from '../../services/mainApi';
import CardGroup from '../CardGroup/CardGroup';
@@ -11,26 +12,40 @@ export default function MainBoard() {
result;
};
- const { data } = useGetTasksQuery();
-
const [create] = useCreateTaskMutation();
+ const [createProject] = useCreateProjectMutation();
+ const { data: cringe, isLoading } = useGetProjectsQuery({});
const onClick = () => {
create({
title: 'My Task 123',
- projectId: 1,
- assignedUserId: 2,
+ projectId: 4,
+ assignedUserId: 1,
deadline: '2025-03-01T12:00:00Z',
});
};
+ const onClick1 = () => {
+ createProject({
+ title: 'My project test 12',
+ description: 'Test desc 123 123 123',
+ });
+ };
+
return (
<>
-
-
+
+
+ {!isLoading &&
+ (cringe as any[]).map((item: any) => (
+
+ ))}
+
+
-
+
+
>
);
}
diff --git a/cool_todo_manager/src/components/TaskCard/TaskCard.tsx b/cool_todo_manager/src/components/TaskCard/TaskCard.tsx
index 98f44a9..490a6fe 100644
--- a/cool_todo_manager/src/components/TaskCard/TaskCard.tsx
+++ b/cool_todo_manager/src/components/TaskCard/TaskCard.tsx
@@ -1,12 +1,12 @@
import { Draggable } from '@hello-pangea/dnd';
-import { DragHandleHorizontalIcon } from '@radix-ui/react-icons';
-import { Box, Button, Card, Flex, Text } from '@radix-ui/themes';
+import { Button, Card, Flex, Text } from '@radix-ui/themes';
type TTaskCard = {
title?: string;
description?: string;
id?: string;
index?: number;
+ status: "todo" | "in-progress" | "completed";
};
export default function TaskCard(props: TTaskCard) {
@@ -21,14 +21,6 @@ export default function TaskCard(props: TTaskCard) {
{props.title}
-
-
-
-
-
)}
diff --git a/cool_todo_manager/src/pages/auth/LoginPage/LoginPage.tsx b/cool_todo_manager/src/pages/auth/LoginPage/LoginPage.tsx
index ebb8fa0..a5a6bc5 100644
--- a/cool_todo_manager/src/pages/auth/LoginPage/LoginPage.tsx
+++ b/cool_todo_manager/src/pages/auth/LoginPage/LoginPage.tsx
@@ -1,4 +1,12 @@
-import { Button, Card, Heading, Text, TextField } from '@radix-ui/themes';
+import {
+ Box,
+ Button,
+ Card,
+ Heading,
+ Link,
+ Text,
+ TextField,
+} from '@radix-ui/themes';
import { Form } from 'radix-ui';
import { useState } from 'react';
import { useLoginMutation } from '../../../services/mainApi';
@@ -66,9 +74,15 @@ export default function LoginPage() {
+
+
+
+ Register
+
+
>
diff --git a/cool_todo_manager/src/pages/auth/RegisterPage/RegisterPage.tsx b/cool_todo_manager/src/pages/auth/RegisterPage/RegisterPage.tsx
index 7dceaf2..21168d0 100644
--- a/cool_todo_manager/src/pages/auth/RegisterPage/RegisterPage.tsx
+++ b/cool_todo_manager/src/pages/auth/RegisterPage/RegisterPage.tsx
@@ -1,11 +1,24 @@
-import { Button, Card, Heading, Text, TextField } from '@radix-ui/themes';
+import {
+ Box,
+ Button,
+ Card,
+ Heading,
+ Link,
+ Text,
+ TextField,
+} from '@radix-ui/themes';
import { Form } from 'radix-ui';
export default function RegisterPage() {
return (
- Register
- e.preventDefault()}>
+
+ Register
+
+ e.preventDefault()}
+ >
Email is required
@@ -42,7 +55,15 @@ export default function RegisterPage() {
-
+
+
+
+
+ Login
+
+
);
diff --git a/cool_todo_manager/src/routes/routes.tsx b/cool_todo_manager/src/routes/routes.tsx
index 2801816..3b10cf0 100644
--- a/cool_todo_manager/src/routes/routes.tsx
+++ b/cool_todo_manager/src/routes/routes.tsx
@@ -1,4 +1,5 @@
import { createRoutesFromElements, Route } from 'react-router-dom';
+import AuthWrapper from '../components/AuthWrapper/AuthWrapper';
import MainBoard from '../components/MainBoard/MainBoard';
import LoginPage from '../pages/auth/LoginPage/LoginPage';
import RegisterPage from '../pages/auth/RegisterPage/RegisterPage';
@@ -6,7 +7,14 @@ import MainPage from '../pages/main/MainPage';
const MyRoutes = createRoutesFromElements(
<>
- }>
+
+
+
+ }
+ >
} />
diff --git a/cool_todo_manager/src/services/mainApi.ts b/cool_todo_manager/src/services/mainApi.ts
index cf5f1fe..f39a73d 100644
--- a/cool_todo_manager/src/services/mainApi.ts
+++ b/cool_todo_manager/src/services/mainApi.ts
@@ -30,6 +30,22 @@ export const mainApi = createApi({
]
: [{ type: 'Task', id: 'LIST' }],
}),
+ getTasksForGroup: builder.query({
+ query: (id: string) => ({
+ url: `tasks/project/${id}`,
+ method: 'GET',
+ }),
+ providesTags: (result) =>
+ result
+ ? [
+ ...result.map((task) => ({
+ type: 'Task' as const,
+ id: task,
+ })),
+ { type: 'Task', id: 'LIST' },
+ ]
+ : [{ type: 'Task', id: 'LIST' }],
+ }),
getTask: builder.query({
query: (id) => ({
url: `tasks/${id}`,
@@ -64,7 +80,7 @@ export const mainApi = createApi({
// PROJECTS
createProject: builder.mutation({
query: (newProject) => ({
- url: 'tasks/create',
+ url: 'projects/create',
method: 'POST',
body: newProject,
}),
@@ -141,5 +157,5 @@ export const authApi = createApi({
});
export const { useLoginMutation, useRegisterMutation } = authApi;
-export const { useGetTasksQuery, useCreateTaskMutation, useUpdateTaskMutation, useDeleteTaskMutation } = mainApi;
+export const { useGetTasksQuery, useCreateTaskMutation, useUpdateTaskMutation, useDeleteTaskMutation, useGetTasksForGroupQuery } = mainApi;
export const { useGetProjectsQuery, useCreateProjectMutation, useUpdateProjectMutation, useDeleteProjectMutation } = mainApi;