Quit-Your-Addictions/lib/screens/rabbit_screen.dart

408 lines
13 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:get_it/get_it.dart';
import 'package:go_router/go_router.dart';
import 'package:Rabbit_Habit/blocs/new_habit_cubit.dart';
import 'package:Rabbit_Habit/config/constraint.dart';
import 'package:Rabbit_Habit/models/new_habit_model.dart';
import 'package:Rabbit_Habit/repo/icons_repository.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
final GetIt getIt = GetIt.instance;
final tr = getIt.get<AppLocalizations>();
class HabitScreen extends StatefulWidget {
final String? id;
const HabitScreen({super.key, required this.id});
@override
State<HabitScreen> createState() => _HabitScreenState();
}
class _HabitScreenState extends State<HabitScreen> {
TextEditingController nameController = TextEditingController();
TextEditingController descriptionController = TextEditingController();
onSaveHabitPressed(ThemeData themeData) async {
nameController.text = nameController.text.trim();
descriptionController.text = descriptionController.text.trim();
if (nameController.text.isNotEmpty) {
if (widget.id == null) {
await context
.read<NewHabitCubit>()
.addNewHabit(nameController.text, descriptionController.text,
context.read<NewHabitCubit>().state.iconCodePoint)
.then((value) {
while (context.canPop()) {
context.pop();
}
context.pushReplacement('/home');
});
} else {
await context
.read<NewHabitCubit>()
.updateHabit(
widget.id!,
nameController.text,
descriptionController.text,
context.read<NewHabitCubit>().state.iconCodePoint,
)
.then((value) {
while (context.canPop()) {
context.pop();
}
context.pushReplacement('/home');
});
}
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
behavior: SnackBarBehavior.floating,
content: Text(
tr.name_cannot_be_empty,
textAlign: TextAlign.center,
style: TextStyle(
color: themeData.colorScheme.onSurface,
fontSize: 15,
fontWeight: FontWeight.w700,
),
),
),
);
}
}
@override
void initState() {
if (widget.id != null) {
context.read<NewHabitCubit>().getHabitToEdit(widget.id!).then((value) {
nameController.text = context.read<NewHabitCubit>().state.name;
descriptionController.text =
context.read<NewHabitCubit>().state.description;
});
}
getIt.registerSingleton<Function>(onSaveHabitPressed,
instanceName: 'onSaveHabitPressed');
super.initState();
}
@override
void dispose() {
getIt.unregister<Function>(
instanceName: 'onSaveHabitPressed',
);
super.dispose();
}
@override
Widget build(BuildContext context) {
ThemeData themeData = Theme.of(context);
return Scaffold(
backgroundColor: themeData.colorScheme.background,
appBar: AppBar(
backgroundColor: themeData.colorScheme.background,
elevation: 0,
title: Text(
widget.id == null ? tr.new_rabbit : tr.edit_rabbit,
style: TextStyle(
color: themeData.primaryColor,
fontWeight: FontWeight.bold,
fontSize: 25,
),
),
),
body: SafeArea(
child: Padding(
padding: defaultHorizontalViewPadding,
child: ListView(
children: [
HabitTextField(controller: nameController, hintText: tr.name),
HabitTextField(
controller: descriptionController,
hintText: tr.description,
last: true,
),
const HabitIconPicker(),
const SaveHabitButton(),
RemoveButton(id: widget.id)
],
),
),
),
);
}
}
class HabitTextField extends StatelessWidget {
final TextEditingController controller;
final String hintText;
final bool last;
const HabitTextField(
{super.key,
required this.controller,
required this.hintText,
this.last = false});
@override
Widget build(BuildContext context) {
ThemeData themeData = Theme.of(context);
return Padding(
padding: defaultTopPadding / 2,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
hintText,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 5,
),
TextFormField(
controller: controller,
textCapitalization: TextCapitalization.sentences,
onTapOutside: (event) {
FocusScope.of(context).unfocus();
},
textInputAction: last ? TextInputAction.done : TextInputAction.next,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w700,
),
cursorColor: themeData.colorScheme.primary,
cursorWidth: 3,
decoration: InputDecoration(
isDense: true,
contentPadding: const EdgeInsets.all(10),
fillColor: themeData.colorScheme.surfaceVariant,
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(
color: themeData.colorScheme.surfaceVariant,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(
color: themeData.colorScheme.surfaceVariant,
),
),
),
),
],
),
);
}
}
class HabitIconItem extends StatelessWidget {
final int index;
final int iconCodePoint;
const HabitIconItem(
{super.key, required this.index, required this.iconCodePoint});
@override
Widget build(BuildContext context) {
ThemeData themeData = Theme.of(context);
return GestureDetector(
onTap: () {
context.read<NewHabitCubit>().setNewHabitIconCodePoint(
IconsRepository().getFeaturedIcons()[index]);
},
child: Container(
decoration: BoxDecoration(
color: iconCodePoint == IconsRepository().getFeaturedIcons()[index]
? themeData.colorScheme.primary
: themeData.colorScheme.surfaceVariant,
borderRadius: BorderRadius.circular(15),
),
child: Icon(
IconsRepository().getIconData(
IconsRepository().getFeaturedIcons()[index],
),
color: iconCodePoint == IconsRepository().getFeaturedIcons()[index]
? themeData.colorScheme.onPrimary
: themeData.colorScheme.onSurface,
),
),
);
}
}
class HabitIconPicker extends StatelessWidget {
const HabitIconPicker({super.key});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
tr.icon,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 5,
),
GridView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: IconsRepository().getFeaturedIcons().length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: MediaQuery.of(context).size.width > 800 ? 13 : 7,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
),
itemBuilder: (context, index) {
return BlocBuilder<NewHabitCubit, NewHabit>(
buildWhen: (previous, current) {
// build only widgets that changed
return previous.iconCodePoint ==
IconsRepository().getFeaturedIcons()[index] ||
current.iconCodePoint ==
IconsRepository().getFeaturedIcons()[index];
},
builder: (context, state) {
return HabitIconItem(
index: index,
iconCodePoint: state.iconCodePoint,
);
},
);
},
),
],
);
}
}
class SaveHabitButton extends StatelessWidget {
const SaveHabitButton({super.key});
@override
Widget build(BuildContext context) {
ThemeData themeData = Theme.of(context);
return Padding(
padding: defaultTopPadding,
child: ElevatedButton(
onPressed: () {
getIt.get<Function>(
instanceName: 'onSaveHabitPressed',
)(themeData);
},
style: ElevatedButton.styleFrom(
backgroundColor: themeData.colorScheme.primary,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
padding: const EdgeInsets.all(15),
),
child: Text(
tr.save,
style: TextStyle(
color: themeData.colorScheme.onPrimary,
fontSize: 18,
fontWeight: FontWeight.w700,
),
),
),
);
}
}
class RemoveButton extends StatelessWidget {
final String? id;
const RemoveButton({super.key, this.id});
@override
Widget build(BuildContext context) {
ThemeData themeData = Theme.of(context);
return Column(
children: [
id == null
? const SizedBox()
: const SizedBox(
height: 10,
),
id == null
? const SizedBox()
: GestureDetector(
onTap: () async {
// show dialog
showDialog(
context: context,
builder: (contextDialog) {
return AlertDialog(
backgroundColor: themeData.colorScheme.surface,
title: Text(
tr.remove_habit_confirmation,
textAlign: TextAlign.center,
style: TextStyle(
color: themeData.colorScheme.onSurface,
fontSize: 18,
fontWeight: FontWeight.w600,
fontFamily: 'Inter',
),
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(contextDialog);
},
child: Text(
tr.cancel,
style: TextStyle(
color: themeData.colorScheme.onSurface,
fontSize: 18,
fontWeight: FontWeight.w700,
),
),
),
TextButton(
onPressed: () async {
await context
.read<NewHabitCubit>()
.deleteHabit(
id!,
)
.then((value) {
Navigator.pop(contextDialog);
while (context.canPop()) {
context.pop();
}
context.pushReplacement('/home');
});
},
child: Text(
tr.remove_rabbit,
style: TextStyle(
color: themeData.colorScheme.primary,
fontSize: 18,
fontWeight: FontWeight.w700,
),
),
),
],
);
},
);
},
child: Text(
tr.remove_rabbit,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500,
),
),
),
],
);
}
}