forked from firka/student-legacy
451 lines
17 KiB
Dart
451 lines
17 KiB
Dart
// ignore_for_file: use_build_context_synchronously
|
|
|
|
import 'package:dropdown_button2/dropdown_button2.dart';
|
|
import 'package:refilc/api/providers/database_provider.dart';
|
|
import 'package:refilc/api/providers/user_provider.dart';
|
|
import 'package:refilc/helpers/subject.dart';
|
|
import 'package:refilc/models/settings.dart';
|
|
import 'package:refilc/theme/colors/colors.dart';
|
|
import 'package:refilc/utils/format.dart';
|
|
import 'package:refilc_kreta_api/models/subject.dart';
|
|
import 'package:refilc_kreta_api/providers/absence_provider.dart';
|
|
import 'package:refilc_kreta_api/providers/grade_provider.dart';
|
|
import 'package:refilc_kreta_api/providers/timetable_provider.dart';
|
|
import 'package:refilc_mobile_ui/common/panel/panel.dart';
|
|
import 'package:refilc_mobile_ui/common/panel/panel_button.dart';
|
|
// import 'package:refilc_plus/models/premium_scopes.dart';
|
|
// import 'package:refilc_plus/providers/plus_provider.dart';
|
|
// import 'package:refilc_plus/ui/mobile/plus/upsell.dart';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
import 'modify_names.i18n.dart';
|
|
|
|
class MenuRenamedSubjects extends StatelessWidget {
|
|
const MenuRenamedSubjects({super.key, required this.settings});
|
|
|
|
final SettingsProvider settings;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return PanelButton(
|
|
padding: const EdgeInsets.only(left: 14.0),
|
|
onPressed: () {
|
|
// if (!Provider.of<PlusProvider>(context, listen: false)
|
|
// .hasScope(PremiumScopes.renameSubjects)) {
|
|
// PlusLockedFeaturePopup.show(
|
|
// context: context, feature: PremiumFeature.subjectrename);
|
|
// return;
|
|
// }
|
|
|
|
Navigator.of(context, rootNavigator: true).push(
|
|
CupertinoPageRoute(builder: (context) => const ModifySubjectNames()),
|
|
);
|
|
},
|
|
title: Text(
|
|
"rename_subjects".i18n,
|
|
style: TextStyle(
|
|
color: AppColors.of(context)
|
|
.text
|
|
.withValues(alpha: settings.renamedSubjectsEnabled ? 1.0 : .5)),
|
|
),
|
|
leading: settings.renamedSubjectsEnabled
|
|
? const Icon(FeatherIcons.penTool)
|
|
: Icon(FeatherIcons.penTool,
|
|
color: AppColors.of(context).text.withValues(alpha: .25)),
|
|
trailingDivider: true,
|
|
trailing: Switch(
|
|
onChanged: (v) async {
|
|
// if (!Provider.of<PlusProvider>(context, listen: false)
|
|
// .hasScope(PremiumScopes.renameSubjects)) {
|
|
// PlusLockedFeaturePopup.show(
|
|
// context: context, feature: PremiumFeature.subjectrename);
|
|
// return;
|
|
// }
|
|
|
|
settings.update(renamedSubjectsEnabled: v);
|
|
await Provider.of<GradeProvider>(context, listen: false)
|
|
.convertBySettings();
|
|
await Provider.of<TimetableProvider>(context, listen: false)
|
|
.convertBySettings();
|
|
await Provider.of<AbsenceProvider>(context, listen: false)
|
|
.convertBySettings();
|
|
},
|
|
value: settings.renamedSubjectsEnabled,
|
|
activeColor: Theme.of(context).colorScheme.secondary,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class ModifySubjectNames extends StatefulWidget {
|
|
const ModifySubjectNames({super.key});
|
|
|
|
@override
|
|
State<ModifySubjectNames> createState() => _ModifySubjectNamesState();
|
|
}
|
|
|
|
class _ModifySubjectNamesState extends State<ModifySubjectNames> {
|
|
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
|
final _subjectName = TextEditingController();
|
|
String? selectedSubjectId;
|
|
|
|
late List<GradeSubject> subjects;
|
|
late UserProvider user;
|
|
late DatabaseProvider dbProvider;
|
|
late SettingsProvider settings;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
subjects = Provider.of<GradeProvider>(context, listen: false)
|
|
.grades
|
|
.map((e) => e.subject)
|
|
.toSet()
|
|
.toList()
|
|
..sort((a, b) => a.name.compareTo(b.name));
|
|
user = Provider.of<UserProvider>(context, listen: false);
|
|
dbProvider = Provider.of<DatabaseProvider>(context, listen: false);
|
|
}
|
|
|
|
Future<Map<String, String>> fetchRenamedSubjects() async {
|
|
return await dbProvider.userQuery.renamedSubjects(userId: user.id!);
|
|
}
|
|
|
|
void showRenameDialog() {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => StatefulBuilder(builder: (context, setS) {
|
|
return AlertDialog(
|
|
shape: const RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.all(Radius.circular(14.0))),
|
|
title: Text("rename_subject".i18n),
|
|
content: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
DropdownButton2(
|
|
items: subjects
|
|
.map((item) => DropdownMenuItem<String>(
|
|
value: item.id,
|
|
child: Text(
|
|
item.name,
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.bold,
|
|
color: AppColors.of(context).text,
|
|
),
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
))
|
|
.toList(),
|
|
onChanged: (String? v) async {
|
|
final renamedSubs = await fetchRenamedSubjects();
|
|
|
|
setS(() {
|
|
selectedSubjectId = v;
|
|
|
|
if (renamedSubs.containsKey(selectedSubjectId)) {
|
|
_subjectName.text = renamedSubs[selectedSubjectId]!;
|
|
} else {
|
|
_subjectName.text = "";
|
|
}
|
|
});
|
|
},
|
|
iconStyleData: IconStyleData(
|
|
iconSize: 14,
|
|
iconEnabledColor: AppColors.of(context).text,
|
|
iconDisabledColor: AppColors.of(context).text,
|
|
),
|
|
underline: const SizedBox(),
|
|
menuItemStyleData: const MenuItemStyleData(
|
|
height: 40,
|
|
padding: EdgeInsets.only(left: 14, right: 14),
|
|
),
|
|
buttonStyleData: ButtonStyleData(
|
|
width: 50,
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
),
|
|
dropdownStyleData: DropdownStyleData(
|
|
width: 300,
|
|
padding: null,
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(14),
|
|
),
|
|
elevation: 8,
|
|
scrollbarTheme: ScrollbarThemeData(
|
|
radius: const Radius.circular(40),
|
|
thickness: WidgetStateProperty.all<double>(6.0),
|
|
trackVisibility: WidgetStateProperty.all<bool>(true),
|
|
),
|
|
offset: const Offset(-10, -10),
|
|
),
|
|
customButton: Container(
|
|
width: double.infinity,
|
|
decoration: BoxDecoration(
|
|
border: Border.all(color: Colors.grey, width: 2),
|
|
borderRadius: BorderRadius.circular(12.0),
|
|
),
|
|
padding: const EdgeInsets.symmetric(
|
|
vertical: 12.0, horizontal: 8.0),
|
|
child: Text(
|
|
selectedSubjectId == null
|
|
? "select_subject".i18n
|
|
: subjects
|
|
.firstWhere(
|
|
(element) => element.id == selectedSubjectId)
|
|
.name,
|
|
style: Theme.of(context).textTheme.titleSmall!.copyWith(
|
|
fontWeight: FontWeight.w700,
|
|
color:
|
|
AppColors.of(context).text.withValues(alpha: 0.75)),
|
|
overflow: TextOverflow.ellipsis,
|
|
maxLines: 2,
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
),
|
|
const Padding(
|
|
padding: EdgeInsets.symmetric(vertical: 8.0),
|
|
child: Icon(FeatherIcons.arrowDown, size: 32),
|
|
),
|
|
TextField(
|
|
controller: _subjectName,
|
|
decoration: InputDecoration(
|
|
border: OutlineInputBorder(
|
|
borderSide:
|
|
const BorderSide(color: Colors.grey, width: 1.5),
|
|
borderRadius: BorderRadius.circular(12.0),
|
|
),
|
|
focusedBorder: OutlineInputBorder(
|
|
borderSide:
|
|
const BorderSide(color: Colors.grey, width: 1.5),
|
|
borderRadius: BorderRadius.circular(12.0),
|
|
),
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 12.0),
|
|
hintText: "modified_name".i18n,
|
|
suffixIcon: IconButton(
|
|
icon: const Icon(
|
|
FeatherIcons.x,
|
|
color: Colors.grey,
|
|
),
|
|
onPressed: () {
|
|
setState(() {
|
|
_subjectName.text = "";
|
|
});
|
|
},
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
child: Text(
|
|
"cancel".i18n,
|
|
style: const TextStyle(fontWeight: FontWeight.w500),
|
|
),
|
|
onPressed: () {
|
|
Navigator.of(context).maybePop();
|
|
},
|
|
),
|
|
TextButton(
|
|
child: Text(
|
|
"done".i18n,
|
|
style: const TextStyle(fontWeight: FontWeight.w500),
|
|
),
|
|
onPressed: () async {
|
|
if (selectedSubjectId != null) {
|
|
final renamedSubs = await fetchRenamedSubjects();
|
|
|
|
renamedSubs[selectedSubjectId!] = _subjectName.text;
|
|
await dbProvider.userStore
|
|
.storeRenamedSubjects(renamedSubs, userId: user.id!);
|
|
await Provider.of<GradeProvider>(context, listen: false)
|
|
.convertBySettings();
|
|
await Provider.of<TimetableProvider>(context, listen: false)
|
|
.convertBySettings();
|
|
await Provider.of<AbsenceProvider>(context, listen: false)
|
|
.convertBySettings();
|
|
}
|
|
Navigator.of(context).pop(true);
|
|
setState(() {});
|
|
},
|
|
),
|
|
],
|
|
);
|
|
}),
|
|
).then((val) {
|
|
_subjectName.text = "";
|
|
selectedSubjectId = null;
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
settings = Provider.of<SettingsProvider>(context);
|
|
return Scaffold(
|
|
key: _scaffoldKey,
|
|
appBar: AppBar(
|
|
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
|
|
leading: BackButton(color: AppColors.of(context).text),
|
|
title: Text(
|
|
"modify_subjects".i18n,
|
|
style: TextStyle(color: AppColors.of(context).text),
|
|
),
|
|
),
|
|
body: Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0),
|
|
child: SingleChildScrollView(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Panel(
|
|
child: SwitchListTile(
|
|
title: Text("italics_toggle".i18n),
|
|
onChanged: (value) =>
|
|
settings.update(renamedSubjectsItalics: value),
|
|
value: settings.renamedSubjectsItalics,
|
|
),
|
|
),
|
|
const SizedBox(
|
|
height: 20,
|
|
),
|
|
InkWell(
|
|
onTap: showRenameDialog,
|
|
borderRadius: BorderRadius.circular(12.0),
|
|
child: Container(
|
|
width: double.infinity,
|
|
decoration: BoxDecoration(
|
|
border: Border.all(color: Colors.grey, width: 2),
|
|
borderRadius: BorderRadius.circular(12.0),
|
|
),
|
|
padding: const EdgeInsets.symmetric(
|
|
vertical: 18.0, horizontal: 12.0),
|
|
child: Center(
|
|
child: Text(
|
|
"rename_new_subject".i18n,
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 18,
|
|
color:
|
|
AppColors.of(context).text.withValues(alpha: .85),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(
|
|
height: 30,
|
|
),
|
|
FutureBuilder<Map<String, String>>(
|
|
future: fetchRenamedSubjects(),
|
|
builder: (context, snapshot) {
|
|
if (!snapshot.hasData || snapshot.data!.isEmpty) {
|
|
return Container();
|
|
}
|
|
|
|
return Panel(
|
|
title: Text("renamed_subjects".i18n),
|
|
child: Column(
|
|
children: snapshot.data!.keys.map(
|
|
(key) {
|
|
GradeSubject? subject = subjects
|
|
.firstWhere((element) => key == element.id);
|
|
String renameTo = snapshot.data![key]!;
|
|
return RenamedSubjectItem(
|
|
subject: subject,
|
|
renamedTo: renameTo,
|
|
modifyCallback: () {
|
|
setState(() {
|
|
selectedSubjectId = subject.id;
|
|
_subjectName.text = renameTo;
|
|
});
|
|
showRenameDialog();
|
|
},
|
|
removeCallback: () {
|
|
setState(() {
|
|
Map<String, String> subs =
|
|
Map.from(snapshot.data!);
|
|
subs.remove(key);
|
|
dbProvider.userStore.storeRenamedSubjects(
|
|
subs,
|
|
userId: user.id!);
|
|
});
|
|
},
|
|
);
|
|
},
|
|
).toList(),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
));
|
|
}
|
|
}
|
|
|
|
class RenamedSubjectItem extends StatelessWidget {
|
|
const RenamedSubjectItem({
|
|
super.key,
|
|
required this.subject,
|
|
required this.renamedTo,
|
|
required this.modifyCallback,
|
|
required this.removeCallback,
|
|
});
|
|
|
|
final GradeSubject subject;
|
|
final String renamedTo;
|
|
final void Function() modifyCallback;
|
|
final void Function() removeCallback;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return ListTile(
|
|
minLeadingWidth: 32.0,
|
|
dense: true,
|
|
contentPadding:
|
|
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 6.0),
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
|
|
visualDensity: VisualDensity.compact,
|
|
onTap: () {},
|
|
leading: Icon(
|
|
SubjectIcon.resolveVariant(subject: subject, context: context),
|
|
color: AppColors.of(context).text.withValues(alpha: .75)),
|
|
title: InkWell(
|
|
onTap: modifyCallback,
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
subject.name.capital(),
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.w500,
|
|
fontSize: 14,
|
|
color: AppColors.of(context).text.withValues(alpha: .75)),
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
Text(
|
|
renamedTo,
|
|
style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 16),
|
|
maxLines: 2,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
trailing: InkWell(
|
|
onTap: removeCallback,
|
|
child: Icon(FeatherIcons.trash,
|
|
color: AppColors.of(context).red.withValues(alpha: .75)),
|
|
),
|
|
);
|
|
}
|
|
}
|