Files
worker/lib/features/home/presentation/widgets/quick_action_section.dart
2025-12-01 11:31:26 +07:00

155 lines
4.5 KiB
Dart

/// Widget: Quick Action Section
///
/// Section container with title and grid of action items.
/// Groups related actions together (e.g., Products & Cart, Loyalty, etc.)
library;
import 'package:flutter/material.dart';
import 'package:worker/features/home/presentation/widgets/quick_action_item.dart';
/// Quick Action Section Data Model
class QuickAction {
final IconData icon;
final String label;
final String? badge;
final VoidCallback? onTap;
const QuickAction({
required this.icon,
required this.label,
this.badge,
this.onTap,
});
}
/// Quick Action Section Widget
///
/// Displays a titled card containing a grid of action buttons.
/// Each section groups related functionality.
class QuickActionSection extends StatelessWidget {
/// Section title
final String title;
/// List of actions in this section
final List<QuickAction> actions;
const QuickActionSection({
super.key,
required this.title,
required this.actions,
});
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Container(
margin: const EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
color: colorScheme.surface,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.07),
blurRadius: 15,
offset: const Offset(0, 4),
),
],
),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 16,
children: [
// Section Title
Text(
title,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w700,
color: colorScheme.onSurface,
height: 1.0, // Reduce line height to minimize spacing
),
),
// Action Grid (always 3 columns to match HTML)
// Using Transform to remove spacing between title and grid
Transform.translate(
offset: const Offset(0, -4),
child: _buildActionGrid(),
),
],
),
),
);
}
Widget _buildActionGrid() {
// Determine grid columns based on item count
// If 2 items: 2 columns (no scroll, rectangular aspect ratio)
// If 3 items: 3 columns (no scroll)
// If more than 3: 3 columns (scrollable horizontally)
final int crossAxisCount = actions.length == 2 ? 2 : 3;
final bool isScrollable = actions.length > 3;
// Use rectangular aspect ratio for 2 items to reduce height
// 1.5 means width is 1.5x the height (more rectangular/wider)
final double aspectRatio = actions.length == 2 ? 1.5 : 0.85;
if (!isScrollable) {
// Non-scrollable grid for 2 or 3 items
return GridView.builder(
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: crossAxisCount,
childAspectRatio: aspectRatio,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
),
itemCount: actions.length,
itemBuilder: (context, index) {
final action = actions[index];
return QuickActionItem(
icon: action.icon,
label: action.label,
badge: action.badge,
onTap: action.onTap,
);
},
);
}
// Scrollable horizontal grid for more than 3 items
// Calculate grid height based on number of rows needed
final int rows = (actions.length / crossAxisCount).ceil();
const double itemHeight = 100; // Approximate height of each item
final double gridHeight = (rows * itemHeight) + ((rows - 1) * 8);
return SizedBox(
height: gridHeight,
child: GridView.builder(
padding: EdgeInsets.zero,
scrollDirection: Axis.horizontal,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: crossAxisCount,
childAspectRatio: 1.0,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
),
itemCount: actions.length,
itemBuilder: (context, index) {
final action = actions[index];
return QuickActionItem(
icon: action.icon,
label: action.label,
badge: action.badge,
onTap: action.onTap,
);
},
),
);
}
}