Refactor data services and extract utility functions#60
Merged
Conversation
Extract LocalStorageService and SupabaseService classes into their own files, reducing dataService.ts from 1,267 lines to a thin interface + factory module (~45 lines). All public exports remain backward compatible. https://claude.ai/code/session_012AmNjF3Ju9VJwSWybJqBEw
Move all billing/duration calculation functions into a dedicated calculationUtils.ts as pure functions, removing ~100 lines from TimeTrackingContext. Context methods now delegate to these utilities. https://claude.ai/code/session_012AmNjF3Ju9VJwSWybJqBEw
Move exportToCSV, exportToJSON, generateInvoiceData, and CSV parsing logic into exportUtils.ts as pure functions, removing ~350 lines from TimeTrackingContext. Context methods now delegate to these utilities. https://claude.ai/code/session_012AmNjF3Ju9VJwSWybJqBEw
Move the task-editing dialog from ArchiveEditDialog.tsx into a dedicated TaskEditInArchiveDialog.tsx, reducing ArchiveEditDialog from 850 to ~270 lines. Unused Select imports are removed from ArchiveEditDialog. https://claude.ai/code/session_012AmNjF3Ju9VJwSWybJqBEw
OfflineContext.processQueue was a stub that looped over queued actions without executing any of them, silently dropping all offline changes. Fix: when the app comes back online, processQueue now dispatches a 'timetracker:sync-required' custom DOM event and clears the queue. TimeTrackingContext listens for this event and calls forceSyncToDatabase, pushing all in-memory React state to Supabase. Only triggers when the user is authenticated (Supabase mode). Also fixes the eslint-disable comment on the online/offline effect that was masking a legitimate missing dependency (processQueue). https://claude.ai/code/session_012AmNjF3Ju9VJwSWybJqBEw
…rites In saveCurrentDay, saveArchivedDays, and updateArchivedDay, the project_id field was set as `project?.id || task.project || null`. When a project wasn't found by name (e.g. after renaming or deletion), this fell back to writing the project *name string* into a UUID column, silently corrupting the database record. Fix: use `project?.id || null` — if the project can't be resolved, store null rather than an invalid value. project_name already preserves the display name for historical reference. https://claude.ai/code/session_012AmNjF3Ju9VJwSWybJqBEw
…abaseService Remove debug logging from the two highest-volume files (40 and 65 logs respectively). console.error and console.warn calls are preserved. https://claude.ai/code/session_012AmNjF3Ju9VJwSWybJqBEw
Remove debug logging from AuthContext, OfflineContext, dataService, supabase lib, useRealtimeSync, Index, UpdateNotification, and InstallPrompt. Empty if/else blocks that contained only a console.log are also removed. console.error and console.warn are preserved throughout. https://claude.ai/code/session_012AmNjF3Ju9VJwSWybJqBEw
Remove stray `});` in supabaseService.ts getArchivedDays (leftover from removed multi-line console.log call) and empty else blocks in TimeTrackingContext.tsx and supabaseService.ts that triggered no-empty lint errors. https://claude.ai/code/session_012AmNjF3Ju9VJwSWybJqBEw
Deploying timetrackerpro with
|
| Latest commit: |
b3d577d
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://6058dd28.timetrackerpro.pages.dev |
| Branch Preview URL: | https://claude-project-improvement-r.timetrackerpro.pages.dev |
- Delete src/hooks/.useReportSummary-Claude.ts (unused, exposed API key) - Delete src/utils/supabase.ts (duplicate Supabase client, never imported) - Delete src/hooks/useRealtimeSync.ts (body fully disabled, never called) - Delete src/hooks/useOffline.tsx (hook never called anywhere) - Remove saveCurrentDayRef from TimeTrackingContext (useRef never assigned) - Remove useRealtimeSync import and commented-out call from TimeTrackingContext - Remove SYNC_REQUIRED_EVENT import and dead listener from TimeTrackingContext - Strip OfflineContext down to isOnline + online/offline toasts; remove addToQueue, offlineQueue, processQueue, and SYNC_REQUIRED_EVENT which were never wired up to any data operations https://claude.ai/code/session_012AmNjF3Ju9VJwSWybJqBEw
- Add [Unreleased] Removed section listing all six deleted/stripped items - Correct stale "real-time sync" feature claim in [0.21.1] entry - Remove deleted useRealtimeSync() entry from custom hooks list in architecture.md https://claude.ai/code/session_012AmNjF3Ju9VJwSWybJqBEw
…fety
1. Online reconnection no longer triggers sync (TimeTrackingContext)
- After the offline-queue dead code removal, no mechanism remained to
call forceSyncToDatabase() when the browser comes back online.
- Add a 'online' window event listener in TimeTrackingContext that calls
forceSyncToDatabase() when the user is authenticated. Mirrors the
existing 'beforeunload' handler pattern.
2. trackAuthCall stores no log details (src/lib/supabase.ts)
- The function incremented authCallCount but created a timestamp variable
it never used and pushed nothing to dbCallLog, making auth call
debugging impossible.
- Complete the implementation to match trackDbCall: push a log entry to
dbCallLog with timestamp, operation, and stack-derived source.
3. data.tasks crash on malformed localStorage record (localStorageService.ts)
- getCurrentDay() called data.tasks.map() without a null guard. When a
stored record is missing the tasks field the call throws and the outer
try-catch silently swallows the entire day, returning null.
- Replace with (data.tasks ?? []).map() so a missing field produces an
empty task list instead of an exception.
https://claude.ai/code/session_012AmNjF3Ju9VJwSWybJqBEw
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR refactors the monolithic
dataService.tsfile by extracting service implementations and utility functions into separate, focused modules. The changes improve code organization, maintainability, and reusability without altering functionality.Key Changes
Service Layer Refactoring
dataService.ts: ExtractedLocalStorageServiceandSupabaseServiceimplementations into dedicated files (localStorageService.tsandsupabaseService.ts)dataService.tsnow serves as a clean interface/facade, exporting only theDataServiceinterface andCurrentDayDatatypeUtility Function Extraction
Created
calculationUtils.ts: Extracted calculation functions for hours and revenue:getHoursWorkedForDay()getRevenueForDay()getBillableHoursForDay()getNonBillableHoursForDay()getTotalHoursForPeriod()getRevenueForPeriod()Created
exportUtils.ts: Extracted export and invoice generation functions:exportToCSV()exportToJSON()generateInvoiceData()parseCSVImport()Component Refactoring
TaskEditInArchiveDialog: Moved fromArchiveEditDialog.tsxto its own component file for better separation of concernsArchiveEditDialog.tsxnow imports the extracted componentContext Updates
TimeTrackingContext.tsx: Refactored to use extracted utility functions instead of inline implementationsImplementation Details
localStorageService.tsfor centralized managementhttps://claude.ai/code/session_012AmNjF3Ju9VJwSWybJqBEw