This PR fixes #5024. Local recoil state was not updated when workspace name is changed. This PR updates local recoil state so that dropdown (and other parts of the app) correctly shows the workspace name without reload.
96 lines
2.6 KiB
TypeScript
96 lines
2.6 KiB
TypeScript
import { useCallback, useEffect, useState } from 'react';
|
|
import styled from '@emotion/styled';
|
|
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
|
import { useDebouncedCallback } from 'use-debounce';
|
|
|
|
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
|
import { TextInput } from '@/ui/input/components/TextInput';
|
|
import { useUpdateWorkspaceMutation } from '~/generated/graphql';
|
|
import { isDefined } from '~/utils/isDefined';
|
|
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
|
import { logError } from '~/utils/logError';
|
|
|
|
const StyledComboInputContainer = styled.div`
|
|
display: flex;
|
|
flex-direction: row;
|
|
> * + * {
|
|
margin-left: ${({ theme }) => theme.spacing(4)};
|
|
}
|
|
`;
|
|
|
|
type NameFieldProps = {
|
|
autoSave?: boolean;
|
|
onNameUpdate?: (name: string) => void;
|
|
};
|
|
|
|
export const NameField = ({
|
|
autoSave = true,
|
|
onNameUpdate,
|
|
}: NameFieldProps) => {
|
|
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
|
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
|
|
|
|
const [displayName, setDisplayName] = useState(
|
|
currentWorkspace?.displayName ?? '',
|
|
);
|
|
|
|
const [updateWorkspace] = useUpdateWorkspaceMutation();
|
|
|
|
// TODO: Enhance this with react-web-hook-form (https://www.react-hook-form.com)
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
const debouncedUpdate = useCallback(
|
|
useDebouncedCallback(async (name: string) => {
|
|
// update local recoil state when workspace name is updated
|
|
setCurrentWorkspace((currentValue) => {
|
|
if (currentValue === null) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
...currentValue,
|
|
displayName: name,
|
|
};
|
|
});
|
|
if (isDefined(onNameUpdate)) {
|
|
onNameUpdate(displayName);
|
|
}
|
|
if (!autoSave || !name) {
|
|
return;
|
|
}
|
|
try {
|
|
const { data, errors } = await updateWorkspace({
|
|
variables: {
|
|
input: {
|
|
displayName: name,
|
|
},
|
|
},
|
|
});
|
|
|
|
if (isDefined(errors) || isUndefinedOrNull(data?.updateWorkspace)) {
|
|
throw errors;
|
|
}
|
|
} catch (error) {
|
|
logError(error);
|
|
}
|
|
}, 500),
|
|
[updateWorkspace, setCurrentWorkspace],
|
|
);
|
|
|
|
useEffect(() => {
|
|
debouncedUpdate(displayName);
|
|
return debouncedUpdate.cancel;
|
|
}, [debouncedUpdate, displayName]);
|
|
|
|
return (
|
|
<StyledComboInputContainer>
|
|
<TextInput
|
|
label="Name"
|
|
value={displayName}
|
|
onChange={setDisplayName}
|
|
placeholder="Apple"
|
|
fullWidth
|
|
/>
|
|
</StyledComboInputContainer>
|
|
);
|
|
};
|