PMU/lib/presentation/home_page/home_page.dart
2024-12-19 08:53:16 +04:00

264 lines
9.3 KiB
Dart

import 'package:card_app/components/extensions/context_x.dart';
import 'package:card_app/components/utils/debounce.dart';
import 'package:card_app/domain/models/card.dart';
import 'package:card_app/presentation/common/svg_objects.dart';
import 'package:card_app/presentation/home_page/bloc/bloc.dart';
import 'package:card_app/presentation/home_page/bloc/events.dart';
import 'package:card_app/presentation/like_bloc/know_bloc.dart';
import 'package:card_app/presentation/like_bloc/know_event.dart';
import 'package:card_app/presentation/locale_bloc/locale_events.dart';
import 'package:card_app/repositories/WordsRepository.dart';
import 'package:card_app/repositories/mock_repository.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../details_page/details_page.dart';
import '../like_bloc/know_state.dart';
import '../locale_bloc/locale_bloc.dart';
import '../locale_bloc/locale_state.dart';
import 'bloc/state.dart';
part 'card.dart';
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Body());
}
}
class Body extends StatefulWidget {
const Body({super.key});
@override
_BodyState createState() => _BodyState();
}
class _BodyState extends State<Body> {
final SearchController searchController = SearchController();
final scrollController = ScrollController();
// Future<List<CardData>?>? data;
@override
void initState() {
SvgObjects.init();
WidgetsBinding.instance.addPostFrameCallback((_) {
context.read<HomeBloc>().add(const HomeLoadDataEvent());
context.read<KnowBloc>().add(const LoadKnowsEvent());
});
scrollController.addListener(_onNextPageListener);
super.initState();
//data = WordsRepository().loadData(); // Инициализация данных
}
void _onNextPageListener() {
if (scrollController.offset > scrollController.position.maxScrollExtent - 300) {
final bloc = context.read<HomeBloc>();
if (!bloc.state.isPaginationLoading) {
bloc.add(HomeLoadDataEvent(
search: searchController.text,
nextPage: bloc.state.data?.nextPage,
));
}
}
}
@override
void dispose() {
searchController.dispose();
scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
child: Column(children: [
Row(
children: [
Expanded(
flex: 4,
child: Padding(
padding: const EdgeInsets.all(12),
child: CupertinoSearchTextField(
placeholder: context.locale.search,
onChanged: (search) {
Debounce.run(() => context.read<HomeBloc>().add(HomeLoadDataEvent(search: search)));
},
),
),
),
GestureDetector(
onTap: () =>
context.read<LocaleBloc>().add(const ChangeLocaleEvent()),
child: SizedBox.square(
dimension: 50,
child: Padding(
padding: const EdgeInsets.only(right: 12),
child: BlocBuilder<LocaleBloc, LocaleState>(
builder: (context, state) {
return state.currentLocale.languageCode == 'ru'
? const SvgRu()
: const SvgUk();
},
),
),
),
),
],
),
BlocBuilder<HomeBloc, HomeState>(
builder: (context, state) => state.error != null
? Text(state.error ?? '',
style: Theme.of(context).textTheme.headlineLarge?.copyWith(color: Colors.red))
: state.isLoading
? const CircularProgressIndicator()
: BlocBuilder<KnowBloc, KnowState>(
builder: (context, knowState) {
return Expanded(
child: RefreshIndicator(
onRefresh: _onRefresh,
child: ListView.builder(
controller: scrollController,
padding: EdgeInsets.zero,
itemCount: state.data?.data?.length ?? 0,
itemBuilder: (context, index) {
final data = state.data?.data?[index];
return data != null
? _Card.fromData(
data,
onKnow:_onKnow,
isKnown: knowState.knownIds?.contains(data.id) == true,
onTap: () => _navToDetails(context, data),
)
: const SizedBox.shrink();
},
),
));
}
),
),
BlocBuilder<HomeBloc, HomeState>(
builder: (context, state) => state.isPaginationLoading
? const CircularProgressIndicator()
: const SizedBox.shrink(),
)
]));
}
void _navToDetails(BuildContext context, CardData data) {
Navigator.push(
context,
CupertinoPageRoute(builder: (context) => DetailPage((data))),
);
}
void _showSnackBar(BuildContext context, String title, bool isKnow) {
WidgetsBinding.instance.addPostFrameCallback((_) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(
'${context.locale.start} ${isKnow ? context.locale.known : context.locale.unknown} ${context.locale.end} $title',
style: Theme.of(context).textTheme.bodyLarge,
),
backgroundColor: Colors.indigoAccent,
duration: const Duration(seconds: 2),
));
});
}
Future<void> _onRefresh() {
context.read<HomeBloc>().add(HomeLoadDataEvent(search: searchController.text));
return Future.value(null);
}
void _onKnow(String? id, String title, bool isKnown){
if (id != null){
context.read<KnowBloc>().add(ChangeKnowEvent(id));
_showSnackBar(context, title, !isKnown);
}
}
}
// class _CardState extends State<_Card> {
// bool isKnow = false;
//
// @override
// Widget build(BuildContext context) {
// return GestureDetector(
// onTap: widget.onTap,
// child: Container(
// constraints: const BoxConstraints(minHeight: 140, maxWidth: 240),
// padding: const EdgeInsets.all(20),
// margin: const EdgeInsets.all(10),
// decoration: BoxDecoration(
// color: Colors.black12,
// borderRadius: BorderRadius.circular(10),
// ),
// child: LayoutBuilder(builder: (context, constraints) {
// double imageWidth = constraints.maxWidth;
// {
// return Stack(
// children: [
// Column(
// children: [
// Column(
// children: [
// Image.network(widget.image, width: 300),
// Text(
// widget.word,
// style: Theme.of(context).textTheme.headlineLarge,
// ),
// Text(
// widget.translation,
// style: Theme.of(context).textTheme.bodyMedium,
// ),
// ],
// ),
// Align(
// alignment: Alignment.bottomRight,
// child: Padding(
// padding: const EdgeInsets.only(left: 8.0),
// child: GestureDetector(
// onTap: () => onKnow?.call(id, text, isKnown),
// child: AnimatedSwitcher(
// duration: const Duration(milliseconds: 200),
// child: isKnow
// ? const Icon(Icons.check_circle,
// color: Colors.green, key: ValueKey(0))
// : const Icon(Icons.check_circle_outline, key: ValueKey(1)),
// ),
// ),
// ),
// ),
// ],
// ),
// Align(
// alignment: Alignment.center,
// )
// ],
// );
// }
// })),
// );
// }
// }