init 1.0.0
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using LehrerApp.Core.Interfaces;
|
||||
using LehrerApp.Core.Models;
|
||||
using LehrerApp.Core.Services;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
|
||||
namespace LehrerApp.Desktop.ViewModels;
|
||||
|
||||
public partial class DashboardViewModel : ObservableObject
|
||||
{
|
||||
private readonly IGroupRepository _groups;
|
||||
private readonly ILessonRepository _lessons;
|
||||
private readonly IWorkTaskRepository _tasks;
|
||||
private readonly SchoolYearService _sy;
|
||||
|
||||
[ObservableProperty] private string _greeting = "";
|
||||
[ObservableProperty] private string _currentDate = "";
|
||||
[ObservableProperty] private string _currentSchoolYear = "";
|
||||
|
||||
public ObservableCollection<LessonItem> TodaysLessons { get; } = [];
|
||||
public ObservableCollection<TaskItem> OpenTasks { get; } = [];
|
||||
public ObservableCollection<GroupChip> CurrentGroups { get; } = [];
|
||||
|
||||
// Navigation-Callback – wird von App.axaml.cs verdrahtet
|
||||
public Action<Guid>? OnNavigateToGroup { get; set; }
|
||||
|
||||
public DashboardViewModel(IGroupRepository groups, ILessonRepository lessons,
|
||||
IWorkTaskRepository tasks, SchoolYearService sy)
|
||||
{
|
||||
_groups = groups; _lessons = lessons; _tasks = tasks; _sy = sy;
|
||||
Load();
|
||||
}
|
||||
|
||||
private void Load()
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
var today = DateOnly.FromDateTime(now);
|
||||
CurrentDate = now.ToString("dddd, d. MMMM yyyy", new CultureInfo("de-DE"));
|
||||
CurrentSchoolYear = _sy.CurrentSchoolYear();
|
||||
Greeting = now.Hour < 12 ? "Guten Morgen" : now.Hour < 18 ? "Guten Tag" : "Guten Abend";
|
||||
|
||||
TodaysLessons.Clear();
|
||||
var groups = _groups.GetBySchoolYear(_sy.CurrentSchoolYear()).ToDictionary(g => g.Id);
|
||||
foreach (var l in groups.Keys.SelectMany(gid => _lessons.GetByGroupAndDate(gid, today))
|
||||
.OrderBy(l => l.LessonNumber))
|
||||
{
|
||||
if (groups.TryGetValue(l.GroupId, out var g))
|
||||
TodaysLessons.Add(new() { GroupName = g.Name, Topic = l.Topic });
|
||||
}
|
||||
|
||||
OpenTasks.Clear();
|
||||
foreach (var t in _tasks.GetByStatus(WorkTaskStatus.Open)
|
||||
.Concat(_tasks.GetByStatus(WorkTaskStatus.InProgress))
|
||||
.OrderBy(t => t.DueDate ?? DateOnly.MaxValue).Take(5))
|
||||
OpenTasks.Add(new() { Title = t.Title,
|
||||
DueDate = t.DueDate?.ToString("dd.MM.") ?? "",
|
||||
IsOverdue = t.DueDate.HasValue && t.DueDate < today });
|
||||
|
||||
CurrentGroups.Clear();
|
||||
foreach (var g in groups.Values.OrderBy(g => g.Name))
|
||||
CurrentGroups.Add(new() { GroupId = g.Id, Name = g.Name, Subject = g.Subject ?? "" });
|
||||
}
|
||||
|
||||
[RelayCommand] private void OpenGroup(GroupChip? c) { if (c is not null) OnNavigateToGroup?.Invoke(c.GroupId); }
|
||||
[RelayCommand] private void Refresh() => Load();
|
||||
}
|
||||
|
||||
public class LessonItem { public string GroupName { get; set; } = ""; public string Topic { get; set; } = ""; }
|
||||
public class TaskItem { public string Title { get; set; } = ""; public string DueDate { get; set; } = ""; public bool IsOverdue { get; set; } }
|
||||
public class GroupChip { public Guid GroupId { get; set; } public string Name { get; set; } = ""; public string Subject { get; set; } = ""; }
|
||||
@@ -0,0 +1,196 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using LehrerApp.Core.Interfaces;
|
||||
using LehrerApp.Core.Models;
|
||||
using LehrerApp.Core.Services;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace LehrerApp.Desktop.ViewModels.Groups;
|
||||
|
||||
// ── Gruppenliste ──────────────────────────────────────────────────────────────
|
||||
|
||||
public partial class GroupListViewModel : ObservableObject
|
||||
{
|
||||
private readonly IGroupRepository _groups;
|
||||
private readonly SchoolYearService _sy;
|
||||
|
||||
public Action<Guid>? OnNavigateToDetail { get; set; }
|
||||
public Action? OnAddGroup { get; set; }
|
||||
|
||||
[ObservableProperty] private string _selectedSchoolYear = "";
|
||||
[ObservableProperty] private string _searchText = "";
|
||||
[ObservableProperty] private GroupListItem? _selectedGroup;
|
||||
|
||||
public ObservableCollection<string> SchoolYears { get; } = [];
|
||||
public ObservableCollection<GroupListItem> Groups { get; } = [];
|
||||
|
||||
public GroupListViewModel(IGroupRepository groups, SchoolYearService sy)
|
||||
{
|
||||
_groups = groups; _sy = sy;
|
||||
foreach (var y in sy.RecentSchoolYears()) SchoolYears.Add(y);
|
||||
SelectedSchoolYear = sy.CurrentSchoolYear();
|
||||
}
|
||||
|
||||
partial void OnSelectedSchoolYearChanged(string value) => LoadGroups();
|
||||
partial void OnSearchTextChanged(string value) => LoadGroups();
|
||||
partial void OnSelectedGroupChanged(GroupListItem? value)
|
||||
{
|
||||
if (value is not null) OnNavigateToDetail?.Invoke(value.Id);
|
||||
}
|
||||
|
||||
public void LoadGroups()
|
||||
{
|
||||
Groups.Clear();
|
||||
var all = _groups.GetBySchoolYear(SelectedSchoolYear);
|
||||
var filtered = string.IsNullOrWhiteSpace(SearchText) ? all
|
||||
: all.Where(g => g.Name.Contains(SearchText, StringComparison.OrdinalIgnoreCase)
|
||||
|| (g.Subject?.Contains(SearchText, StringComparison.OrdinalIgnoreCase) ?? false));
|
||||
foreach (var g in filtered.OrderBy(g => g.Name))
|
||||
Groups.Add(new GroupListItem(g));
|
||||
}
|
||||
|
||||
[RelayCommand] private void AddGroup() => OnAddGroup?.Invoke();
|
||||
[RelayCommand] private void Refresh() => LoadGroups();
|
||||
}
|
||||
|
||||
public class GroupListItem
|
||||
{
|
||||
public Guid Id { get; }
|
||||
public string Name { get; }
|
||||
public string Subject { get; }
|
||||
public string DisplayName { get; }
|
||||
public string TypeLabel { get; }
|
||||
public string GradingLabel { get; }
|
||||
|
||||
public GroupListItem(LearningGroup g)
|
||||
{
|
||||
Id = g.Id;
|
||||
Name = g.Name;
|
||||
Subject = g.Subject ?? "";
|
||||
TypeLabel = g.Type == GroupType.Class ? "Klasse" : "Kurs";
|
||||
GradingLabel = g.GradingSystem == GradingSystem.Grades1To6 ? "1–6" : "0–15";
|
||||
DisplayName = string.IsNullOrEmpty(Subject) ? Name : $"{Name} · {Subject}";
|
||||
}
|
||||
}
|
||||
|
||||
// ── Gruppendetail ─────────────────────────────────────────────────────────────
|
||||
|
||||
public partial class GroupDetailViewModel : ObservableObject
|
||||
{
|
||||
private readonly IGroupRepository _groups;
|
||||
private readonly IStudentRepository _students;
|
||||
private readonly IExamRepository _exams;
|
||||
private readonly IGradeRepository _grades;
|
||||
|
||||
[ObservableProperty] private LearningGroup? _group;
|
||||
[ObservableProperty] private string _groupTitle = "";
|
||||
[ObservableProperty] private string _groupSubtitle = "";
|
||||
[ObservableProperty] private int _studentCount;
|
||||
|
||||
public ObservableCollection<StudentSummary> Students { get; } = [];
|
||||
public ObservableCollection<ExamSummary> Exams { get; } = [];
|
||||
|
||||
public GroupDetailViewModel(IGroupRepository groups, IStudentRepository students,
|
||||
IExamRepository exams, IGradeRepository grades)
|
||||
{
|
||||
_groups = groups; _students = students; _exams = exams; _grades = grades;
|
||||
}
|
||||
|
||||
public void LoadGroup(Guid id)
|
||||
{
|
||||
Group = _groups.GetById(id);
|
||||
if (Group is null) return;
|
||||
GroupTitle = Group.Name;
|
||||
GroupSubtitle = $"{Group.SchoolYear} · " +
|
||||
$"{(Group.Type == GroupType.Class ? "Klasse" : "Kurs")} · " +
|
||||
$"Stufe {Group.GradeLevel} · Noten {(Group.GradingSystem == GradingSystem.Grades1To6 ? "1–6" : "0–15")}";
|
||||
|
||||
Students.Clear();
|
||||
var enrolled = _students.GetByGroup(Group.Id, Group.SchoolYear);
|
||||
StudentCount = enrolled.Count;
|
||||
foreach (var s in enrolled) Students.Add(new StudentSummary(s));
|
||||
|
||||
Exams.Clear();
|
||||
foreach (var e in _exams.GetByGroup(Group.Id)) Exams.Add(new ExamSummary(e));
|
||||
}
|
||||
|
||||
[RelayCommand] private void AddStudent() { /* TODO */ }
|
||||
[RelayCommand] private void AddExam() { /* TODO */ }
|
||||
[RelayCommand] private void Refresh() { if (Group is not null) LoadGroup(Group.Id); }
|
||||
}
|
||||
|
||||
public class StudentSummary
|
||||
{
|
||||
public Guid Id { get; }
|
||||
public string FullName { get; }
|
||||
public StudentSummary(Core.Models.Student s) { Id = s.Id; FullName = s.FullName; }
|
||||
}
|
||||
|
||||
public class ExamSummary
|
||||
{
|
||||
public Guid Id { get; }
|
||||
public string Title { get; }
|
||||
public string Date { get; }
|
||||
public string StatusLabel { get; }
|
||||
public ExamSummary(Core.Models.Exam e)
|
||||
{
|
||||
Id = e.Id; Title = e.Title; Date = e.Date.ToString("dd.MM.yyyy");
|
||||
StatusLabel = e.Status switch
|
||||
{
|
||||
ExamStatus.Planned => "Geplant",
|
||||
ExamStatus.Conducted => "Durchgeführt",
|
||||
ExamStatus.Graded => "Korrigiert",
|
||||
ExamStatus.Returned => "Zurückgegeben",
|
||||
_ => "",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// ── Dialog: Neue Lerngruppe anlegen ──────────────────────────────────────────
|
||||
|
||||
public partial class AddGroupDialogViewModel : ObservableObject
|
||||
{
|
||||
private readonly IGroupRepository _groups;
|
||||
private readonly SchoolYearService _sy;
|
||||
|
||||
[ObservableProperty] private string _name = "";
|
||||
[ObservableProperty] private string _subject = "";
|
||||
[ObservableProperty] private int _gradeLevel = 10;
|
||||
[ObservableProperty] private GradingSystem _gradingSystem = GradingSystem.Grades1To6;
|
||||
[ObservableProperty] private string _selectedSchoolYear = "";
|
||||
[ObservableProperty] private string _validationMessage = "";
|
||||
|
||||
public List<string> SchoolYears { get; }
|
||||
public LearningGroup? Result { get; private set; }
|
||||
|
||||
public AddGroupDialogViewModel(IGroupRepository groups, SchoolYearService sy)
|
||||
{
|
||||
_groups = groups; _sy = sy;
|
||||
SchoolYears = sy.RecentSchoolYears(3);
|
||||
SelectedSchoolYear = sy.CurrentSchoolYear();
|
||||
// Notensystem automatisch nach Klassenstufe
|
||||
PropertyChanged += (_, e) =>
|
||||
{
|
||||
if (e.PropertyName == nameof(GradeLevel))
|
||||
GradingSystem = GradeLevel >= 11 ? GradingSystem.Points0To15
|
||||
: GradingSystem.Grades1To6;
|
||||
};
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Save()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Name)) { ValidationMessage = "Name erforderlich."; return; }
|
||||
if (GradeLevel is < 1 or > 13) { ValidationMessage = "Klassenstufe 1–13."; return; }
|
||||
Result = new LearningGroup
|
||||
{
|
||||
Name = Name.Trim(),
|
||||
Subject = string.IsNullOrWhiteSpace(Subject) ? null : Subject.Trim(),
|
||||
Type = GroupType.Course,
|
||||
GradeLevel = GradeLevel,
|
||||
GradingSystem = GradingSystem,
|
||||
SchoolYear = SelectedSchoolYear,
|
||||
};
|
||||
_groups.Save(Result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using LehrerApp.Core.Services;
|
||||
using LehrerApp.Desktop.ViewModels.Groups;
|
||||
using LehrerApp.Desktop.ViewModels.Students;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace LehrerApp.Desktop.ViewModels;
|
||||
|
||||
public partial class MainWindowViewModel : ObservableObject
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
[ObservableProperty] private ObservableObject? _currentPage;
|
||||
[ObservableProperty] private NavItem _activeNavItem = NavItem.Dashboard;
|
||||
[ObservableProperty] private string _currentSchoolYear = "";
|
||||
|
||||
public MainWindowViewModel(IServiceProvider services,
|
||||
DashboardViewModel dashboard, SchoolYearService sy)
|
||||
{
|
||||
_services = services;
|
||||
CurrentSchoolYear = sy.CurrentSchoolYear();
|
||||
CurrentPage = dashboard;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void NavigateTo(NavItem item)
|
||||
{
|
||||
ActiveNavItem = item;
|
||||
CurrentPage = item switch
|
||||
{
|
||||
NavItem.Dashboard => _services.GetRequiredService<DashboardViewModel>(),
|
||||
NavItem.Groups => _services.GetRequiredService<GroupListViewModel>(),
|
||||
NavItem.Students => _services.GetRequiredService<StudentListViewModel>(),
|
||||
NavItem.Exams => new PlaceholderViewModel { Title = "Klausuren", Icon = "📝" },
|
||||
NavItem.Planner => new PlaceholderViewModel { Title = "Unterrichtsplanung", Icon = "📅" },
|
||||
NavItem.Workload => new PlaceholderViewModel { Title = "Arbeitszeit", Icon = "⏱" },
|
||||
NavItem.Settings => new PlaceholderViewModel { Title = "Einstellungen", Icon = "⚙️" },
|
||||
_ => CurrentPage,
|
||||
};
|
||||
}
|
||||
|
||||
public void NavigateToGroupDetail(Guid groupId)
|
||||
{
|
||||
ActiveNavItem = NavItem.Groups;
|
||||
var vm = _services.GetRequiredService<GroupDetailViewModel>();
|
||||
vm.LoadGroup(groupId);
|
||||
CurrentPage = vm;
|
||||
}
|
||||
|
||||
public void NavigateToStudent(Guid studentId)
|
||||
{
|
||||
ActiveNavItem = NavItem.Students;
|
||||
var vm = _services.GetRequiredService<StudentDetailViewModel>();
|
||||
vm.LoadStudent(studentId);
|
||||
CurrentPage = vm;
|
||||
}
|
||||
}
|
||||
|
||||
public enum NavItem { Dashboard, Groups, Students, Exams, Planner, Workload, Settings }
|
||||
|
||||
public partial class PlaceholderViewModel : ObservableObject
|
||||
{
|
||||
[ObservableProperty] private string _title = "";
|
||||
[ObservableProperty] private string _icon = "";
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using LehrerApp.Core.Interfaces;
|
||||
using LehrerApp.Core.Models;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace LehrerApp.Desktop.ViewModels.Students;
|
||||
|
||||
public partial class StudentListViewModel : ObservableObject
|
||||
{
|
||||
private readonly IStudentRepository _students;
|
||||
public Action<Guid>? OnNavigateToDetail { get; set; }
|
||||
|
||||
[ObservableProperty] private string _searchText = "";
|
||||
[ObservableProperty] private bool _showInactive;
|
||||
[ObservableProperty] private StudentListItem? _selectedStudent;
|
||||
|
||||
public ObservableCollection<StudentListItem> Students { get; } = [];
|
||||
|
||||
public StudentListViewModel(IStudentRepository students)
|
||||
{
|
||||
_students = students;
|
||||
LoadStudents();
|
||||
}
|
||||
|
||||
partial void OnSearchTextChanged(string value) => LoadStudents();
|
||||
partial void OnShowInactiveChanged(bool value) => LoadStudents();
|
||||
partial void OnSelectedStudentChanged(StudentListItem? value)
|
||||
{
|
||||
if (value is not null) OnNavigateToDetail?.Invoke(value.Id);
|
||||
}
|
||||
|
||||
public void LoadStudents()
|
||||
{
|
||||
Students.Clear();
|
||||
var all = _students.GetAll(ShowInactive);
|
||||
var f = string.IsNullOrWhiteSpace(SearchText) ? all
|
||||
: all.Where(s => s.LastName.Contains(SearchText, StringComparison.OrdinalIgnoreCase)
|
||||
|| s.FirstName.Contains(SearchText, StringComparison.OrdinalIgnoreCase));
|
||||
foreach (var s in f) Students.Add(new StudentListItem(s));
|
||||
}
|
||||
|
||||
[RelayCommand] private void AddStudent() { /* TODO */ }
|
||||
[RelayCommand] private void Refresh() => LoadStudents();
|
||||
}
|
||||
|
||||
public class StudentListItem
|
||||
{
|
||||
public Guid Id { get; }
|
||||
public string FullName { get; }
|
||||
public string DateOfBirth { get; }
|
||||
public StudentListItem(Student s)
|
||||
{
|
||||
Id = s.Id; FullName = s.FullName;
|
||||
DateOfBirth = s.DateOfBirth?.ToString("dd.MM.yyyy") ?? "";
|
||||
}
|
||||
}
|
||||
|
||||
public partial class StudentDetailViewModel : ObservableObject
|
||||
{
|
||||
private readonly IStudentRepository _students;
|
||||
private readonly IEnrollmentRepository _enrollments;
|
||||
private readonly IGroupRepository _groups;
|
||||
private readonly IDocumentationRepository _docs;
|
||||
|
||||
[ObservableProperty] private Student? _student;
|
||||
[ObservableProperty] private string _studentTitle = "";
|
||||
[ObservableProperty] private bool _isEditing;
|
||||
[ObservableProperty] private string _editFirstName = "";
|
||||
[ObservableProperty] private string _editLastName = "";
|
||||
|
||||
public ObservableCollection<EnrollmentEntry> Enrollments { get; } = [];
|
||||
public ObservableCollection<DocEntry> Documentation { get; } = [];
|
||||
|
||||
public StudentDetailViewModel(IStudentRepository students,
|
||||
IEnrollmentRepository enrollments, IGroupRepository groups,
|
||||
IDocumentationRepository docs)
|
||||
{
|
||||
_students = students; _enrollments = enrollments;
|
||||
_groups = groups; _docs = docs;
|
||||
}
|
||||
|
||||
public void LoadStudent(Guid id)
|
||||
{
|
||||
Student = _students.GetById(id);
|
||||
if (Student is null) return;
|
||||
StudentTitle = Student.FullName;
|
||||
EditFirstName = Student.FirstName;
|
||||
EditLastName = Student.LastName;
|
||||
|
||||
Enrollments.Clear();
|
||||
foreach (var e in _enrollments.GetByStudent(Student.Id))
|
||||
{
|
||||
var g = _groups.GetById(e.GroupId);
|
||||
if (g is null) continue;
|
||||
Enrollments.Add(new() { SchoolYear = e.SchoolYear, GroupName = g.Name, Subject = g.Subject ?? "" });
|
||||
}
|
||||
|
||||
Documentation.Clear();
|
||||
foreach (var d in _docs.GetByStudent(Student.Id))
|
||||
Documentation.Add(new() { Date = d.Date.ToString("dd.MM.yyyy"), Title = d.Title,
|
||||
TypeLabel = d.Type switch
|
||||
{
|
||||
DocumentationType.Conversation => "Gespräch",
|
||||
DocumentationType.Incident => "Vorkommnis",
|
||||
DocumentationType.SupportPlan => "Förderplan",
|
||||
DocumentationType.Absence => "Fehlzeit",
|
||||
_ => "",
|
||||
},
|
||||
IsConfidential = d.IsConfidential });
|
||||
}
|
||||
|
||||
[RelayCommand] private void StartEdit() => IsEditing = true;
|
||||
[RelayCommand] private void CancelEdit()
|
||||
{
|
||||
if (Student is null) return;
|
||||
EditFirstName = Student.FirstName; EditLastName = Student.LastName;
|
||||
IsEditing = false;
|
||||
}
|
||||
[RelayCommand] private void SaveEdit()
|
||||
{
|
||||
if (Student is null) return;
|
||||
Student.FirstName = EditFirstName; Student.LastName = EditLastName;
|
||||
_students.Save(Student);
|
||||
StudentTitle = Student.FullName;
|
||||
IsEditing = false;
|
||||
}
|
||||
}
|
||||
|
||||
public class EnrollmentEntry { public string SchoolYear { get; set; } = ""; public string GroupName { get; set; } = ""; public string Subject { get; set; } = ""; }
|
||||
public class DocEntry { public string Date { get; set; } = ""; public string Title { get; set; } = ""; public string TypeLabel { get; set; } = ""; public bool IsConfidential { get; set; } }
|
||||
@@ -0,0 +1,43 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using LehrerApp.Sync;
|
||||
using LehrerApp.Sync.Models;
|
||||
|
||||
namespace LehrerApp.Desktop.ViewModels;
|
||||
|
||||
public partial class SyncStatusViewModel : ObservableObject
|
||||
{
|
||||
private readonly SyncEngine? _engine;
|
||||
|
||||
[ObservableProperty] private string _statusText = "Kein Server konfiguriert";
|
||||
[ObservableProperty] private string _lastSyncText = "";
|
||||
[ObservableProperty] private bool _isSyncing;
|
||||
[ObservableProperty] private bool _isServerConfigured;
|
||||
[ObservableProperty] private int _pendingCount;
|
||||
|
||||
public SyncStatusViewModel(SyncEngine? engine)
|
||||
{
|
||||
_engine = engine;
|
||||
IsServerConfigured = engine is not null;
|
||||
if (_engine is not null) _engine.StatusChanged += OnStatus;
|
||||
}
|
||||
|
||||
private void OnStatus(SyncStatus s)
|
||||
{
|
||||
IsSyncing = s.State == SyncState.Syncing;
|
||||
PendingCount = s.PendingEvents;
|
||||
StatusText = s.State switch
|
||||
{
|
||||
SyncState.Idle => PendingCount > 0 ? $"{PendingCount} ausstehend" : "Synchronisiert",
|
||||
SyncState.Syncing => "Synchronisiere…",
|
||||
SyncState.Offline => "Offline",
|
||||
SyncState.Error => $"Fehler: {s.ErrorMessage}",
|
||||
_ => "",
|
||||
};
|
||||
LastSyncText = s.LastSyncAt.HasValue ? $"Zuletzt: {s.LastSyncAt:HH:mm}" : "Noch nie";
|
||||
}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanSync))]
|
||||
private async Task SyncNow() { if (_engine is not null) await _engine.SyncNowAsync(); }
|
||||
private bool CanSync() => _engine is not null && !IsSyncing;
|
||||
}
|
||||
Reference in New Issue
Block a user