Skip to main content
← Blog

Building the Project Assignee Feature

VauDium ·

The server was already prepared. Adding UI, building a search screen, and filling in the missing data.

Building the Project Assignee Feature

Fecit has a project feature. Multiple people join a project and share tasks. But there was no way to know “who’s doing this task?”

We decided to build the assignee feature.

The Server Was Already Ready

Looking at the code, the server already had an assigned_to field. API endpoints existed. Permission checks were implemented. Someone had laid the groundwork.

The data model was in place too. Tasks store the assignee’s ID in assigned_to, validated against project membership. When the assignee changes, the previous assignee’s sync marks the task as deleted. Thoughtful design, already done.

What was missing was the UI.

Where to Put It

We placed an “Assignee” row right below the project selector in the task detail screen. Tap it, and a search screen opens.

Initially we used a BottomSheet modal to show the member list. But with many members, search would be needed. We applied the same pattern from address autocomplete — navigate to a dedicated search screen.

The search screen shows project members. You can search by nickname. Your own entry gets a small “me” badge. Tap a member to assign them, and you’re back on the previous screen.

How to Show the Name

We need to display the assignee’s name. The server returns only an ID in assigned_to. Getting the name requires fetching user info separately.

First we fetched the project member list on the client and matched by ID. It worked, but calling the membership API every time a task opens is wasteful.

We decided to include assignee info in the server’s task response. Added an assignee field that carries the assignee’s nickname and ID alongside the task. One request, all the info you need.

Now You See It, Now You Don’t

After implementation, the assignee would show up and then disappear. Refresh, and it’s back.

Tracing the cause: individual API calls (set assignee, get task) included assignee info. But list queries (gather) and incremental sync (sync) didn’t.

The server returns tasks through two paths. Individual APIs go through an “enrich” step that fills in project info, assignee info, and more. But list and sync endpoints use batch merging for performance. Project info was in the batch merge. Assignee wasn’t — it was newly added.

We added assignee to the batch merge. Collect all assignee IDs, query them in one call, match results to each task. Same pattern as project info.

Default Assignee

When you create a task with a project, you become the default assignee. Setting a project on an existing task does the same. Remove the project, and the assignee clears too.

The create screen also lets you pick a different assignee. Select a project, and an assignee row appears. Defaults to you, but you can choose another member.

Desktop Too

After confirming it worked on mobile, we added the same feature to desktop. Desktop uses a dropdown — an assignee row below the project section, click to show a member list dropdown.

Looking Back

Having server infrastructure already in place meant we could finish in a day. API endpoints, permission checks, data model — when the foundation exists, adding UI is fast.

But “it works” and “it works correctly” are different things. We had to restructure the server response to include names. We had to catch missing data in list and sync endpoints. Even simple features require checking every path data flows through.