calendar

mail@pastecode.io avatar
unknown
dart
3 years ago
16 kB
2
Indexable
Never
import 'package:flutter/material.dart';

import 'components/model/calendar_model.dart';

enum CalendarViews { dates, months, year }

class MyApp extends StatefulWidget {
  @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 = [];

  @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(() {});
    }
  }

  @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 - 7],index,
          );
        }
        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,int index) {
    return GestureDetector(
      onTap: (){
        if (_sequentialDates!.contains(index)) {
          setState(() {
            _sequentialDates!.removeWhere((val) => val == index);
          });
        } else {
          setState(() {
            _selectedItems.add(index);
          });
        }
      },
      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),
                  ),
                );
              }),
        ),
      ],
    );
  }
}