task_scheduler 0.0.2 copy "task_scheduler: ^0.0.2" to clipboard
task_scheduler: ^0.0.2 copied to clipboard

The Task Scheduler Widget is a Flutter component designed to display a schedule with customizable time slots and tasks. It provides functionalities to schedule tasks, rearrange them, and visualize the [...]

example/lib/main.dart

import 'dart:developer';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:task_scheduler/task_scheduler.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Task Scheduler',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Task Scheduler Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  // minute intervals
  int timeInterval = 30;

  // declare the TaskScheduler and TaskScheduleView
  late TaskScheduler taskScheduler;
  late TaskScheduleView taskScheduleView;

  List<String> resources = ['Cedric', 'Yung', 'Moss', 'Matt'];

  // declare resource headers
  List<ScheduleResourceHeader> headers = [
    ScheduleResourceHeader(
        id: '1',
        title: 'Cedric',
        position: 0,
        child: Stack(
          children: [
            Container(
              width: 64,
              height: 64,
              decoration: BoxDecoration(
                shape: BoxShape.circle,
                border: Border.all(
                  color: Colors.red,
                  width: 2,
                ),
              ),
              child: CircleAvatar(
                backgroundImage: NetworkImage(
                    'https://cdn.pixabay.com/photo/2018/08/28/12/41/avatar-3637425_1280.png'), // Replace URL with your image URL
              ),
            ),
            Positioned(
              bottom: 0,
              right: 0,
              child: Container(
                padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
                decoration: BoxDecoration(
                  color: Colors.blue,
                  borderRadius: BorderRadius.only(topLeft: Radius.circular(12)),
                ),
                child: Text(
                  'Cedric',
                  style: TextStyle(color: Colors.white, fontSize: 12),
                ),
              ),
            ),
          ],
        )),
    ScheduleResourceHeader(
        id: '2',
        title: 'Yung',
        position: 1,
        child: Stack(
          children: [
            Container(
              width: 64,
              height: 64,
              decoration: BoxDecoration(
                shape: BoxShape.circle,
                border: Border.all(
                  color: Colors.orange,
                  width: 2,
                ),
              ),
              child: CircleAvatar(
                backgroundImage: NetworkImage(
                    'https://cdn.pixabay.com/photo/2020/05/08/02/55/african-american-5143919_1280.png'),
              ),
            ),
            Positioned(
              bottom: 0,
              right: 0,
              child: Container(
                padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
                decoration: BoxDecoration(
                  color: Colors.blue,
                  borderRadius: BorderRadius.only(topLeft: Radius.circular(12)),
                ),
                child: Text(
                  'Yung',
                  style: TextStyle(color: Colors.white, fontSize: 12),
                ),
              ),
            ),
          ],
        )),
    ScheduleResourceHeader(
        id: '3',
        position: 2,
        title: 'Moss',
        child: Stack(
          children: [
            Container(
              width: 64,
              height: 64,
              decoration: BoxDecoration(
                shape: BoxShape.circle,
                border: Border.all(
                  color: Colors.green,
                  width: 2,
                ),
              ),
              child: CircleAvatar(
                backgroundImage: NetworkImage(
                    'https://cdn.pixabay.com/photo/2016/05/26/14/39/parrot-1417286_1280.png'),
              ),
            ),
            Positioned(
              bottom: 0,
              right: 0,
              child: Container(
                padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
                decoration: BoxDecoration(
                  color: Colors.blue,
                  borderRadius: BorderRadius.only(topLeft: Radius.circular(12)),
                ),
                child: Text(
                  'Moss',
                  style: TextStyle(color: Colors.white, fontSize: 12),
                ),
              ),
            ),
          ],
        )),
    ScheduleResourceHeader(
        id: '4',
        position: 3,
        title: 'Matt',
        child: Stack(
          children: [
            Container(
              width: 64,
              height: 64,
              decoration: BoxDecoration(
                shape: BoxShape.circle,
                border: Border.all(
                  color: Colors.black,
                  width: 2,
                ),
              ),
              child: CircleAvatar(
                backgroundImage: NetworkImage(
                    'https://cdn.pixabay.com/photo/2016/05/12/23/03/lamb-1388937_1280.png'),
              ),
            ),
            Positioned(
              bottom: 0,
              right: 0,
              child: Container(
                padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
                decoration: BoxDecoration(
                  color: Colors.blue,
                  borderRadius: BorderRadius.only(topLeft: Radius.circular(12)),
                ),
                child: Text(
                  'Matt',
                  style: TextStyle(color: Colors.white, fontSize: 12),
                ),
              ),
            ),
          ],
        ))
  ];

  @override
  void initState() {
    super.initState();

    // declare entries
    List<ScheduleEntry> entries = [
      ScheduleEntry(
        color: Colors.blue,
        id: '123',
        resource: ResourceScheduleEntry(
          index:
              0, // uses this index to add entries against resources, i.e. 0 = 1st resource, 1 = 2nd etc
          hour: 9,
          minutes: 60,
        ),
        duration: 60,
        options: TaskSchedulerSettings(
          isTaskDraggable: true, // false to disable drag
        ),
        onTap: () {
          ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
              content: Text("Support"),
              backgroundColor: Colors.green,
              behavior: SnackBarBehavior.floating));
        },
        child: Text('Support', style: TextStyle(fontSize: 14)),
      ),
      ScheduleEntry(
        color: Colors.green,
        id: '123444',
        resource: ResourceScheduleEntry(
          index:
              0, // uses this index to add entries against resources, i.e. 0 = 1st resource, 1 = 2nd etc
          hour: 8,
          minutes: 30,
        ),
        duration: 30,
        options: TaskSchedulerSettings(
          isTaskDraggable: true, // false to disable drag
          taskResizeMode: {
            'allowResize': true,
            'onResizeEnd': onResizeEnd,
            'onResizeUpdate': onResizeUpdate
          },
        ),
        onTap: () {
          ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
              content: Text("Plan"),
              backgroundColor: Colors.green,
              behavior: SnackBarBehavior.floating));
        },
        child: Text(
          'Plan',
          style: TextStyle(fontSize: 14),
        ),
      ),
      ScheduleEntry(
        color: Colors.pink,
        id: '12344',
        resource: ResourceScheduleEntry(
          index:
              1, // uses this index to add entries against resources, i.e. 0 = 1st resource, 1 = 2nd etc
          hour: 8,
          minutes: 0,
        ),
        duration: 120,
        options: TaskSchedulerSettings(
          isTaskDraggable: true, // false to disable drag
        ),
        onTap: () {
          ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
              content: Text("Project"),
              backgroundColor: Colors.green,
              behavior: SnackBarBehavior.floating));
        },
        child: Text('Project', style: TextStyle(fontSize: 14)),
      ),
      ScheduleEntry(
        color: Colors.orange,
        id: '12345',
        resource: ResourceScheduleEntry(
          index:
              3, // uses this index to add entries against resources, i.e. 0 = 1st resource, 1 = 2nd etc
          hour: 8,
          minutes: 0,
        ),
        duration: 240,
        options: TaskSchedulerSettings(
          isTaskDraggable: true, // false to disable drag
        ),
        onTap: () {
          ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
              content: Text("General"),
              backgroundColor: Colors.green,
              behavior: SnackBarBehavior.floating));
        },
        child: Text('General', style: TextStyle(fontSize: 14)),
      )
    ];

    List<BlockedEntry> blockedEntries = [
      BlockedEntry(
          resource: ResourceScheduleEntry(
            index:
                2, // uses this index to add entries against resources, i.e. 0 = 1st resource, 1 = 2nd etc
            hour: 8,
            minutes: 0,
          ),
          duration: 60),
      BlockedEntry(
          resource: ResourceScheduleEntry(
            index:
                2, // uses this index to add entries against resources, i.e. 0 = 1st resource, 1 = 2nd etc
            hour: 11,
            minutes: 0,
          ),
          duration: 120),
      BlockedEntry(
          resource: ResourceScheduleEntry(
            index:
                0, // uses this index to add entries against resources, i.e. 0 = 1st resource, 1 = 2nd etc
            hour: 9,
            minutes: 0,
          ),
          duration: 60),
      BlockedEntry(
          resource: ResourceScheduleEntry(
            index:
                1, // uses this index to add entries against resources, i.e. 0 = 1st resource, 1 = 2nd etc
            hour: 10,
            minutes: 30,
          ),
          duration: 60)
    ];

    // instatiate the TaskScheduleView and pass TaskScheduler
    taskScheduleView = TaskScheduleView(
        taskScheduler: TaskScheduler(
      scheduleStartTime: ScheduleTimeline(hour: 8),
      scheduleEndTime: ScheduleTimeline(hour: 17),
      onEmptySlotPressed: handleEmptySlotTap,
      onDragAccept: handleDrop,
      entries: [],
      headers: CalendarView.weekView(),
      timeFormat: SchedulerTimeSettings(
        minuteInterval: timeInterval,
        use24HourFormat: true,
        includePeriod: true,
        includeMinutes: false,
      ),
    ));

    taskScheduler = taskScheduleView.loadScheduleView(entries: entries);
  }

  void handleDrop(Map<String, dynamic> data) {
    TaskScheduleView view = TaskScheduleView(
        taskScheduler: TaskScheduler(
      scheduleStartTime: taskScheduler.scheduleStartTime,
      scheduleEndTime: taskScheduler.scheduleEndTime,
      onEmptySlotPressed: handleEmptySlotTap,
      onDragAccept: handleDrop,
      entries: taskScheduler.entries,
      headers: taskScheduler.headers,
      timeFormat: taskScheduler.timeFormat,
    ));

    setState(() {
      try {
        taskScheduler = view.updateScheduleView(view, data);
      } catch (e) {
        print(e.toString());
      }
    });
  }

  void onResizeEnd(Map<String, dynamic> resizeData) {
    // Define the function to handle resize end event
    // You can implement the logic here to handle resize end
    print('onResizeEnd');
  }

  void onResizeUpdate(ScheduleEntry entry) {
    // Define the function to handle resize update event
    // You can implement the logic here to handle resize update
    print('onResizeUpdate');
    taskScheduleView.onResizeEntry(entry);
  }

  void _createNewEntry(BuildContext context, Map<String, dynamic> data) {
    print(data);
    int resourceIndex = data['resource']['index'];
    String resourceName = data['resource_title'];
    String hour = (data['resource']['hour'] < 10)
        ? '0${data['resource']['hour']}'
        : data['resource']['hour'].toString();
    String minutes = (data['resource']['minutes'] < 10)
        ? '0${data['resource']['minutes']}'
        : data['resource']['minutes'].toString();

    TextEditingController titleController = TextEditingController();
    TextEditingController durationController = TextEditingController();

    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: const Text('Create New Entry'),
          content: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              TextField(
                keyboardType: TextInputType.text,
                controller: titleController,
                decoration: InputDecoration(hintText: "Enter title"),
              ),
              SizedBox(height: 15),
              TextField(
                keyboardType: TextInputType.number,
                controller: durationController,
                decoration: InputDecoration(hintText: "Enter duration"),
              ),
              SizedBox(height: 15),
              Text(
                "Time: $hour:$minutes\nResource: $resourceName",
                style: TextStyle(fontSize: 14),
              ),
            ],
          ),
          actions: <Widget>[
            TextButton(
              child: const Text('Cancel'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
            TextButton(
              child: const Text('Create'),
              onPressed: () {
                String title = titleController.text;
                String duration = durationController.text;

                Navigator.of(context).pop();

                if (title.isNotEmpty && duration.isNotEmpty) {
                  // create a new task scheduler
                  TaskScheduler newTaskScheduler = TaskScheduler(
                    scheduleStartTime: taskScheduler.scheduleStartTime,
                    scheduleEndTime: taskScheduler.scheduleEndTime,
                    onEmptySlotPressed: handleEmptySlotTap,
                    onDragAccept: handleDrop,
                    entries: taskScheduler.entries,
                    headers: taskScheduler.headers,
                    timeFormat: taskScheduler.timeFormat,
                  );

                  List<Color> colors = [
                    Colors.purple,
                    Colors.blue,
                    Colors.green,
                    Colors.orange,
                    Colors.lime,
                    Colors.cyan,
                    Colors.grey
                  ];

                  ScheduleEntry newEntry = ScheduleEntry(
                    color: colors[Random().nextInt(colors.length)],
                    id: generateId(5),
                    resource: ResourceScheduleEntry(
                      index: resourceIndex,
                      hour: int.parse(hour),
                      minutes: int.parse(minutes),
                    ),
                    duration: int.parse(duration),
                    options: TaskSchedulerSettings(
                      isTaskDraggable: true, // false to disable drag
                    ),
                    onTap: () {
                      print('clicked');
                      // implement onTap logic
                    },
                    child: Text(title, style: TextStyle(fontSize: 14)),
                  );

                  // check that the resource slot is available
                  if (taskScheduleView.isResourceSlotAvailable(newEntry)) {
                    // slot is available, add entry
                    newTaskScheduler.entries?.add(newEntry);
                  } else {
                    // slot not available
                    ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
                        content: Text("Error: Slot not Available."),
                        backgroundColor: Colors.red,
                        behavior: SnackBarBehavior.floating));
                  }

                  setState(() {
                    taskScheduler = newTaskScheduler;
                  });
                }
              },
            ),
          ],
        );
      },
    );
  }

  String generateId(int length) {
    const charset =
        'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    Random random = Random();
    return List.generate(
        length, (index) => charset[random.nextInt(charset.length)]).join();
  }

  void handleEmptySlotTap(Map<String, dynamic> data) {
    // Handle the returned data here
    _createNewEntry(context, data);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
          // Center is a layout widget. It takes a single child and positions it
          // in the middle of the parent.
          child:
              taskScheduler), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}
6
likes
0
points
0
downloads

Publisher

verified publisherpermanentlink.co.za

Weekly Downloads

The Task Scheduler Widget is a Flutter component designed to display a schedule with customizable time slots and tasks. It provides functionalities to schedule tasks, rearrange them, and visualize them efficiently.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, intl

More

Packages that depend on task_scheduler