Skip to main content

Documentation Index

Fetch the complete documentation index at: https://grantmaster.dev/llms.txt

Use this file to discover all available pages before exploring further.

Engineering reference: For service contracts, EventBus events, and data-layer details see src/features/journals/journals.md.

Journals

Overview

The journals feature provides time-tracking and time-off management for team members in GrantMaster. Employees submit daily journal entries documenting hours worked on projects, with optional entries for leave (vacation, sick, parental, study). Managers review and approve submissions, and the system supports auto-approval workflows based on organization rules. Additionally, the journal submission workflow allows comprehensive monthly reflection with AI-assisted entry generation and manager validation. Key characteristics:
  • Dual entry types: daily work logs and journal submissions
  • Approval workflows for compliance and audit trails
  • Auto-approval rules (optional per organization)
  • Locking mechanism to prevent editing after approval
  • EventBus integration for notifications (internal dispatcher) and audit logging
Firestore collection: journals (legacy name; contains JournalEntry documents) Monthly submissions collection: journalSubmissions (contains JournalSubmission documents)

Page Organization

The journals feature spans two separate pages, each with their own PageDef in src/features/journals/pages.config.ts:

Journaling Page (/journaling/:tab)

TabValuePermissionDescription
Daily Logdaily-logSUBMIT_JOURNAL_SUBMISSIONCalendar grid for creating and reviewing daily entries
My Submissionsmy-submissionsSUBMIT_JOURNAL_SUBMISSIONUser’s journal submission history and drafts
Team Feedteam-feedCross-team activity feed
InsightsinsightsAnalytics and time-tracking insights
AI-first features include cross-document RAG for context-aware journal generation, calendar/activity sync, and compliance-first entry generation.

Timesheets Page (/timesheet/:tab)

TabValueDescription
Weekly Matrixweekly-matrix7-day × projects grid editor for structured time entry
SubmissionssubmissionsSubmission tracking and history
ApprovalsapprovalsManager approval queue for timesheet entries
ReportsreportsTimesheet reports and exports
The Timesheets page provides a structured, spreadsheet-like interface for time entry, separate from the narrative-focused Journaling page.

Data Model

Firestore Collections

CollectionDocument TypeDescription
journalsJournalEntryDaily journal entries (work logs, leave). Organized by date and user. Includes status (pending → submitted → approved/rejected) and locking for audit.
journalSubmissionsJournalSubmissionJournal submissions. Parent doc; contains subcollection history for edit audit trail.
journalSubmissions/{id}/historyJournalSubmissionHistoryImmutable audit log of changes to a monthly submission (draft, submitted, approved, rejected, edited).

Key TypeScript Types

JournalEntry (src/schemas/journals.schema.ts)
  • Core fields: id, userId, userName, date, projectId, projectName, hours, activityType, description, organizationId
  • Status: 'pending', 'submitted', 'approved', 'rejected'
  • Controls: isLocked (prevents editing after approval), isEdited (tracks manager edits)
  • Audit: auditFlag (severity), auditMessage, createdAt, updatedAt, submittedAt
  • Leave: entryType (‘work’, ‘vacation’, ‘sick_leave’, ‘parental_leave’, ‘study_leave’), leaveDetails
  • Approval: approvedBy, approvedAt, approvalComment, rejectedBy, rejectedAt, rejectionReason
  • NGO: volunteerId, volunteerName, isVolunteerTime, inKindValue (market value of volunteer hours)
JournalSubmission (src/schemas/journals.schema.ts)
  • Core: id, organizationId, userId, userName, month (YYYY-MM format)
  • Status: JournalSubmissionStatus enum: DRAFT, SUBMITTED, APPROVED, REJECTED, ESCALATED
  • Workflow: submittedAt, submittedBy, reviewedAt, reviewedBy, reviewerComment, escalatedAt, escalationReason
  • Content: input (user-provided narrative), generatedEntries (AI-generated journal entries)
  • Validation: validationFeedback[], isValid
  • Audit: version, createdAt, lastModifiedAt, aiGenerationMetadata
  • Compliance: complianceScore (auto-calculated)

Key Behaviors

Daily Journal Workflow

  1. Entry Creation:
    • User creates a journal entry via calendar grid, weekly matrix, or manual entry form
    • Entry defaults to status: 'pending', isLocked: false
    • Each entry is auto-saved via journalService.saveEntries() (batch operation)
  2. Submission:
    • User submits batch of entries → journalService.submitJournals()
    • System checks organization’s auto-approval rules
    • Auto-approve path: If daily hours ≤ threshold, no excluded projects, description meets requirements → status becomes 'approved', locked
    • Manual approval path: Otherwise → status becomes 'submitted', awaiting manager review
    • Event emitted: JOURNAL_SUBMITTED (notifies manager via internal notification system) or JOURNAL_APPROVED (if auto-approved)
  3. Manager Review:
    • Manager dashboard displays pending submissions grouped by employee
    • Approve: journalService.approveJournals()status: 'approved', isLocked: true, event JOURNAL_APPROVED
    • Reject: journalService.rejectJournals()status: 'rejected', isLocked: false, event JOURNAL_REJECTED with reason
    • Optionally add comment
  4. Locking & Audit:
    • Approved entries are locked (isLocked: true) and cannot be edited
    • Rejected entries are unlocked and returned for revision
    • All status changes logged to audit trail

Journal Submission Workflow

  1. Draft Creation:
    • User navigates to the journal submission wizard
    • Completes interview form (JournalInput) with narrative questions
    • Save as draft → journalWorkflowService.saveDraft(), status DRAFT
    • Auto-drafts are stored; user can return to edit
  2. AI Generation:
    • User submits draft for AI processing
    • Genkit generates daily entries from narrative via useJournalGeneration hook
    • Entries are validated against compliance rules (compliance score calculated)
    • User reviews generated entries and validation feedback
    • Can edit/delete individual entries before final submission
  3. Submission:
    • User submits → journalWorkflowService.submitJournal()
    • Status changes to SUBMITTED
    • Event JOURNAL_SUBMITTED notifies manager
    • Entries are marked isLocked: false (still editable by manager if needed)
  4. Manager Approval/Rejection:
    • Manager reviews submission on dashboard
    • Approve: journalWorkflowService.approveJournal()APPROVED, generated entries locked
    • Reject: journalWorkflowService.rejectJournal()REJECTED, entries remain unlocked for revision
    • Manager can edit individual entries; changes logged to history subcollection
  5. Audit Trail:
    • All changes (draft, edit, submit, approve, reject) immutably logged in history subcollection
    • Each change record includes: timestamp, actor, change type, modified fields, optional comment

Service Contract

ServiceOwnsKey Methods
JournalServiceDaily journal CRUD, approval workflow, lockingcreateJournal(), updateJournal(), deleteJournal(), getJournalsPaginated(), submitJournals(), approveJournals(), rejectJournals(), lockJournals(), saveEntries()
JournalWorkflowServiceJournal submission CRUD, journal submission workflow, history auditingsaveDraft(), loadDraft(), listDrafts(), deleteDraft(), submitJournal(), loadSubmission(), listSubmissions(), approveJournal(), rejectJournal(), updateEntry(), deleteEntry(), fetchJournalHistory()
journalEventServiceEvent emission for approval workflowsemitJournalSubmittedEvent(), emitJournalApprovedEvent(), emitJournalRejectedEvent(), toJournalEventRecord(), toJournalEventRecordFromEntry()
JournalContextLegacy bridge to new tRPC hooks; filters and selectorsuseJournals(), useJournal(), useJournalsByUser(), useJournalsByProject(), usePendingJournals(), useApprovedJournals(), useLockedJournals() + date-range selectors
Note: JournalService and JournalWorkflowService both extend BaseService, providing error handling, validation, audit logging, and infrastructure dependency injection.

Events

Emitted

EventTriggerSeverityPersistedPayload
JOURNAL_SUBMITTEDUser submits a daily journal or journal submission for approvalINFOYesjournalId, employeeId, employeeName, projectId, projectName, hours, date, managerId (optional)
JOURNAL_APPROVEDManager or auto-approval system approves journalINFOYesjournalId, employeeId, employeeName, projectId, projectName, hours, approvedBy, approvedByName, approvedAt
JOURNAL_REJECTEDManager rejects journal (daily or monthly)WARNINGYesjournalId, employeeId, employeeName, projectId, projectName, hours, rejectedBy, rejectedByName, rejectedAt, reason
All events routed via EventBus → persisted to systemEvents collection → listeners (internal event subscribers) notify managers and employees.

Consumed

  • Internal notification subscribers: Subscribe to JOURNAL_SUBMITTED, JOURNAL_APPROVED, JOURNAL_REJECTED to trigger in-app and email notifications
  • Audit/compliance handlers: May subscribe to approval events for reporting

Dependencies

Internal:
  • @/core/BaseService — base class for CRUD and validation
  • @/core/eventBus — EventBus for approval/rejection notifications
  • @/core/firebase — Firestore instance
  • @/core/firestoreCollections — collection path utilities
  • @/features/compliance/services/journalComplianceService — compliance scoring for journal submissions
  • @/features/ai/services/ragService (via useJournalGeneration) — AI generation of daily entries
External:
  • Firebase (Firestore, Auth)
  • Internal notification system (src/features/notifications/)
  • Sentry (error reporting)

File Structure

src/features/journals/
├── JournalContext.tsx                  # Legacy context bridge; provides useJournals(), selectors
├── JournalGenerationContext.tsx        # Context for AI generation state (useJournalGeneration hook)
├── index.ts                            # Public API barrel export
├── public.ts                           # (Appears unused; may be legacy)
├── services/
│   ├── JournalService.ts               # Daily journal CRUD, approval workflow, locking
│   ├── JournalService.test.ts
│   ├── journalWorkflowService.ts        # Journal submission CRUD and workflow
│   ├── journalWorkflowService.test.ts
│   ├── journalEventService.ts          # Event emission helpers (JOURNAL_SUBMITTED, JOURNAL_APPROVED, JOURNAL_REJECTED)
│   ├── journalSubmissionService.ts     # (May be deprecated; check usage)
│   ├── timerEntryService.ts            # Active timer state (in-progress time tracking)
│   ├── timerService.ts                 # Timer start/stop/track logic
│   ├── bulkApprovalService.ts          # Batch approval operations
│   └── bulkJournalApprovalService.ts   # (Possible alternate; check overlap)
├── hooks/
│   ├── useJournals.ts                  # tRPC hook for fetching/filtering journal entries
│   ├── useJournalGeneration.ts         # Hook wrapping AI generation (Genkit integration)
│   └── usePendingApprovalsCount.ts     # Count of pending submissions for manager dashboard
├── components/
│   ├── JournalDetailsModal.tsx          # Modal for viewing/editing a single entry
│   ├── JournalHistory.tsx               # Audit trail display + PDF export
│   ├── JournalPreview.tsx               # Compact entry preview card
│   ├── TraditionalJournalModal.tsx      # Modal for manual daily entry creation
│   ├── journal/
│   │   ├── AuditPanel.tsx               # Displays audit flags/compliance warnings
│   │   ├── CalendarGrid.tsx             # Month-view calendar entry editor
│   │   ├── EntryList.tsx                # Table of daily entries with filters
│   │   └── WeeklyMatrix.tsx             # Week-view grid editor (7 days × projects)
│   ├── journalSubmission/
│   │   ├── ActivityPreviewCard.tsx      # Card showing generated entry from AI
│   │   ├── DraftsList.tsx               # List of draft journal submissions
│   │   ├── EditEntryModal.tsx           # Employee edits AI-generated entry
│   │   ├── ManagerEditEntryModal.tsx    # Manager edits/reviews entry post-approval
│   │   ├── SubmissionHistory.tsx        # Change log (version, actor, timestamp)
│   │   └── ValidationPanel.tsx          # Shows validation feedback & compliance score
│   ├── pages/
│   │   ├── ManagerReviewDashboard.tsx   # Manager's approval interface
│   │   ├── JournalReview.tsx      # (Appears related to journal review; check overlap with Dashboard)
│   │   ├── JournalSubmissions.tsx           # Journal submission list/navigation page
│   │   └── Wizard.tsx                   # Multi-step form for journal submission input
│   └── pdf/
│       └── JournalPDF.tsx               # Renders journal entries as PDF
└── README.md                            # Original README (may be outdated)

Naming Gotchas

⚠️ Firestore collection names differ from feature terminology:
  • Firestore collection: journals (legacy; never rename) Code terminology: JournalEntry, “journals feature”
  • Firestore collection: journalSubmissions (legacy; never rename) Code terminology: JournalSubmission, “journal submissions”
  • Firestore subcollection: history (audit log) Code terminology: JournalSubmissionHistory
Why: Early-stage naming preserved for backward compatibility; collection renames would break production data.

Integration Notes

  • Status transitions: pendingsubmitted (user action) → approved/rejected (manager action). Rejected journals are unlocked and re-enter pending.
  • Locking: Set by lockJournals() when approved; enforced at update/delete time via business rule check.
  • Auto-approval: Configured in Organization.autoApprovalRules.journals (max daily hours, excluded projects, description length).
  • AI generation: Triggered via useJournalGeneration hook; uses Genkit to expand narrative into structured daily entries.
  • Compliance scoring: journalWorkflowService.updateWithGeneratedEntries() auto-calculates compliance score against organization rules.
  • Audit trail: All events persisted to systemEvents collection; journal submissions have immutable history subcollection per submission.