Commit 1cde5da1 authored by Ermolaev Timur's avatar Ermolaev Timur

#142 Реализовал создание проекта, переход на конкретный проект

parent c83389aa
...@@ -51,7 +51,6 @@ router.get('/my',auth, async (req:Request, res:Response): Promise<Response>=> { ...@@ -51,7 +51,6 @@ router.get('/my',auth, async (req:Request, res:Response): Promise<Response>=> {
router.post('/',auth, async (req:Request, res:Response): Promise<Response> => { router.post('/',auth, async (req:Request, res:Response): Promise<Response> => {
if (!req.body) return res.status(400).send({Message:'problem in incoming req.body'}) if (!req.body) return res.status(400).send({Message:'problem in incoming req.body'})
const {user, title,color}= req.body; const {user, title,color}= req.body;
const member:Member = new Member; const member:Member = new Member;
member.user= user; member.user= user;
member.roleProject= MemberRole.ADMIN; member.roleProject= MemberRole.ADMIN;
......
...@@ -17,7 +17,6 @@ function NewMemberModalContent({ members, users, onChangeNewMemberHandler, onCha ...@@ -17,7 +17,6 @@ function NewMemberModalContent({ members, users, onChangeNewMemberHandler, onCha
getOptionLabel={(item) => item.displayName || ""} getOptionLabel={(item) => item.displayName || ""}
style={{ marginBottom: '15px' }} style={{ marginBottom: '15px' }}
/> />
<CustomAutocomplete <CustomAutocomplete
name={'role'} name={'role'}
label={'Роль'} label={'Роль'}
......
import { Button } from "@mui/material";
import { Box } from "@mui/system";
import { memo } from "react";
import FormElement from "../../UI/Form/FormElement/FormElement"
const NewProjectModalContent = ({ inputChangeHandler, projectTitle, createNewProjectHandler, handleClose }) => {
return <>
<FormElement
onChange={(e)=>{inputChangeHandler(e)}}
name={"title"}
label={"Название"}
state={projectTitle}
/>
<Box sx={{ display: 'flex', justifyContent: 'space-between', marginTop: '10px'}}>
<Button
type="submit"
color="primary"
variant="outlined"
onClick={()=>{createNewProjectHandler()}}
>
Создать
</Button>
<Button
type="submit"
color="primary"
variant="outlined"
onClick={()=>{handleClose()}}
>
Отмена
</Button>
</Box>
</>
};
export default memo(NewProjectModalContent);
\ No newline at end of file
import { Box, Button, Grid, Modal } from "@mui/material";
import { useState } from "react";
import { useSelector } from "react-redux";
import FormElement from "../../UI/Form/FormElement/FormElement";
import { Typography } from "@mui/material";
import AddCircleIcon from '@mui/icons-material/AddCircle';
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
p: 4,
};
const ProjectForm = ({ onSubmit }) => {
const users = useSelector(state => state.users)
console.log(users)
const [open, setOpen] = useState(false);
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
const [state, setState] = useState({
title: ""
});
const submitFormHandler = (e) => {
e.preventDefault();
let project = { title: state.title }
console.log(project);
if (project.title === "") {
alert("Нельзя создать проект без названия")
} else {
onSubmit(project);
}
};
const inputChangeHandler = (e) => {
const { name, value } = e.target;
setState(prevState => {
return { ...prevState, [name]: value };
});
};
return (
<div >
<AddCircleIcon onClick={handleOpen} />
<Modal
open={open}
onClose={handleClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
onSubmit={submitFormHandler}
>
<Box sx={style}>
<form >
<Grid container direction="column" spacing={2}>
<Typography variant="h4">Новый проект</Typography>
<FormElement
onChange={inputChangeHandler}
name={"title"}
label={"Title"}
state={state}
/>
<Grid item>
<Button
type="submit"
color="primary"
variant="contained"
>
Создать
</Button>
</Grid>
</Grid>
</form>
</Box>
</Modal>
</div>
);
};
export default ProjectForm;
\ No newline at end of file
import { Button, Card, CardActions, CardContent, Grid, IconButton, Typography } from "@mui/material"; import {Grid, Typography } from "@mui/material";
import { Link } from "react-router-dom"; import { useSelector } from "react-redux";
import ArrowForwardIcon from "@mui/icons-material/ArrowForward"; import { memo, useMemo } from "react";
import { useDispatch, useSelector } from "react-redux";
import DeleteIcon from "@mui/icons-material/Delete";
import { deleteProject, fetchProject } from "../../../../../store/actions/projectsActions";
import { memo, useEffect, useMemo } from "react";
import { Box } from "@mui/system";
import DeleteButton from "../../../../UI/DeleteButton/DeleteButton"; import DeleteButton from "../../../../UI/DeleteButton/DeleteButton";
import ArrowIncrementButton from "../../../../UI/ArrowIncrementButton/ArrowIncrementButton"; import ArrowIncrementButton from "../../../../UI/ArrowIncrementButton/ArrowIncrementButton";
...@@ -14,6 +9,7 @@ const styleBlock = { ...@@ -14,6 +9,7 @@ const styleBlock = {
borderRadius: '5px', borderRadius: '5px',
width: '100%', width: '100%',
padding: '15px', padding: '15px',
height: '10%',
} }
const styleText = { const styleText = {
...@@ -21,7 +17,7 @@ const styleText = { ...@@ -21,7 +17,7 @@ const styleText = {
fontWeight: '600', fontWeight: '600',
} }
const ProjectItem = ({ title, members, onClickProjectHandler }) => { const ProjectItem = ({ title, members, onClickProjectHandler, onClickGoToSpecificProjectHandler }) => {
const { user } = useSelector(state => state.users); const { user } = useSelector(state => state.users);
const currentRoleInProject = useMemo(() => { const currentRoleInProject = useMemo(() => {
...@@ -40,7 +36,7 @@ const ProjectItem = ({ title, members, onClickProjectHandler }) => { ...@@ -40,7 +36,7 @@ const ProjectItem = ({ title, members, onClickProjectHandler }) => {
</Grid> </Grid>
<Grid item> <Grid item>
<DeleteButton /> <DeleteButton />
<ArrowIncrementButton /> <ArrowIncrementButton onClick={onClickGoToSpecificProjectHandler}/>
</Grid> </Grid>
</Grid> </Grid>
</> </>
......
...@@ -2,15 +2,16 @@ import {Grid} from "@mui/material"; ...@@ -2,15 +2,16 @@ import {Grid} from "@mui/material";
import { memo } from "react"; import { memo } from "react";
import ProjectItem from "./ProjectItem/ProjectItem"; import ProjectItem from "./ProjectItem/ProjectItem";
const ProjectsList = ({projects, onClickProjectHandler}) => { const ProjectsList = ({projects, onClickProjectHandler, onClickGoToSpecificProjectHandler}) => {
return ( return (
<Grid item container gap={3}> <Grid item container gap={3} sx={{ height: '79vh', overflow: 'auto', overflowX: 'hidden'}}>
{projects?.map(project => { {projects?.map(project => {
return <ProjectItem return <ProjectItem
title={project.title} title={project.title}
members={project.members} members={project.members}
key={project.id} key={project.id}
onClickProjectHandler={()=>{onClickProjectHandler(project)}} onClickProjectHandler={()=>{onClickProjectHandler(project)}}
onClickGoToSpecificProjectHandler={(e)=>{onClickGoToSpecificProjectHandler(e, project.id)}}
/> />
})} })}
</Grid> </Grid>
......
...@@ -7,10 +7,10 @@ const style = { ...@@ -7,10 +7,10 @@ const style = {
display: 'flex', display: 'flex',
justifyContent: 'space-between', justifyContent: 'space-between',
alignItems: 'center', alignItems: 'center',
marginBottom: '10px' marginBottom: '10px',
} }
const ProjectsWrapper = ({ onClickProjectHandler, projects }) => { const ProjectsWrapper = ({ onClickProjectHandler, projects, onClickGoToSpecificProjectHandler, handleOpen }) => {
return <> return <>
...@@ -18,9 +18,13 @@ const ProjectsWrapper = ({ onClickProjectHandler, projects }) => { ...@@ -18,9 +18,13 @@ const ProjectsWrapper = ({ onClickProjectHandler, projects }) => {
<Grid item xs={4}> <Grid item xs={4}>
<Typography variant="h2" sx={style}> <Typography variant="h2" sx={style}>
Проекты Проекты
<Button variant="outlined">Создать</Button> <Button variant="outlined" onClick={()=>{handleOpen()}}>Создать</Button>
</Typography> </Typography>
<ProjectsList projects={projects} onClickProjectHandler={onClickProjectHandler} /> <ProjectsList
projects={projects}
onClickProjectHandler={onClickProjectHandler}
onClickGoToSpecificProjectHandler={onClickGoToSpecificProjectHandler}
/>
</Grid> </Grid>
</> </>
......
...@@ -11,18 +11,20 @@ import NewMemberModalContent from "../../components/ProjectComponents/NewMemberM ...@@ -11,18 +11,20 @@ import NewMemberModalContent from "../../components/ProjectComponents/NewMemberM
const FullProject = ({projectId}) => { const FullProject = ({ projectId }) => {
const { project } = useSelector(state => state.projects); const { project } = useSelector(state => state.projects);
const [modal, setModal] = useState(false)
const [newMember, setNewMember] = useState(null)
const [currentMember, setCurrentMember] = useState(null)
const { user, users } = useSelector(state => state.users); const { user, users } = useSelector(state => state.users);
const dispatch = useDispatch(); const dispatch = useDispatch();
const params = useParams() const params = useParams()
const navigate = useNavigate() const navigate = useNavigate()
const [modal, setModal] = useState(false)
const [newMember, setNewMember] = useState(null)
const [currentMember, setCurrentMember] = useState(null)
useEffect(() => { useEffect(() => {
if (projectId) { if (projectId) {
dispatch(fetchProject(projectId)) dispatch(fetchProject(projectId))
...@@ -73,13 +75,11 @@ const FullProject = ({projectId}) => { ...@@ -73,13 +75,11 @@ const FullProject = ({projectId}) => {
dispatch(deleteMember(id, project?.project?.id)) dispatch(deleteMember(id, project?.project?.id))
}, [dispatch, project?.project?.id]) }, [dispatch, project?.project?.id])
const onClickTasksHandler = useCallback((id) => { const onClickTasksHandler = useCallback(() => {
navigate('/workers-tasks') navigate('/workers-tasks')
}, [navigate]) }, [navigate])
return <> return <>
<Grid>
<ProjectInfo <ProjectInfo
project={project.project} project={project.project}
handleOpen={handleOpen} handleOpen={handleOpen}
...@@ -111,8 +111,6 @@ const FullProject = ({projectId}) => { ...@@ -111,8 +111,6 @@ const FullProject = ({projectId}) => {
</NewMemberModalContent> </NewMemberModalContent>
</DefaultModal> </DefaultModal>
</Grid>
</> </>
}; };
......
import { Grid, Typography } from "@mui/material"; import { Grid } from "@mui/material";
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import HasAccess from "../../components/UI/HasAccess/HasAccess"; import { createProject, fetchProjects } from "../../store/actions/projectsActions";
import { fetchProjects } from "../../store/actions/projectsActions";
import ProjectsList from "../../components/ProjectsComponents/ProjectsWrapper/ProjectsList/ProjectsList";
import FullProject from "../FullProject/FullProject"; import FullProject from "../FullProject/FullProject";
import ProjectsWrapper from "../../components/ProjectsComponents/ProjectsWrapper/ProjectsWrapper"; import ProjectsWrapper from "../../components/ProjectsComponents/ProjectsWrapper/ProjectsWrapper";
import { useNavigate } from "react-router-dom";
import DefaultModal from "../../components/UI/DefaultModal/DefaultModal";
import NewProjectModalContent from "../../components/ProjectsComponents/NewProjectModalContent/NewProjectModalContent";
const Projects = () => { const Projects = () => {
const { projects } = useSelector(state => state.projects.projects);
const { user } = useSelector(state => state.users)
const dispatch = useDispatch(); const dispatch = useDispatch();
const { projects, project, loading } = useSelector(state => state.projects.projects); const navigate = useNavigate()
const [currentProject, setCurrentProject] = useState(null) const [currentProject, setCurrentProject] = useState(null)
const [projectTitle, setProjectTitle] = useState('');
const [modal, setModal] = useState(false)
useEffect(() => { useEffect(() => {
dispatch(fetchProjects()) dispatch(fetchProjects())
}, [dispatch]); }, [dispatch]);
const onClickProjectHandler = useCallback((project)=>{ const inputChangeHandler = (e) => {
setProjectTitle(e.target.value)
};
const onClickProjectHandler = useCallback((project) => {
setCurrentProject(project) setCurrentProject(project)
}, []) }, [])
const onClickGoToSpecificProjectHandler = useCallback((e, projectId) => {
e.stopPropagation();
navigate(`/projects/${projectId}`)
}, [navigate])
const createNewProjectHandler = useCallback(() => {
console.log({ title: projectTitle, user: user.id })
dispatch(createProject({ title: projectTitle, user: user.id }, navigate))
}, [dispatch, projectTitle, user.id, navigate])
const handleOpen = useCallback(async () => {
setModal(true)
}, [])
const handleClose = useCallback(() => {
setModal(false)
}, [])
return <> return <>
{projects?.length > 0 || project?.length > 0 ? (<> <Grid container justifyContent='space-between'>
<Grid container spacing={1}>
<Grid
container
item
direction="row"
justifyContent="space-between"
>
<ProjectsWrapper projects={projects} onClickProjectHandler={onClickProjectHandler}/> <ProjectsWrapper
projects={projects}
onClickProjectHandler={onClickProjectHandler}
onClickGoToSpecificProjectHandler={onClickGoToSpecificProjectHandler}
handleOpen={handleOpen}
/>
<Grid item xs={7} > <Grid item xs={7} >
{currentProject ? <FullProject projectId={currentProject?.id}/> : null} {currentProject ? <FullProject projectId={currentProject?.id} /> : null}
</Grid>
</Grid> </Grid>
</Grid> </Grid>
</>) :
<h1>Созданных проектов нет</h1> <DefaultModal
} modal={modal}
handleClose={() => { handleClose() }}
>
<NewProjectModalContent
handleClose={handleClose}
projectTitle={projectTitle}
inputChangeHandler={inputChangeHandler}
createNewProjectHandler={createNewProjectHandler}
/>
</DefaultModal>
</> </>
}; };
......
...@@ -264,7 +264,6 @@ function WeekCalendar() { ...@@ -264,7 +264,6 @@ function WeekCalendar() {
}, [currentTask, dispatch, hoursInDay, userId]) }, [currentTask, dispatch, hoursInDay, userId])
const deleteTaskHandler = useCallback(async (e, taskId) => { const deleteTaskHandler = useCallback(async (e, taskId) => {
console.log(e)
e.stopPropagation(); e.stopPropagation();
await dispatch(deleteCalendarTask(taskId, userId)) await dispatch(deleteCalendarTask(taskId, userId))
}, [dispatch, userId]) }, [dispatch, userId])
......
...@@ -102,7 +102,6 @@ export const createProject = (projectData, navigate) => { ...@@ -102,7 +102,6 @@ export const createProject = (projectData, navigate) => {
try { try {
const response = await axios.post("/projects", projectData); const response = await axios.post("/projects", projectData);
dispatch(createProjectSuccess()); dispatch(createProjectSuccess());
console.log(response.data)
navigate("/projects/" + response.data.project.id) navigate("/projects/" + response.data.project.id)
dispatch(showNotification("Проект успешно создан")) dispatch(showNotification("Проект успешно создан"))
} catch (e) { } catch (e) {
...@@ -157,8 +156,7 @@ export const changeMemberRole = (userId, data) => { ...@@ -157,8 +156,7 @@ export const changeMemberRole = (userId, data) => {
return async (dispatch) => { return async (dispatch) => {
dispatch(changeMemberRoleSuccess()); dispatch(changeMemberRoleSuccess());
try { try {
const response = await axios.put(`/projects/change-project-role/${userId}`, data); await axios.put(`/projects/change-project-role/${userId}`, data);
console.log(response.data)
dispatch(changeMemberRoleRequest()); dispatch(changeMemberRoleRequest());
await dispatch(fetchProject(data?.projectId)) await dispatch(fetchProject(data?.projectId))
} catch (e) { } catch (e) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment