import React, { useState, useEffect } from 'react'; import styled from 'styled-components/macro'; import GlobalTopNavbar from 'App/TopNavbar'; import Empty from 'shared/undraw/Empty'; import { useCreateTeamMutation, useGetProjectsQuery, useCreateProjectMutation, GetProjectsDocument, GetProjectsQuery, } from 'shared/generated/graphql'; import { Link } from 'react-router-dom'; import NewProject from 'shared/components/NewProject'; import { useCurrentUser } from 'App/context'; import Button from 'shared/components/Button'; import { usePopup, Popup } from 'shared/components/PopupMenu'; import { useForm } from 'react-hook-form'; import Input from 'shared/components/Input'; import updateApolloCache from 'shared/utils/cache'; import produce from 'immer'; import NOOP from 'shared/utils/noop'; import theme from 'App/ThemeStyles'; import { mixin } from '../shared/utils/styles'; type CreateTeamData = { teamName: string }; type CreateTeamFormProps = { onCreateTeam: (teamName: string) => void; }; const CreateTeamFormContainer = styled.form``; const CreateTeamButton = styled(Button)` width: 100%; `; const CreateTeamForm: React.FC = ({ onCreateTeam }) => { const { register, handleSubmit } = useForm(); const createTeam = (data: CreateTeamData) => { onCreateTeam(data.teamName); }; return ( Create ); }; const ProjectAddTile = styled.div` background-color: ${props => mixin.rgba(props.theme.colors.bg.primary, 0.4)}; background-size: cover; background-position: 50%; color: #fff; line-height: 20px; padding: 8px; position: relative; text-decoration: none; border-radius: 3px; display: block; `; const ProjectTile = styled(Link)<{ color: string }>` background-color: ${props => props.color}; background-size: cover; background-position: 50%; color: #fff; line-height: 20px; padding: 8px; position: relative; text-decoration: none; border-radius: 3px; display: block; `; const ProjectTileFade = styled.div` background-color: rgba(0, 0, 0, 0.15); bottom: 0; left: 0; position: absolute; right: 0; top: 0; `; const ProjectListItem = styled.li` width: 23.5%; padding: 0; margin: 0 2% 2% 0; box-sizing: border-box; position: relative; cursor: pointer; &:hover ${ProjectTileFade} { background-color: rgba(0, 0, 0, 0.25); } `; const ProjectList = styled.ul` display: flex; flex-wrap: wrap; & ${ProjectListItem}:nth-of-type(4n) { margin-right: 0; } `; const ProjectTileDetails = styled.div` display: flex; height: 80px; position: relative; flex-direction: column; justify-content: space-between; `; const ProjectAddTileDetails = styled.div` display: flex; height: 80px; position: relative; flex-direction: column; align-items: center; justify-content: center; `; const ProjectTileName = styled.div<{ centered?: boolean }>` flex: 0 0 auto; font-size: 16px; font-weight: 700; display: inline-block; overflow: hidden; max-height: 40px; width: 100%; word-wrap: break-word; ${props => props.centered && 'text-align: center;'} `; const Wrapper = styled.div` position: relative; display: flex; flex-direction: row; align-items: flex-start; justify-content: center; overflow-y: auto; `; const ProjectSectionTitleWrapper = styled.div` align-items: center; display: flex; justify-content: space-between; height: 32px; margin-bottom: 24px; padding: 8px 0; position: relative; margin-top: 16px; `; const SectionActions = styled.div` display: flex; align-items: center; `; const SectionAction = styled(Button)` padding: 6px 12px; `; const SectionActionLink = styled(Link)` margin-right: 8px; `; const ProjectSectionTitle = styled.h3` font-size: 16px; color: ${props => props.theme.colors.text.primary}; `; const ProjectsContainer = styled.div` margin: 40px 16px 0; width: 100%; max-width: 825px; min-width: 288px; `; const AddTeamButton = styled(Button)` padding: 6px 12px; position: absolute; top: 6px; right: 12px; `; type ShowNewProject = { open: boolean; initialTeamID: null | string; }; const Projects = () => { const { showPopup, hidePopup } = usePopup(); const { loading, data } = useGetProjectsQuery({ pollInterval: 3000, fetchPolicy: 'cache-and-network' }); useEffect(() => { document.title = 'Taskcafé'; }, []); const [createProject] = useCreateProjectMutation({ update: (client, newProject) => { updateApolloCache(client, GetProjectsDocument, cache => produce(cache, draftCache => { if (newProject.data) { draftCache.projects.push({ ...newProject.data.createProject }); } }), ); }, }); const [showNewProject, setShowNewProject] = useState({ open: false, initialTeamID: null }); const { user } = useCurrentUser(); const [createTeam] = useCreateTeamMutation({ update: (client, createData) => { updateApolloCache(client, GetProjectsDocument, cache => produce(cache, draftCache => { if (createData.data) { draftCache.teams.push({ ...createData.data?.createTeam }); } }), ); }, }); const colors = theme.colors.multiColors; if (data && user) { const { projects, teams, organizations } = data; const organizationID = organizations[0].id ?? null; const personalProjects = projects .filter(p => p.team === null) .sort((a, b) => { const textA = a.name.toUpperCase(); const textB = b.name.toUpperCase(); return textA < textB ? -1 : textA > textB ? 1 : 0; // eslint-disable-line no-nested-ternary }); const projectTeams = teams .sort((a, b) => { const textA = a.name.toUpperCase(); const textB = b.name.toUpperCase(); return textA < textB ? -1 : textA > textB ? 1 : 0; // eslint-disable-line no-nested-ternary }) .map(team => { return { id: team.id, name: team.name, projects: projects .filter(project => project.team && project.team.id === team.id) .sort((a, b) => { const textA = a.name.toUpperCase(); const textB = b.name.toUpperCase(); return textA < textB ? -1 : textA > textB ? 1 : 0; // eslint-disable-line no-nested-ternary }), }; }); return ( <> {true && ( // TODO: add permision check { showPopup( $target, { hidePopup(); }} > { if (organizationID) { createTeam({ variables: { name: teamName, organizationID } }); hidePopup(); } }} /> , ); }} > Add Team )}
Personal Projects {personalProjects.map((project, idx) => ( {project.name} ))} { setShowNewProject({ open: true, initialTeamID: 'no-team' }); }} > Create new project
{projectTeams.map(team => { return (
{team.name} {true && ( // TODO: add permision check Projects Members Settings )} {team.projects.map((project, idx) => ( {project.name} ))} {true && ( // TODO: add permision check { setShowNewProject({ open: true, initialTeamID: team.id }); }} > Create new project )}
); })} {showNewProject.open && ( { if (user) { createProject({ variables: { teamID, name } }); setShowNewProject({ open: false, initialTeamID: null }); } }} onClose={() => { setShowNewProject({ open: false, initialTeamID: null }); }} teams={teams} /> )}
); } return ; }; export default Projects;