Skip to content

Commit

Permalink
fix(GoalDependencies): add validation form, minor fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
LamaEats authored and 9teen90nine committed Jul 6, 2023
1 parent 0908a74 commit 5414c11
Show file tree
Hide file tree
Showing 11 changed files with 86 additions and 55 deletions.
1 change: 0 additions & 1 deletion src/components/ActivityFeed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { gapL, gapM, gray5 } from '@taskany/colors';
export const ActivityFeed = styled.div`
display: grid;
row-gap: ${gapM};
padding-top: 0;
padding-bottom: 250px;
position: relative;
z-index: 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
"Add dependency": "",
"Add": ""
"Add": "",
"Add blocking dependency": "",
"Add related dependency": ""
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
"Add dependency": "Добавить цель",
"Add": "Добавить"
"Add dependency": "Добавить зависимость",
"Add": "Добавить",
"Add blocking dependency": "Добавить блокирующую зависимость",
"Add related dependency": "Добавить связанную зависимость"
}
51 changes: 35 additions & 16 deletions src/components/GoalDependencyForm/GoalDependencyForm.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { FormInput, PlusIcon, Button } from '@taskany/bricks';
import { gray7 } from '@taskany/colors';
import { useState, useCallback, useEffect } from 'react';
import { useForm, Controller } from 'react-hook-form';
import { useState, useCallback, useEffect, useMemo } from 'react';
import { useForm } from 'react-hook-form';
import styled from 'styled-components';

import { GoalByIdReturnType } from '../../../trpc/inferredTypes';
Expand Down Expand Up @@ -31,17 +31,18 @@ interface GoalDependencyAddFormProps {
goalId: string;
kind: dependencyKind;
onSubmit: (values: ToggleGoalDependency) => void;
isEmpty: boolean;
}

export const GoalDependencyAddForm: React.FC<GoalDependencyAddFormProps> = ({ goalId, kind, onSubmit }) => {
export const GoalDependencyAddForm: React.FC<GoalDependencyAddFormProps> = ({ goalId, kind, isEmpty, onSubmit }) => {
const [selected, setSelected] = useState<GoalByIdReturnType | null>(null);
const [query, setQuery] = useState(['']);
const {
control,
register,
handleSubmit,
setValue,
reset,
formState: { isSubmitSuccessful },
formState: { isSubmitSuccessful, errors },
} = useForm({
resolver: zodResolver(toggleGoalDependencySchema),
mode: 'onChange',
Expand Down Expand Up @@ -78,14 +79,35 @@ export const GoalDependencyAddForm: React.FC<GoalDependencyAddFormProps> = ({ go
setQuery([goal.projectId!, String(goal.scopeId)]);
}, []);

useEffect(() => {
if (selected) {
if (query[0] !== selected.projectId || query[1] !== String(selected.scopeId)) {
resetFormHandler();
}
}
}, [query, selected, resetFormHandler]);

const translate = useMemo(() => {
return {
default: tr('Add dependency'),
[dependencyKind.blocks]: tr('Add blocking dependency'),
[dependencyKind.dependsOn]: tr('Add dependency'),
[dependencyKind.relatedTo]: tr('Add related dependency'),
};
}, []);

return (
<InlineForm
renderTrigger={(props) => (
<StyledInlineTrigger text={tr('Add dependency')} icon={<PlusIcon noWrap size="s" />} {...props} />
<StyledInlineTrigger
text={isEmpty ? translate[kind] : translate.default}
icon={<PlusIcon noWrap size="s" />}
{...props}
/>
)}
submitted={isSubmitSuccessful}
isSubmitted={isSubmitSuccessful}
onSubmit={handleSubmit(onSubmit)}
reset={resetFormHandler}
onReset={resetFormHandler}
>
<GoalSuggest
renderTrigger={() => (
Expand All @@ -95,19 +117,16 @@ export const GoalDependencyAddForm: React.FC<GoalDependencyAddFormProps> = ({ go
value={query.join('-')}
onChange={handleInputChange}
brick="right"
error={errors.relation?.id}
/>
)}
value={query.join('-')}
onChange={handleGoalSelect}
/>
<Button text={tr('Add')} brick="left" type="submit" view="primary" outline disabled={selected == null} />
<Controller
name="relation"
control={control}
render={({ field }) => <input type="hidden" {...field} value={field.value.id} />}
/>
<Controller name="id" control={control} render={({ field }) => <input type="hidden" {...field} />} />
<Controller name="kind" control={control} render={({ field }) => <input type="hidden" {...field} />} />
<Button text={tr('Add')} brick="left" type="submit" view="primary" outline />
<input type="hidden" {...register('relation.id')} />
<input type="hidden" {...register('id')} />
<input type="hidden" {...register('kind')} />
</InlineForm>
);
};
49 changes: 26 additions & 23 deletions src/components/GoalDependencyList/GoalDependencyList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,9 @@ const GoalDependencyListItem: React.FC<GoalDependencyListItemProps> = ({ onRemov
</Title>
</NextLink>
</StyledTitleContainer>
{canEdit ? <StyledCleanButton onClick={onRemoveHandler} /> : null}
{nullable(canEdit, () => (
<StyledCleanButton onClick={onRemoveHandler} />
))}
</TitleItem>
),
},
Expand Down Expand Up @@ -184,30 +186,31 @@ export function GoalDependencyListByKind<T extends GoalDependencyItem>({
<CircleIconInner as={MessageTextAltIcon} size="s" color={backgroundColor} />
</Circle>
<StyledWrapper>
<StyledHeadingWrapper>
<Text color={gray6} weight="thin">
{heading[kind]}
</Text>
</StyledHeadingWrapper>
{nullable(items.length, () => (
<StyledTable columns={6}>
{items.map((item) => (
<GoalDependencyListItem
key={item.id}
canEdit={canEdit}
projectId={item.projectId}
title={item.title}
state={item.state ?? undefined}
issuer={item.activity ?? undefined}
owner={item.owner!}
shortId={`${item.projectId}-${item.scopeId}`}
estimate={item.estimate[item.estimate.length - 1]?.estimate}
onRemove={() => onRemoveHandler(item)}
/>
))}
</StyledTable>
<>
<StyledHeadingWrapper>
<Text color={gray6} weight="thin">
{heading[kind]}
</Text>
</StyledHeadingWrapper>
<StyledTable columns={6}>
{items.map((item) => (
<GoalDependencyListItem
key={item.id}
canEdit={canEdit}
projectId={item.projectId}
title={item.title}
state={item.state ?? undefined}
issuer={item.activity ?? undefined}
owner={item.owner!}
shortId={`${item.projectId}-${item.scopeId}`}
estimate={item.estimate[item.estimate.length - 1]?.estimate}
onRemove={() => onRemoveHandler(item)}
/>
))}
</StyledTable>
</>
))}

{children}
</StyledWrapper>
</ActivityFeedItem>
Expand Down
1 change: 1 addition & 0 deletions src/components/GoalPage/GoalPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ export const GoalPage = ({ user, ssrTime, params: { id } }: ExternalPageProps<{
onSubmit={dependency.onAddHandler}
kind={deps.kind}
goalId={id}
isEmpty={deps.goals.length === 0}
/>
))}
</GoalDependencyListByKind>
Expand Down
1 change: 1 addition & 0 deletions src/components/GoalPreview/GoalPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ const GoalPreview: React.FC<GoalPreviewProps> = ({ preview, onClose, onDelete })
onSubmit={dependency.onAddHandler}
kind={deps.kind}
goalId={id}
isEmpty={deps.goals.length === 0}
/>
))}
</GoalDependencyListByKind>
Expand Down
18 changes: 9 additions & 9 deletions src/components/InlineForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ interface InlineFormProps {
renderTrigger?: (props: RenderTriggerProps) => React.ReactNode;
onSubmit: () => void;
children: React.ReactNode;
reset: () => void;
submitted?: boolean;
onReset: () => void;
isSubmitted?: boolean;
className?: string;
}

Expand All @@ -28,8 +28,8 @@ const StyledFormWrapper = styled.div`
export const InlineForm: React.FC<InlineFormProps> = ({
renderTrigger,
onSubmit,
reset,
submitted,
onReset,
isSubmitted,
children,
className,
}) => {
Expand Down Expand Up @@ -62,17 +62,17 @@ export const InlineForm: React.FC<InlineFormProps> = ({
});

useEffect(() => {
if (submitted) {
if (isSubmitted) {
toggle();
reset();
onReset();
}
}, [reset, submitted]);
}, [onReset, isSubmitted]);

useEffect(() => {
if (!visible) {
reset();
onReset();
}
}, [visible, reset]);
}, [visible, onReset]);

return (
<StyledWrapper ref={wrapperRef} className={className}>
Expand Down
4 changes: 3 additions & 1 deletion src/schema/goal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ export const toggleGoalDependencySchema = z.object({
id: z.string().optional(),
kind: z.nativeEnum(dependencyKind),
relation: z.object({
id: z.string(),
id: z.string().cuid({
message: tr('Choose a dependency'),
}),
}),
});

Expand Down
3 changes: 2 additions & 1 deletion src/schema/schema.i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
"Goal's description must be a string": "",
"Goal's project or team are required": "",
"Criteria weight is required": "",
"Criteria weight must be longer than 1 symbol": ""
"Criteria weight must be longer than 1 symbol": "",
"Choose a dependency": ""
}
3 changes: 2 additions & 1 deletion src/schema/schema.i18n/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
"Goal's description must be a string": "",
"Goal's project or team are required": "",
"Criteria weight is required": "",
"Criteria weight must be longer than 1 symbol": ""
"Criteria weight must be longer than 1 symbol": "",
"Choose a dependency": ""
}

0 comments on commit 5414c11

Please sign in to comment.