Notes
Notes - notes.io |
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import '../services/family_services.dart';
import 'slide_menu.dart';
import 'family_members_page.dart';
import 'location_utils.dart';
DateTime normalizeDate(DateTime date) =>
DateTime(date.year, date.month, date.day);
class CustomHomePage extends StatefulWidget {
final Map<DateTime, List<Map<String, dynamic>>> events;
const CustomHomePage({super.key, required this.events});
@override
State<CustomHomePage> createState() => _CustomHomePageState();
}
class _CustomHomePageState extends State<CustomHomePage> {
List<DropdownMenuItem<String>> _assignableOptions = [];
final PageController _pageController = PageController(viewportFraction: 0.7);
double _currentPage = 0.0;
String _userName = 'User';
String? _currentUserRole;
List<Map<String, dynamic>> taskData = [];
List<String> reminders = [];
StreamSubscription? _invitationSubscription;
TextEditingController taskController = TextEditingController();
TextEditingController pointController = TextEditingController();
TextEditingController reminderController = TextEditingController();
DateTime? selectedDate;
String? selectedPerson = 'Family';
bool usePoint = false;
bool useDate = false;
@override
void initState() {
super.initState();
_loadUserName();
_loadUserRole(); // bu içeriden _loadAssignableMembers çağırıyor
_checkForInvitations();
_loadTasks();
_loadReminders();
saveChildLocationIfNeeded();
}
@override
void dispose() {
_invitationSubscription?.cancel();
_pageController.dispose();
super.dispose();
}
void _loadUserName() async {
final user = FirebaseAuth.instance.currentUser;
if (user != null) {
final doc = await FirebaseFirestore.instance
.collection('users')
.doc(user.uid)
.get();
if (doc.exists && doc.data()!.containsKey('fullName')) {
if (!mounted) return;
setState(() {
_userName = doc.data()!['fullName'].split(' ').first;
});
}
}
}
void _loadReminders() async {
final uid = FirebaseAuth.instance.currentUser?.uid;
if (uid == null) return;
final doc =
await FirebaseFirestore.instance.collection('users').doc(uid).get();
if (doc.exists && doc.data()!.containsKey('reminders')) {
if (!mounted) return;
setState(() {
reminders = List<String>.from(doc.data()!['reminders']);
});
}
}
Future<void> _loadAssignableMembers() async {
final uid = FirebaseAuth.instance.currentUser?.uid;
if (uid == null) return;
final userDoc = await FirebaseFirestore.instance.collection('users').doc(uid).get();
final familyRef = userDoc.data()?['familyRef'];
if (familyRef == null) return;
final membersSnapshot = await FirebaseFirestore.instance
.collection('families')
.doc(familyRef)
.collection('members')
.get();
List<DropdownMenuItem<String>> options = [];
// 1. FAMILY
options.add(const DropdownMenuItem(
value: 'Family', child: Text('👨👩👧👦 Family')));
// 2. PARENTS
List<String> parentUids = [];
String? fatherUid, motherUid;
String? fatherName, motherName;
// CHILDREN
List<String> childrenUids = [];
List<String> boysUids = [];
List<String> girlsUids = [];
List<DropdownMenuItem<String>> individualItems = [];
for (var doc in membersSnapshot.docs) {
final data = doc.data();
final role = (data['role'] ?? '').toString().toUpperCase();
final name = data['name'] ?? '';
final gender = (data['gender'] ?? '').toString().toUpperCase();
if (role == 'ANIMAL' || role == 'PLANT') continue; // Skip pets/plants
if (role == 'FATHER') {
fatherUid = doc.id;
fatherName = name;
parentUids.add(doc.id);
} else if (role == 'MOTHER') {
motherUid = doc.id;
motherName = name;
parentUids.add(doc.id);
} else if (role == 'BOY') {
boysUids.add(doc.id);
childrenUids.add(doc.id);
individualItems.add(DropdownMenuItem(
value: doc.id, child: Text('👦 $name')));
} else if (role == 'GIRL') {
girlsUids.add(doc.id);
childrenUids.add(doc.id);
individualItems.add(DropdownMenuItem(
value: doc.id, child: Text('👧 $name')));
} else {
individualItems.add(DropdownMenuItem(
value: doc.id, child: Text('👤 $name')));
}
}
// 2. PARENTS visible
if (parentUids.isNotEmpty) {
options.add(DropdownMenuItem(
value: 'PARENTS', child: Text('🧑🤝🧑 Parents')));
}
// 3. FATHER
if (fatherUid != null && fatherName != null) {
options.add(DropdownMenuItem(
value: fatherUid, child: Text('👨 $fatherName')));
}
// 4. MOTHER
if (motherUid != null && motherName != null) {
options.add(DropdownMenuItem(
value: motherUid, child: Text('👩 $motherName')));
}
// 5. CHILDREN
if (childrenUids.length >= 2) {
options.add(DropdownMenuItem(
value: 'CHILDREN', child: Text('👶 Children')));
}
// 6. BOYS
for (var item in individualItems.where((e) => e.value != null && boysUids.contains(e.value))) {
options.add(item);
}
// 7. GIRLS
for (var item in individualItems.where((e) => e.value != null && girlsUids.contains(e.value))) {
options.add(item);
}
// Others
for (var item in individualItems.where((e) =>
e.value != null &&
!boysUids.contains(e.value) &&
!girlsUids.contains(e.value) &&
e.value != fatherUid &&
e.value != motherUid)) {
options.add(item);
}
if (!mounted) return;
setState(() {
_assignableOptions = options;
});
}
void _loadUserRole() async {
final uid = FirebaseAuth.instance.currentUser?.uid;
if (uid == null) return;
final doc = await FirebaseFirestore.instance.collection('users').doc(uid).get();
if (doc.exists) {
if (!mounted) return;
setState(() {
_currentUserRole = (doc.data()?['role'] ?? '').toString().toUpperCase();
});
if (_currentUserRole == 'MOTHER' || _currentUserRole == 'FATHER') {
_loadAssignableMembers();
}
}
}
void _saveReminders() async {
final uid = FirebaseAuth.instance.currentUser?.uid;
if (uid == null) return;
await FirebaseFirestore.instance
.collection('users')
.doc(uid)
.set({'reminders': reminders}, SetOptions(merge: true));
}
void _addOrEditReminder({int? index}) {
if (index != null) {
reminderController.text = reminders[index];
} else {
reminderController.clear();
}
showDialog(
context: context,
builder: (_) => AlertDialog(
title: Text(index != null ? "Remindırı Düzenle" : "Yeni Remindır"),
content: TextField(
controller: reminderController,
decoration: const InputDecoration(labelText: "Hatırlatıcı"),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text("İptal")),
ElevatedButton(
onPressed: () {
final text = reminderController.text.trim();
if (text.isEmpty) return;
if (!mounted) return;
setState(() {
if (index != null) {
reminders[index] = text;
} else {
reminders.add(text);
}
});
_saveReminders();
Navigator.pop(context);
},
child: const Text("Kaydet"),
),
],
),
);
}
void _deleteReminder(int index) {
if (!mounted) return;
setState(() => reminders.removeAt(index));
_saveReminders();
}
void _loadTasks() async {
final uid = FirebaseAuth.instance.currentUser?.uid;
if (uid == null) return;
final userDoc = await FirebaseFirestore.instance.collection('users').doc(uid).get();
final role = userDoc.data()?['role']?.toString().toUpperCase() ?? '';
final gender = userDoc.data()?.containsKey('gender') == true
? (userDoc.data()?['gender'] ?? '').toString().toUpperCase()
: '';
final name = userDoc.data()?['fullName']?.toString() ?? '';
final familyRef = userDoc.data()?['familyRef'];
if (familyRef == null) return;
final membersSnapshot = await FirebaseFirestore.instance
.collection('families')
.doc(familyRef)
.collection('members')
.get();
List<Map<String, dynamic>> visibleTasks = [];
for (var member in membersSnapshot.docs) {
final memberId = member.id;
final taskSnap = await FirebaseFirestore.instance
.collection('users')
.doc(memberId)
.collection('tasks')
.get();
for (var doc in taskSnap.docs) {
final task = doc.data();
task['id'] = doc.id;
final assignedTo = task['assignedTo'];
if (role == 'MOTHER' || role == 'FATHER') {
visibleTasks.add(task);
} else if (role == 'BOY' || role == 'GIRL') {
if (assignedTo == 'Family' ||
assignedTo == uid ||
assignedTo == 'CHILDREN' ||
(assignedTo == 'Boy' && role == 'BOY') ||
(assignedTo == 'Girl' && role == 'GIRL')) {
visibleTasks.add(task);
}
}
}
}
if (!mounted) return;
setState(() {
taskData = visibleTasks;
});
}
void _checkForInvitations() async {
final refCode = await FamilyService().getCurrentUserRefCode();
if (refCode == null) return;
_invitationSubscription =
FamilyService().getUserInvitationsStream(refCode).listen((snapshot) {
if (!mounted) return;
if (snapshot.docs.isNotEmpty) {
final invitation = snapshot.docs.first;
final data = invitation.data() as Map<String, dynamic>;
showDialog(
context: context,
barrierDismissible: false,
builder: (_) => AlertDialog(
title: const Text("Aile Daveti"),
content: Text(
"${data['fromName']} seni '${data['role']}' rolüyle ${data['familyName']} ailesine davet etti. Katılmak ister misin?"),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text("Hayır")),
ElevatedButton(
onPressed: () async {
await FamilyService().acceptInvitation(invitation);
if (!mounted) return;
Navigator.pop(context);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Daveti kabul ettiniz.")));
},
child: const Text("Evet"),
),
],
),
);
}
});
}
@override
Widget build(BuildContext context) {
final greeting = getGreeting();
return Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(100),
child: AppBar(
elevation: 0,
automaticallyImplyLeading: false,
flexibleSpace: SafeArea(
child: Stack(
clipBehavior: Clip.none,
children: [
Center(
child: Padding(
padding: const EdgeInsets.only(top: 20),
child: Container(
margin: const EdgeInsets.only(left: 50, right: 20),
padding: const EdgeInsets.only(left: 33, right: 12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 10,
offset: Offset(0, 15),
),
],
),
height: 55,
alignment: const Alignment(-1.0, -0.7),
child: Text(
_userName,
style: const TextStyle(
fontSize: 19,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
),
),
),
Positioned(
top: 18,
left: 25,
child: GestureDetector(
onTap: () {
showDialog(
context: context,
builder: (context) => const SlideMenu(),
);
},
child: Container(
width: 50,
height: 50,
decoration: const BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
child: ClipOval(
child: Image.asset(
'assets/images/person.png',
fit: BoxFit.cover,
),
),
),
),
),
Positioned(
top: 37,
right: 25,
child: const Icon(
Icons.notifications_none,
size: 32,
color: Colors.black,
),
),
Positioned(
top: 48,
right: 100,
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => const FamilyMembersPage()),
);
},
child: Image.asset(
'assets/images/family/familytest.png',
width: 40,
height: 40,
fit: BoxFit.contain,
),
),
),
],
),
),
),
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(greeting,
style:
const TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
const SizedBox(height: 20),
GestureDetector(
onTap: () => _addOrEditReminder(),
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.orange[900],
borderRadius: BorderRadius.circular(12)),
child: const Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(' Reminders',
style: TextStyle(color: Colors.white, fontSize: 18)),
Icon(Icons.add, color: Colors.white)
],
),
),
),
const SizedBox(height: 10),
Container(
height: 75,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.orange[900]!, width: 2),
),
child: reminders.isEmpty
? const Center(child: Text("Henüz hatırlatıcı eklenmedi."))
: ListView.builder(
itemCount: reminders.length,
itemBuilder: (context, i) {
return ListTile(
leading: Text(
"${i + 1}.",
style: TextStyle(
color: Colors.orange[900],
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
title: Text(reminders[i]),
trailing: Wrap(
children: [
IconButton(
icon:
Icon(Icons.edit, color: Color(0xFFBF360C)),
onPressed: () => _addOrEditReminder(index: i),
),
IconButton(
icon: Icon(Icons.delete,
color: Color(0xFFBF360C)),
onPressed: () => _deleteReminder(i),
),
],
),
);
},
),
),
const SizedBox(height: 20),
GestureDetector(
onTap: () {
if (_currentUserRole == 'CHILD') {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Çocuklar görev atayamaz.")),
);
} else {
_showTaskDialog();
}
},
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.orange[900],
borderRadius: BorderRadius.circular(12)),
child: const Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(' To-Do List',
style: TextStyle(color: Colors.white, fontSize: 18)),
Icon(Icons.add, color: Colors.white)
],
),
),
),
const SizedBox(height: 10),
SizedBox(
height: 200,
child: PageView.builder(
controller: _pageController,
itemCount: taskData.length,
onPageChanged: (i) =>
setState(() => _currentPage = i.toDouble()),
itemBuilder: (context, index) {
final task = taskData[index];
final isFocused = _currentPage.round() == index;
return GestureDetector(
onTap: () {
showDialog(
context: context,
builder: (_) => AlertDialog(
title: const Text("Görev Seç"),
content: const Text("Ne yapmak istiyorsun?"),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
_showTaskDialog(existingTask: task);
},
child: const Text("Düzenle")),
TextButton(
onPressed: () {
Navigator.pop(context);
_deleteTask(task['id']);
},
child: const Text("Sil",
style: TextStyle(color: Colors.red))),
TextButton(
onPressed: () => Navigator.of(context, rootNavigator: true).pop(),
child: const Text("İptal")),
],
),
);
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
margin: const EdgeInsets.symmetric(horizontal: 8),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color:
isFocused ? Colors.orange[900] : Colors.grey[200],
borderRadius: BorderRadius.circular(24),
boxShadow: [
BoxShadow(
color: Colors.grey.shade400,
blurRadius: 6,
offset: const Offset(0, 3))
],
),
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Flexible(
child: Text(
'📝 ${task['task'] ?? ''}', // ✅ Emoji ikon
style: TextStyle(
color: isFocused
? Colors.white
: Colors.black87,
fontSize: 18,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
),
],
),
if (task['point'] != null)
Padding(
padding: const EdgeInsets.only(top: 6.0),
child: Text(
'⭐ ${task['point']}',
style: TextStyle(
color: isFocused
? Colors.white
: Colors.black87,
fontSize: 18,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
),
if (task['assignedTo'] != null)
Padding(
padding: const EdgeInsets.only(top: 4.0),
child: Text(
'👤 ${task['assignedTo']}',
style: TextStyle(
color: isFocused
? Colors.white
: Colors.black87,
fontSize: 18,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
),
],
),
),
),
);
},
),
),
],
),
),
);
}
String getGreeting() {
final hour = DateTime.now().hour;
if (hour >= 5 && hour < 12) return 'Good morning, $_userName.';
if (hour >= 12 && hour < 18) return 'Good afternoon, $_userName.';
if (hour >= 18 && hour < 22) return 'Good evening, $_userName.';
return 'Good night, $_userName.';
}
void _showTaskDialog({Map<String, dynamic>? existingTask}) {
if (existingTask != null) {
taskController.text = existingTask['task'] ?? '';
pointController.text = (existingTask['point']?.toString() ?? '');
selectedPerson = existingTask['assignedTo'] ?? 'Family';
usePoint = existingTask['point'] != null;
useDate = existingTask['date'] != null;
selectedDate = existingTask['date'] != null
? DateTime.tryParse(existingTask['date'])
: null;
} else {
taskController.clear();
pointController.clear();
selectedPerson = 'Family';
usePoint = false;
useDate = false;
selectedDate = null;
}
showDialog(
context: context,
builder: (_) => StatefulBuilder(
builder: (context, setState) => AlertDialog(
title: Text(
existingTask != null ? "Görevi Düzenle" : "Yeni Görev Oluştur"),
content: SingleChildScrollView(
child: Column(
children: [
TextField(
controller: taskController,
decoration: const InputDecoration(labelText: "Görev Adı")),
DropdownButtonFormField<String>(
value: _assignableOptions.any((item) => item.value == selectedPerson) ? selectedPerson : null,
onChanged: (val) => setState(() => selectedPerson = val),
items: _assignableOptions,
decoration: const InputDecoration(labelText: "Atanacak Kişi"),
),
CheckboxListTile(
title: const Text("Puan eklemek istiyor musunuz?"),
value: usePoint,
onChanged: (val) => setState(() => usePoint = val ?? false),
),
if (usePoint)
TextField(
controller: pointController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(labelText: "Puan"),
),
CheckboxListTile(
title: const Text("Tarih eklemek istiyor musunuz?"),
value: useDate,
onChanged: (val) async {
setState(() => useDate = val ?? false);
if (useDate) {
final pickedDate = await showDatePicker(
context: context,
initialDate: selectedDate ?? DateTime.now(),
firstDate: DateTime(2020),
lastDate: DateTime(2030),
);
if (pickedDate != null) {
setState(() => selectedDate = pickedDate);
}
} else {
selectedDate = null;
}
},
),
],
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text("İptal")),
ElevatedButton(
onPressed: () async {
final uid = FirebaseAuth.instance.currentUser?.uid;
if (uid == null || taskController.text.trim().isEmpty) return;
final data = {
'task': taskController.text.trim(),
'point': usePoint
? int.tryParse(pointController.text.trim())
: null,
'date': useDate && selectedDate != null
? selectedDate!.toIso8601String()
: null,
'assignedTo': selectedPerson,
};
final tasksRef = FirebaseFirestore.instance
.collection('users')
.doc(uid)
.collection('tasks');
if (existingTask != null && existingTask['id'] != null) {
await tasksRef.doc(existingTask['id']).update(data);
} else {
await tasksRef.add(data);
}
Navigator.pop(context);
_loadTasks();
},
child: const Text("Kaydet"),
)
],
),
),
);
}
void _deleteTask(String id) async {
final uid = FirebaseAuth.instance.currentUser?.uid;
if (uid == null) return;
await FirebaseFirestore.instance
.collection('users')
.doc(uid)
.collection('tasks')
.doc(id)
.delete();
_loadTasks();
}
}
![]() |
Notes is a web-based application for online taking notes. You can take your notes and share with others people. If you like taking long notes, notes.io is designed for you. To date, over 8,000,000,000+ notes created and continuing...
With notes.io;
- * You can take a note from anywhere and any device with internet connection.
- * You can share the notes in social platforms (YouTube, Facebook, Twitter, instagram etc.).
- * You can quickly share your contents without website, blog and e-mail.
- * You don't need to create any Account to share a note. As you wish you can use quick, easy and best shortened notes with sms, websites, e-mail, or messaging services (WhatsApp, iMessage, Telegram, Signal).
- * Notes.io has fabulous infrastructure design for a short link and allows you to share the note as an easy and understandable link.
Fast: Notes.io is built for speed and performance. You can take a notes quickly and browse your archive.
Easy: Notes.io doesn’t require installation. Just write and share note!
Short: Notes.io’s url just 8 character. You’ll get shorten link of your note when you want to share. (Ex: notes.io/q )
Free: Notes.io works for 14 years and has been free since the day it was started.
You immediately create your first note and start sharing with the ones you wish. If you want to contact us, you can use the following communication channels;
Email: [email protected]
Twitter: http://twitter.com/notesio
Instagram: http://instagram.com/notes.io
Facebook: http://facebook.com/notesio
Regards;
Notes.io Team
