P3 Stream J: widget data repository (DataStore-backed)

Ports iOS WidgetDataManager.swift semantics. DTO + JSON serialization +
pending-completion tracking + stats (overdueCount / dueWithin7 / dueWithin8To30).
Same-process DataStore is sufficient for Glance widgets.

Unblocks Streams K (widgets) / L (scheduler) / M (actions).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trey T
2026-04-18 12:40:48 -05:00
parent 7aab8b0f29
commit 6d7b5ee990
4 changed files with 566 additions and 41 deletions
@@ -0,0 +1,49 @@
package com.tt.honeyDue.widget
import kotlinx.serialization.Serializable
/**
* DTO persisted to the widget DataStore as JSON, mirroring iOS
* `WidgetDataManager.swift`'s on-disk task representation.
*
* iOS field map (for reference — keep in sync):
* - id Int (task id)
* - title String
* - priority Int (priority id)
* - dueDate String? ISO-8601 ("yyyy-MM-dd" or full datetime)
* - isOverdue Bool
* - daysUntilDue Int
* - residenceId Int
* - residenceName String
* - categoryIcon String SF-symbol-style identifier
* - completed Bool
*
* Kotlin uses [Long] for ids to accommodate any server-side auto-increment range.
*/
@Serializable
data class WidgetTaskDto(
val id: Long,
val title: String,
val priority: Long,
val dueDate: String?,
val isOverdue: Boolean,
val daysUntilDue: Int,
val residenceId: Long,
val residenceName: String,
val categoryIcon: String,
val completed: Boolean
)
/**
* Summary metrics computed from the cached task list.
*
* Windows match iOS `calculateMetrics` semantics:
* - overdueCount tasks with isOverdue == true
* - dueWithin7 tasks with 0 <= daysUntilDue <= 7
* - dueWithin8To30 tasks with 8 <= daysUntilDue <= 30
*/
data class WidgetStats(
val overdueCount: Int,
val dueWithin7: Int,
val dueWithin8To30: Int
)