sonjuro
sonjuro

Reputation: 43

Flutter: How to pass snapshot to floating action button?

I want to pass this documentSnapshot to my FloatingActionButton so that I can use it on another page, but how? I want to pass the documentSnapshot data to my AddTaskPage.

My documentSnapshot is under StreamBuilder.

This is my code:

final DocumentSnapshot documentSnapshot = snapshot.data!.docs[index];

This is my FloatingActionButton:

floatingActionButton: FadeInRight(
  delay: const Duration(milliseconds: 200),
  duration: const Duration(milliseconds: 500),
  child: FloatingActionButton.extended(
  label: const Text(
    'Add Timeline',
    style: TextStyle(
      color: Colors.white,
      fontFamily: 'poppins',
      fontWeight: FontWeight.w400,
      fontSize: 15,
      letterSpacing: 1,
    ),
  ),
  backgroundColor: Colors.black,
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.circular(6),
  ),
  onPressed: () {
    showModalBottomSheet(
      // isScrollControlled: true,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(10),
          topRight: Radius.circular(10),
        ),
      ),
        context: context,
        builder: (context) => const AddTaskPage(),
      );
    },
  ),
),

This is my AddTaskPage() code:

    import 'package:animate_do/animate_do.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:todoapp/authentication/auth.provider.dart';
import 'package:todoapp/models/timeline.model.dart';
import 'package:todoapp/services/notifications_service.dart';

class AddTaskPage extends StatefulWidget {
  const AddTaskPage({
    super.key,
  });
  @override
  State<AddTaskPage> createState() => _AddTaskPageState();
}

class _AddTaskPageState extends State<AddTaskPage> {
  final dateController = TextEditingController();
  final timeController = TextEditingController();
  final topicController = TextEditingController();

  final _formKey = GlobalKey<FormState>();

  final db = FirebaseFirestore.instance;

  final notifyHelper = NotifyHelper();

  DocumentReference uidRef = FirebaseFirestore.instance
      .collection('timeline')
      .doc(FirebaseAuth.instance.currentUser!.uid);

  void dateOnTap() async {
    TimeOfDay? pickTime = await showTimePicker(
        context: context,
        initialEntryMode: TimePickerEntryMode.input,
        initialTime: TimeOfDay.now());
    if (pickTime != null) {
      DateTime parsedTime =
          DateFormat.jm().parse(pickTime.format(context).toString());
      //converting to DateTime so that we can further format on different pattern.
      String formattedTime = DateFormat().add_jm().format(parsedTime);
      setState(() {
        timeController.text = formattedTime;
//  DateFormat.yMMMMd().format(pickTime);
      });
    }
  }

  // String uidFunction(String uid) {
  //   // dart unique string generator
  //   String _randomString = uid.toString() +
  //       math.Random().nextInt(9999).toString() +
  //       math.Random().nextInt(9999).toString() +
  //       math.Random().nextInt(9999).toString();
  //   return _randomString;
  // }

  void addFunction() async {
    final uid =
        await Provider.of<AuthProvider>(context, listen: false).getCurrentUID();
    DocumentReference ref =
        db.collection('users').doc(uid).collection('time-line').doc();
    if (dateController.text.trim().isNotEmpty &&
        timeController.text.trim().isNotEmpty &&
        topicController.text.trim().isNotEmpty) {
      await db
          .collection('users')
          .doc(uid)
          .collection('time-line')
          .add(Timeline(
                  id: ref.id, // auto generated id
                  date: dateController.text.trim(),
                  time: timeController.text.trim(),
                  topic: topicController.text.trim(),
                  isDone: false)
              .toJson());

      // DateTime date = DateFormat.jm().parse(timeController.text.toString());
      // var myTime = DateFormat('HH:mm').format(date);
      // var hour = int.parse(formattedTime.toString().split(':')[0]);
      // var min = int.parse(formattedTime.toString().split(':')[1]);

      notifyHelper.displayNotification(
          title: topicController.text.trim(), body: 'Don\'t forget your task!');

      // notifyHelper.scheduledNotification(hour, min, timeline);
    } else {
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
          content: Text(
        'All fields required!',
        style: TextStyle(fontFamily: 'poppins', fontWeight: FontWeight.w400),
      )));
    }
    Navigator.of(context).pop();
  }

  void cancelAddFunction() {
    Navigator.of(context).pop();
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 15),
      child: Column(
        children: [
          Container(
            width: 60,
            height: 5,
            decoration: BoxDecoration(
                color: Colors.grey.shade300,
                borderRadius: BorderRadius.circular(10)),
          ),
          const SizedBox(
            height: 20,
          ),
          const Align(
            alignment: Alignment.topLeft,
            child: Text(
              'Add timeline 🗓️',
              style: TextStyle(
                  color: Colors.black,
                  fontFamily: 'poppins',
                  fontWeight: FontWeight.w500,
                  fontSize: 20,
                  letterSpacing: 1),
            ),
          ),
          const SizedBox(
            height: 30,
          ),
          Form(
            key: _formKey,
            child: Column(
              children: [
                textFieldDate(
                    dateController, 'Date', Icons.date_range_outlined),
                const SizedBox(
                  height: 20,
                ),
                textFieldTime(
                    timeController,
                    DateFormat.jm().format(DateTime.now()),
                    const Icon(
                      Icons.calendar_month_outlined,
                      color: Colors.black,
                    ),
                    dateOnTap),
                const SizedBox(
                  height: 20,
                ),
                textFieldTopic(
                    topicController,
                    'Topic',
                    const Icon(
                      Icons.topic_outlined,
                      color: Colors.black,
                    )),
              ],
            ),
          ),
          Expanded(child: Container()),
          btnSection()
        ],
      ),
    );
  }

  Widget textFieldDate(
    controller,
    hintText,
    icon,
  ) {
    return FadeInUp(
      duration: const Duration(milliseconds: 700),
      child: TextFormField(
        readOnly: true,
        cursorColor: Colors.black,
        style: const TextStyle(
            fontFamily: 'poppins',
            fontWeight: FontWeight.w400,
            fontSize: 15,
            color: Colors.black),
        onTap: (() async {
          DateTime? pickDate = await showDatePicker(
              context: context,
              initialDate: DateTime.now(),
              firstDate: DateTime(2000),
              lastDate: DateTime(3000));
          if (pickDate != null) {
            setState(() {
              controller.text = DateFormat.yMMMMd().format(pickDate);
            });
          }
        }),
        decoration: InputDecoration(
            contentPadding: const EdgeInsets.all(15),
            prefixIcon: Icon(
              icon,
              color: Colors.black,
            ),
            filled: true,
            fillColor: Colors.white,
            hintText: hintText,
            hintStyle: const TextStyle(
                fontFamily: 'poppins',
                fontWeight: FontWeight.w400,
                fontSize: 15,
                color: Color(0xff929292)),
            focusedBorder: const OutlineInputBorder(
                borderSide: BorderSide(color: Colors.black, width: 1)),
            enabledBorder: const OutlineInputBorder(
                borderSide: BorderSide(color: Colors.grey, width: 1)),
            errorBorder: const OutlineInputBorder(
                borderSide: BorderSide(
                    color: Colors.red, style: BorderStyle.solid, width: 1)),
            focusedErrorBorder: const OutlineInputBorder(
                borderSide: BorderSide(
                    color: Colors.red, style: BorderStyle.solid, width: 1))),
        controller: controller,
        validator: (value) {
          if (value == null || value.isEmpty) {
            return 'Please fill the text field!';
          }
          return null;
        },
      ),
    );
  }

  Widget textFieldTime(controller, hintText, icon, dateOnTap) {
    return FadeInUp(
      duration: const Duration(milliseconds: 700),
      child: TextFormField(
        readOnly: true,
        cursorColor: Colors.black,
        style: const TextStyle(
            fontFamily: 'poppins',
            fontWeight: FontWeight.w400,
            fontSize: 15,
            color: Colors.black),
        onTap: dateOnTap,
        decoration: InputDecoration(
            contentPadding: const EdgeInsets.all(15),
            prefixIcon: icon,
            filled: true,
            fillColor: Colors.white,
            hintText: hintText,
            hintStyle: const TextStyle(
                fontFamily: 'poppins',
                fontWeight: FontWeight.w400,
                fontSize: 15,
                color: Color(0xff929292)),
            focusedBorder: const OutlineInputBorder(
                borderSide: BorderSide(color: Colors.black, width: 1)),
            enabledBorder: const OutlineInputBorder(
                borderSide: BorderSide(color: Colors.grey, width: 1)),
            errorBorder: const OutlineInputBorder(
                borderSide: BorderSide(
                    color: Colors.red, style: BorderStyle.solid, width: 1)),
            focusedErrorBorder: const OutlineInputBorder(
                borderSide: BorderSide(
                    color: Colors.red, style: BorderStyle.solid, width: 1))),
        controller: controller,
        validator: (value) {
          if (value == null || value.isEmpty) {
            return 'Please fill the text field!';
          }
          return null;
        },
      ),
    );
  }

  Widget textFieldTopic(controller, hintText, icon) {
    return FadeInUp(
      duration: const Duration(milliseconds: 700),
      child: TextFormField(
        minLines: 1,
        maxLines: 3,
        cursorColor: Colors.black,
        style: const TextStyle(
            fontFamily: 'poppins',
            fontWeight: FontWeight.w400,
            fontSize: 15,
            color: Colors.black),
        decoration: InputDecoration(
            contentPadding: const EdgeInsets.all(15),
            prefixIcon: icon,
            filled: true,
            fillColor: Colors.white,
            hintText: hintText,
            hintStyle: const TextStyle(
                fontFamily: 'poppins',
                fontWeight: FontWeight.w400,
                fontSize: 15,
                color: Color(0xff929292)),
            focusedBorder: const OutlineInputBorder(
                borderSide: BorderSide(color: Colors.black, width: 1)),
            enabledBorder: const OutlineInputBorder(
                borderSide: BorderSide(color: Colors.grey, width: 1)),
            errorBorder: const OutlineInputBorder(
                borderSide: BorderSide(
                    color: Colors.red, style: BorderStyle.solid, width: 1)),
            focusedErrorBorder: const OutlineInputBorder(
                borderSide: BorderSide(
                    color: Colors.red, style: BorderStyle.solid, width: 1))),
        controller: controller,
        validator: (value) {
          if (value == null || value.isEmpty) {
            return 'Please fill the text field!';
          }
          return null;
        },
      ),
    );
  }

  Widget btnAddTimeline(addFunction, text) {
    return FadeInUp(
      duration: const Duration(milliseconds: 500),
      delay: const Duration(milliseconds: 200),
      child: ElevatedButton(
          onPressed: addFunction,
          style: ButtonStyle(
              elevation: MaterialStateProperty.all(0),
              backgroundColor: MaterialStateProperty.all(Colors.black),
              fixedSize: MaterialStateProperty.all(const Size(0, 54)),
              shape: MaterialStateProperty.all(RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10)))),
          child: Text(
            text,
            style: const TextStyle(
                color: Colors.white,
                fontFamily: 'poppins',
                fontWeight: FontWeight.w400,
                fontSize: 17,
                letterSpacing: 1),
          )),
    );
  }

  Widget btnCancelAddTimeline(cancelAddFunction, icon) {
    return FadeInLeft(
      duration: const Duration(milliseconds: 500),
      delay: const Duration(milliseconds: 200),
      child: ElevatedButton(
          onPressed: cancelAddFunction,
          style: ButtonStyle(
              side: MaterialStateProperty.all(
                  const BorderSide(color: Colors.black)),
              elevation: MaterialStateProperty.all(0),
              backgroundColor: MaterialStateProperty.all(Colors.white),
              fixedSize: MaterialStateProperty.all(const Size(0, 54)),
              shape: MaterialStateProperty.all(RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10)))),
          child: Icon(
            icon,
            color: Colors.black,
          )),
    );
  }

  Widget btnSection() {
    return Row(
      children: [
        Expanded(
            flex: 1,
            child: btnCancelAddTimeline(cancelAddFunction, Icons.clear)),
        const SizedBox(
          width: 10,
        ),
        Expanded(
            flex: 4, child: btnAddTimeline(addFunction, 'Add New Timeline'))
      ],
    );
  }
}

Upvotes: 0

Views: 107

Answers (1)

Eliott Bouvard
Eliott Bouvard

Reputation: 180

Depend a lot of what you want to do with these data and where you define your document snapshot.

But reading your question, i guess your FAB is defined in a Scaffold and your StreamBuilder inside the Scaffold body ?

If so you can invert these and access documentSnapshot.data() in all of your Scaffold children (FAB included). Something like that :

StreamBuilder(
  stream: getUsersTimelineSnapshots(context)
    .map((snapshot) => snapshot.docs.toList()),
  builder: (context, snapshot) {
    if (snapshot.hasError) {
      return Scaffold(
        body: Text('Error: ${snapshot.error}'),
      );
    }

    if (!snapshot.hasData) {
      return Scaffold(
        body: Text('Loading...'),
      );
    }

    return Scaffold(
      //Your FAB
      floatingActionButton: FadeInRight(
        delay: const Duration(milliseconds: 200),
        duration: const Duration(milliseconds: 500),
        child: FloatingActionButton.extended(
          label: const Text(
            'Add Timeline',
            style: TextStyle(
                color: Colors.white,
                fontFamily: 'poppins',
                fontWeight: FontWeight.w400,
                fontSize: 15,
                letterSpacing: 1),
          ),
          backgroundColor: Colors.black,
          shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(6)),
          onPressed: () {
            showModalBottomSheet(
                // isScrollControlled: true,
                shape: const RoundedRectangleBorder(
                    borderRadius: BorderRadius.only(
                        topLeft: Radius.circular(10),
                        topRight: Radius.circular(10))),
                context: context,
                builder: (context) => const AddTaskPage(snapshot.data));//Here you will get a List<DocumentSnapshot>
          },
        ),
      ),
      //Rest of your old scaffold here
    );
  },
);

But again, without more infos about your code, it will be difficult to provide a more accurate answer.

Upvotes: 2

Related Questions