redux setup
This commit is contained in:
parent
62617bfb6f
commit
e82b06b508
69
cool_todo_manager/package-lock.json
generated
69
cool_todo_manager/package-lock.json
generated
@ -12,18 +12,22 @@
|
|||||||
"@radix-ui/react-form": "^0.1.2",
|
"@radix-ui/react-form": "^0.1.2",
|
||||||
"@radix-ui/react-icons": "^1.3.2",
|
"@radix-ui/react-icons": "^1.3.2",
|
||||||
"@radix-ui/themes": "^3.2.0",
|
"@radix-ui/themes": "^3.2.0",
|
||||||
|
"@reduxjs/toolkit": "^2.6.0",
|
||||||
"@tailwindcss/vite": "^4.0.6",
|
"@tailwindcss/vite": "^4.0.6",
|
||||||
"@tanstack/react-query": "^5.66.0",
|
"@tanstack/react-query": "^5.66.0",
|
||||||
"@tanstack/react-query-devtools": "^5.66.0",
|
"@tanstack/react-query-devtools": "^5.66.0",
|
||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
"jotai": "^2.12.0",
|
"jotai": "^2.12.0",
|
||||||
|
"js-cookie": "^3.0.5",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
|
"react-redux": "^9.2.0",
|
||||||
"react-router-dom": "^6.26.2",
|
"react-router-dom": "^6.26.2",
|
||||||
"tailwindcss": "^4.0.6"
|
"tailwindcss": "^4.0.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.19.0",
|
"@eslint/js": "^9.19.0",
|
||||||
|
"@types/js-cookie": "^3.0.6",
|
||||||
"@types/react": "^19.0.8",
|
"@types/react": "^19.0.8",
|
||||||
"@types/react-dom": "^19.0.3",
|
"@types/react-dom": "^19.0.3",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
@ -2547,6 +2551,30 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@reduxjs/toolkit": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.6.0.tgz",
|
||||||
|
"integrity": "sha512-mWJCYpewLRyTuuzRSEC/IwIBBkYg2dKtQas8mty5MaV2iXzcmicS3gW554FDeOvLnY3x13NIk8MB1e8wHO7rqQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"immer": "^10.0.3",
|
||||||
|
"redux": "^5.0.1",
|
||||||
|
"redux-thunk": "^3.1.0",
|
||||||
|
"reselect": "^5.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.9.0 || ^17.0.0 || ^18 || ^19",
|
||||||
|
"react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-redux": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@remix-run/router": {
|
"node_modules/@remix-run/router": {
|
||||||
"version": "1.19.2",
|
"version": "1.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.2.tgz",
|
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.2.tgz",
|
||||||
@ -3131,6 +3159,13 @@
|
|||||||
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
|
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/js-cookie": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz",
|
||||||
|
"integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/json-schema": {
|
"node_modules/@types/json-schema": {
|
||||||
"version": "7.0.15",
|
"version": "7.0.15",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||||
@ -4423,6 +4458,16 @@
|
|||||||
"node": ">= 4"
|
"node": ">= 4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/immer": {
|
||||||
|
"version": "10.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz",
|
||||||
|
"integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/immer"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/import-fresh": {
|
"node_modules/import-fresh": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
|
||||||
@ -4520,6 +4565,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/js-cookie": {
|
||||||
|
"version": "3.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
|
||||||
|
"integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/js-tokens": {
|
"node_modules/js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
@ -5394,12 +5448,27 @@
|
|||||||
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
|
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/redux-thunk": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"redux": "^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/regenerator-runtime": {
|
"node_modules/regenerator-runtime": {
|
||||||
"version": "0.14.1",
|
"version": "0.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
||||||
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
|
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/reselect": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/resolve-from": {
|
"node_modules/resolve-from": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
||||||
|
|||||||
@ -14,18 +14,22 @@
|
|||||||
"@radix-ui/react-form": "^0.1.2",
|
"@radix-ui/react-form": "^0.1.2",
|
||||||
"@radix-ui/react-icons": "^1.3.2",
|
"@radix-ui/react-icons": "^1.3.2",
|
||||||
"@radix-ui/themes": "^3.2.0",
|
"@radix-ui/themes": "^3.2.0",
|
||||||
|
"@reduxjs/toolkit": "^2.6.0",
|
||||||
"@tailwindcss/vite": "^4.0.6",
|
"@tailwindcss/vite": "^4.0.6",
|
||||||
"@tanstack/react-query": "^5.66.0",
|
"@tanstack/react-query": "^5.66.0",
|
||||||
"@tanstack/react-query-devtools": "^5.66.0",
|
"@tanstack/react-query-devtools": "^5.66.0",
|
||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
"jotai": "^2.12.0",
|
"jotai": "^2.12.0",
|
||||||
|
"js-cookie": "^3.0.5",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
|
"react-redux": "^9.2.0",
|
||||||
"react-router-dom": "^6.26.2",
|
"react-router-dom": "^6.26.2",
|
||||||
"tailwindcss": "^4.0.6"
|
"tailwindcss": "^4.0.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.19.0",
|
"@eslint/js": "^9.19.0",
|
||||||
|
"@types/js-cookie": "^3.0.6",
|
||||||
"@types/react": "^19.0.8",
|
"@types/react": "^19.0.8",
|
||||||
"@types/react-dom": "^19.0.3",
|
"@types/react-dom": "^19.0.3",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
import { Theme } from '@radix-ui/themes';
|
import { Theme } from '@radix-ui/themes';
|
||||||
import '@radix-ui/themes/styles.css';
|
import '@radix-ui/themes/styles.css';
|
||||||
import { QueryClientProvider } from '@tanstack/react-query';
|
import { QueryClientProvider } from '@tanstack/react-query';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
|
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
|
||||||
import queryClient from './api/queryClient';
|
import queryClient from './api/queryClient';
|
||||||
|
import { store } from './api/RTKQuery';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
import MyRoutes from './routes/routes';
|
import MyRoutes from './routes/routes';
|
||||||
|
|
||||||
@ -10,10 +12,12 @@ const router = createBrowserRouter(MyRoutes);
|
|||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
<Theme className='size-full' accentColor="amber" grayColor="gray">
|
<Theme className="size-full" accentColor="amber" grayColor="gray">
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
|
<Provider store={store}>
|
||||||
{/* <ThemePanel /> */}
|
{/* <ThemePanel /> */}
|
||||||
<RouterProvider router={router} />
|
<RouterProvider router={router} />
|
||||||
|
</Provider>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
</Theme>
|
</Theme>
|
||||||
);
|
);
|
||||||
|
|||||||
16
cool_todo_manager/src/api/RTKQuery.ts
Normal file
16
cool_todo_manager/src/api/RTKQuery.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { configureStore } from '@reduxjs/toolkit';
|
||||||
|
import { setupListeners } from '@reduxjs/toolkit/query';
|
||||||
|
import { authApi, mainApi } from '../services/mainApi';
|
||||||
|
|
||||||
|
export const store = configureStore({
|
||||||
|
reducer: {
|
||||||
|
[mainApi.reducerPath]: mainApi.reducer,
|
||||||
|
[authApi.reducerPath]: authApi.reducer,
|
||||||
|
},
|
||||||
|
middleware: (getDefaultMiddleware) =>
|
||||||
|
getDefaultMiddleware()
|
||||||
|
.concat(mainApi.middleware)
|
||||||
|
.concat(authApi.middleware),
|
||||||
|
});
|
||||||
|
|
||||||
|
setupListeners(store.dispatch);
|
||||||
15
cool_todo_manager/src/components/AuthWrapper/AuthWrapper.tsx
Normal file
15
cool_todo_manager/src/components/AuthWrapper/AuthWrapper.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { useNavigate } from "react-router-dom"
|
||||||
|
|
||||||
|
export default function AuthWrapper() {
|
||||||
|
const navigate = useNavigate()
|
||||||
|
|
||||||
|
if(!localStorage.getItem('token')) {
|
||||||
|
navigate('/login')
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
import { Droppable } from '@hello-pangea/dnd';
|
import { Droppable } from '@hello-pangea/dnd';
|
||||||
import { Box } from '@radix-ui/themes';
|
import { Box } from '@radix-ui/themes';
|
||||||
|
import { useState } from 'react';
|
||||||
import TaskCard from '../TaskCard/TaskCard';
|
import TaskCard from '../TaskCard/TaskCard';
|
||||||
|
|
||||||
const tasks = [
|
const tasks = [
|
||||||
@ -12,11 +13,13 @@ type TCardGroup = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function CardGroup(props: TCardGroup) {
|
export default function CardGroup(props: TCardGroup) {
|
||||||
|
const [localTasks, setLocalTasks] = useState(tasks)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Droppable droppableId={props.id}>
|
<Droppable droppableId={props.id}>
|
||||||
{(provided) => (
|
{(provided) => (
|
||||||
<Box ref={provided.innerRef} {...provided.droppableProps}>
|
<Box ref={provided.innerRef} {...provided.droppableProps}>
|
||||||
{tasks.map((task, i) => (
|
{localTasks.map((task, i) => (
|
||||||
<TaskCard
|
<TaskCard
|
||||||
key={task.id}
|
key={task.id}
|
||||||
id={task.id.toString() + props.id}
|
id={task.id.toString() + props.id}
|
||||||
|
|||||||
@ -1,17 +1,36 @@
|
|||||||
import { DragDropContext } from '@hello-pangea/dnd';
|
import { DragDropContext } from '@hello-pangea/dnd';
|
||||||
|
import { Button } from '@radix-ui/themes';
|
||||||
|
import {
|
||||||
|
useCreateTaskMutation,
|
||||||
|
useGetTasksQuery,
|
||||||
|
} from '../../services/mainApi';
|
||||||
import CardGroup from '../CardGroup/CardGroup';
|
import CardGroup from '../CardGroup/CardGroup';
|
||||||
|
|
||||||
|
|
||||||
export default function MainBoard() {
|
export default function MainBoard() {
|
||||||
|
const dragEndHandle = (result: TDragResult) => {
|
||||||
|
result;
|
||||||
|
};
|
||||||
|
|
||||||
const dragEndHandle = (result: TDragResult ) => {
|
const { data } = useGetTasksQuery();
|
||||||
result
|
|
||||||
}
|
const [create] = useCreateTaskMutation();
|
||||||
|
|
||||||
|
const onClick = () => {
|
||||||
|
create({
|
||||||
|
title: 'My Task 123',
|
||||||
|
projectId: 1,
|
||||||
|
assignedUserId: 2,
|
||||||
|
deadline: '2025-03-01T12:00:00Z',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<DragDropContext onDragEnd={dragEndHandle}>
|
<DragDropContext onDragEnd={dragEndHandle}>
|
||||||
<CardGroup id='qwhdf' />
|
<CardGroup id="qwhdf" />
|
||||||
<CardGroup id='123fsduiyuiyi' />
|
<CardGroup id="123fsduiyuiyi" />
|
||||||
</DragDropContext>
|
</DragDropContext>
|
||||||
|
<Button onClick={onClick}>asdasdasd </Button>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,24 +1,42 @@
|
|||||||
import { Button, Card, Heading, Text, TextField } from '@radix-ui/themes';
|
import { Button, Card, Heading, Text, TextField } from '@radix-ui/themes';
|
||||||
import { Form } from 'radix-ui';
|
import { Form } from 'radix-ui';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { useLoginMutation } from '../../../services/mainApi';
|
||||||
|
|
||||||
export default function LoginPage() {
|
export default function LoginPage() {
|
||||||
|
const [login, { isError }] = useLoginMutation();
|
||||||
|
|
||||||
|
const [username, setUsername] = useState('');
|
||||||
|
const [password, setPassword] = useState('');
|
||||||
|
|
||||||
|
const submitHandler = (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
|
e.preventDefault();
|
||||||
|
login({ username, password });
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Card className="absolute top-1/2 left-1/2 -translate-y-1/2 -translate-x-1/2 w-fit">
|
<Card className="absolute top-1/2 left-1/2 -translate-y-1/2 -translate-x-1/2 w-fit">
|
||||||
<Heading size="4" className='text-center !mb-2'>Login</Heading>
|
<Heading size="4" className="text-center !mb-2">
|
||||||
|
Login
|
||||||
|
</Heading>
|
||||||
|
|
||||||
<Form.Root className="flex flex-col gap-4" onSubmit={e => e.preventDefault()}>
|
<Form.Root
|
||||||
|
className="flex flex-col gap-4"
|
||||||
|
onSubmit={submitHandler}
|
||||||
|
>
|
||||||
<Form.Field name="email">
|
<Form.Field name="email">
|
||||||
<Form.Message match={'valueMissing'}>
|
<Form.Message match={'valueMissing'}>
|
||||||
<Text>Email is required</Text>
|
<Text>Username is required</Text>
|
||||||
</Form.Message>
|
|
||||||
|
|
||||||
<Form.Message match={'typeMismatch'}>
|
|
||||||
<Text>Email is not valid</Text>
|
|
||||||
</Form.Message>
|
</Form.Message>
|
||||||
|
|
||||||
<Form.Control asChild>
|
<Form.Control asChild>
|
||||||
<TextField.Root type="email" placeholder="Email">
|
<TextField.Root
|
||||||
|
type="text"
|
||||||
|
placeholder="Username"
|
||||||
|
value={username}
|
||||||
|
onChange={(e) => setUsername(e.target.value)}
|
||||||
|
>
|
||||||
<TextField.Slot />
|
<TextField.Slot />
|
||||||
</TextField.Root>
|
</TextField.Root>
|
||||||
</Form.Control>
|
</Form.Control>
|
||||||
@ -33,12 +51,18 @@ export default function LoginPage() {
|
|||||||
<TextField.Root
|
<TextField.Root
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
|
value={password}
|
||||||
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
>
|
>
|
||||||
<TextField.Slot />
|
<TextField.Slot />
|
||||||
</TextField.Root>
|
</TextField.Root>
|
||||||
</Form.Control>
|
</Form.Control>
|
||||||
</Form.Field>
|
</Form.Field>
|
||||||
|
|
||||||
|
{isError && (
|
||||||
|
<Text>{'Unable to login. Please try again.'}</Text>
|
||||||
|
)}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
// onClick={(e) => e.preventDefault()}
|
// onClick={(e) => e.preventDefault()}
|
||||||
className="mt-4"
|
className="mt-4"
|
||||||
|
|||||||
145
cool_todo_manager/src/services/mainApi.ts
Normal file
145
cool_todo_manager/src/services/mainApi.ts
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
|
||||||
|
|
||||||
|
export const mainApi = createApi({
|
||||||
|
reducerPath: 'api',
|
||||||
|
baseQuery: fetchBaseQuery({
|
||||||
|
baseUrl: 'http://109.107.166.17:3000/api/',
|
||||||
|
prepareHeaders: (headers) => {
|
||||||
|
headers.set(
|
||||||
|
'Authorization',
|
||||||
|
`Bearer ${localStorage.getItem('token')}`,
|
||||||
|
);
|
||||||
|
return headers;
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
tagTypes: ['Task', 'Project'],
|
||||||
|
endpoints: (builder) => ({
|
||||||
|
getTasks: builder.query<string[], void>({
|
||||||
|
query: () => ({
|
||||||
|
url: 'tasks',
|
||||||
|
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<string, string>({
|
||||||
|
query: (id) => ({
|
||||||
|
url: `tasks/${id}`,
|
||||||
|
method: 'GET',
|
||||||
|
}),
|
||||||
|
providesTags: (result, error, id) => [{ type: 'Task', id }],
|
||||||
|
}),
|
||||||
|
updateTask: builder.mutation({
|
||||||
|
query: (task) => ({
|
||||||
|
url: `tasks/${task.id}`,
|
||||||
|
method: 'PATCH',
|
||||||
|
body: task,
|
||||||
|
}),
|
||||||
|
invalidatesTags: (result, error, id) => [{ type: 'Task', id }],
|
||||||
|
}),
|
||||||
|
deleteTask: builder.mutation({
|
||||||
|
query: (id) => ({
|
||||||
|
url: `tasks/${id}`,
|
||||||
|
method: 'DELETE',
|
||||||
|
}),
|
||||||
|
invalidatesTags: (result, error, id) => [{ type: 'Task', id }],
|
||||||
|
}),
|
||||||
|
createTask: builder.mutation({
|
||||||
|
query: (newTask) => ({
|
||||||
|
url: 'tasks/create',
|
||||||
|
method: 'POST',
|
||||||
|
body: newTask,
|
||||||
|
}),
|
||||||
|
invalidatesTags: [{ type: 'Task', id: 'LIST' }],
|
||||||
|
}),
|
||||||
|
|
||||||
|
// PROJECTS
|
||||||
|
createProject: builder.mutation({
|
||||||
|
query: (newProject) => ({
|
||||||
|
url: 'tasks/create',
|
||||||
|
method: 'POST',
|
||||||
|
body: newProject,
|
||||||
|
}),
|
||||||
|
invalidatesTags: [{ type: 'Project', id: 'LIST' }],
|
||||||
|
}),
|
||||||
|
getProjects: builder.query({
|
||||||
|
query: () => ({
|
||||||
|
url: 'projects',
|
||||||
|
method: 'GET',
|
||||||
|
}),
|
||||||
|
providesTags: (result, error, id) => [
|
||||||
|
{ type: 'Project', id: 'LIST' },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
getProject: builder.query({
|
||||||
|
query: (id) => ({
|
||||||
|
url: `projects/${id}`,
|
||||||
|
method: 'GET',
|
||||||
|
}),
|
||||||
|
providesTags: (result, error, id) => [{ type: 'Project', id }],
|
||||||
|
}),
|
||||||
|
updateProject: builder.mutation({
|
||||||
|
query: ({ id, project }) => ({
|
||||||
|
url: `projects/${id}`,
|
||||||
|
method: 'PATCH',
|
||||||
|
body: project,
|
||||||
|
}),
|
||||||
|
invalidatesTags: (result, error, id) => [{ type: 'Project', id }],
|
||||||
|
}),
|
||||||
|
deleteProject: builder.mutation({
|
||||||
|
query: (id) => ({
|
||||||
|
url: `projects/${id}`,
|
||||||
|
method: 'DELETE',
|
||||||
|
}),
|
||||||
|
invalidatesTags: (result, error, id) => [{ type: 'Project', id }],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const authApi = createApi({
|
||||||
|
reducerPath: 'authApi',
|
||||||
|
baseQuery: fetchBaseQuery({
|
||||||
|
baseUrl: 'http://109.107.166.17:3000/api/auth/',
|
||||||
|
|
||||||
|
}),
|
||||||
|
endpoints: (builder) => ({
|
||||||
|
login: builder.mutation({
|
||||||
|
query: (credentials) => ({
|
||||||
|
url: 'login',
|
||||||
|
method: 'POST',
|
||||||
|
body: credentials,
|
||||||
|
}),
|
||||||
|
async onQueryStarted(arg, { queryFulfilled }) {
|
||||||
|
try {
|
||||||
|
const response = await queryFulfilled;
|
||||||
|
if (response.data) {
|
||||||
|
localStorage.setItem(
|
||||||
|
'token',
|
||||||
|
response.data.access_token,
|
||||||
|
);
|
||||||
|
window.location.href = '/';
|
||||||
|
}
|
||||||
|
} catch (error) {}
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
register: builder.mutation({
|
||||||
|
query: (credentials) => ({
|
||||||
|
url: 'register',
|
||||||
|
method: 'POST',
|
||||||
|
body: credentials,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const { useLoginMutation, useRegisterMutation } = authApi;
|
||||||
|
export const { useGetTasksQuery, useCreateTaskMutation, useUpdateTaskMutation, useDeleteTaskMutation } = mainApi;
|
||||||
|
export const { useGetProjectsQuery, useCreateProjectMutation, useUpdateProjectMutation, useDeleteProjectMutation } = mainApi;
|
||||||
Loading…
x
Reference in New Issue
Block a user