Skip to content

Commit b77c86a

Browse files
committed
Add PUT endpoint to update main tasks and GET endpoint for subtasks by project
1 parent 2f4368b commit b77c86a

2 files changed

Lines changed: 116 additions & 10 deletions

File tree

Controllers/MainTasksController.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,28 @@ public MainTasksController(MongoDbService mongoDbService)
3131
_subTasksCollection = _mongoDbService.GetCollection<SubTaskModel>("subtasks");
3232
}
3333

34+
// PUT /api/maintasks/{id} - Update a main task
35+
[HttpPut("{id}")]
36+
[Authorize(Policy = "DetailedTaskEdit")]
37+
public async Task<IActionResult> Update(string id, [FromBody] UpdateMainTaskDto dto)
38+
{
39+
if (!ObjectId.TryParse(id, out _))
40+
return BadRequest(new { message = "Invalid main task ID format." });
41+
if (dto == null)
42+
return BadRequest(new { message = "Invalid JSON or null body. Ensure Content-Type: application/json." });
43+
if (string.IsNullOrWhiteSpace(dto.Title))
44+
return BadRequest(new { message = "Title is required." });
45+
46+
var update = Builders<MainTaskModel>.Update
47+
.Set(x => x.Title, dto.Title)
48+
.Set(x => x.Description, dto.Description);
49+
50+
var result = await _mainTasksCollection.UpdateOneAsync(x => x.Id == id, update);
51+
if (result.MatchedCount == 0)
52+
return NotFound(new { message = "MainTask not found." });
53+
return NoContent();
54+
}
55+
3456
// GET /api/maintasks - Get all main tasks
3557
[HttpGet]
3658
public async Task<IActionResult> GetAll()
@@ -147,5 +169,12 @@ public class CreateMainTaskDto
147169
public string? Description { get; set; }
148170
}
149171

172+
// DTO for updating main tasks
173+
public class UpdateMainTaskDto
174+
{
175+
public string Title { get; set; }
176+
public string Description { get; set; }
177+
}
178+
150179
}
151180
}

Controllers/SubTasksController.cs

Lines changed: 87 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,37 @@ public async Task<IActionResult> GetAll([FromQuery] string? projectId = null)
6262
}
6363
}
6464

65+
// GET /api/subtasks/project/{projectId} - Get all subtasks for a specific project
66+
[HttpGet("project/{projectId}")]
67+
[Authorize(Policy = "ProjectRead")]
68+
public async Task<IActionResult> GetByProject(string projectId)
69+
{
70+
if (string.IsNullOrWhiteSpace(projectId))
71+
return BadRequest(new { message = "ProjectId is required." });
72+
73+
try
74+
{
75+
// If client, verify they have access to the project
76+
if (User.IsInRole("Client"))
77+
{
78+
var db = _mongoDbService.GetDatabase();
79+
var projectsCollection = db.GetCollection<FlowModels.Project>("project");
80+
var userId = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
81+
82+
var project = await projectsCollection.Find(p => p.Id == projectId).FirstOrDefaultAsync();
83+
if (project == null || project?.Permissions == null || (userId != null && !project.Permissions.ContainsKey(userId)))
84+
return StatusCode(403, new { message = "You do not have permission to view tasks from this project." });
85+
}
86+
87+
var subTasks = await _subTasksCollection.Find(st => st.ProjectId == projectId).ToListAsync();
88+
return Ok(subTasks ?? new List<SubTaskModel>());
89+
}
90+
catch (Exception ex)
91+
{
92+
return StatusCode(500, new { message = "Failed to fetch subtasks for project.", detail = ex.Message });
93+
}
94+
}
95+
6596
// GET /api/subtasks/me - Get subtasks for the currently authenticated user
6697
[HttpGet("me")]
6798
public async Task<IActionResult> GetForCurrentUser()
@@ -165,6 +196,22 @@ public async Task<IActionResult> Create([FromBody] CreateSubTaskDto subTaskDto)
165196
if (string.IsNullOrWhiteSpace(subTaskDto.ProjectId))
166197
return BadRequest(new { message = "ProjectId is required." });
167198

199+
// Parse dates from string format (YYYY-MM-DD)
200+
DateTime? startDate = null;
201+
DateTime? endDate = null;
202+
203+
if (!string.IsNullOrWhiteSpace(subTaskDto.StartDate))
204+
{
205+
if (DateTime.TryParse(subTaskDto.StartDate, out var parsedStart))
206+
startDate = DateTime.SpecifyKind(parsedStart, DateTimeKind.Utc);
207+
}
208+
209+
if (!string.IsNullOrWhiteSpace(subTaskDto.EndDate))
210+
{
211+
if (DateTime.TryParse(subTaskDto.EndDate, out var parsedEnd))
212+
endDate = DateTime.SpecifyKind(parsedEnd, DateTimeKind.Utc);
213+
}
214+
168215
var subTask = new SubTaskModel
169216
{
170217
Id = ObjectId.GenerateNewId().ToString(),
@@ -177,8 +224,8 @@ public async Task<IActionResult> Create([FromBody] CreateSubTaskDto subTaskDto)
177224
Category = subTaskDto.Category,
178225
CreatedBy = subTaskDto.CreatedBy,
179226
AssignedTo = subTaskDto.AssignedTo ?? new List<string>(),
180-
StartDate = subTaskDto.StartDate,
181-
EndDate = subTaskDto.EndDate,
227+
StartDate = startDate,
228+
EndDate = endDate,
182229
CreatedAt = DateTime.UtcNow
183230
};
184231

@@ -232,6 +279,22 @@ public async Task<IActionResult> Update(string id, [FromBody] UpdateSubTaskDto s
232279
if (existingSubTask == null)
233280
return NotFound(new { message = "SubTask not found." });
234281

282+
// Parse dates from string format (YYYY-MM-DD)
283+
DateTime? startDate = null;
284+
DateTime? endDate = null;
285+
286+
if (!string.IsNullOrWhiteSpace(subTaskDto.StartDate))
287+
{
288+
if (DateTime.TryParse(subTaskDto.StartDate, out var parsedStart))
289+
startDate = DateTime.SpecifyKind(parsedStart, DateTimeKind.Utc);
290+
}
291+
292+
if (!string.IsNullOrWhiteSpace(subTaskDto.EndDate))
293+
{
294+
if (DateTime.TryParse(subTaskDto.EndDate, out var parsedEnd))
295+
endDate = DateTime.SpecifyKind(parsedEnd, DateTimeKind.Utc);
296+
}
297+
235298
var updatedSubTask = new SubTaskModel
236299
{
237300
Id = id,
@@ -244,8 +307,8 @@ public async Task<IActionResult> Update(string id, [FromBody] UpdateSubTaskDto s
244307
Category = subTaskDto.Category,
245308
CreatedBy = subTaskDto.CreatedBy,
246309
AssignedTo = subTaskDto.AssignedTo ?? new List<string>(),
247-
StartDate = subTaskDto.StartDate,
248-
EndDate = subTaskDto.EndDate,
310+
StartDate = startDate,
311+
EndDate = endDate,
249312
CreatedAt = existingSubTask.CreatedAt,
250313
Comments = existingSubTask.Comments
251314
};
@@ -333,8 +396,22 @@ public async Task<IActionResult> Patch(string id, [FromBody] Dictionary<string,
333396
updateDefs.Add(Builders<SubTaskModel>.Update.Set(st => st.Priority, value?.ToString()));
334397
break;
335398
case "categoryid":
336-
updateDefs.Add(Builders<SubTaskModel>.Update.Set(st => st.CategoryId, value?.ToString()));
337-
break;
399+
{
400+
var categoryIdValue = value?.ToString();
401+
// Treat "uncategorized" (or empty) as clearing the category
402+
if (string.IsNullOrWhiteSpace(categoryIdValue) || categoryIdValue.Equals("uncategorized", StringComparison.OrdinalIgnoreCase))
403+
{
404+
updateDefs.Add(Builders<SubTaskModel>.Update.Set(st => st.CategoryId, null));
405+
updateDefs.Add(Builders<SubTaskModel>.Update.Set(st => st.Category, null));
406+
}
407+
else
408+
{
409+
if (!ObjectId.TryParse(categoryIdValue, out _))
410+
return BadRequest(new { message = "CategoryId must be a valid ObjectId or 'uncategorized'." });
411+
updateDefs.Add(Builders<SubTaskModel>.Update.Set(st => st.CategoryId, categoryIdValue));
412+
}
413+
break;
414+
}
338415
case "assignedto":
339416
if (value is JsonElement element && element.ValueKind == JsonValueKind.Array)
340417
{
@@ -465,8 +542,8 @@ public class CreateSubTaskDto
465542
public string? CategoryId { get; set; }
466543
public string? CreatedBy { get; set; }
467544
public List<string>? AssignedTo { get; set; }
468-
public DateTime? StartDate { get; set; }
469-
public DateTime? EndDate { get; set; }
545+
public string? StartDate { get; set; }
546+
public string? EndDate { get; set; }
470547
}
471548

472549
// DTO for updating subtasks
@@ -481,8 +558,8 @@ public class UpdateSubTaskDto
481558
public string? CategoryId { get; set; }
482559
public string? CreatedBy { get; set; }
483560
public List<string>? AssignedTo { get; set; }
484-
public DateTime? StartDate { get; set; }
485-
public DateTime? EndDate { get; set; }
561+
public string? StartDate { get; set; }
562+
public string? EndDate { get; set; }
486563
}
487564
}
488565
}

0 commit comments

Comments
 (0)