diff --git a/apps/blade/src/app/_components/issues/create-edit-dialog.tsx b/apps/blade/src/app/_components/issues/create-edit-dialog.tsx index 68fc7b3e3..4586af220 100644 --- a/apps/blade/src/app/_components/issues/create-edit-dialog.tsx +++ b/apps/blade/src/app/_components/issues/create-edit-dialog.tsx @@ -190,6 +190,7 @@ export function CreateEditDialog(props: CreateEditDialogComponentProps) { }: Partial = initialValues ?? {}; const resolvedEventData = initial.eventData; const resolvedRoles = initial.teamVisibilityIds ?? defaults.roles; + const resolvedAssigneeIds = initial.assigneeIds ?? defaults.assigneeIds; if (initial.isEvent) { return { ...defaults, @@ -200,6 +201,7 @@ export function CreateEditDialog(props: CreateEditDialogComponentProps) { links: initial.links ?? defaults.links, date: normalizeTaskDueDate(initial.date ?? defaults.date), roles: resolvedRoles, + assigneeIds: resolvedAssigneeIds, }; } return { @@ -211,6 +213,7 @@ export function CreateEditDialog(props: CreateEditDialogComponentProps) { date: normalizeTaskDueDate(initial.date ?? defaults.date), links: initial.links ?? defaults.links, roles: resolvedRoles, + assigneeIds: resolvedAssigneeIds, }; }, [initialValues]); const [formValues, setFormValues] = useState( @@ -262,6 +265,16 @@ export function CreateEditDialog(props: CreateEditDialogComponentProps) { const baseId = useId(); const effectiveTeam = formValues.team || (rolesData?.[0]?.id ?? ""); + const usersOnTeamQuery = api.issues.getUsersOnTeam.useQuery( + { teamId: effectiveTeam }, + { enabled: isOpen && !!effectiveTeam }, + ); + const assigneesForTeam = useMemo( + () => usersOnTeamQuery.data ?? [], + [usersOnTeamQuery.data], + ); + const isAssigneesLoading = usersOnTeamQuery.isLoading; + const assigneesError = usersOnTeamQuery.error; const isFormValid = issueFormSchema.safeParse({ ...formValues, @@ -285,6 +298,17 @@ export function CreateEditDialog(props: CreateEditDialogComponentProps) { ), [formValues.eventData?.roles, roleIdSet], ); + const assigneeIdSet = useMemo( + () => new Set(assigneesForTeam.map((user) => user.id)), + [assigneesForTeam], + ); + const safeAssigneeIds = useMemo( + () => + usersOnTeamQuery.isSuccess + ? formValues.assigneeIds.filter((userId) => assigneeIdSet.has(userId)) + : formValues.assigneeIds, + [assigneeIdSet, formValues.assigneeIds, usersOnTeamQuery.isSuccess], + ); // Helper for event form const updateEventData = ( @@ -410,7 +434,7 @@ export function CreateEditDialog(props: CreateEditDialogComponentProps) { team: effectiveTeam, teamVisibilityIds: safeVisibilityIds.length > 0 ? safeVisibilityIds : undefined, - assigneeIds: formValues.assigneeIds, + assigneeIds: safeAssigneeIds, }; try { @@ -481,7 +505,7 @@ export function CreateEditDialog(props: CreateEditDialogComponentProps) { : normalizeTaskDueDate(formValues.date), teamVisibilityIds: safeVisibilityIds.length > 0 ? safeVisibilityIds : undefined, - assigneeIds: formValues.assigneeIds, + assigneeIds: safeAssigneeIds, }); await utils.issues.invalidate(); @@ -522,7 +546,7 @@ export function CreateEditDialog(props: CreateEditDialogComponentProps) { eventData: formValues.eventData, teamVisibilityIds: safeVisibilityIds.length > 0 ? safeVisibilityIds : undefined, - assigneeIds: formValues.assigneeIds, + assigneeIds: safeAssigneeIds, }); } }; @@ -663,13 +687,91 @@ export function CreateEditDialog(props: CreateEditDialogComponentProps) { updateForm("team", v)} + onValueChange={(v) => { + setFormValues((previous) => ({ + ...previous, + team: v, + assigneeIds: [], + })); + }} roles={rolesData ?? []} isLoading={isRolesLoading} error={rolesError} /> +
+ +
+ {isAssigneesLoading && ( +

+ Loading team members... +

+ )} + + {!!assigneesError && ( +

+ Failed to load team members +

+ )} + + {!isAssigneesLoading && + !assigneesError && + assigneesForTeam.length === 0 && ( +

+ No team members found for this team +

+ )} + + {!isAssigneesLoading && + !assigneesError && + assigneesForTeam.map((user) => { + const assigneeCheckboxId = `${baseId}-assignee-${user.id}`; + return ( +
+ { + const selectedIds = formValues.assigneeIds; + updateForm( + "assigneeIds", + checked + ? Array.from( + new Set([...selectedIds, user.id]), + ) + : selectedIds.filter( + (id) => id !== user.id, + ), + ); + }} + /> +
+ + {user.email && ( + + {user.email} + + )} +
+
+ ); + })} + +

+ Select one or more team members responsible for this issue +

+
+
+