feat: add seating plan drag and quick assessment
This commit is contained in:
@@ -243,6 +243,11 @@ public partial class GroupDetailViewModel : ObservableObject
|
||||
PlanningTab = planningTab;
|
||||
CompetencyOverviewTab = competencyOverviewTab;
|
||||
SeatingPlanTab = seatingPlanTab;
|
||||
SeatingPlanTab.OnAssessmentChanged = () =>
|
||||
{
|
||||
ParticipationTab.LoadSessions();
|
||||
ParticipationTab.RefreshCurrentGrid();
|
||||
};
|
||||
}
|
||||
|
||||
public void LoadGroup(Guid id)
|
||||
|
||||
@@ -108,11 +108,11 @@ public partial class ParticipationTabViewModel : ObservableObject
|
||||
|
||||
public void LoadSessions()
|
||||
{
|
||||
var selectedId = SelectedSession?.Id;
|
||||
Sessions.Clear();
|
||||
foreach (var s in _sessions.GetByGroup(_groupId))
|
||||
Sessions.Add(new ParticipationSessionItem(s));
|
||||
if (SelectedSession is null && Sessions.Any())
|
||||
SelectedSession = Sessions[0];
|
||||
SelectedSession = Sessions.FirstOrDefault(s => s.Id == selectedId) ?? Sessions.FirstOrDefault();
|
||||
}
|
||||
|
||||
partial void OnSelectedSessionChanged(ParticipationSessionItem? value)
|
||||
|
||||
@@ -12,6 +12,9 @@ public partial class SeatingPlanTabViewModel : ObservableObject
|
||||
private readonly ISeatingPlanRepository _plans;
|
||||
private readonly IStudentRepository _students;
|
||||
private readonly IGroupMembershipRepository _memberships;
|
||||
private readonly IParticipationSessionRepository _sessions;
|
||||
private readonly IParticipationRepository _participation;
|
||||
private readonly IParticipationAspectRepository _aspects;
|
||||
private Guid _groupId;
|
||||
private SeatingPlan? _currentPlan;
|
||||
private bool _isReadOnly;
|
||||
@@ -25,19 +28,26 @@ public partial class SeatingPlanTabViewModel : ObservableObject
|
||||
public ObservableCollection<SeatingPlanSummary> Plans { get; } = [];
|
||||
public ObservableCollection<SeatCellViewModel> Seats { get; } = [];
|
||||
public ObservableCollection<StudentSeatOption> StudentOptions { get; } = [];
|
||||
public ObservableCollection<StudentSeatOption> UnassignedStudents { get; } = [];
|
||||
|
||||
public bool HasPlans => Plans.Count > 0;
|
||||
public bool HasSelectedPlan => _currentPlan is not null;
|
||||
public bool IsEditable => !_isReadOnly;
|
||||
public Func<SeatingPlan?, Task<SeatingPlan?>>? OnEditPlan { get; set; }
|
||||
public Func<SeatingPlanSummary, Task<bool>>? OnConfirmDelete { get; set; }
|
||||
public Func<SeatAssessmentViewModel, Task>? OnAssessStudent { get; set; }
|
||||
public Action? OnAssessmentChanged { get; set; }
|
||||
|
||||
public SeatingPlanTabViewModel(ISeatingPlanRepository plans, IStudentRepository students,
|
||||
IGroupMembershipRepository memberships)
|
||||
IGroupMembershipRepository memberships, IParticipationSessionRepository sessions,
|
||||
IParticipationRepository participation, IParticipationAspectRepository aspects)
|
||||
{
|
||||
_plans = plans;
|
||||
_students = students;
|
||||
_memberships = memberships;
|
||||
_sessions = sessions;
|
||||
_participation = participation;
|
||||
_aspects = aspects;
|
||||
}
|
||||
|
||||
public SeatingPlanDialogViewModel CreateDialogViewModel(SeatingPlan? plan) =>
|
||||
@@ -87,6 +97,7 @@ public partial class SeatingPlanTabViewModel : ObservableObject
|
||||
Seats.Clear();
|
||||
if (plan is null)
|
||||
{
|
||||
UnassignedStudents.Clear();
|
||||
PlanColumns = 1;
|
||||
PlanTitle = "";
|
||||
PlanSubtitle = "";
|
||||
@@ -124,6 +135,49 @@ public partial class SeatingPlanTabViewModel : ObservableObject
|
||||
other.SetSelectionSilently(StudentSeatOption.Empty);
|
||||
}
|
||||
|
||||
SaveSeatAssignments();
|
||||
}
|
||||
|
||||
private void UpdateAssignmentSummary()
|
||||
{
|
||||
var assigned = Seats.Count(s => s.SelectedOption.StudentId.HasValue);
|
||||
var total = StudentOptions.Count - 1;
|
||||
AssignmentSummary = $"{assigned} von {total} Schülern zugeordnet";
|
||||
var assignedIds = Seats.Where(s => s.SelectedOption.StudentId.HasValue)
|
||||
.Select(s => s.SelectedOption.StudentId!.Value).ToHashSet();
|
||||
UnassignedStudents.Clear();
|
||||
foreach (var option in StudentOptions.Where(o => o.StudentId.HasValue && !assignedIds.Contains(o.StudentId.Value)))
|
||||
UnassignedStudents.Add(option);
|
||||
}
|
||||
|
||||
public void MoveSeat(SeatCellViewModel source, SeatCellViewModel target)
|
||||
{
|
||||
if (!IsEditable || source == target || !source.SelectedOption.StudentId.HasValue) return;
|
||||
var targetOption = target.SelectedOption;
|
||||
target.SetSelectionSilently(source.SelectedOption);
|
||||
source.SetSelectionSilently(targetOption);
|
||||
SaveSeatAssignments();
|
||||
}
|
||||
|
||||
public void AssignStudent(StudentSeatOption student, SeatCellViewModel target)
|
||||
{
|
||||
if (!IsEditable || !student.StudentId.HasValue) return;
|
||||
foreach (var other in Seats.Where(s => s != target && s.SelectedOption.StudentId == student.StudentId))
|
||||
other.SetSelectionSilently(StudentSeatOption.Empty);
|
||||
target.SetSelectionSilently(student);
|
||||
SaveSeatAssignments();
|
||||
}
|
||||
|
||||
public void ClearSeat(SeatCellViewModel seat)
|
||||
{
|
||||
if (!IsEditable || !seat.SelectedOption.StudentId.HasValue) return;
|
||||
seat.SetSelectionSilently(StudentSeatOption.Empty);
|
||||
SaveSeatAssignments();
|
||||
}
|
||||
|
||||
private void SaveSeatAssignments()
|
||||
{
|
||||
if (_currentPlan is null) return;
|
||||
_currentPlan.Assignments = Seats
|
||||
.Where(s => s.SelectedOption.StudentId.HasValue)
|
||||
.Select(s => new SeatAssignment
|
||||
@@ -136,11 +190,13 @@ public partial class SeatingPlanTabViewModel : ObservableObject
|
||||
UpdateAssignmentSummary();
|
||||
}
|
||||
|
||||
private void UpdateAssignmentSummary()
|
||||
public async Task AssessStudent(SeatCellViewModel seat)
|
||||
{
|
||||
var assigned = Seats.Count(s => s.SelectedOption.StudentId.HasValue);
|
||||
var total = StudentOptions.Count - 1;
|
||||
AssignmentSummary = $"{assigned} von {total} Schülern zugeordnet";
|
||||
if (!seat.SelectedOption.StudentId.HasValue || OnAssessStudent is null) return;
|
||||
var assessment = new SeatAssessmentViewModel(_sessions, _participation, _aspects,
|
||||
_groupId, seat.SelectedOption.StudentId.Value, seat.SelectedOption.DisplayName, IsEditable);
|
||||
await OnAssessStudent(assessment);
|
||||
OnAssessmentChanged?.Invoke();
|
||||
}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanEdit))]
|
||||
@@ -203,11 +259,14 @@ public partial class SeatCellViewModel : ObservableObject
|
||||
private bool _suppressChange;
|
||||
|
||||
[ObservableProperty] private StudentSeatOption _selectedOption;
|
||||
[ObservableProperty] private bool _isDropTarget;
|
||||
public int Row { get; }
|
||||
public int Column { get; }
|
||||
public string PositionLabel => $"Reihe {Row + 1} · Platz {Column + 1}";
|
||||
public ObservableCollection<StudentSeatOption> Options { get; }
|
||||
public bool CanEdit { get; }
|
||||
public bool IsOccupied => SelectedOption.StudentId.HasValue;
|
||||
public string StudentName => IsOccupied ? SelectedOption.DisplayName : "Freier Platz";
|
||||
|
||||
public SeatCellViewModel(int row, int column, ObservableCollection<StudentSeatOption> options,
|
||||
StudentSeatOption selectedOption, Action<SeatCellViewModel> onChanged, bool canEdit)
|
||||
@@ -222,6 +281,8 @@ public partial class SeatCellViewModel : ObservableObject
|
||||
|
||||
partial void OnSelectedOptionChanged(StudentSeatOption value)
|
||||
{
|
||||
OnPropertyChanged(nameof(IsOccupied));
|
||||
OnPropertyChanged(nameof(StudentName));
|
||||
if (!_suppressChange) _onChanged(this);
|
||||
}
|
||||
|
||||
@@ -233,6 +294,281 @@ public partial class SeatCellViewModel : ObservableObject
|
||||
}
|
||||
}
|
||||
|
||||
public partial class SeatAssessmentViewModel : ObservableObject
|
||||
{
|
||||
private readonly IParticipationRepository _entries;
|
||||
private readonly ParticipationEntry? _entry;
|
||||
private readonly bool _canEdit;
|
||||
|
||||
[ObservableProperty] private int _selectedAspectIndex;
|
||||
[ObservableProperty] private string _attendanceLabel = "Noch nicht kontrolliert";
|
||||
[ObservableProperty] private string _homeworkLabel = "Keine Hausaufgabe aufgegeben";
|
||||
|
||||
public string StudentName { get; }
|
||||
public string SessionDisplay { get; }
|
||||
public bool CanEdit => _canEdit && _entry is not null;
|
||||
public string ReadOnlyHint => _entry is null
|
||||
? "Für heute existiert keine Sitzung. In einer archivierten Gruppe kann keine neue angelegt werden."
|
||||
: "Archivierte Lerngruppe – Bewertung nur ansehen.";
|
||||
public ObservableCollection<SeatAssessmentAspectRow> AspectRows { get; } = [];
|
||||
public ObservableCollection<SeatAttendanceChoice> AttendanceChoices { get; } = [];
|
||||
public ObservableCollection<SeatHomeworkChoice> HomeworkChoices { get; } = [];
|
||||
|
||||
public SeatAssessmentViewModel(IParticipationSessionRepository sessions,
|
||||
IParticipationRepository entries, IParticipationAspectRepository aspects,
|
||||
Guid groupId, Guid studentId, string studentName, bool canEdit)
|
||||
{
|
||||
_entries = entries;
|
||||
_canEdit = canEdit;
|
||||
StudentName = studentName;
|
||||
var today = DateOnly.FromDateTime(DateTime.Today);
|
||||
var session = sessions.GetByGroup(groupId).FirstOrDefault(s => s.Date == today);
|
||||
if (session is null && canEdit)
|
||||
{
|
||||
session = new ParticipationSession
|
||||
{
|
||||
GroupId = groupId,
|
||||
Date = today,
|
||||
Comment = "Sitzplan",
|
||||
};
|
||||
sessions.Save(session);
|
||||
}
|
||||
SessionDisplay = session is null ? "Keine Sitzung für heute" : $"{session.Date:dd.MM.yyyy} · {session.Comment}";
|
||||
_entry = session is null ? null
|
||||
: entries.GetBySessionAndStudent(session.Id, studentId)
|
||||
?? new ParticipationEntry { SessionId = session.Id, StudentId = studentId };
|
||||
|
||||
var aspectDefinitions = aspects.GetDefaults().Concat(aspects.GetByGroup(groupId)).ToList();
|
||||
if (aspectDefinitions.Count == 0) aspectDefinitions = DefaultParticipationAspects.All.Select(a => new ParticipationAspect
|
||||
{
|
||||
Key = a.Key, Label = a.Label, ValueType = a.ValueType, MaxPoints = a.MaxPoints,
|
||||
}).ToList();
|
||||
foreach (var (aspect, index) in aspectDefinitions.Select((a, i) => (a, i)))
|
||||
{
|
||||
var value = _entry?.Ratings.FirstOrDefault(r => r.Key == aspect.Key)?.Value;
|
||||
AspectRows.Add(new SeatAssessmentAspectRow(index, aspect, value, ApplyRating));
|
||||
}
|
||||
|
||||
BuildAttendanceChoices();
|
||||
BuildHomeworkChoices();
|
||||
RefreshStatusChoices();
|
||||
SelectAspect(0);
|
||||
}
|
||||
|
||||
private void BuildAttendanceChoices()
|
||||
{
|
||||
AttendanceChoices.Add(new("✓", "Anwesend", "Strg+1", AttendanceStatus.Present, SetAttendance));
|
||||
AttendanceChoices.Add(new("?", "Entschuldigung offen", "Strg+2", AttendanceStatus.ExcusePending, SetAttendance));
|
||||
AttendanceChoices.Add(new("⊘", "Entschuldigt", "Strg+5", AttendanceStatus.Excused, SetAttendance));
|
||||
AttendanceChoices.Add(new("◇", "Schulveranstaltung", "Strg+7", AttendanceStatus.OtherSchoolEvent, SetAttendance));
|
||||
AttendanceChoices.Add(new("✕", "Geschwänzt", "Strg+9", AttendanceStatus.Truant, SetAttendance));
|
||||
AttendanceChoices.Add(new("!", "Unentschuldigt", "Strg+0", AttendanceStatus.Unexcused, SetAttendance));
|
||||
AttendanceChoices.Add(new("·", "Nicht kontrolliert", "Strg+X", null, SetAttendance));
|
||||
}
|
||||
|
||||
private void BuildHomeworkChoices()
|
||||
{
|
||||
HomeworkChoices.Add(new("✓", "Gemacht", "⌥1", HomeworkStatus.Completed, SetHomework));
|
||||
HomeworkChoices.Add(new("◐", "Teilweise", "⌥3", HomeworkStatus.PartiallyCompleted, SetHomework));
|
||||
HomeworkChoices.Add(new("◕", "Rest nachgereicht", "⌥4", HomeworkStatus.PartialSubmittedLate, SetHomework));
|
||||
HomeworkChoices.Add(new("◒", "Rest fehlt", "⌥5", HomeworkStatus.PartialMissingOverdue, SetHomework));
|
||||
HomeworkChoices.Add(new("!", "Nicht gemacht", "⌥7", HomeworkStatus.MissingOpen, SetHomework));
|
||||
HomeworkChoices.Add(new("↺", "Nachgereicht", "⌥8", HomeworkStatus.SubmittedLate, SetHomework));
|
||||
HomeworkChoices.Add(new("✕", "Nicht nachgereicht", "⌥0", HomeworkStatus.MissingOverdue, SetHomework));
|
||||
HomeworkChoices.Add(new("·", "Keine aufgegeben", "⌥X", null, SetHomework));
|
||||
}
|
||||
|
||||
public void SelectAspect(int index)
|
||||
{
|
||||
if (index < 0 || index >= AspectRows.Count) return;
|
||||
SelectedAspectIndex = index;
|
||||
foreach (var row in AspectRows) row.IsActive = row.Index == index;
|
||||
}
|
||||
|
||||
public void MoveAspect(int delta)
|
||||
{
|
||||
if (AspectRows.Count == 0) return;
|
||||
SelectAspect(Math.Clamp(SelectedAspectIndex + delta, 0, AspectRows.Count - 1));
|
||||
}
|
||||
|
||||
public void SetRatingByNumber(int number)
|
||||
{
|
||||
if (!CanEdit) return;
|
||||
var row = AspectRows.ElementAtOrDefault(SelectedAspectIndex);
|
||||
if (row is null) return;
|
||||
if (row.ValueType == AspectValueType.Points)
|
||||
row.ApplyValue(Math.Clamp(number, 0, row.MaxPoints));
|
||||
else
|
||||
{
|
||||
var steps = ParticipationRatingScale.Steps(row.ValueType);
|
||||
if (number >= 1 && number <= steps.Count) row.ApplyValue(steps[number - 1].Value);
|
||||
}
|
||||
}
|
||||
|
||||
public void AdjustCurrentRating(int delta)
|
||||
{
|
||||
if (!CanEdit) return;
|
||||
var row = AspectRows.ElementAtOrDefault(SelectedAspectIndex);
|
||||
row?.Adjust(delta);
|
||||
}
|
||||
|
||||
public void ClearCurrentRating()
|
||||
{
|
||||
if (!CanEdit) return;
|
||||
AspectRows.ElementAtOrDefault(SelectedAspectIndex)?.ApplyValue(null);
|
||||
}
|
||||
|
||||
public void ApplyAttendanceShortcut(int? digit, bool clear)
|
||||
{
|
||||
if (!CanEdit) return;
|
||||
var status = clear ? null : digit switch
|
||||
{
|
||||
1 => AttendanceStatus.Present, 2 => AttendanceStatus.ExcusePending,
|
||||
5 => AttendanceStatus.Excused, 7 => AttendanceStatus.OtherSchoolEvent,
|
||||
9 => AttendanceStatus.Truant, 0 => AttendanceStatus.Unexcused,
|
||||
_ => (AttendanceStatus?)null,
|
||||
};
|
||||
if (clear || digit is 0 or 1 or 2 or 5 or 7 or 9) SetAttendance(status);
|
||||
}
|
||||
|
||||
public void ApplyHomeworkShortcut(int? digit, bool clear)
|
||||
{
|
||||
if (!CanEdit) return;
|
||||
var status = clear ? null : digit switch
|
||||
{
|
||||
1 => HomeworkStatus.Completed, 3 => HomeworkStatus.PartiallyCompleted,
|
||||
4 => HomeworkStatus.PartialSubmittedLate, 5 => HomeworkStatus.PartialMissingOverdue,
|
||||
7 => HomeworkStatus.MissingOpen, 8 => HomeworkStatus.SubmittedLate,
|
||||
0 => HomeworkStatus.MissingOverdue, _ => (HomeworkStatus?)null,
|
||||
};
|
||||
if (clear || digit is 0 or 1 or 3 or 4 or 5 or 7 or 8) SetHomework(status);
|
||||
}
|
||||
|
||||
private void ApplyRating(string key, int? value)
|
||||
{
|
||||
if (!CanEdit || _entry is null) return;
|
||||
var existing = _entry.Ratings.FirstOrDefault(r => r.Key == key);
|
||||
if (value is null)
|
||||
{
|
||||
if (existing is not null) _entry.Ratings.Remove(existing);
|
||||
}
|
||||
else if (existing is null) _entry.Ratings.Add(new AspectRating { Key = key, Value = value.Value });
|
||||
else existing.Value = value.Value;
|
||||
_entries.Save(_entry);
|
||||
}
|
||||
|
||||
private void SetAttendance(AttendanceStatus? status)
|
||||
{
|
||||
if (!CanEdit || _entry is null) return;
|
||||
_entry.Attendance = status;
|
||||
_entries.Save(_entry);
|
||||
RefreshStatusChoices();
|
||||
}
|
||||
|
||||
private void SetHomework(HomeworkStatus? status)
|
||||
{
|
||||
if (!CanEdit || _entry is null) return;
|
||||
_entry.Homework = status;
|
||||
_entry.HomeworkMissing = HomeworkDisplay.CountsAsMissing(status);
|
||||
_entries.Save(_entry);
|
||||
RefreshStatusChoices();
|
||||
}
|
||||
|
||||
private void RefreshStatusChoices()
|
||||
{
|
||||
AttendanceLabel = AttendanceDisplay.Label(_entry?.Attendance);
|
||||
HomeworkLabel = HomeworkDisplay.Label(_entry is null ? null : HomeworkDisplay.Effective(_entry));
|
||||
foreach (var choice in AttendanceChoices) choice.IsSelected = choice.Status == _entry?.Attendance;
|
||||
var homework = _entry is null ? null : HomeworkDisplay.Effective(_entry);
|
||||
foreach (var choice in HomeworkChoices) choice.IsSelected = choice.Status == homework;
|
||||
}
|
||||
}
|
||||
|
||||
public partial class SeatAssessmentAspectRow : ObservableObject
|
||||
{
|
||||
private readonly Action<string, int?> _apply;
|
||||
[ObservableProperty] private bool _isActive;
|
||||
[ObservableProperty] private int? _value;
|
||||
public int Index { get; }
|
||||
public string Key { get; }
|
||||
public string Label { get; }
|
||||
public AspectValueType ValueType { get; }
|
||||
public int MaxPoints { get; }
|
||||
public string Shortcut => Index switch { 0 => "Q", 1 => "W", 2 => "E", 3 => "R", 4 => "T", _ => "" };
|
||||
public string DisplayValue => ParticipationRatingScale.DisplayLabel(ValueType, Value);
|
||||
public ObservableCollection<SeatRatingChoice> Choices { get; } = [];
|
||||
|
||||
public SeatAssessmentAspectRow(int index, ParticipationAspect aspect, int? value,
|
||||
Action<string, int?> apply)
|
||||
{
|
||||
Index = index; Key = aspect.Key; Label = aspect.Label; ValueType = aspect.ValueType;
|
||||
MaxPoints = aspect.MaxPoints; _value = value; _apply = apply;
|
||||
var steps = ValueType == AspectValueType.Points
|
||||
? Enumerable.Range(0, Math.Min(MaxPoints, 9) + 1).Select(v => (v, v.ToString())).ToList()
|
||||
: ParticipationRatingScale.Steps(ValueType).ToList();
|
||||
foreach (var (step, i) in steps.Select((s, i) => (s, i)))
|
||||
Choices.Add(new SeatRatingChoice(step.Item2, ValueType == AspectValueType.Points ? step.Item1.ToString() : (i + 1).ToString(),
|
||||
step.Item1, step.Item1 == value, ApplyValue));
|
||||
}
|
||||
|
||||
public void ApplyValue(int? value)
|
||||
{
|
||||
Value = value;
|
||||
OnPropertyChanged(nameof(DisplayValue));
|
||||
foreach (var choice in Choices) choice.IsSelected = choice.Value == value;
|
||||
_apply(Key, value);
|
||||
}
|
||||
|
||||
public void Adjust(int delta)
|
||||
{
|
||||
if (ValueType == AspectValueType.Points)
|
||||
{
|
||||
ApplyValue(Math.Clamp((Value ?? (delta > 0 ? -1 : MaxPoints + 1)) + delta, 0, MaxPoints));
|
||||
return;
|
||||
}
|
||||
var steps = ParticipationRatingScale.Steps(ValueType).Select(s => s.Value).ToList();
|
||||
if (steps.Count == 0) return;
|
||||
var index = Value.HasValue ? steps.IndexOf(Value.Value) : (delta > 0 ? -1 : steps.Count);
|
||||
ApplyValue(steps[Math.Clamp(index + delta, 0, steps.Count - 1)]);
|
||||
}
|
||||
|
||||
[RelayCommand] private void Clear() => ApplyValue(null);
|
||||
[RelayCommand] private void Increment() => Adjust(1);
|
||||
[RelayCommand] private void Decrement() => Adjust(-1);
|
||||
}
|
||||
|
||||
public partial class SeatRatingChoice(string label, string shortcut, int value, bool isSelected,
|
||||
Action<int?> apply) : ObservableObject
|
||||
{
|
||||
public string Label { get; } = label;
|
||||
public string Shortcut { get; } = shortcut;
|
||||
public int Value { get; } = value;
|
||||
[ObservableProperty] private bool _isSelected = isSelected;
|
||||
[RelayCommand] private void Apply() => apply(Value);
|
||||
}
|
||||
|
||||
public partial class SeatAttendanceChoice(string symbol, string label, string shortcut,
|
||||
AttendanceStatus? status, Action<AttendanceStatus?> apply) : ObservableObject
|
||||
{
|
||||
public string Symbol { get; } = symbol;
|
||||
public string Label { get; } = label;
|
||||
public string Shortcut { get; } = shortcut;
|
||||
public AttendanceStatus? Status { get; } = status;
|
||||
[ObservableProperty] private bool _isSelected;
|
||||
[RelayCommand] private void Apply() => apply(Status);
|
||||
}
|
||||
|
||||
public partial class SeatHomeworkChoice(string symbol, string label, string shortcut,
|
||||
HomeworkStatus? status, Action<HomeworkStatus?> apply) : ObservableObject
|
||||
{
|
||||
public string Symbol { get; } = symbol;
|
||||
public string Label { get; } = label;
|
||||
public string Shortcut { get; } = shortcut;
|
||||
public HomeworkStatus? Status { get; } = status;
|
||||
[ObservableProperty] private bool _isSelected;
|
||||
[RelayCommand] private void Apply() => apply(Status);
|
||||
}
|
||||
|
||||
public partial class SeatingPlanDialogViewModel : ObservableObject
|
||||
{
|
||||
private readonly ISeatingPlanRepository _plans;
|
||||
@@ -256,8 +592,8 @@ public partial class SeatingPlanDialogViewModel : ObservableObject
|
||||
_groupId = groupId;
|
||||
_editingPlan = editingPlan;
|
||||
if (editingPlan is null) return;
|
||||
Name = editingPlan.Name;
|
||||
Room = editingPlan.Room;
|
||||
Name = editingPlan.Name ?? "";
|
||||
Room = editingPlan.Room ?? "";
|
||||
Rows = editingPlan.Rows;
|
||||
Columns = editingPlan.Columns;
|
||||
}
|
||||
@@ -281,8 +617,8 @@ public partial class SeatingPlanDialogViewModel : ObservableObject
|
||||
if (!valid) return;
|
||||
|
||||
var plan = _editingPlan ?? new SeatingPlan { GroupId = _groupId };
|
||||
plan.Name = Name.Trim();
|
||||
plan.Room = Room.Trim();
|
||||
plan.Name = Name?.Trim() ?? "";
|
||||
plan.Room = Room?.Trim() ?? "";
|
||||
plan.Rows = decimal.ToInt32(Rows);
|
||||
plan.Columns = decimal.ToInt32(Columns);
|
||||
try
|
||||
|
||||
Reference in New Issue
Block a user