From 28addf43b496fcd576c4530244f993ed218a9bdd Mon Sep 17 00:00:00 2001 From: Hazem Krimi Date: Wed, 16 Jun 2021 00:42:28 +0100 Subject: [PATCH] Update project page --- src/pages/Project/index.tsx | 581 +++++++++++++++++++++++++++++++++--- src/pages/Project/styles.ts | 6 + 2 files changed, 538 insertions(+), 49 deletions(-) diff --git a/src/pages/Project/index.tsx b/src/pages/Project/index.tsx index 47510dd..4becf43 100644 --- a/src/pages/Project/index.tsx +++ b/src/pages/Project/index.tsx @@ -1,10 +1,19 @@ +import * as Yup from 'yup'; +import { useFormik } from 'formik'; import { useReactToPrint } from 'react-to-print'; import { useHistory, useParams } from 'react-router-dom'; import { useEffect, useState, useRef } from 'react'; -import { useLazyQuery, useReactiveVar } from '@apollo/client'; +import { useLazyQuery, useMutation, useReactiveVar } from '@apollo/client'; import { Redirect } from 'react-router'; -import { roleVar } from '../../graphql/state'; -import { Design, Empty, Settings, Specification } from '../../assets'; +import { roleVar, userVar } from '../../graphql/state'; +import { + Design, + Empty, + FullBuild, + MVP, + Settings, + Specification, +} from '../../assets'; import { Box, Button, @@ -14,11 +23,24 @@ import { Link, Specification as SpecificationPrint, Chip, + Alert, + Modal, + Input, } from '../../components'; import { Wrapper } from './styles'; import { + AddProjectDesignMutation, + AddProjectDesignMutationVariables, + AddProjectFullBuildMutation, + AddProjectFullBuildMutationVariables, + AddProjectMvpMutation, + AddProjectMvpMutationVariables, + ChangeProjectStateMutation, + ChangeProjectStateMutationVariables, + GetAllProjectsByClientIdQuery, + GetAllProjectsByClientIdQueryVariables, GetAllProjectsQuery, - GetAllProjectsQueryVariables, + GetAllUsersQueryVariables, GetProjectByIdQuery, GetProjectByIdQueryVariables, GetPrototypeByIdQuery, @@ -26,20 +48,49 @@ import { ProjectOutput, ProtoTypeOutput, } from '../../graphql/types'; -import { GET_ALL_PROJECTS, GET_PROJECT_BY_ID } from '../../graphql/project.api'; +import { + ADD_PROJECT_DESIGN, + ADD_PROJECT_FULL_BUILD, + ADD_PROJECT_MVP, + CHANGE_PROJECT_STATE, + GET_ALL_PROJECTS, + GET_ALL_PROJECTS_BY_CLIENT_ID, + GET_PROJECT_BY_ID, +} from '../../graphql/project.api'; import { GET_PROTOTYPE_BY_ID } from '../../graphql/prototype.api'; const Project = () => { const role = useReactiveVar(roleVar); + const currentUser = useReactiveVar(userVar); const history = useHistory(); const printRef = useRef(null); const { id } = useParams<{ id: string }>(); const [project, setProject] = useState(); const [prototype, setPrototype] = useState>(); + const [error, setError] = useState(''); + const [designModal, setDesignModal] = useState(false); + const [mvpModal, setMvpModal] = useState(false); + const [fullBuildModal, setFullBuildModal] = useState(false); + + const [ + getProjectsByClientId, + { loading: clientProjectsLoading }, + ] = useLazyQuery< + GetAllProjectsByClientIdQuery, + GetAllProjectsByClientIdQueryVariables + >(GET_ALL_PROJECTS_BY_CLIENT_ID, { + variables: { + id: currentUser?.id!, + }, + onCompleted({ getAllProjectsByClientId }) { + setProject(getAllProjectsByClientId[0]); + }, + fetchPolicy: 'network-only', + }); const [getProjects, { loading: projectsLoading }] = useLazyQuery< GetAllProjectsQuery, - GetAllProjectsQueryVariables + GetAllUsersQueryVariables >(GET_ALL_PROJECTS, { onCompleted({ getAllProjects }) { setProject(getAllProjects[0]); @@ -66,6 +117,64 @@ const Project = () => { }, }); + const [changeProjectState] = useMutation< + ChangeProjectStateMutation, + ChangeProjectStateMutationVariables + >(CHANGE_PROJECT_STATE, { + onCompleted({ changeProjectState: changedStateProject }) { + setProject(changedStateProject); + }, + onError({ graphQLErrors }) { + setError(graphQLErrors[0].extensions?.info); + setTimeout(() => setError(''), 3000); + }, + }); + + const [addProjectDesign] = useMutation< + AddProjectDesignMutation, + AddProjectDesignMutationVariables + >(ADD_PROJECT_DESIGN, { + onCompleted({ addProjectDesign: projectWithDesign }) { + setDesignModal(false); + setProject(projectWithDesign); + }, + onError({ graphQLErrors }) { + setDesignModal(false); + setError(graphQLErrors[0].extensions?.info); + setTimeout(() => setError(''), 3000); + }, + }); + + const [addProjectMvp] = useMutation< + AddProjectMvpMutation, + AddProjectMvpMutationVariables + >(ADD_PROJECT_MVP, { + onCompleted({ addProjectMvp: projectWithMvp }) { + setMvpModal(false); + setProject(projectWithMvp); + }, + onError({ graphQLErrors }) { + setMvpModal(false); + setError(graphQLErrors[0].extensions?.info); + setTimeout(() => setError(''), 3000); + }, + }); + + const [addProjectFullBuild] = useMutation< + AddProjectFullBuildMutation, + AddProjectFullBuildMutationVariables + >(ADD_PROJECT_FULL_BUILD, { + onCompleted({ addProjectFullBuild: projectWithFullBuild }) { + setFullBuildModal(false); + setProject(projectWithFullBuild); + }, + onError({ graphQLErrors }) { + setFullBuildModal(false); + setError(graphQLErrors[0].extensions?.info); + setTimeout(() => setError(''), 3000); + }, + }); + const handlePrint = useReactToPrint({ content: () => printRef.current, }); @@ -73,12 +182,16 @@ const Project = () => { useEffect(() => { if (id) { getProject({ variables: { id } }); - } else { - getProjects(); - } + } else if (role === 'client') { + getProjectsByClientId({ + variables: { + id: currentUser?.id!, + }, + }); + } else getProjects(); // eslint-disable-next-line - }, [id]); + }, [id, role]); useEffect(() => { if (project) getPrototype({ variables: { id: project?.template?.id } }); @@ -86,10 +199,186 @@ const Project = () => { // eslint-disable-next-line }, [project]); + const addDesignForm = useFormik({ + initialValues: { + fileName: '', + fileSource: '', + }, + onSubmit: ({ fileName, fileSource }) => { + addProjectDesign({ + variables: { + design: { + id: project?.id!, + name: fileName, + src: fileSource, + }, + }, + }); + }, + }); + + const addMvpForm = useFormik({ + initialValues: { + fileName: '', + fileSource: '', + }, + onSubmit: ({ fileName, fileSource }) => { + addProjectMvp({ + variables: { + mvp: { + id: project?.id!, + name: fileName, + src: fileSource, + }, + }, + }); + }, + }); + + const addFullBuildForm = useFormik({ + initialValues: { + url: '', + }, + validationSchema: Yup.object().shape({ + url: Yup.string().required('URL is required'), + }), + onSubmit: ({ url }) => { + addProjectFullBuild({ + variables: { + fullBuild: { + id: project?.id!, + url, + }, + }, + }); + }, + }); + return role !== 'admin' ? ( <> - {!projectsLoading && !projectLoading && !prototypeLoading ? ( + {!projectsLoading && + !clientProjectsLoading && + !projectLoading && + !prototypeLoading ? ( <> + {designModal && ( + setDesignModal(false)} + onConfirm={addDesignForm.handleSubmit} + > + + ) => { + const formData = new FormData(); + + if (event.target.files && event.target.files[0]) { + formData.append('file', event.target.files[0]); + formData.append('upload_preset', 'xofll5kc'); + + addDesignForm.setFieldValue('fileName', ''); + addDesignForm.setFieldValue('fileSource', ''); + + const data = await ( + await fetch(`${process.env.REACT_APP_CLOUDINARY_URL}`, { + method: 'POST', + body: formData, + }) + ).json(); + + const filename = data.original_filename; + const filesource = data.secure_url; + + addDesignForm.setFieldValue('fileName', filename); + addDesignForm.setFieldValue('fileSource', filesource); + } + }} + error={ + addDesignForm.touched.fileName && + (!!addDesignForm.errors.fileName || + !!addDesignForm.errors.fileSource) + } + errorMessage={addDesignForm.errors.fileName} + /> + + )} + {mvpModal && ( + setMvpModal(false)} + onConfirm={addMvpForm.handleSubmit} + > + + ) => { + const formData = new FormData(); + + if (event.target.files && event.target.files[0]) { + formData.append('file', event.target.files[0]); + formData.append('upload_preset', 'xofll5kc'); + + addMvpForm.setFieldValue('fileName', ''); + addMvpForm.setFieldValue('fileSource', ''); + + const data = await ( + await fetch(`${process.env.REACT_APP_CLOUDINARY_URL}`, { + method: 'POST', + body: formData, + }) + ).json(); + + const filename = data.original_filename; + const filesource = data.secure_url; + + addMvpForm.setFieldValue('fileName', filename); + addMvpForm.setFieldValue('fileSource', filesource); + } + }} + error={ + addMvpForm.touched.fileName && + (!!addMvpForm.errors.fileName || + !!addMvpForm.errors.fileSource) + } + errorMessage={addMvpForm.errors.fileName} + /> + + )} + {fullBuildModal && ( + setMvpModal(false)} + onConfirm={addFullBuildForm.handleSubmit} + > + + + )} {project ? ( @@ -109,42 +398,83 @@ const Project = () => { {project.name} + {error && ( + + + + )} {project.state === 'Approved' ? ( <> - +