diff --git a/src/ClaudeDo.Worker/Hub/WorkerHub.cs b/src/ClaudeDo.Worker/Hub/WorkerHub.cs index 07fca4d..ff98f31 100644 --- a/src/ClaudeDo.Worker/Hub/WorkerHub.cs +++ b/src/ClaudeDo.Worker/Hub/WorkerHub.cs @@ -1,3 +1,4 @@ +using System.Globalization; using System.Reflection; using ClaudeDo.Data; using ClaudeDo.Data.Models; @@ -7,6 +8,8 @@ using ClaudeDo.Worker.Lifecycle; using ClaudeDo.Worker.Planning; using ClaudeDo.Worker.Prime; using ClaudeDo.Worker.Queue; +using ClaudeDo.Worker.Report; +using ClaudeDo.Worker.Report.Interfaces; using ClaudeDo.Worker.State; using ClaudeDo.Worker.Worktrees; using TaskStatus = ClaudeDo.Data.Models.TaskStatus; @@ -75,6 +78,7 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub private readonly PlanningChainCoordinator _planningChain; private readonly IPrimeScheduleSignal _primeSignal; private readonly ITaskStateService _state; + private readonly IWeekReportService _report; public WorkerHub( QueueService queue, @@ -92,7 +96,8 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub PlanningMergeOrchestrator planningMergeOrchestrator, PlanningChainCoordinator planningChain, IPrimeScheduleSignal primeSignal, - ITaskStateService state) + ITaskStateService state, + IWeekReportService report) { _queue = queue; _waker = waker; @@ -110,6 +115,7 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub _planningChain = planningChain; _primeSignal = primeSignal; _state = state; + _report = report; } // Maps the two exceptions service methods throw into client-facing HubExceptions: @@ -520,4 +526,38 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub await new PrimeScheduleRepository(ctx).DeleteAsync(id); _primeSignal.Signal(); } + + private static DateOnly Day(string iso) => DateOnly.ParseExact(iso, "yyyy-MM-dd", CultureInfo.InvariantCulture); + + public Task GetWeekReport(string startIso, string endIso) => + _report.GetStoredAsync(Day(startIso), Day(endIso)); + + public Task GenerateWeekReport(string startIso, string endIso) => + HubGuard(() => _report.GenerateAsync(Day(startIso), Day(endIso)), "report generation failed"); + + public async Task> GetDailyNotes(string dayIso) + { + using var ctx = _dbFactory.CreateDbContext(); + var notes = await new DailyNoteRepository(ctx).ListByDayAsync(Day(dayIso)); + return notes.Select(n => new DailyNoteDto(n.Id, n.Date.ToString("yyyy-MM-dd"), n.Text, n.SortOrder)).ToList(); + } + + public async Task AddDailyNote(string dayIso, string text) + { + using var ctx = _dbFactory.CreateDbContext(); + var n = await new DailyNoteRepository(ctx).AddAsync(Day(dayIso), text); + return new DailyNoteDto(n.Id, n.Date.ToString("yyyy-MM-dd"), n.Text, n.SortOrder); + } + + public async Task UpdateDailyNote(string id, string text) + { + using var ctx = _dbFactory.CreateDbContext(); + await new DailyNoteRepository(ctx).UpdateAsync(id, text); + } + + public async Task DeleteDailyNote(string id) + { + using var ctx = _dbFactory.CreateDbContext(); + await new DailyNoteRepository(ctx).DeleteAsync(id); + } } diff --git a/src/ClaudeDo.Worker/Report/DailyNoteDto.cs b/src/ClaudeDo.Worker/Report/DailyNoteDto.cs new file mode 100644 index 0000000..f2e734b --- /dev/null +++ b/src/ClaudeDo.Worker/Report/DailyNoteDto.cs @@ -0,0 +1,3 @@ +namespace ClaudeDo.Worker.Report; + +public sealed record DailyNoteDto(string Id, string Date, string Text, int SortOrder);