import 'package:flutter/material.dart';
import 'components/model/calendar_model.dart';
enum CalendarViews { dates, months, year }
class MyApp extends StatefulWidget {
final bool multiSelection;
const MyApp({Key? key, this.multiSelection = false}) : super(key: key);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int _currentPage = 0;
final PageController _controller = PageController(
initialPage: 999,
);
DateTime? _currentDateTime;
DateTime? _selectedDateTime;
List<CalendarModel>? _sequentialDates = [];
int? midYear;
CalendarViews _currentView = CalendarViews.dates;
final List<String> _weekDays = [
'MON',
'TUE',
'WED',
'THU',
'FRI',
'SAT',
'SUN'
];
final List<String> _monthNames = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
];
List<int> _selectedItems = [];
final bool isSelected = false;
@override
void initState() {
super.initState();
final date = DateTime.now();
_currentDateTime = DateTime(date.year, date.month);
_selectedDateTime = DateTime(date.year, date.month, date.day);
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
setState(() => _getCalendar());
});
}
@override
void dispose() {
super.dispose();
}
onChanged(int index) {
bool next = index > _currentPage;
_currentPage = index;
print("currentPage: ${_currentPage}");
print("next: ${next}");
print("index: ${index}");
if (_currentView == CalendarViews.dates) {
setState(() => (next) ? _getNextMonth() : _getPrevMonth());
} else if (_currentView == CalendarViews.year) {
if (next) {
midYear = (midYear == null) ? _currentDateTime!.year + 9 : midYear! + 9;
} else {
midYear = (midYear == null) ? _currentDateTime!.year - 9 : midYear! - 9;
}
setState(() {});
}
}
void _itemChange(int itemValue, bool isSelected) {
setState(() {
if (isSelected) {
_selectedItems.add(itemValue);
} else {
_selectedItems.remove(itemValue);
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(
children: [
/// Dropdown
Align(
alignment: Alignment.centerRight,
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
focusColor: Theme.of(context).primaryColor,
value: _monthNames[_currentDateTime!.month - 1],
/* value: changeMonthIndex
.state[ref.watch(changeMontIndexWithSlider)],*/
//value: changeMonthIndex.state[ref.watch(selectedIndex)],
icon: const Icon(Icons.keyboard_arrow_down),
items:
_monthNames.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: TextStyle(
fontSize: 18,
color: Theme.of(context).accentColor),
));
}).toList(),
onChanged: (value) {
setState(() {
_monthNames[_currentDateTime!.month - 1] = value!;
});
// ref.read(changeMonth.state).state = value as List<String>;
//_chosenValue = value!;
/*setState(() {
_chosenValue = value;
});*/
},
)),
),
/// Middle month year
InkWell(
onTap: () =>
setState(() => _currentView = CalendarViews.months),
child: Center(
child: Text(
'${_monthNames[_currentDateTime!.month - 1]} ${_currentDateTime!.year}',
style: TextStyle(
color: Theme.of(context).accentColor,
fontSize: 18,
fontWeight: FontWeight.w700),
),
),
),
const SizedBox(
height: 50,
),
/// Date List
SizedBox(
height: 40,
child: GridView.builder(
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 7),
itemCount: _weekDays.length,
itemBuilder: (context, index) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: FittedBox(
fit: BoxFit.scaleDown,
child: Text(_weekDays[index])),
);
}),
),
Expanded(
child: PageView.builder(
controller: _controller,
scrollDirection: Axis.horizontal,
physics: const BouncingScrollPhysics(),
onPageChanged: onChanged,
itemBuilder: (BuildContext context, int index) {
return Container(
margin: const EdgeInsets.all(15),
height: MediaQuery.of(context).size.height,
//height: MediaQuery.of(context).size.height * 0.6,
child: (_currentView == CalendarViews.dates)
? _datesView()
: (_currentView == CalendarViews.months)
? _showMonthsList()
: _yearsView(
midYear ?? _currentDateTime!.year));
},
),
),
],
),
),
),
);
}
// dates view
Widget _datesView() {
return _calendarBody();
}
// next / prev month buttons
Widget _toggleBtn(bool next) {
return InkWell(
onTap: () {
if (_currentView == CalendarViews.dates) {
setState(() => (next) ? _getNextMonth() : _getPrevMonth());
} else if (_currentView == CalendarViews.year) {
if (next) {
midYear =
(midYear == null) ? _currentDateTime!.year + 9 : midYear! + 9;
} else {
midYear =
(midYear == null) ? _currentDateTime!.year - 9 : midYear! - 9;
}
setState(() {});
}
},
child: Container(
alignment: Alignment.center,
width: 50,
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
border: Border.all(color: Theme.of(context).primaryColor),
boxShadow: [
BoxShadow(
color: Colors.white.withOpacity(0.5),
offset: const Offset(3, 3),
blurRadius: 3,
spreadRadius: 0,
),
],
gradient: LinearGradient(
colors: [Colors.black, Colors.black.withOpacity(0.1)],
stops: [0.5, 1],
begin: Alignment.bottomRight,
end: Alignment.topLeft,
)),
child: Icon(
(next) ? Icons.arrow_forward_ios : Icons.arrow_back_ios,
color: Colors.white,
),
));
}
// calendar
Widget _calendarBody() {
if (_sequentialDates == null) return Container();
return GridView.builder(
shrinkWrap: true,
padding: EdgeInsets.zero,
itemCount: _sequentialDates!.length + 7,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
mainAxisSpacing: 20,
crossAxisCount: 7,
crossAxisSpacing: 20,
),
itemBuilder: (context, index) {
if (index < 7) return Text('');
if (_sequentialDates![index - 7].date == _selectedDateTime) {
/*if (_selectedItems.contains(index)) {
setState(() {
_selectedItems.removeWhere((val) => val == index);
});
} else {
setState(() {
_selectedItems.add(index);
});
}*/
return _selector(
//_sequentialDates![index]
_sequentialDates![index - 7],isSelected,
);
}
return _calendarDates(_sequentialDates![index - 7]);
},
);
}
// calendar header
Widget _weekDayTitle(int index) {
return Text(
_weekDays[index],
style: TextStyle(
color: Theme.of(context).cardColor,
fontSize: 12,
fontWeight: FontWeight.w500,
),
);
}
// calendar element
Widget _calendarDates(CalendarModel calendarDate) {
return InkWell(
onTap: () {
if (_selectedDateTime != calendarDate.date) {
if (calendarDate.nextMonth) {
_getNextMonth();
} else if (calendarDate.prevMonth) {
_getPrevMonth();
}
setState(() => _selectedDateTime = calendarDate.date!);
}
},
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Spacer(),
Container(
height: 5,
width: 5,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: calendarDate.thisMonth
? Theme.of(context).accentColor
: Theme.of(context).cardColor.withOpacity(0.5)),
),
const Spacer(),
Text(
'${calendarDate.date!.day}',
style: TextStyle(
color: (calendarDate.thisMonth)
? Theme.of(context).accentColor
//(calendarDate.date!.weekday == DateTime.sunday) ? Colors.black : Colors.white
: Theme.of(context).cardColor.withOpacity(0.5)
//(calendarDate.date!.weekday == DateTime.sunday) ? Colors.yellow.withOpacity(0.5) : Colors.white.withOpacity(0.5),
),
),
const Spacer(),
],
),
);
}
// date selector
Widget _selector(
CalendarModel calendarDate,bool iseSelected
) {
// var isSelected = _sequentialDates!.contains(calendarDate);
return GestureDetector(
onTap: () {
_itemChange;
},
child: Container(
width: 30,
height: 30,
decoration: BoxDecoration(
color: calendarDate == _sequentialDates
? Theme.of(context).secondaryHeaderColor
: Theme.of(context).buttonColor,
borderRadius: BorderRadius.circular(10),
),
child: Container(
decoration: BoxDecoration(
//color: Colors.white.withOpacity(0.9),
borderRadius: BorderRadius.circular(10),
),
child: Column(
children: [
const Spacer(),
Container(
height: 5,
width: 5,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: calendarDate == _sequentialDates
? Theme.of(context).accentColor
: Theme.of(context).primaryColor),
),
const Spacer(),
Text(
'${calendarDate.date!.day}',
style: TextStyle(
color: calendarDate == _sequentialDates
? Colors.black
: Colors.white,
fontWeight: FontWeight.w700),
),
const Spacer(),
],
),
),
),
);
}
// get next month calendar
void _getNextMonth() {
if (_currentDateTime!.month == 12) {
_currentDateTime = DateTime(_currentDateTime!.year + 1, 1);
} else {
_currentDateTime =
DateTime(_currentDateTime!.year, _currentDateTime!.month + 1);
}
_getCalendar();
}
// get previous month calendar
void _getPrevMonth() {
if (_currentDateTime!.month == 1) {
_currentDateTime = DateTime(_currentDateTime!.year - 1, 12);
} else {
_currentDateTime =
DateTime(_currentDateTime!.year, _currentDateTime!.month - 1);
}
_getCalendar();
}
// get calendar for current month
void _getCalendar() {
_sequentialDates = CustomCalendar().getMonthCalendar(
_currentDateTime!.month, _currentDateTime!.year,
startWeekDay: StartWeekDay.monday);
}
// show months list
Widget _showMonthsList() {
return Column(
children: <Widget>[
InkWell(
onTap: () => setState(() => _currentView = CalendarViews.year),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Text(
'${_currentDateTime!.year}',
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w700,
color: Colors.black),
),
),
),
const Divider(
color: Colors.white,
),
Expanded(
child: ListView.builder(
padding: EdgeInsets.zero,
itemCount: _monthNames.length,
itemBuilder: (context, index) => ListTile(
onTap: () {
_currentDateTime = DateTime(_currentDateTime!.year, index + 1);
_getCalendar();
setState(() => _currentView = CalendarViews.dates);
},
title: Center(
child: Text(
_monthNames[index],
style: TextStyle(
fontSize: 18,
color: (index == _currentDateTime!.month - 1)
? Colors.blueAccent
: Colors.black),
),
),
),
),
),
],
);
}
// years list views
Widget _yearsView(int midYear) {
return Column(
children: <Widget>[
Row(
children: <Widget>[
_toggleBtn(false),
const Spacer(),
_toggleBtn(true),
],
),
Expanded(
child: GridView.builder(
shrinkWrap: true,
itemCount: 9,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
),
itemBuilder: (context, index) {
int thisYear;
if (index < 4) {
thisYear = midYear - (4 - index);
} else if (index > 4) {
thisYear = midYear + (index - 4);
} else {
thisYear = midYear;
}
return ListTile(
onTap: () {
_currentDateTime =
DateTime(thisYear, _currentDateTime!.month);
_getCalendar();
setState(() => _currentView = CalendarViews.months);
},
title: Text(
'$thisYear',
style: TextStyle(
fontSize: 18,
color: (thisYear == _currentDateTime!.year)
? Colors.pink
: Colors.black),
),
);
}),
),
],
);
}
void selectDate(CalendarModel calendarModel) {
if (widget.multiSelection) {
final isSelected = _sequentialDates!.contains(calendarModel);
setState(() {
isSelected
? _sequentialDates!.remove(calendarModel)
: _sequentialDates!.add(calendarModel);
});
} else {
Navigator.pop(context, calendarModel);
}
}
}