Files
pfm-ocr/lib/features/camera/camera_drawer_mode_toggle.dart
T
fhanyuh caf8e98378 chore: normalize line endings (CRLF -> LF)
No content changes: git diff --ignore-all-space over these files is empty.
The churn came from editing on Windows against a repo checked out with LF.
2026-08-27 10:40:49 +07:00

126 lines
4.2 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../config/app_config.dart';
import 'scan_mode_provider.dart';
/// DO / Product Scan mode toggle pill rendered in the [CameraDrawer].
///
/// Extracted from [CameraDrawer] to keep that file under the 256-line §3
/// threshold (AGENTS.md §3, touched during task 8.1). Reads and writes
/// [scanModeProvider] directly — the global source of truth shared with
/// [DocumentsScreen] (task 8.1, docs/api-contract-map.md G11).
///
/// Color convention:
/// - DO active → [AppConfig.doModeColor] (orange)
/// - Product active → [AppConfig.primaryColor] (green)
class CameraDrawerModeToggle extends ConsumerWidget {
const CameraDrawerModeToggle({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final activeMode = ref.watch(scanModeProvider);
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Mode',
style: AppConfig.bodySmall.copyWith(
color: Colors.grey.shade500,
fontWeight: FontWeight.w600,
letterSpacing: 0.5,
),
),
const SizedBox(height: 8),
Container(
height: 48,
decoration: BoxDecoration(
color: Colors.grey.shade100,
borderRadius: BorderRadius.circular(12),
),
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Row(
children: [
_buildSegment(
ref: ref,
value: 'DO',
label: 'DO Scan',
activeIcon: Icons.description,
inactiveIcon: Icons.description_outlined,
activeMode: activeMode,
activeColor: AppConfig.doModeColor,
),
_buildSegment(
ref: ref,
value: 'Product',
label: 'Product Scan',
activeIcon: Icons.inventory_2,
inactiveIcon: Icons.inventory_2_outlined,
activeMode: activeMode,
activeColor: AppConfig.primaryColor,
),
],
),
),
),
],
),
);
}
Widget _buildSegment({
required WidgetRef ref,
required String value,
required String label,
required IconData activeIcon,
required IconData inactiveIcon,
required String activeMode,
required Color activeColor,
}) {
final isActive = activeMode == value;
return Expanded(
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => ref.read(scanModeProvider.notifier).state = value,
child: Container(
decoration: BoxDecoration(
color: isActive ? activeColor : Colors.transparent,
borderRadius: BorderRadius.circular(8),
boxShadow: isActive
? [
BoxShadow(
color: activeColor.withOpacity(0.2),
blurRadius: 4,
offset: const Offset(0, 2),
)
]
: [],
),
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
isActive ? activeIcon : inactiveIcon,
size: 16,
color: isActive ? Colors.white : Colors.grey.shade500,
),
const SizedBox(width: 6),
Text(
label,
style: AppConfig.bodyMedium.copyWith(
fontWeight: isActive ? FontWeight.bold : FontWeight.normal,
color: isActive ? Colors.white : Colors.grey.shade600,
),
),
],
),
),
),
);
}
}