Skip to content

Commit 910b5ec

Browse files
author
David Warwick
committed
Refactor survey logic and enhance AnswerController
Updated `Survey.razor` to use `Value`/`ValueChanged` bindings for `MudCheckBox`, aligning with MudBlazor conventions. Refactored `Survey.razor.cs` to introduce branching logic for question groups, adding `_groupsToVisit` and `_visitedGroups` for dynamic question loading. Enhanced `AnswerController` with support for `QuestionGroups`, improved logging, and added handling for `SelectAllThatApplyQuestion` options. Refactored `PostAnswer` for better error handling and robustness. Improved chart data generation for `Rating1To10` questions. General improvements include better readability, maintainability, and additional comments.
1 parent b2d413a commit 910b5ec

File tree

3 files changed

+33
-32
lines changed

3 files changed

+33
-32
lines changed

JwtIdentity.Client/Pages/Survey/Survey.razor

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,8 @@
138138
{
139139
var index = i;
140140
var option = saQuestion.Options[index];
141-
<MudCheckBox @key="option" T="bool" Checked="@answer.SelectedOptions[index]"
142-
CheckedChanged="@((bool isChecked) => HandleSelectAllThatApplyOption(answer, index, isChecked, option.Id))"
141+
<MudCheckBox @key="option" T="bool" Value="@answer.SelectedOptions[index]"
142+
ValueChanged="@((bool isChecked) => HandleSelectAllThatApplyOption(answer, index, isChecked, option.Id))"
143143
Label="@option.OptionText" Color="Color.Primary" Disabled="@(Preview || (IsAnonymousUser && !AgreedToTerms))" />
144144
}
145145
</MudStack>

JwtIdentity.Client/Pages/Survey/Survey.razor.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public class SurveyModel : BlazorBase, IAsyncDisposable
4747
protected bool IsLastQuestion => CurrentQuestionIndex >= QuestionsToShow.Count - 1;
4848
protected bool IsFirstQuestion => CurrentQuestionIndex == 0;
4949
protected int TotalQuestionsShown => CurrentQuestionIndex + 1;
50-
50+
5151
// Track which groups need to be visited based on branching logic
5252
private HashSet<int> _groupsToVisit = new();
5353
private HashSet<int> _visitedGroups = new();
@@ -544,7 +544,7 @@ protected void InitializeBranchingQuestions()
544544
_groupsToVisit.Clear();
545545
_groupsToVisit.Add(0); // Always start with group 0
546546
_visitedGroups.Clear();
547-
547+
548548
LoadQuestionsForCurrentGroup();
549549
}
550550
CurrentQuestionIndex = 0;
@@ -556,7 +556,7 @@ private void LoadQuestionsForCurrentGroup()
556556
.Where(q => q.GroupId == _currentGroupId)
557557
.OrderBy(q => q.QuestionNumber)
558558
.ToList();
559-
559+
560560
QuestionsToShow.AddRange(groupQuestions);
561561
_visitedGroups.Add(_currentGroupId);
562562
}

JwtIdentity/Controllers/AnswerController.cs

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
using System.Security.Claims;
21
using JwtIdentity.Interfaces;
2+
using System.Security.Claims;
33

44
namespace JwtIdentity.Controllers
55
{
@@ -28,7 +28,7 @@ public AnswerController(ApplicationDbContext context, IMapper mapper, IApiAuthSe
2828
public async Task<ActionResult<AnswerViewModel>> GetAnswersForSurveyForLoggedInUser(string guid, [FromQuery] bool Preview)
2929
{
3030
_logger.LogInformation("Getting answers for survey {SurveyGuid} for logged-in user. Preview mode: {IsPreview}", guid, Preview);
31-
31+
3232
try
3333
{
3434
// get the ip address of the user
@@ -69,6 +69,7 @@ await _context.Answers
6969
survey = await _context.Surveys
7070
.Where(s => s.Guid == guid)
7171
.Include(s => s.Questions).ThenInclude(q => q.Answers.Where(a => a.CreatedById == userId))
72+
.Include(x => x.QuestionGroups)
7273
.FirstOrDefaultAsync();
7374

7475
if (survey == null)
@@ -105,17 +106,17 @@ await _context.Questions
105106
.Where(mc => mcIds.Contains(mc.Id))
106107
.Include(mc => mc.Options)
107108
.LoadAsync();
108-
109+
109110
// Now load each select-all-that-apply question's Options
110111
await _context.Questions
111112
.OfType<SelectAllThatApplyQuestion>()
112113
.Where(sa => selectAllIds.Contains(sa.Id))
113114
.Include(sa => sa.Options)
114115
.LoadAsync();
115116

116-
_logger.LogInformation("Successfully retrieved survey {SurveyGuid} with {QuestionCount} questions for user {UserId}",
117+
_logger.LogInformation("Successfully retrieved survey {SurveyGuid} with {QuestionCount} questions for user {UserId}",
117118
guid, survey.Questions.Count, userId);
118-
119+
119120
return Ok(_mapper.Map<SurveyViewModel>(survey));
120121
}
121122
catch (DbUpdateException dbEx)
@@ -134,20 +135,20 @@ await _context.Questions
134135
public async Task<ActionResult<SurveyViewModel>> GetSurveyResults(string guid)
135136
{
136137
_logger.LogInformation("Getting survey results for survey {SurveyGuid}", guid);
137-
138+
138139
try
139140
{
140141
var survey = await _context.Surveys
141142
.Where(s => s.Guid == guid)
142143
.Include(s => s.Questions).ThenInclude(q => q.Answers)
143144
.FirstOrDefaultAsync();
144-
145+
145146
if (survey == null)
146147
{
147148
_logger.LogWarning("Survey with GUID {SurveyGuid} not found", guid);
148149
return BadRequest("Survey does not exist");
149150
}
150-
151+
151152
_logger.LogDebug("Found survey: {SurveyId}, {SurveyTitle}", survey.Id, survey.Title);
152153

153154
// Pull out the IDs of any multiple-choice questions in memory
@@ -156,7 +157,7 @@ public async Task<ActionResult<SurveyViewModel>> GetSurveyResults(string guid)
156157
.Select(mc => mc.Id)
157158
.ToList();
158159
_logger.LogDebug("Found {Count} multiple choice questions", mcIds.Count);
159-
160+
160161
// Pull out the IDs of any select-all-that-apply questions in memory
161162
var selectAllIds = survey.Questions
162163
.OfType<SelectAllThatApplyQuestion>()
@@ -170,17 +171,17 @@ await _context.Questions
170171
.Where(mc => mcIds.Contains(mc.Id))
171172
.Include(mc => mc.Options)
172173
.LoadAsync();
173-
174+
174175
// Now load each select-all-that-apply question's Options
175176
await _context.Questions
176177
.OfType<SelectAllThatApplyQuestion>()
177178
.Where(sa => selectAllIds.Contains(sa.Id))
178179
.Include(sa => sa.Options)
179180
.LoadAsync();
180181

181-
_logger.LogInformation("Successfully retrieved survey results for {SurveyGuid} with {QuestionCount} questions",
182+
_logger.LogInformation("Successfully retrieved survey results for {SurveyGuid} with {QuestionCount} questions",
182183
guid, survey.Questions.Count);
183-
184+
184185
return Ok(_mapper.Map<SurveyViewModel>(survey));
185186
}
186187
catch (DbUpdateException dbEx)
@@ -199,7 +200,7 @@ await _context.Questions
199200
public async Task<ActionResult<SurveyDataViewModel>> GetAnswersForSurveyForCharts(string guid)
200201
{
201202
_logger.LogInformation("Getting chart data for survey {SurveyGuid}", guid);
202-
203+
203204
try
204205
{
205206
int userId = apiAuthService.GetUserId(User);
@@ -232,7 +233,7 @@ public async Task<ActionResult<SurveyDataViewModel>> GetAnswersForSurveyForChart
232233
.Select(mc => mc.Id)
233234
.ToList();
234235
_logger.LogDebug("Found {Count} multiple choice questions", mcIds.Count);
235-
236+
236237
// Pull out the IDs of any select-all-that-apply questions in memory
237238
var selectAllIds = survey.Questions
238239
.OfType<SelectAllThatApplyQuestion>()
@@ -246,7 +247,7 @@ await _context.Questions
246247
.Where(mc => mcIds.Contains(mc.Id))
247248
.Include(mc => mc.Options)
248249
.LoadAsync();
249-
250+
250251
// Now load each select-all-that-apply question's Options
251252
await _context.Questions
252253
.OfType<SelectAllThatApplyQuestion>()
@@ -282,7 +283,7 @@ await _context.Questions
282283
// get the question.Answers as Rating1To10Answer
283284
var ratingAnswers = await _context.Answers.OfType<Rating1To10Answer>().AsNoTracking().Where(a => a.QuestionId == question.Id).ToListAsync();
284285
_logger.LogDebug("Found {Count} rating answers for question {QuestionId}", ratingAnswers.Count, question.Id);
285-
286+
286287
var ratingGroups = ratingAnswers.GroupBy(a => a.SelectedOptionId).ToDictionary(g => g.Key, g => g.Count());
287288
surveyDataViewModel.SurveyData = Enumerable.Range(1, 10).Select(i => new ChartData { X = i.ToString(), Y = ratingGroups.ContainsKey(i) ? ratingGroups[i] : 0 }).ToList();
288289
surveyDataViewModel.Rating1To10Question = _mapper.Map<Rating1To10QuestionViewModel>(question);
@@ -373,9 +374,9 @@ await _context.Questions
373374
surveyData.Add(surveyDataViewModel);
374375
}
375376

376-
_logger.LogInformation("Successfully generated chart data for survey {SurveyGuid} with {QuestionCount} questions for user {UserId}",
377+
_logger.LogInformation("Successfully generated chart data for survey {SurveyGuid} with {QuestionCount} questions for user {UserId}",
377378
guid, survey.Questions.Count, userId);
378-
379+
379380
return Ok(surveyData);
380381
}
381382
catch (DbUpdateException dbEx)
@@ -400,7 +401,7 @@ await _context.Questions
400401
public async Task<ActionResult<AnswerViewModel>> PostAnswer(AnswerViewModel answerViewModel)
401402
{
402403
_logger.LogInformation("Saving answer for question ID {QuestionId}", answerViewModel?.QuestionId);
403-
404+
404405
try
405406
{
406407
if (answerViewModel == null)
@@ -424,10 +425,10 @@ public async Task<ActionResult<AnswerViewModel>> PostAnswer(AnswerViewModel answ
424425
else
425426
{
426427
_logger.LogDebug("Updating existing answer ID {AnswerId}", answer.Id);
427-
428+
428429
var existingAnswer = await _context.Answers.AsNoTracking()
429430
.FirstOrDefaultAsync(x => x.Id == answerViewModel.Id);
430-
431+
431432
if (existingAnswer == null)
432433
{
433434
_logger.LogWarning("Attempted to update answer ID {AnswerId} that doesn't exist", answer.Id);
@@ -450,9 +451,9 @@ public async Task<ActionResult<AnswerViewModel>> PostAnswer(AnswerViewModel answ
450451
if (answer.Complete)
451452
{
452453
var surveyInfo = await (from q in _context.Questions
453-
join s in _context.Surveys on q.SurveyId equals s.Id
454-
where q.Id == answer.QuestionId
455-
select new { SurveyId = s.Id, s.Guid })
454+
join s in _context.Surveys on q.SurveyId equals s.Id
455+
where q.Id == answer.QuestionId
456+
select new { SurveyId = s.Id, s.Guid })
456457
.FirstOrDefaultAsync();
457458

458459
if (surveyInfo != null)
@@ -474,19 +475,19 @@ join s in _context.Surveys on q.SurveyId equals s.Id
474475
}
475476
catch (DbUpdateException dbEx)
476477
{
477-
_logger.LogError(dbEx, "Database error occurred while saving answer for question {QuestionId}: {Message}",
478+
_logger.LogError(dbEx, "Database error occurred while saving answer for question {QuestionId}: {Message}",
478479
answerViewModel?.QuestionId, dbEx.Message);
479480
return StatusCode(StatusCodes.Status500InternalServerError, "A database error occurred. Please try again later.");
480481
}
481482
catch (InvalidCastException icEx)
482483
{
483-
_logger.LogError(icEx, "Type casting error while processing answer of type {AnswerType}: {Message}",
484+
_logger.LogError(icEx, "Type casting error while processing answer of type {AnswerType}: {Message}",
484485
answerViewModel?.AnswerType, icEx.Message);
485486
return StatusCode(StatusCodes.Status500InternalServerError, "An error occurred processing the answer data. Please try again later.");
486487
}
487488
catch (Exception ex)
488489
{
489-
_logger.LogError(ex, "Error saving answer for question {QuestionId}: {Message}",
490+
_logger.LogError(ex, "Error saving answer for question {QuestionId}: {Message}",
490491
answerViewModel?.QuestionId, ex.Message);
491492
return StatusCode(StatusCodes.Status500InternalServerError, "An unexpected error occurred. Please try again later.");
492493
}

0 commit comments

Comments
 (0)