Skip to content

Repository files navigation

applog

An application logger tool to track job applications using a simple interface with filtering, status updates, and email notifications. Can be upgraded to scrape job listings and automate the workflow.


Implementation Status

1. User Interface

  • Design & Layout
    • Modern, minimal interface in beige/white color palette with dark grey text
    • Full dark mode support with theme-aware colors (light/dark modes fully functional)
    • Main layout with search bar (fully functional)
    • Job list/cards display with hover effects
    • Total applications counter displayed on main page
    • Sort jobs by latest/newest first on main screen (by application_date DESC)
  • Search & Filtering
    • Search field (main field, across the screen)
    • Filter sidebar with dropdowns (company, status, location)
    • Hide inactive job statuses (Rejected, Withdrawn, No Response) by default from main screen
    • Display filtered count in applications counter (shows "X of Y applications")
    • Add option to filter by location in the search bar
    • Location dropdown with "Other" option for zero-typing job creation (Phase 3 - ROADMAP.md ✅)
  • Forms & Input
    • Add job form (separate page at /add-job with all fields)
    • Vertically expandable text fields for description and notes
    • Job detail page with "View Details" navigation
    • Status editing from job detail page (click "Edit" button next to status badge)
    • Delete job from job detail page with confirmation dialog
    • Edit/delete buttons on job cards
    • Optional field to store apartment offer links (multiple links with '+ Add link' UI)
    • Edit job details functionality (Issue #3)
  • Note History & Timeline
    • Vertical timeline display showing timestamped notes
    • Notes sorted in reverse chronological order (newest first)
    • Timestamps formatted as DD/MM/YYYY HH:mm for readability
    • "Add Note" form on job detail page
    • Note count indicator on job cards
    • Automatic timestamp capture for each note
  • Date & Value Formatting
    • Application dates displayed as DD/MM/YYYY on main page and detail page
    • Note timestamps displayed as DD/MM/YYYY HH:mm
    • Salary values formatted with K suffix (e.g., "120K" instead of "120000")
  • Note Templates
    • Templates Management page (/templates route)
    • Create, edit, and delete reusable note templates
    • Real-time search by template name or content
    • Template selector in job detail page with search
    • Hover tooltips showing full template content
    • Click to insert template into note textarea (non-destructive)
    • "View All Templates" dialog
    • Auto-clear success messages after 3 seconds
    • Settings icon link to Templates Management page
    • Handle note templates in job creation form (Issue #2)
      • Decision needed: Add template selector to creation form OR remove notes field from creation entirely

2. Core Application Logic

Data Management

  • CRUD Operations - job_service.py
    • Create job applications
    • Read by ID and URL
    • Update with partial or full field changes
    • Delete job applications
    • Add timestamped notes to existing applications
  • Validation & Data Integrity
    • Field validation (empty dict, invalid field names)
    • Atomic updates (all-or-nothing, no partial updates)
    • Transaction rollback on failures
    • Notes field migrated to JSON with automatic timestamp capture
    • Explicitly track job_url field presence (not just rely on SQLAlchemy NOT NULL)

Duplicate Prevention

  • Exact Duplicate Detection
    • Check for existing job_url (reject if already exists)
  • Similar Job Detection
    • Detect same job from different sources (LinkedIn, Indeed, company site)
    • Match criteria: company_name + job_title + location + different URL domain
    • Prompt user confirmation via UI layer before creating similar entry

Search & Discovery

  • Search Functionality
    • Full-text search across company, title, and description
  • Filtering System
    • Filter by company, status, and location

Tracking Features

  • Automatic Data Capture
    • Capture created date (created_at timestamp)
    • Automatically assign "Applied" status on creation
    • Track updated date (updated_at timestamp)
  • Location-Based Tracking
    • Track region of each job listing to align with apartment renting search

Note Templates

  • Template CRUD Operations - template_service.py
    • Create reusable note templates
    • Read templates by ID
    • Get all templates ordered by name
    • Search templates by name or content (case-insensitive)
    • Update existing templates
    • Delete templates
  • Template Validation
    • Require name and content fields
    • Field validation (empty dict, invalid field names)
    • Transaction rollback on failures

3. Database

  • Implementation
    • SQLite database (single-user, local storage)
    • SQLAlchemy ORM models and configuration
    • Notes field as JSON column storing timestamped note entries
  • Schema Enhancements
    • Convert salary_range field from string to tuple(int, int) or separate min/max columns
    • Extract and store keywords, company name, source website metadata
    • Optional: Create separate Company database table with relationships

4. Testing & Documentation

  • Unit Tests (49 tests with comprehensive coverage - all passing)
    • Job Service Tests (31 tests)
      • Create: duplicate detection, validation, empty data, rollback handling
      • Read: by ID and URL, valid/invalid cases, edge cases
      • Update: field validation, partial updates, nonexistent IDs, rollback
      • Delete: success/failure scenarios, rollback
      • Notes: add_note functionality, append to existing notes, edge cases
    • Template Service Tests (18 tests)
      • Create: validation, missing fields, empty data, rollback
      • Read: by ID, get all templates, search by name/content
      • Update: field validation, empty dict, nonexistent IDs
      • Delete: success/failure scenarios
  • Integration Tests
    • Search/filter functionality tests
    • Form submission end-to-end tests
  • Documentation
    • Usage documentation

5. Code Quality & Refactoring

  • Component Organization (✅ Complete - Branch: refactor/component-extraction)
    • Create applog/components/ directory structure
      • components/jobs/ - Job-related components
      • components/shared/ - Shared/reusable components
      • components/main/ - Main page components
      • components/templates/ - Template management components
    • Extract reusable UI components from applog.py (✅ 100% complete - App runs successfully!)
      • Job card component → jobs/job_card.py (with visual docstrings)
      • Job detail page → jobs/job_detail.py (877 lines, ~50 functions, with visual docstrings)
      • Add job form → jobs/add_job.py (with visual docstrings)
      • Note timeline → jobs/notes.py (with visual docstrings)
      • Filter sidebar → shared/sidebar.py (with visual docstrings)
      • Status badge → shared/status_badge.py (with visual docstrings)
      • Search bar → shared/search_bar.py (with visual docstrings)
      • Formatters → shared/formatters.py (date formatting utilities)
      • Job list wrapper → jobs/job_list.py (with visual docstrings)
      • Main index page → main/index_page.py (with visual docstrings)
      • Templates page → templates/template_form.py + templates/template_list.py (with visual docstrings)
    • Code Quality Improvements
      • Naming convention: _button_* prefix for all buttons (type-first organization)
      • Naming convention: _formatting_* prefix for all styling dictionaries
      • Visual docstrings added to all component functions (emoji + description + visual example)
      • Component organization documented in LESSONS.md (type vs. domain strategies)
    • Module Integration (✅ Complete)
      • Configured __init__.py files for proper module exports
      • Fixed import patterns (direct function calls vs. module.function access)
      • Created page wrapper functions in applog.py for state injection
      • Cleared stale bytecode cache and resolved import errors
    • Refactoring Complete!
      • All pages extracted into component modules
      • Visual docstrings added to all functions
      • Proper module exports via __init__.py files
      • Consistent naming conventions throughout
      • Full integration testing of all features (recommended before merge)
      • Optional: Split large files into sub-modules if needed (only if files exceed 500 lines)

6. Future Services (v2+)

  • Email Notifications
    • Create email notifications after a certain period of time
    • Email response parsing to update job status automatically
    • Batch check on next run if service was offline
  • URL Scraping
    • Auto-extract job details from posting URLs
  • Advanced Features
    • Authentication (if multi-user support needed)
    • Web hosting deployment
    • Company database with historical tracking
  • Security
    • SQL injection protection (SQLAlchemy parameterized queries handle automatically)
    • Input validation for URL formats
    • Rate limiting (if deployed publicly)

Project Architecture

Tech Stack

  • Frontend: Reflex (pure Python framework that compiles to React)
  • Backend: Python with SQLAlchemy ORM
  • Database: SQLite (single-user, local storage)
  • Testing: pytest with 49 comprehensive tests (all passing)
  • Deployment: Local development server only

Database Schema

JobApplication Table:

  • id - Primary key
  • company_name - Company name (indexed)
  • job_title - Position title
  • job_url - Job posting URL (unique, for duplicate detection)
  • location - Job location (indexed)
  • description - Job description text
  • status - Application status (indexed)
    • Options: Applied, Screening, Interview, Offer, Rejected, Accepted, Withdrawn, No Response
  • application_date - Date applied
  • salary_range - Salary range (optional, string format)
  • notes - JSON array of timestamped note entries: [{"timestamp": "ISO-8601", "note": "text"}, ...]
  • created_at - Record creation timestamp
  • updated_at - Record update timestamp

NoteTemplate Table:

  • id - Primary key
  • name - Template name (indexed)
  • content - Template text content
  • created_at - Template creation timestamp
  • updated_at - Template update timestamp

Component Organization

Current Approach: Hybrid Naming Convention

The project uses a hybrid naming convention that balances type-based and domain-based organization for components in single files:

Type-First Prefixes (for component kind):

  • _button_* - All button components (e.g., _button_save, _button_cancel)
  • _formatting_* - All styling dictionaries (e.g., _formatting_card, _formatting_dialog)
  • _grid_* - Grid row components
  • _section_* - Major page sections

Domain-First Prefixes (for features):

  • _template_* - Template system components
  • _note_* - Note management components
  • _job_* - Job-related components

Why This Works:

  • Enables both access patterns: "find all buttons" (_button_*) AND "find all template components" (_template_*)
  • Works well with IDE search (Cmd+T / Cmd+Shift+O in VSCode)
  • Scales up to ~100 components per file
  • No tooling overhead required

Example:

# Type-based grouping
_button_save          # Easy to find all buttons
_button_cancel
_button_template_insert

# Domain-based grouping
_template_selector_list   # Easy to find all template components
_template_search_input
_template_settings_tooltip

File Organization (Current)

applog/
├── components/
│   ├── jobs/
│   │   ├── __init__.py        # Module exports
│   │   ├── job_card.py        # Job card display (~120 lines)
│   │   ├── job_detail.py      # Job detail page (~877 lines, 50+ functions)
│   │   ├── add_job.py         # Add job form (~340 lines)
│   │   ├── job_list.py        # Job list wrapper component (~30 lines)
│   │   └── notes.py           # Note timeline components
│   ├── shared/
│   │   ├── __init__.py        # Module exports
│   │   ├── sidebar.py         # Filter sidebar
│   │   ├── search_bar.py      # Search bar component
│   │   ├── status_badge.py    # Status badge component
│   │   └── formatters.py      # Date/currency formatting utilities
│   ├── main/
│   │   ├── __init__.py        # Module exports
│   │   └── index_page.py      # Main index page layout (~160 lines)
│   └── templates/
│       ├── __init__.py        # Module exports
│       ├── template_form.py   # Template form components (~220 lines)
│       └── template_list.py   # Template list display (~252 lines)
├── applog.py                  # Main app (State + page assembly, ~530 lines)
├── models/                    # Database models
│   ├── job_application.py
│   └── note_template.py
├── services/                  # Business logic layer
│   ├── job_service.py
│   └── template_service.py
└── database.py                # Database initialization

Future: Directory Structure (100+ Components)

When the project grows beyond ~100 components, the plan is to reorganize into:

components/
├── jobs/
│   ├── detail/
│   │   ├── buttons.py      # All detail page buttons
│   │   ├── forms.py        # All form components
│   │   ├── dialogs.py      # Dialog components
│   │   └── __init__.py     # Barrel exports (dual access patterns)
│   ├── list/
│   │   ├── cards.py
│   │   └── filters.py
│   └── __init__.py
├── shared/
│   ├── buttons.py          # Shared button components
│   ├── inputs.py
│   └── status_badge.py
└── templates/
    ├── form.py
    └── list.py

Barrel Export Pattern (in __init__.py):

# Feature-domain exports (primary)
from .buttons import button_save, button_cancel, button_edit

# Component-type grouped exports (for refactoring)
__all_buttons__ = [button_save, button_cancel, button_edit]
__all_forms__ = [...]

This provides:

  • Feature-domain imports: from components.jobs.detail import button_save
  • Type-based refactoring: from components.jobs.detail import __all_buttons__

Design Philosophy

The Trade-off: You cannot optimize for both type-based AND domain-based access with a single hierarchy. The hybrid naming convention is a pragmatic compromise that works well for small-to-medium projects.

Scaling Path:

  1. < 100 components: Hybrid naming in flat files ✅ (current)
  2. 100-500 components: Directory structure + barrel exports (planned)
  3. 500+ components: Add component catalog + Storybook (future)

Key Principle: Don't over-engineer early. The current approach is optimal for the project's scale.

Full Details: See LESSONS_LEARNED.md "Component Organization" section for the complete analysis of type vs. domain trade-offs, barrel export examples, and production best practices.


Application Flow

Current MVP Flow

  1. Add Job: User navigates to /add-job and fills out the form with job details
  2. Data Storage: Job application is saved to SQLite database with automatic timestamp and "Applied" status
  3. View Jobs: Main page displays all applications with search/filter capabilities
    • Total applications counter displayed under "Add Job" button
    • "Templates" button for quick access to template management
    • Dates formatted as DD/MM/YYYY for easy reading
    • Salary values formatted with K suffix
    • Filter by company, status, or location
  4. View Details: Click "View Details" on any job card to see full information
  5. Edit Status: From job detail page, click "Edit" next to status badge to update application status
  6. Track Progress: Add timestamped notes to track application progress (emails, interviews, etc.)
    • Use template selector to quickly insert common note text
    • Search templates by name or content
    • Hover over templates to preview full content
    • Click template to insert into note textarea (non-destructive)
    • "View All" button to see all templates in a dialog
    • Settings icon to manage templates
  7. Note History: View vertical timeline of all notes with automatic timestamps
    • Notes displayed newest first (reverse chronological)
    • Timestamps formatted as DD/MM/YYYY HH:mm
  8. Delete Job: From job detail page, click "Delete Job Application" button at bottom with confirmation dialog
  9. Manage Templates: Navigate to /templates to create, edit, search, and delete note templates
    • Create reusable note templates with name and content
    • Real-time search across template names and content
    • Edit existing templates
    • Delete templates with confirmation
    • Success messages auto-clear after 3 seconds

Pages

  • / - Main dashboard with job list, search, filters, application counter, and Templates navigation button
  • /add-job - Add new job application form (wired to database)
  • /job/[id] - Job detail page with note history, status editing, add note with template selector, and delete job functionality
  • /templates - Templates Management page for creating, editing, searching, and deleting note templates

Roadmap

See ROADMAP.md for detailed upcoming features and implementation plan.

Phase 1: Complete ✅

  • ✅ Reset edit mode on page exit
  • ✅ Smart cancel with confirmation dialog
  • ✅ Auto-populate application date to today

Phase 2: Complete ✅

  • ✅ Sort jobs by application date (newest first)
  • ✅ Hide inactive job statuses by default
  • ✅ Filter-aware application counter (shows "X of Y")
  • ✅ Remove notes field from job creation (commented out for potential future re-add)

Phase 3: Complete ✅

  • ✅ Location dropdown with "Other" option (zero-typing for 5 common locations)

Coming Soon:

  • Full job editing capability (Phase 4)

About

An application logger tool. The purpose is to track my applications and display them using a simple interface that offers filtering, status updates, email notifications. Later can be upgraded to also scrape for job listings which can automate the whole flow.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages