Edit button locate, delete, group header

This commit is contained in:
ivan-pelly
2026-04-10 17:52:52 -07:00
parent b287276ec0
commit 0036e25b9c
25 changed files with 629 additions and 82 deletions
+96
View File
@@ -324,6 +324,38 @@ public class StudentController : BaseController
});
}
[HttpDelete("{idStudent:guid}/goals/{idGoal:guid}")]
[Authorize(Roles = $"{UserRoles.Teacher},{UserRoles.ProgramAdmin}")]
[ProducesResponseType(typeof(ResponseResult<object>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ResponseResult<object>), StatusCodes.Status404NotFound)]
public async Task<ActionResult<ResponseResult<object>>> DeleteGoal(Guid idStudent, Guid idGoal)
{
var (userId, email, programId, role, error) = GetProgramUserFromClaims();
if (error is not null)
{
return error;
}
var students = await _studentRepository.GetMyStudentsAsync(userId, programId, role, "all");
if (!students.Select(s => s.StudentId).Contains(idStudent))
{
return NotFound(new ResponseResult<object>
{
Success = false,
Message = "Student not found."
});
}
var deleted = await _studentRepository.DeleteGoalAsync(idGoal);
return Ok(new ResponseResult<object>
{
Success = true,
Message = deleted ? "Goal deleted." : "Goal not found."
});
}
[HttpPost("{idStudent:guid}/progress-event")]
[Authorize(Roles = $"{UserRoles.Teacher},{UserRoles.Paraeducator},{UserRoles.ProgramAdmin}")]
[ProducesResponseType(typeof(ResponseResult), StatusCodes.Status201Created)]
@@ -412,6 +444,38 @@ public class StudentController : BaseController
}
}
[HttpDelete("{idStudent:guid}/progress-events/{idProgressEvent:guid}")]
[Authorize(Roles = $"{UserRoles.Teacher},{UserRoles.ProgramAdmin}")]
[ProducesResponseType(typeof(ResponseResult<object>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ResponseResult<object>), StatusCodes.Status404NotFound)]
public async Task<ActionResult<ResponseResult<object>>> DeleteProgressEvent(Guid idStudent, Guid idProgressEvent)
{
var (userId, email, programId, role, error) = GetProgramUserFromClaims();
if (error is not null)
{
return error;
}
var students = await _studentRepository.GetMyStudentsAsync(userId, programId, role, "all");
if (!students.Select(s => s.StudentId).Contains(idStudent))
{
return NotFound(new ResponseResult<object>
{
Success = false,
Message = "Student not found."
});
}
var deleted = await _studentRepository.DeleteProgressEventAsync(idProgressEvent);
return Ok(new ResponseResult<object>
{
Success = true,
Message = deleted ? "Progress event deleted." : "Progress event not found."
});
}
[HttpGet("progress-events/{idProgressEvent:guid}/benchmarks")]
[Authorize(Roles = $"{UserRoles.Teacher},{UserRoles.Paraeducator},{UserRoles.ProgramAdmin}")]
[ProducesResponseType(typeof(ResponseResult<List<Guid>>), StatusCodes.Status200OK)]
@@ -676,6 +740,38 @@ public class StudentController : BaseController
});
}
[HttpDelete("{idStudent:guid}/benchmarks/{idBenchmark:guid}")]
[Authorize(Roles = $"{UserRoles.Teacher},{UserRoles.ProgramAdmin}")]
[ProducesResponseType(typeof(ResponseResult<object>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ResponseResult<object>), StatusCodes.Status404NotFound)]
public async Task<ActionResult<ResponseResult<object>>> DeleteBenchmark(Guid idStudent, Guid idBenchmark)
{
var (userId, email, programId, role, error) = GetProgramUserFromClaims();
if (error is not null)
{
return error;
}
var students = await _studentRepository.GetMyStudentsAsync(userId, programId, role, "all");
if (!students.Select(s => s.StudentId).Contains(idStudent))
{
return NotFound(new ResponseResult<object>
{
Success = false,
Message = "Student not found."
});
}
var deleted = await _studentRepository.DeleteBenchmarkAsync(idBenchmark);
return Ok(new ResponseResult<object>
{
Success = true,
Message = deleted ? "Benchmark deleted." : "Benchmark not found."
});
}
[HttpGet("{idStudent:guid}/progress-report")]
[Authorize(Roles = $"{UserRoles.Teacher},{UserRoles.Paraeducator},{UserRoles.ProgramAdmin}")]
[ProducesResponseType(typeof(ResponseResult<string>), StatusCodes.Status200OK)]
@@ -145,6 +145,19 @@ public class StudentRepository
return rows.Select(r => r.benchmarkId is Guid g ? g : Guid.Parse((string)r.benchmarkId)).ToList();
}
// *****************************************************************
// Deletes a progress event and its benchmark associations.
// *****************************************************************
public async Task<bool> DeleteProgressEventAsync(Guid progressEventId)
{
using var db = Connection;
var rowsAffected = await db.ExecuteScalarAsync<int>(
"sp_ProgressEvent_Delete",
new { p_id_progress_event = progressEventId.ToString() },
commandType: CommandType.StoredProcedure);
return rowsAffected > 0;
}
public async Task<Guid?> GetStudentIdForGoalAsync(Guid idGoal)
{
using var db = Connection;
@@ -276,6 +289,20 @@ public class StudentRepository
return rowsAffected > 0;
}
// *****************************************************************
// Deletes a goal and all its child entities (benchmarks, progress
// events, event-benchmark links, child goals) via cascade SP.
// *****************************************************************
public async Task<bool> DeleteGoalAsync(Guid goalId)
{
using var db = Connection;
var rowsAffected = await db.ExecuteScalarAsync<int>(
"sp_Goal_Delete",
new { p_id_goal = goalId.ToString() },
commandType: CommandType.StoredProcedure);
return rowsAffected > 0;
}
// *****************************************************************
// Returns all benchmarks for a student, grouped under a summary
// with the student identifier. Returns null if student not found.
@@ -367,6 +394,19 @@ public class StudentRepository
return rowsAffected > 0;
}
// *****************************************************************
// Deletes a benchmark and its progress-event associations.
// *****************************************************************
public async Task<bool> DeleteBenchmarkAsync(Guid benchmarkId)
{
using var db = Connection;
var rowsAffected = await db.ExecuteScalarAsync<int>(
"sp_Benchmark_Delete",
new { p_id_benchmark = benchmarkId.ToString() },
commandType: CommandType.StoredProcedure);
return rowsAffected > 0;
}
// *****************************************************************
// Returns a full student profile: student card, goals, benchmarks,
// progress events, and benchmark/event associations in one call.