iOSiOS APP

MomWorkHours

"Log your hours by voice. Let Claude write your timesheet summary."

SwiftSwiftUISwiftDataClaude HaikuSpeech FrameworkEventKitiOS 16+
MomWorkHours

Swift · SwiftUI · SwiftData · Claude Haiku

0
Entry time by voice
0
On-device persistence
0
AI response types
0
Claude Haiku response

OVERVIEW

|

Freelance and part-time working mums squeeze work into fragmented windows, naptime, school pickup gaps, late evenings. Logging these sessions manually was either forgotten mid-session or recorded inaccurately. No tool combined voice-first entry, a visual hours overview, and AI-generated timesheet summaries in one place.

|

A SwiftUI app built on SwiftData. The primary input is a Claude Haiku chat interface, the user speaks or types what they worked on, and the streaming AI extracts date, start/end time, and notes from natural language. A custom intensity-map calendar gives an at-a-glance overview. Confirmed entries are written to iOS Calendar via EventKit. At week's end, Claude generates a professional timesheet narrative from all entries.

|

Work sessions logged in under 10 seconds by voice. The weekly AI summary turns scattered notes into a professional timesheet narrative ready to paste directly into an invoice.

KEY FEATURES

Streaming Claude Chat

ClaudeService.swift posts to the Anthropic API with stream:true. Responses arrive as SSE events parsed via session.bytes(for:). Partial JSON updates the chat UI live as Claude types; the complete response creates the work entry.

Five AI Response Types

The system prompt instructs Claude to return JSON-only in one of five modes: entry (log a session), note (save a note), update (amend a previous entry), search (find a note by UUID), or chat (general Q&A). No markdown, no prose.

Voice Entry via SFSpeechRecognizer

SpeechManager uses SFSpeechRecognizer (en-US) and AVAudioEngine with shouldReportPartialResults:true for real-time transcription. The result feeds into the chat interface as a user message.

Intensity-Map Calendar

CustomCalendarView renders a month grid where each day cell colour encodes hours worked that day. Deeper colour = more hours. Tap any day to see all entries.

EventKit iOS Calendar Sync

Confirmed entries are written to the iOS Calendar via EKEventStore. WorkEntry stores the returned calendarEventID so the event is deleted if the entry is later removed or undone.

Offline Message Queuing

NetworkManager monitors connectivity. When offline, messages are queued in pendingMessages[]. On reconnection, processMessageSilently() drains the queue sequentially, no entry is lost due to poor connectivity.

TECH STACK

Tap to see the reasoning

BUILD TIMELINE

Phase 01

SwiftData & Calendar

Built the @Model WorkEntry and NoteEntry classes, WorkHoursStore CRUD layer, and CustomCalendarView with intensity-map colour coding. Integrated EventKit with requestAccess() on first launch.

CHALLENGES & SOLUTIONS

The streaming response arrives as fragmented JSON. The message field can be extracted from partial JSON for live display; the full entry data (date, startTime, endTime) must wait for the complete response. ClaudeService implements two separate parse functions, one for the display field and one for the action data.

New fields added in updates require schema migration. MigrationManager.swift implements a versioned migration pipeline, each step is a separate function applied in sequence. The app never loses existing work entries on update.

LET'S BUILD SOMETHING TOGETHER

I'm always open to discussing new projects, partnerships, or just a good idea.