* feat: Skeleton loading #404 * fix: skeleton loading * fix: skeleton loading * feat: Skeleton loading #404 * fix: skeleton loading * fix: skeleton loading * Update CompanyPickerSkeleton.tsx * updated changes
This commit is contained in:
@ -59,6 +59,7 @@ export function CompanyAccountOwnerPicker({ company }: OwnProps) {
|
||||
<SingleEntitySelect
|
||||
onEntitySelected={handleEntitySelected}
|
||||
entities={{
|
||||
loading: companies.loading,
|
||||
entitiesToSelect: companies.entitiesToSelect,
|
||||
selectedEntity: companies.selectedEntities[0],
|
||||
}}
|
||||
|
||||
@ -64,6 +64,7 @@ export function PeopleCompanyPicker({ people }: OwnProps) {
|
||||
entities={{
|
||||
entitiesToSelect: companies.entitiesToSelect,
|
||||
selectedEntity: companies.selectedEntities[0],
|
||||
loading: companies.loading,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -16,6 +16,7 @@ import { SingleEntitySelectBase } from './SingleEntitySelectBase';
|
||||
export type EntitiesForSingleEntitySelect<
|
||||
CustomEntityForSelect extends EntityForSelect,
|
||||
> = {
|
||||
loading: boolean;
|
||||
selectedEntity: CustomEntityForSelect;
|
||||
entitiesToSelect: CustomEntityForSelect[];
|
||||
};
|
||||
|
||||
@ -10,6 +10,9 @@ import { isDefined } from '@/utils/type-guards/isDefined';
|
||||
|
||||
import { useEntitySelectScroll } from '../hooks/useEntitySelectScroll';
|
||||
|
||||
import { CompanyPickerSkeleton } from './skeletons/CompanyPickerSkeleton';
|
||||
import { DropdownMenuItemContainerSkeleton } from './skeletons/DropdownMenuItemContainerSkeleton';
|
||||
|
||||
export type EntitiesForSingleEntitySelect<
|
||||
CustomEntityForSelect extends EntityForSelect,
|
||||
> = {
|
||||
@ -50,24 +53,29 @@ export function SingleEntitySelectBase<
|
||||
|
||||
return (
|
||||
<DropdownMenuItemContainer ref={containerRef}>
|
||||
{entitiesInDropdown?.map((entity, index) => (
|
||||
<DropdownMenuSelectableItem
|
||||
key={entity.id}
|
||||
selected={entities.selectedEntity?.id === entity.id}
|
||||
hovered={hoveredIndex === index}
|
||||
onClick={() => onEntitySelected(entity)}
|
||||
>
|
||||
<Avatar
|
||||
avatarUrl={entity.avatarUrl}
|
||||
placeholder={entity.name}
|
||||
size={16}
|
||||
type={entity.avatarType ?? 'rounded'}
|
||||
/>
|
||||
{entity.name}
|
||||
</DropdownMenuSelectableItem>
|
||||
))}
|
||||
{entitiesInDropdown?.length === 0 && (
|
||||
{entities.loading ? (
|
||||
<DropdownMenuItemContainerSkeleton>
|
||||
<CompanyPickerSkeleton count={10} />
|
||||
</DropdownMenuItemContainerSkeleton>
|
||||
) : entitiesInDropdown.length === 0 ? (
|
||||
<DropdownMenuItem>No result</DropdownMenuItem>
|
||||
) : (
|
||||
entitiesInDropdown?.map((entity, index) => (
|
||||
<DropdownMenuSelectableItem
|
||||
key={entity.id}
|
||||
selected={entities.selectedEntity?.id === entity.id}
|
||||
hovered={hoveredIndex === index}
|
||||
onClick={() => onEntitySelected(entity)}
|
||||
>
|
||||
<Avatar
|
||||
avatarUrl={entity.avatarUrl}
|
||||
placeholder={entity.name}
|
||||
size={16}
|
||||
type={entity.avatarType ?? 'rounded'}
|
||||
/>
|
||||
{entity.name}
|
||||
</DropdownMenuSelectableItem>
|
||||
))
|
||||
)}
|
||||
</DropdownMenuItemContainer>
|
||||
);
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
import Skeleton from 'react-loading-skeleton';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
type OwnProps = {
|
||||
count: number;
|
||||
};
|
||||
|
||||
export const SkeletonContainer = styled.div`
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
margin-bottom: ${({ theme }) => theme.spacing(1)};
|
||||
position: relative;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const SkeletonEntityName = styled.div`
|
||||
margin-left: ${({ theme }) => theme.spacing(2)};
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export function CompanyPickerSkeleton({ count }: OwnProps) {
|
||||
const loadSkeletons = Array(count).fill(1);
|
||||
return loadSkeletons.map((_, i) => (
|
||||
<SkeletonContainer key={i}>
|
||||
<Skeleton width={15} height={15} />
|
||||
<SkeletonEntityName>
|
||||
<Skeleton height={8} />
|
||||
</SkeletonEntityName>
|
||||
</SkeletonContainer>
|
||||
));
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
export const DropdownMenuItemContainerSkeleton = styled.div`
|
||||
--horizontal-padding: ${({ theme }) => theme.spacing(1.5)};
|
||||
--vertical-padding: ${({ theme }) => theme.spacing(2)};
|
||||
|
||||
align-items: center;
|
||||
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
color: ${({ theme }) => theme.font.color.secondary};
|
||||
|
||||
font-size: ${({ theme }) => theme.font.size.sm};
|
||||
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
|
||||
height: calc(100% - 2 * var(--vertical-padding));
|
||||
|
||||
padding: var(--vertical-padding) var(--horizontal-padding);
|
||||
width: calc(100% - 2 * var(--horizontal-padding));
|
||||
`;
|
||||
@ -71,18 +71,19 @@ export function useFilteredSearchEntityQuery<
|
||||
limit?: number;
|
||||
searchFilter: string;
|
||||
}): EntitiesForMultipleEntitySelect<CustomEntityForSelect> {
|
||||
const { data: selectedEntitiesData } = queryHook({
|
||||
variables: {
|
||||
where: {
|
||||
id: {
|
||||
in: selectedIds,
|
||||
const { loading: selectedEntitiesLoading, data: selectedEntitiesData } =
|
||||
queryHook({
|
||||
variables: {
|
||||
where: {
|
||||
id: {
|
||||
in: selectedIds,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: {
|
||||
[orderByField]: sortOrder,
|
||||
},
|
||||
} as QueryVariables,
|
||||
});
|
||||
orderBy: {
|
||||
[orderByField]: sortOrder,
|
||||
},
|
||||
} as QueryVariables,
|
||||
});
|
||||
|
||||
const searchFilterByField = searchOnFields.map((field) => ({
|
||||
[field]: {
|
||||
@ -91,7 +92,10 @@ export function useFilteredSearchEntityQuery<
|
||||
},
|
||||
}));
|
||||
|
||||
const { data: filteredSelectedEntitiesData } = queryHook({
|
||||
const {
|
||||
loading: filteredSelectedEntitiesLoading,
|
||||
data: filteredSelectedEntitiesData,
|
||||
} = queryHook({
|
||||
variables: {
|
||||
where: {
|
||||
AND: [
|
||||
@ -111,26 +115,27 @@ export function useFilteredSearchEntityQuery<
|
||||
} as QueryVariables,
|
||||
});
|
||||
|
||||
const { data: entitiesToSelectData } = queryHook({
|
||||
variables: {
|
||||
where: {
|
||||
AND: [
|
||||
{
|
||||
OR: searchFilterByField,
|
||||
},
|
||||
{
|
||||
id: {
|
||||
notIn: selectedIds,
|
||||
const { loading: entitiesToSelectLoading, data: entitiesToSelectData } =
|
||||
queryHook({
|
||||
variables: {
|
||||
where: {
|
||||
AND: [
|
||||
{
|
||||
OR: searchFilterByField,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
limit: limit ?? DEFAULT_SEARCH_REQUEST_LIMIT,
|
||||
orderBy: {
|
||||
[orderByField]: sortOrder,
|
||||
},
|
||||
} as QueryVariables,
|
||||
});
|
||||
{
|
||||
id: {
|
||||
notIn: selectedIds,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
limit: limit ?? DEFAULT_SEARCH_REQUEST_LIMIT,
|
||||
orderBy: {
|
||||
[orderByField]: sortOrder,
|
||||
},
|
||||
} as QueryVariables,
|
||||
});
|
||||
|
||||
return {
|
||||
selectedEntities: (selectedEntitiesData?.searchResults ?? []).map(
|
||||
@ -142,5 +147,9 @@ export function useFilteredSearchEntityQuery<
|
||||
entitiesToSelect: (entitiesToSelectData?.searchResults ?? []).map(
|
||||
mappingFunction,
|
||||
),
|
||||
loading:
|
||||
entitiesToSelectLoading ||
|
||||
filteredSelectedEntitiesLoading ||
|
||||
selectedEntitiesLoading,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user