diff --git a/front/src/modules/companies/components/AddPersonToCompany.tsx b/front/src/modules/companies/components/AddPersonToCompany.tsx index 33b344e61..d7bd68593 100644 --- a/front/src/modules/companies/components/AddPersonToCompany.tsx +++ b/front/src/modules/companies/components/AddPersonToCompany.tsx @@ -1,8 +1,11 @@ import { useState } from 'react'; +import { useMutation, useQuery } from '@apollo/client'; +import { getOperationName } from '@apollo/client/utilities'; import styled from '@emotion/styled'; import { flip, offset, useFloating } from '@floating-ui/react'; import { v4 } from 'uuid'; +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { IconPlus } from '@/ui/display/icon'; import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope'; @@ -62,23 +65,43 @@ export const AddPersonToCompany = ({ goBackToPreviousHotkeyScope, } = usePreviousHotkeyScope(); - const handlePersonSelected = - (companyId: string) => async (newPerson: any | null) => { - if (newPerson) { - // await updatePerson({ - // variables: { - // where: { - // id: newPerson.id, - // }, - // data: { - // company: { connect: { id: companyId } }, - // }, - // }, - // refetchQueries: [getOperationName(GET_PEOPLE) ?? ''], - // }); - handleClosePicker(); - } - }; + // TODO: refactor with useObjectMetadataItem V2 with typed hooks + const { findManyQuery, updateOneMutation, createOneMutation } = + useObjectMetadataItem({ + objectNameSingular: 'person', + }); + + const { data: peopleNotInCompany } = useQuery(findManyQuery, { + variables: { + filter: { + companyId: { + neq: companyId, + }, + }, + }, + }); + + const [updatePerson] = useMutation(updateOneMutation); + const [createPerson] = useMutation(createOneMutation); + + const handlePersonSelected = async ({ + selectedPersonId, + companyId, + }: { + selectedPersonId: string; + companyId: string | null; + }) => { + await updatePerson({ + variables: { + idToUpdate: selectedPersonId, + input: { + companyId: companyId, + }, + }, + refetchQueries: [getOperationName(findManyQuery) ?? ''], + }); + handleClosePicker(); + }; const handleClosePicker = () => { if (isDropdownOpen) { @@ -88,31 +111,44 @@ export const AddPersonToCompany = ({ }; const handleOpenPicker = () => { - if (!isDropdownOpen) { - setIsDropdownOpen(true); - setHotkeyScopeAndMemorizePreviousScope( - RelationPickerHotkeyScope.RelationPicker, - ); - } + // TODO: TEMPORARY - example to implement when the picker is back + handleCreatePerson({ + firstValue: 'John', + secondValue: 'Doe', + }); + // handlePersonSelected({ + // companyId, + // selectedPersonId: peopleNotInCompany.people.edges[0].node.id, + // }); + // if (!isDropdownOpen) { + // setIsDropdownOpen(true); + // setHotkeyScopeAndMemorizePreviousScope( + // RelationPickerHotkeyScope.RelationPicker, + // ); + // } }; - const handleInputKeyDown = async ({ + const handleCreatePerson = async ({ firstValue, secondValue, }: FieldDoubleText) => { if (!firstValue && !secondValue) return; const newPersonId = v4(); - // await insertOnePerson({ - // variables: { - // data: { - // company: { connect: { id: companyId } }, - // id: newPersonId, - // firstName: firstValue, - // lastName: secondValue, - // }, - // }, - // refetchQueries: [getOperationName(GET_PEOPLE) ?? ''], - // }); + + await createPerson({ + variables: { + input: { + companyId: companyId, + id: newPersonId, + name: { + firstName: firstValue, + lastName: secondValue, + }, + }, + }, + refetchQueries: [getOperationName(findManyQuery) ?? ''], + }); + setIsCreationDropdownOpen(false); }; @@ -136,7 +172,7 @@ export const AddPersonToCompany = ({ firstValuePlaceholder="First Name" secondValuePlaceholder="Last Name" onClickOutside={handleEscape} - onEnter={handleInputKeyDown} + onEnter={handleCreatePerson} onEscape={handleEscape} hotkeyScope={RelationPickerHotkeyScope.RelationPicker} /> diff --git a/front/src/modules/companies/components/CompanyTeam.tsx b/front/src/modules/companies/components/CompanyTeam.tsx index 9ff65431b..e2b2b7edd 100644 --- a/front/src/modules/companies/components/CompanyTeam.tsx +++ b/front/src/modules/companies/components/CompanyTeam.tsx @@ -1,8 +1,11 @@ +import { useQuery } from '@apollo/client'; import styled from '@emotion/styled'; +import { isNonEmptyArray } from '@sniptt/guards'; import { Company } from '@/companies/types/Company'; +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { mapPaginatedObjectsToObjects } from '@/object-record/utils/mapPaginatedObjectsToObjects'; import { PeopleCard } from '@/people/components/PeopleCard'; -import { Person } from '@/people/types/Person'; import { AddPersonToCompany } from './AddPersonToCompany'; @@ -43,37 +46,44 @@ const StyledTitle = styled.div` line-height: ${({ theme }) => theme.text.lineHeight.lg}; `; -export const CompanyTeam = ({ company }: CompanyTeamProps) => { - // const { data } = useGetPeopleQuery({ - // variables: { - // orderBy: [], - // where: { - // companyId: { - // equals: company.id, - // }, - // }, - // }, - // }); - const data = { - people: [], - }; +export const CompanyTeam = ({ company }: { company: any }) => { + const { findManyQuery } = useObjectMetadataItem({ + objectNameSingular: 'person', + }); - const peopleIds = data?.people?.map(({ id }) => id); + const { data } = useQuery(findManyQuery, { + variables: { + filter: { + companyId: { + eq: company.id, + }, + }, + }, + }); + + const people = mapPaginatedObjectsToObjects({ + objectNamePlural: 'people', + pagedObjects: data ?? [], + }); + + const peopleIds = people.map((person) => person.id); + + const hasPeople = isNonEmptyArray(peopleIds); return ( <> - {Boolean(data?.people?.length) && ( + {hasPeople && ( Team - {data?.people?.map((person: Person, id) => ( + {people.map((person: any) => ( ))} diff --git a/front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts b/front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts index bf9547d93..c93767e34 100644 --- a/front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts +++ b/front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts @@ -26,7 +26,7 @@ export const EMPTY_MUTATION = gql` export const useObjectMetadataItem = ({ objectNamePlural, objectNameSingular, -}: ObjectMetadataItemIdentifier & { skip?: boolean }) => { +}: ObjectMetadataItemIdentifier) => { const objectMetadataItem = useRecoilValue( objectMetadataItemFamilySelector({ objectNamePlural, diff --git a/front/src/modules/object-record/components/RecordShowPage.tsx b/front/src/modules/object-record/components/RecordShowPage.tsx index e69e7b4a6..03b99e0fa 100644 --- a/front/src/modules/object-record/components/RecordShowPage.tsx +++ b/front/src/modules/object-record/components/RecordShowPage.tsx @@ -2,6 +2,7 @@ import { useParams } from 'react-router-dom'; import { DateTime } from 'luxon'; import { useRecoilState } from 'recoil'; +import { CompanyTeam } from '@/companies/components/CompanyTeam'; import { useFavorites } from '@/favorites/hooks/useFavorites'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition'; @@ -35,14 +36,12 @@ export const RecordShowPage = () => { objectMetadataId: string; }>(); - const { objectMetadataItem: foundObjectMetadataItem } = useObjectMetadataItem( - { - objectNameSingular, - }, - ); + const { objectMetadataItem } = useObjectMetadataItem({ + objectNameSingular, + }); const { favorites, createFavorite, deleteFavorite } = useFavorites({ - objectNamePlural: foundObjectMetadataItem?.namePlural, + objectNamePlural: objectMetadataItem?.namePlural, }); const [, setEntityFields] = useRecoilState( @@ -152,8 +151,8 @@ export const RecordShowPage = () => { avatarType="squared" /> - {foundObjectMetadataItem && - [...foundObjectMetadataItem.fields] + {objectMetadataItem && + [...objectMetadataItem.fields] .sort((a, b) => DateTime.fromISO(a.createdAt) .diff(DateTime.fromISO(b.createdAt)) @@ -182,6 +181,13 @@ export const RecordShowPage = () => { ); })} + {objectNameSingular === 'company' ? ( + <> + + + ) : ( + <> + )} { const formattedObjects: ObjectType[] = - pagedObjects?.[objectNamePlural].edges.map((objectEdge: ObjectEdge) => ({ + pagedObjects?.[objectNamePlural]?.edges?.map((objectEdge: ObjectEdge) => ({ ...objectEdge.node, })) ?? []; diff --git a/front/src/modules/people/components/PeopleCard.tsx b/front/src/modules/people/components/PeopleCard.tsx index 46e20788b..b1efb6d95 100644 --- a/front/src/modules/people/components/PeopleCard.tsx +++ b/front/src/modules/people/components/PeopleCard.tsx @@ -1,8 +1,11 @@ import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; +import { useMutation } from '@apollo/client'; +import { getOperationName } from '@apollo/client/utilities'; import styled from '@emotion/styled'; import { autoUpdate, flip, offset, useFloating } from '@floating-ui/react'; +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { Person } from '@/people/types/Person'; import { IconDotsVertical, IconLinkOff, IconTrash } from '@/ui/display/icon'; import { FloatingIconButton } from '@/ui/input/button/components/FloatingIconButton'; @@ -104,29 +107,34 @@ export const PeopleCard = ({ setIsOptionsOpen(!isOptionsOpen); }; - const handleDetachPerson = () => { - // updatePerson({ - // variables: { - // where: { - // id: person.id, - // }, - // data: { - // company: { - // disconnect: true, - // }, - // }, - // }, - // refetchQueries: [getOperationName(GET_PEOPLE) ?? ''], - // }); + // TODO: refactor with useObjectMetadataItem V2 with typed hooks + const { findManyQuery, updateOneMutation, deleteOneMutation } = + useObjectMetadataItem({ + objectNameSingular: 'person', + }); + + const [updatePerson] = useMutation(updateOneMutation); + const [deletePerson] = useMutation(deleteOneMutation); + + const handleDetachPerson = async () => { + await updatePerson({ + variables: { + idToUpdate: person.id, + input: { + companyId: null, + }, + }, + refetchQueries: [getOperationName(findManyQuery) ?? ''], + }); }; const handleDeletePerson = () => { - // deletePerson({ - // variables: { - // ids: person.id, - // }, - // refetchQueries: [getOperationName(GET_PEOPLE) ?? ''], - // }); + deletePerson({ + variables: { + idToDelete: person.id, + }, + refetchQueries: [getOperationName(findManyQuery) ?? ''], + }); }; return ( diff --git a/front/src/modules/ui/navigation/menu-item/components/MenuItem.tsx b/front/src/modules/ui/navigation/menu-item/components/MenuItem.tsx index 7ff390d74..1a1177ffa 100644 --- a/front/src/modules/ui/navigation/menu-item/components/MenuItem.tsx +++ b/front/src/modules/ui/navigation/menu-item/components/MenuItem.tsx @@ -23,7 +23,7 @@ export type MenuItemProps = { isTooltipOpen?: boolean; className?: string; testId?: string; - onClick?: () => void; + onClick?: (event: MouseEvent) => void; }; export const MenuItem = ({ @@ -38,10 +38,17 @@ export const MenuItem = ({ }: MenuItemProps) => { const showIconButtons = Array.isArray(iconButtons) && iconButtons.length > 0; + const handleMenuItemClick = (event: MouseEvent) => { + event.preventDefault(); + event.stopPropagation(); + + onClick?.(event); + }; + return ( { - const { setCurrentTableCellInEditMode } = useCurrentTableCellEditMode(); + const { objectMetadataConfigState } = useRecordTableScopedStates(); + const objectMetadataConfig = useRecoilValue(objectMetadataConfigState); + + const basePathToShowPage = objectMetadataConfig?.basePathToShowPage; + + const { setCurrentTableCellInEditMode } = useCurrentTableCellEditMode(); const setHotkeyScope = useSetHotkeyScope(); const { setDragSelectionStartEnabled } = useDragSelect(); @@ -37,8 +43,7 @@ export const useTableCell = () => { const isEmpty = useIsFieldEmpty(); - const { entityId, fieldDefinition, basePathToShowPage } = - useContext(FieldContext); + const { entityId, fieldDefinition } = useContext(FieldContext); const [, setFieldInitialValue] = useRecoilState( entityFieldInitialValueFamilyState({