Skip to main content

shared_component 1.4.6+66.9 copy "shared_component: ^1.4.6+66.9" to clipboard
shared_component: ^1.4.6+66.9 copied to clipboard

A Flutter package that provides utilities for managing generic widgets for all modules.

simpliWORKS™ Shared Component Framework #

The shared_component package is the foundational enterprise UI toolkit and utility layer for the multi-module simpliWORKS™ ERP suite (spanning CRM, Expense, Store, Deliver, Finance, Master, Recycle, Resolve, and future modules).


1. Overview & Architectural Philosophy #

The primary objective of shared_component is to deliver:

  • Maximum Reuse: High-quality, robust components shared seamlessly across business domains.
  • Visual & Behavioral Consistency: Unified typography, spacing, styling, animations, and micro-interactions.
  • Maintainability & Testability: Single-point bug fixes and standardized test coverage across all ERP modules.
  • Zero Module Coupling: shared_component has zero dependencies on business modules.
┌─────────────────────────────────────────────────────────────────────────────┐
│                       simpliWORKS™ ERP Modules                              │
│   (CRM, Expense, Deliver, Store, Finance, Master, Recycle, Resolve, etc.)  │
└──────────────────────────────────────┬──────────────────────────────────────┘
                                       │ (Depends Strictly One-Way)
                                       ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                   package:shared_component                                  │
│   ├── Widgets (Buttons, Cards, Dialogs, Dropdowns, Feedback, Form, Layout)  │
│   ├── Controllers (Theme, Font, Session, Security, Role, Dropdowns)         │
│   ├── Utilities (Toast, Export, Validation, Numbers, Dates, Storage)        │
│   ├── Monitoring & Telemetry (ApiInterceptor, ErrorTracker, Dashboard)      │
│   └── Theming & Localization                                                │
└─────────────────────────────────────────────────────────────────────────────┘

Important

Core Principle: Share what is genuinely common. Keep what is genuinely module-specific.
shared_component is NOT a dumping ground. Screen reuse inside a single module does not warrant global sharing. Never place module-specific business workflows or hard-coded domain logic into this package.


2. Directory Structure #

shared_component/lib/
├── auth_middleware/          # Routing & session authentication guards
├── bindings/                 # Initial GetX bindings (Login, Preferences)
├── charts/                   # Syncfusion chart implementations (Bar, Line, Spline, Pie)
├── controllers/              # Shared GetX controllers (Session, Theme, Security, Role)
├── custom_plugins/           # In-tree vendored plugin forks (PlutoGrid, DropdownSearch)
├── data/                     # Core generic DTO models (BaseModel, DropdownModel, UploadModel)
├── data_source/              # Weighbridge & unloading data sources (Protected domain)
├── datagrid/                 # Reusable PlutoGrid and TrinaGrid wrappers
├── dependency/               # Global dependency injection container (GetIt setup)
├── gen/                      # Auto-generated asset and font bindings
├── localization/             # Multi-language translation dictionaries & services
├── monitoring/               # Error tracking, UI route observing & telemetry dashboard
├── network/                  # Dio HTTP client, interceptors & platform adapters
├── routes/                   # Platform navigation factories & route registries
├── services/                 # Device and background services (Location, File, Download)
├── theme/                    # AppTheme definition, dynamic styling & ThemeService
├── ui/                       # Full shared screen flows (Auth, Preferences, Address, Downloads)
├── utils/                    # Pure formatters, validators, extensions, enums & constants
│   ├── app_extensions/       # Extensions on String, DateTime, BuildContext, Color, etc.
│   └── enums/                # Centralized enums (Appearance, Clients, Modules, etc.)
└── widgets/                  # All reusable UI widgets categorized by single responsibility
    ├── buttons/              # AppButton, AppButton2, AppIconButton, AppBulkActionBar
    ├── cards/                # AppCard, AppSummaryCard, AppPropertyGrid, AppModernTile
    ├── dialogs/              # GenericDialogBox, ConfirmDialogBox, RoleManagerDialog
    ├── dropdown/             # AppDropdown<T>, AppMultiSelectDropdown<T>, CustomDropdownSingle
    ├── feedback/             # LoadingIndicator, NoPermissionAvailable, NotFoundPage
    ├── filters/              # AppFilterPanel
    ├── form/                 # AppTextFieldFormWidget, AppCheckBox, AppSwitch, AppRadioButton
    ├── hardware/             # BoomBarrier, InternalWeighing, OpenGate (Protected domain)
    ├── header/               # Header, HeaderWidget, AppWebHeader, Footer
    ├── images/               # AppNetworkImage, AppSvgViewer, AppProfileImage
    ├── layout/               # AppScaffold, AppContainer, ResponsiveLayout
    ├── misc/                 # AppTimelineWidget, AppGoogleMap
    ├── navigation/           # SidebarXDrawer, AllAppsDrawer, EventsDrawer
    ├── pickers/              # AppMediaPicker, AppDatePicker, FilePickerWidget
    └── security/             # SecurityLockWidget, PermissionWrapperWidget

3. Public API & Single-Import Pattern #

Downstream ERP modules must import the shared toolkit using the unified barrel imports:

// ✅ Primary import for all widgets, layouts, and core utilities
import 'package:shared_component/shared_component.dart';

// ✅ Optional lightweight import for pure utilities, formatters, and enums
import 'package:shared_component/utils/utils.dart';

4. Component Catalog & Quick Reference #

Category Component File Path Purpose & Best Use Case
Dropdowns AppDropdown<T> lib/widgets/dropdown/app_dropdown.dart Strongly-typed single select with instant search, async pagination & add-new.
Dropdowns AppMultiSelectDropdown<T> lib/widgets/dropdown/app_multi_select_dropdown.dart Multi-item selection with badge chips, search, and bulk select/clear.
Buttons AppButton / AppButton2 lib/widgets/buttons/app_buttons.dart Theme-aware button with built-in tap debouncing and loading state.
Buttons AppBulkActionBar lib/widgets/buttons/app_bulk_action_bar.dart Floating bulk action toolbar for multi-row data grid operations.
Forms AppTextFieldFormWidget lib/widgets/form/app_text_field_form_widget.dart Standard text input with integrated debouncing, search, and validation.
Cards AppSummaryCard lib/widgets/cards/app_summary_card.dart Responsive key-value summary widget for entity overviews.
Cards AppPropertyGrid lib/widgets/cards/app_property_grid.dart Grid of key-value pairs with built-in copy-to-clipboard actions.
Cards AppCard lib/widgets/cards/app_card_widgets.dart Theme-aware container supporting Glassmorphism and dynamic elevations.
Dialogs GenericDialogBox lib/widgets/dialogs/app_dialogs.dart Standard modal dialog with responsive sizing and primary/secondary actions.
Dialogs ConfirmDialogBox lib/widgets/dialogs/app_dialogs.dart Confirmation prompt for destructive actions (Delete, Void, Cancel).
Feedback LoadingIndicator lib/widgets/feedback/loading_indicator.dart Configurable multi-style spinner with modal barrier backdrop.
Feedback NoPermissionAvailable lib/widgets/feedback/no_permission_available.dart Standardized 403 Forbidden state with back/home navigation actions.
Feedback NotFoundPage lib/widgets/feedback/not_found_page.dart Standardized 404 Route Not Found screen.
Filters AppFilterPanel lib/widgets/filters/app_filter_panel.dart Dynamic multi-field filter panel (text, dropdown, date-range, boolean).
Grids EditablePlutoGridWidget lib/datagrid/editable_pluto_grid_widget.dart High-performance enterprise datagrid with pagination, search, and inline editing.
Pickers AppMediaPicker lib/widgets/pickers/app_media_picker.dart Web & Mobile cross-platform file/image upload with thumbnail previews.
Timeline AppTimelineWidget<T> lib/widgets/misc/app_timeline_widget.dart Responsive audit trail and status tracking (horizontal on Web, vertical on Mobile).
Layout AppScaffold lib/widgets/layout/app_layout_widgets.dart Enterprise scaffold handling SidebarX drawers, global headers, and theme padding.

5. Usage Examples #

A. Generic Single Dropdown (AppDropdown<T>) #

AppDropdown<CustomerModel>(
  hintText: 'Select Customer',
  items: controller.customers,
  selectedItem: controller.selectedCustomer.value,
  itemLabel: (customer) => '${customer.code} - ${customer.name}',
  filterFn: (customer, query) =>
      customer.name.toLowerCase().contains(query.toLowerCase()) ||
      customer.code.toLowerCase().contains(query.toLowerCase()),
  onChanged: (customer) => controller.onCustomerSelected(customer),
  showSearch: true,
  showAddNew: true,
  addNewLabel: 'Add New Customer',
  onAddNew: () => controller.openAddCustomerDialog(),
)

B. Generic Multi-Select Dropdown (AppMultiSelectDropdown<T>) #

AppMultiSelectDropdown<BranchModel>(
  hintText: 'Select Branches',
  items: controller.branches,
  selectedItems: controller.selectedBranches,
  itemLabel: (branch) => branch.branchName,
  onChanged: (selectedList) => controller.updateBranches(selectedList),
)

C. Standard Form Input (AppTextFieldFormWidget) #

AppTextFieldFormWidget(
  hint: 'Enter Voucher Number',
  controller: controller.voucherNoTextController,
  keyboardType: TextInputType.text,
  isValidator: true,
  validationMessage: 'Voucher number is required',
  onChanged: (val) => controller.onVoucherChanged(val),
)

D. Modal Dialog (GenericDialogBox) #

Get.dialog(
  GenericDialogBox(
    headerText: 'Approve Expense Voucher',
    content: Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        AppText('Are you sure you want to approve Voucher #V-2026-001?'),
        const SizedBox(height: 12),
        AppTextFieldFormWidget(
          hint: 'Remarks (Optional)',
          controller: controller.remarksController,
        ),
      ],
    ),
    primaryButtonText: 'Approve',
    onPrimaryButtonPressed: () => controller.submitApproval(),
    secondaryButtonText: 'Cancel',
    onSecondaryButtonPressed: () => Get.back(),
  ),
);

E. Entity Summary Card (AppSummaryCard) #

AppSummaryCard(
  title: 'Lead Information',
  crossAxisCount: 3,
  items: [
    AppSummaryItem(label: 'Lead Code', value: lead.code),
    AppSummaryItem(label: 'Contact Person', value: lead.contactPerson),
    AppSummaryItem(label: 'Phone', value: lead.mobileNo, icon: Icons.phone),
    AppSummaryItem(
      label: 'Status',
      valueWidget: AppBadge(text: lead.status, color: Colors.green),
    ),
  ],
)

F. Dynamic Filter Panel (AppFilterPanel) #

AppFilterPanel(
  title: 'Filter Dispatches',
  fields: [
    FilterField(key: 'search', label: 'Search Query', type: FilterFieldType.text),
    FilterField(
      key: 'status',
      label: 'Dispatch Status',
      type: FilterFieldType.dropdown,
      options: [
        FilterFieldOption(label: 'Pending', value: 'PENDING'),
        FilterFieldOption(label: 'In Transit', value: 'IN_TRANSIT'),
        FilterFieldOption(label: 'Delivered', value: 'DELIVERED'),
      ],
    ),
    FilterField(key: 'dateRange', label: 'Date Range', type: FilterFieldType.dateRange),
  ],
  onApply: (filters) => controller.applyFilters(filters),
  onReset: () => controller.clearFilters(),
)

G. Cross-Platform Media Upload (AppMediaPicker) #

AppMediaPicker(
  label: 'Attach Proof of Delivery',
  maxFiles: 5,
  maxFileSizeMB: 10,
  allowMultiple: true,
  onFilesChanged: (files) => controller.uploadedFiles.assignAll(files),
)

H. Centralized Utilities & Toast Notifications #

// Toast notifications
AppToast.success(context, title: 'Saved', message: 'Record created successfully');
AppToast.error(context, title: 'Failed', message: 'Could not connect to server');

// Form Validation
String? error = AppValidators.email('invalid-email');

// Number & Currency Formatting
String formattedPrice = AppNumberUtils.formatCurrency(1250000.50); // ₹ 12,50,000.50

// Excel & CSV Export
await AppExportUtils.exportToExcel(
  fileName: 'Dispatches_Report',
  sheetName: 'Dispatches',
  headers: ['ID', 'Vehicle', 'Driver', 'Status'],
  data: dispatches.map((d) => [d.id, d.vehicleNo, d.driverName, d.status]).toList(),
);

6. Architecture Rules & Guidelines #

A. State Management Boundary #

  • Stateless UI: Shared components must not maintain long-lived business state. Use StatelessWidget or StatefulWidget strictly for local UI interactions (animations, dropdown menu overlay state, text focus).
  • GetX Separation: Module business state belongs in module-level GetxController instances. Shared components communicate via ValueChanged<T>, VoidCallback, or builder delegates.

B. Business Logic & API Boundary #

✅ Correct Flow:
UI View ──> Module Controller ──> Module Service/Repo ──> Shared ApiService (Dio)

❌ FORBIDDEN:
Shared Widget ──> Direct Business Module API Calls

C. Generic Design vs Anti-Patterns #

❌ Anti-Pattern (Never Do This) ✅ Recommended Pattern
if (module == 'CRM') { ... } Pass configuration flags or callback delegates.
Hard-coding domain DTOs (LeadModel, ExpenseModel) in shared widgets. Use generic types (AppDropdown<T>) with itemLabel and filterFn.
Creating duplicate widgets with minor styling differences. Parameterize styling or wrap with AppCard / AppContainer.
Leaving ScrollController or TextEditingController undisposed. Always clean up controllers and stream subscriptions in dispose() / onClose().

7. Decision Tree: Reuse, Extend, or Create? #

flowchart TD
    Start["New UI Requirement"] --> Search["1. Search package:shared_component"]
    Search --> Found{"Suitable component found?"}
    Found -- "Yes (100% fit)" --> Reuse["✅ Direct Reuse"]
    Found -- "Almost (needs small generic tweak)" --> Extend["⚠️ Extend component with optional generic parameter"]
    Found -- "No" --> IsGeneric{"Is the requirement truly cross-module generic?"}
    IsGeneric -- "Yes (Used by 2+ modules)" --> Create["✨ Create new component in shared_component/lib/widgets/"]
    IsGeneric -- "No (Module-specific workflow)" --> ModuleOnly["📦 Keep inside <module>/lib/<module>_app/ui/"]

8. Protected Hardware & Weighbridge Domain #

The following components and controllers provide mission-critical hardware communication (boom barriers, weighbridge scales, RFID scanners) and must not be refactored without explicit hardware domain sign-off:

  • lib/widgets/hardware/boom_barrier_widget.dart
  • lib/widgets/hardware/internal_weighing_widget.dart
  • lib/widgets/hardware/weighing_open_gate_functionality.dart
  • lib/controllers/internal_transfer_weighing_controller.dart
  • lib/data_source/new_weighing_sizes_data_source.dart

9. Developer Pre-Commit Checklist #

Before submitting changes to shared_component:

  • ❌ Grep Usages: Checked all 8+ consuming ERP modules for breaking changes.
  • ❌ Backward Compatibility: Preserved existing method signatures and exports in shared_component.dart and utils.dart.
  • ❌ Zero Module Dependencies: Verified no imports of crm_module, expense_module, deliver_module, etc. exist in shared_component.
  • ❌ Memory Safety: Verified all controllers, focus nodes, and listeners are properly disposed in dispose() / onClose().
  • ❌ Static Analysis: Executed flutter analyze or Dart analyzer with 0 errors and 0 warnings.
  • ❌ Unit Tests: Verified unit and widget tests pass (flutter test).