Skip to content

Duplicate Code: Identical EmptyCard and InitialCard Widgets #38

@github-actions

Description

@github-actions

Analysis of commit eaf30ea

Summary

Two nearly identical widget components (EmptyCard and InitialCard) exist in the codebase with the exact same structure and implementation. Both widgets create an empty centered column with no content, differing only in their class names.

Duplication Details

Pattern: Identical Widget Components

  • Severity: High
  • Occurrences: 2 instances
  • Locations:
    • lib/ui/widgets/empty_card.dart (lines 3-17)
    • lib/ui/widgets/initial_card.dart (lines 3-17)

Code Sample from EmptyCard:

class EmptyCard extends StatelessWidget {
  const EmptyCard({
    Key? key,
  }) : super(key: key);

  `@override`
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: const [],
      ),
    );
  }
}

Code Sample from InitialCard:

class InitialCard extends StatelessWidget {
  const InitialCard({
    Key? key,
  }) : super(key: key);

  `@override`
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: const [],
      ),
    );
  }
}

Impact Analysis

  • Maintainability: Any changes to the empty state UI need to be duplicated across both files, increasing maintenance burden and risk of inconsistencies.
  • Bug Risk: If one component is updated but not the other, it creates inconsistent user experiences between loading and empty states.
  • Code Bloat: 34 lines of duplicated code that provide identical functionality with different names.

Refactoring Recommendations

Option 1: Merge into Single Parameterized Component (Recommended)

Extract to a unified widget that can handle both loading and empty states:

Estimated effort: 30 minutes
Benefits:

  • Single source of truth for empty state UI
  • Easier to maintain and update
  • Reduces codebase size
  • Future flexibility to add state-specific content

Implementation:

// lib/ui/widgets/empty_state_card.dart
class EmptyStateCard extends StatelessWidget {
  const EmptyStateCard({
    Key? key,
    this.child,
  }) : super(key: key);
  
  final Widget? child;

  `@override`
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: child != null ? [child!] : const [],
      ),
    );
  }
}

Then update lib/ui/pages/home.dart:

  • Replace const InitialCard() with const EmptyStateCard(child: CircularProgressIndicator())
  • Replace const EmptyCard() with const EmptyStateCard()

Option 2: Use One Component, Delete the Other

Simply use EmptyCard for both cases and delete InitialCard:

Estimated effort: 15 minutes
Benefits:

  • Immediate reduction in duplication
  • Simplest solution

Implementation:

  • Update lib/ui/pages/home.dart line 75 to use EmptyCard() instead of InitialCard()
  • Delete lib/ui/widgets/initial_card.dart
  • Remove export from lib/ui/widgets/widgets.dart

Implementation Checklist

  • Review duplication findings
  • Decide between Option 1 (parameterized component) or Option 2 (reuse existing)
  • Implement chosen refactoring approach
  • Update imports in home.dart
  • Remove unused widget file
  • Update widgets.dart exports
  • Run tests to verify no functionality broken
  • Verify UI displays correctly for both loading and empty states

Analysis Metadata

  • Analyzed Files: 28 Dart files (excluding tests and generated files)
  • Detection Method: Static code analysis and pattern matching
  • Commit: eaf30ea
  • Analysis Date: 2026-02-17

AI generated by Duplicate Code Detector

To add this workflow in your repository, run gh aw add github/gh-aw/.github/workflows/duplicate-code-detector.md@94662b1dee8ce96c876ba9f33b3ab8be32de82a4. See usage guide.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions