Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions apps/backend/lambdas/projects/controllers/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,9 @@ export const createProject: RouteHandler = async ({ event, auth }) => {
}

try {
// Creating the project and its roster together: a project that saved
// without its staff would look complete but fail the form's own
// "at least one staff member" rule on the next read.
// Creating the project and its roster together so a partial save cannot
// leave a project without the staff the caller picked. The roster may be
// empty — admins reach every project through `users.is_admin`.
const inserted = await db.transaction().execute(async (trx) => {
const row = await trx
.insertInto('branch.projects')
Expand Down
7 changes: 0 additions & 7 deletions apps/frontend/src/app/components/ProjectFormModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,6 @@ function validate(values: ProjectFormValues): FieldErrors {
}
}

if (values.members.length === 0) {
errors.members = 'Select AT LEAST 1 staff member for the project';
}

return errors;
}

Expand Down Expand Up @@ -343,13 +339,10 @@ export default function ProjectFormModal({

<StaffPicker
label="Assigned Staff"
required
options={staff}
isLoading={staffLoading}
value={values.members}
onChange={(v) => update('members', v)}
isError={showError('members')}
errorMessage={errors.members}
disabled={saving}
/>

Expand Down
14 changes: 7 additions & 7 deletions apps/frontend/test/components/ProjectFormModal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ describe('ProjectFormModal staff roles', () => {
]);
});

it('drops a removed member from the roster it saves', async () => {
it('saves an empty roster, since admins reach every project anyway', async () => {
renderEdit();

const list = await screen.findByRole('list', {
Expand All @@ -173,11 +173,11 @@ describe('ProjectFormModal staff roles', () => {

fireEvent.click(screen.getByRole('button', { name: 'Save' }));

expect(
await screen.findByText('Select AT LEAST 1 staff member for the project'),
).toBeInTheDocument();
expect(
mockFetch.mock.calls.some(([, init]) => init?.method === 'PUT'),
).toBe(false);
await waitFor(() => {
expect(
mockFetch.mock.calls.some(([, init]) => init?.method === 'PUT'),
).toBe(true);
});
expect(savedBody().members).toEqual([]);
});
});
Loading