121 lines
3.5 KiB
Dart
121 lines
3.5 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:niogu_app/core/components/app_bar_with_tab.dart';
|
|
import 'package:niogu_app/core/providers/app_provider.dart';
|
|
import 'package:niogu_app/core/enums/user_role.dart';
|
|
import 'package:niogu_app/features/goods/products/presentation/providers/product_provider.dart';
|
|
import 'package:niogu_app/features/goods/products/presentation/screens/product_screen.dart';
|
|
import 'package:niogu_app/features/goods/raw_materials/presentation/providers/raw_material_provider.dart';
|
|
import 'package:niogu_app/features/goods/raw_materials/presentation/screens/raw_material_screen.dart';
|
|
import 'package:sizer/sizer.dart';
|
|
|
|
class GoodScreen extends ConsumerStatefulWidget {
|
|
const GoodScreen({super.key});
|
|
|
|
@override
|
|
ConsumerState<GoodScreen> createState() => _GoodScreenState();
|
|
}
|
|
|
|
class _GoodScreenState extends ConsumerState<GoodScreen>
|
|
with SingleTickerProviderStateMixin {
|
|
late TabController _tabController;
|
|
|
|
final FocusNode _searchFocusNode = FocusNode();
|
|
|
|
Color _searchIconColor = Colors.grey;
|
|
|
|
Timer? _debounce;
|
|
|
|
int _tabIndex = 0;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
_tabController = TabController(length: 2, vsync: this);
|
|
|
|
_tabController.addListener(_handleTabSelection);
|
|
|
|
_searchFocusNode.addListener(() {
|
|
setState(() {
|
|
_searchIconColor = _searchFocusNode.hasFocus
|
|
? Colors.black
|
|
: Colors.grey;
|
|
});
|
|
});
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_searchFocusNode.dispose();
|
|
_tabController.removeListener(_handleTabSelection);
|
|
_tabController.dispose();
|
|
_debounce?.cancel();
|
|
super.dispose();
|
|
}
|
|
|
|
void _handleTabSelection() {
|
|
if (_tabController.index != _tabIndex) {
|
|
setState(() {
|
|
_tabIndex = _tabController.index;
|
|
});
|
|
}
|
|
}
|
|
|
|
void _onSearchChanged(String value) {
|
|
if (_debounce?.isActive ?? false) _debounce?.cancel();
|
|
_debounce = Timer(const Duration(milliseconds: 800), () {
|
|
if (_tabIndex == 0) {
|
|
ref.read(productSearchProvider.notifier).state = value;
|
|
} else {
|
|
ref.read(rawMaterialSearchProvider.notifier).state = value;
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return LayoutBuilder(
|
|
builder: (context, constraints) {
|
|
final currentUserRole = ref.watch(currentUserRoleProvider);
|
|
|
|
return SafeArea(
|
|
top: false,
|
|
bottom: true,
|
|
right: false,
|
|
left: false,
|
|
child: Scaffold(
|
|
backgroundColor: Colors.white,
|
|
resizeToAvoidBottomInset: false,
|
|
appBar: AppBarWithTab(
|
|
hintText:
|
|
"Cari nama ${_tabIndex == 0 ? 'produk' : 'bahan baku'}...",
|
|
searchIconColor: _searchIconColor,
|
|
showSwitchOutlet: currentUserRole == UserRole.owner,
|
|
searchFocusNode: _searchFocusNode,
|
|
tabController: _tabController,
|
|
onTap: (value) {
|
|
setState(() {
|
|
_tabIndex = value;
|
|
});
|
|
},
|
|
onSearchChanged: (value) => _onSearchChanged(value),
|
|
tabs: [
|
|
Tab(text: "Produk", height: 10.h),
|
|
Tab(text: "Bahan Baku", height: 10.h),
|
|
],
|
|
),
|
|
|
|
body: TabBarView(
|
|
controller: _tabController,
|
|
children: [const ProductScreen(), const RawMaterialScreen()],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|