| 712 | return true; |
| 713 | } |
| 714 | public async Task<bool> DeleteColumnAsync(int boardId, int columnId, int userId) |
| 715 | { |
| 716 | var board = await _db.Boards |
| 717 | .Include(b => b.Columns) |
| 718 | .Include(b => b.Members) |
| 719 | .Include(b => b.Workspace).ThenInclude(w => w.Members) |
| 720 | .FirstOrDefaultAsync(b => b.Id == boardId); |
| 721 | |
| 722 | if (board == null) return false; |
| 723 | |
| 724 | var isMember = board.OwnerId == userId |
| 725 | || board.Members.Any(m => m.UserId == userId && m.Status == "Accepted") |
| 726 | || (board.Workspace != null && board.Workspace.Members.Any(wm => wm.UserId == userId && wm.Status == "Accepted")); |
| 727 | |
| 728 | if (!isMember) return false; |
| 729 | |
| 730 | var column = board.Columns.FirstOrDefault(c => c.Id == columnId); |
| 731 | if (column == null) return false; |
| 732 | |
| 733 | _db.Columns.Remove(column); |
| 734 | |
| 735 | // Re-index remaining columns to close gap |
| 736 | var remainingColumns = board.Columns.Where(c => c.Id != columnId).OrderBy(c => c.Order).ToList(); |
| 737 | for (int i = 0; i < remainingColumns.Count; i++) |
| 738 | { |
| 739 | remainingColumns[i].Order = i; |
| 740 | } |
| 741 | |
| 742 | await _db.SaveChangesAsync(); |
| 743 | return true; |
| 744 | } |
| 745 | |
| 746 | public async Task<ColumnDto?> UpdateColumnAsync(int boardId, int columnId, UpdateColumnDto dto, int userId) |
| 747 | { |