3

I have a flutter scheduler calendar, I have managed to populate the scheduler with the data from the db. I have made the cards on the scheduler clickable. Each card has a set of data in the database. Like the first row populates the first card, the second is populated by the second row. I want to be able to get the click on any card and get the id, and redirect to a webview to show the webpage

+------+--------+---------------------+------------+
| ID   |title   | dose                | urls       |
+------+--------+---------------------+------------+
| 1001 | Texas  | 1st                 | google.com |
| 1002 | Texas  | 2nd                 |facebook.com|
| 1003 | Ohio   | 1st                 | azure.com  |
| 1004 | Ohio   | 2nd                 | med.com    |
| 1005 | Utah   | 1st                 | tell.com   |
| 1006 | Utah   | 2nd                 | burger.com |
| 1007 | Utah   | 3rd                 | whatif.com |
+------+--------+---------------------+------------+

this is what I have

my function to listen for calendar clicks and try to redirect to the webpage using the id

void onCalendarTapped(CalendarTapDetails calendarTapDetails) async{
    if (calendarTapDetails.targetElement != CalendarElement.calendarCell &&
        calendarTapDetails.targetElement != CalendarElement.appointment) {
      print("the index  is ");
          calendarTapDetails.targetElement.index;
      return;
    }

    SharedPreferences prefs = await  SharedPreferences.getInstance();
    var userid = prefs.getString('id');
    var email = prefs.getString('email');
    var gender = prefs.getString('gender');

    // for (Schedule s in participantSchedules){
      var scheular = await db.getSchedulesById(participantSchedules[0].id);
      print(scheular);
      print("the link is " + scheular.botUrl!+'&userId=$userid'+'&email=$email'+'&gender=$gender'+'&sendData=true');

      Navigator.push(context,
          MaterialPageRoute(builder: (context) => WebViewPage(scheular.botUrl!+'&userId=$userid'+'&email=$email'+'&gender=$gender'+'&sendData=true', scheular.title!)));

    //}

    }

My function to populate the items on the calendar

 Future<void> init() async {
    participantSchedules = await db.getScheduleByparticipantId(participantid!);
    setState(() {
      appointments = getMeetingDetails();
      _events = DataSource(appointments);
    });
  }

How I am getting the title and some other fields not on the table above

List<Meeting> getMeetingDetails() {
    final List<Meeting> meetingCollection = <Meeting>[];
    eventNameCollection = <String>[];
    //display the titles here
    for (Schedule s in participantSchedules) {
      eventNameCollection.add(s.title!);
      meetingCollection.add(Meeting(
        from: DateTime.parse(s.windowStart!),
        to: DateTime.parse(s.windowEnd!),
        background: getCalendarTileColor(
            DateTime.parse(s.windowStart!),
            DateTime.parse(s.windowEnd!), null),
        isAllDay: true,
        eventName: s.title!,
        startTimeZone: '',
        endTimeZone: '',
        description: '',
      ));
    }

    return meetingCollection;
  }

How can I get the id on the card and pass it to my query below, as this only picks the value with index 0 only while I want it to be dynamic. Using a for loop loops through all the items and displays all the urls at once

var scheular = await db.getSchedulesById(participantSchedules[0].id);

so that I can populate my push route with the details from the selected card alone?

  Navigator.push(context,
          MaterialPageRoute(builder: (context) => WebViewPage(scheular.botUrl!+'&userId=$userid'+'&email=$email'+'&gender=$gender'+'&sendData=true', scheular.title!)));

The whole class

//ignore: must_be_immutable
class WAFollowUps extends StatefulWidget {
  const WAFollowUps(this.participantid, {Key? key}) : super(key: key);
  final String? participantid;


  @override
  WAFollowUpsState createState() => WAFollowUpsState(this.participantid);
}

List<Color> _colorCollection = <Color>[];
List<String> _colorNames = <String>[];
int _selectedColorIndex = 0;
int _selectedCardIndex = 0;
int _selectedTimeZoneIndex = 0;
List<String> _timeZoneCollection = <String>[];
DataSource _events = DataSource(<Meeting>[]);
Meeting? _selectedAppointment;
late DateTime _startDate;
late TimeOfDay _startTime;
late DateTime _endDate;
late TimeOfDay _endTime;
bool _isAllDay = false;
String _subject = '';
String _notes = '';

class WAFollowUpsState extends State<WAFollowUps> {
  List<WATransactionModel> transactionList = <WATransactionModel>[];
  List<Schedule> participantSchedules = <Schedule>[];
  //Schedule schedule;
  CemDatabase db = CemDatabase.getInstance();
  String? participantid;

  //List<Schedules> participantsid = <Schedules>[];

  WAFollowUpsState(this.participantid);

  CalendarView _calendarView = CalendarView.schedule;
  late List<String> eventNameCollection;
  late List<Meeting> appointments;

  @override
  void initState() {
    init();
    _calendarView = CalendarView.schedule;
    _selectedAppointment = null;
    _selectedCardIndex = 0;
    _selectedColorIndex = 0;
    _selectedTimeZoneIndex = 0;
    _subject = '';
    _notes = '';
    super.initState();
  }

  Future<void> init() async {
    participantSchedules = await db.getScheduleByparticipantId(participantid!);
    setState(() {
      appointments = getMeetingDetails();
      _events = DataSource(appointments);
    });
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
        resizeToAvoidBottomInset: false,
        body: Padding(
            padding: const EdgeInsets.fromLTRB(5, 0, 5, 5),
            child: getEventCalendar(_calendarView, _events, onCalendarTapped)));
  }

  SfCalendar getEventCalendar(CalendarView _calendarView,
      CalendarDataSource _calendarDataSource,
      CalendarTapCallback calendarTapCallback) {
    return SfCalendar(
      view: _calendarView,
      dataSource: _calendarDataSource,
      onTap: calendarTapCallback,
      initialDisplayDate: DateTime(DateTime
          .now()
          .year, DateTime
          .now()
          .month,
          DateTime
              .now()
              .day, 0, 0, 0),
      scheduleViewSettings: ScheduleViewSettings(
        hideEmptyScheduleWeek: true,
        monthHeaderSettings: MonthHeaderSettings(
          height: 0,
        ),
      ),
      // timeSlotViewSettings: TimeSlotViewSettings(
      //     minimumAppointmentDuration: const Duration(minutes: 60))
    );
  }

  void onCalendarTapped(CalendarTapDetails calendarTapDetails,  ) async{
    if (calendarTapDetails.targetElement != CalendarElement.calendarCell &&
        calendarTapDetails.targetElement != CalendarElement.appointment) {
      return;
    }
    SharedPreferences prefs = await  SharedPreferences.getInstance();
    var userid = prefs.getString('id');
    var email = prefs.getString('email');
    var gender = prefs.getString('gender');

   // for (Schedule s in participantSchedules){
      var scheular = await db.getSchedulesById(participantSchedules[11].id);
      print(scheular);
      print("the link is " + scheular.botUrl!+'&userId=$userid'+'&email=$email'+'&gender=$gender'+'&sendData=true');

      Navigator.push(context,
          MaterialPageRoute(builder: (context) => WebViewPage(scheular.botUrl!+'&userId=$userid'+'&email=$email'+'&gender=$gender'+'&sendData=true', scheular.title!)));

    // }

    }

  List<Meeting> getMeetingDetails() {
    final List<Meeting> meetingCollection = <Meeting>[];
    eventNameCollection = <String>[];
    //display the titles here
    for (Schedule s in participantSchedules) {
      eventNameCollection.add(s.title!);

      meetingCollection.add(Meeting(
        from: DateTime.parse(s.windowStart!),
        to: DateTime.parse(s.windowEnd!),
        background: getCalendarTileColor(
            DateTime.parse(s.windowStart!),
            DateTime.parse(s.windowEnd!), null),
        isAllDay: true,
        eventid: s.id!,
        eventName: s.title!,
        startTimeZone: '',
        endTimeZone: '',
        description: '',
      ));
    }

    return meetingCollection;
  }

  Color getCalendarTileColor(DateTime begin, DateTime end,
      DateTime? dateCompleted) {
    final DateTime today = DateTime.now();
    _colorCollection = <Color>[];
    if (today.isBefore(begin)) { // not completed but window has not begun yet
      return Color(0xFF636363);
    } else if (today.isAfter(end) &&
        dateCompleted == null) { // not completed and window expired
      return Color(0xFFFF00FF);
    } else if (today.isAfter(begin) && today.isBefore(end) &&
        dateCompleted == null) { // not completed but still within window
      return Color(0xFF3D4FB5);
    } else if (today.isAfter(end) &&
        dateCompleted!.isAfter(end)) { // completed after window ended
      return Color(0xFFE47C73);
    } else if (dateCompleted!.isAfter(begin) &&
        dateCompleted.isBefore(end)) { // completed on time
      return Color(0xFF0F8644);
    }
    return Colors.white;
  }
}

class DataSource extends CalendarDataSource {
  DataSource(List<Meeting> source) {
    appointments = source;
  }

  @override
  bool isAllDay(int index) => appointments![index].isAllDay;

  @override
  String getSubject(int index) => appointments![index].eventName;

  @override
  String getStartTimeZone(int index) => appointments![index].startTimeZone;

  @override
  String getNotes(int index) => appointments![index].description;

  @override
  String getEndTimeZone(int index) => appointments![index].endTimeZone;

  @override
  Color getColor(int index) => appointments![index].background;

  @override
  DateTime getStartTime(int index) => appointments![index].from;

  @override
  DateTime getEndTime(int index) => appointments![index].to;
}

class Meeting {
  Meeting({required this.from,
    required this.to,
    this.eventid,
    this.background = Colors.green,
    this.isAllDay = false,
    this.eventName = '',
    this.startTimeZone = '',
    this.endTimeZone = '',
    this.description = ''});

  final String eventName;
  final DateTime from;
  final DateTime to;
  final Color background;
  final bool isAllDay;
  final String startTimeZone;
  final String endTimeZone;
  final String description;
  final int? eventid;
}


class WebViewPage extends StatefulWidget {
  final String url;
  final String title;

  WebViewPage(this.url, this.title);

  @override
  WebViewPageState createState() =>
      WebViewPageState(this.url, this.title);
}

class WebViewPageState extends State<WebViewPage> {
  final String url;
  final String title;

  WebViewPageState(this.url, this.title);

  @override
  void initState() {
    super.initState();
    // Enable hybrid composition.
    if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
          extendBodyBehindAppBar: true,
          appBar: AppBar(
            backgroundColor: Colors.transparent,
            title: Text(
              this.title,
              style: boldTextStyle(color: Colors.black, size: 20),
            ),
            actions: <Widget>[
              TextButton(
                onPressed: () {},
                child: Text('Finish'),
              ),
            ],
            leading: Container(
              margin: EdgeInsets.all(8),
              decoration: boxDecorationWithRoundedCorners(
                backgroundColor: context.cardColor,
                borderRadius: BorderRadius.circular(12),
                border: Border.all(color: Colors.grey.withOpacity(0.2)),
              ),
              child: Icon(Icons.arrow_back, color: Banking_blackColor),
            ).onTap(() {
              finish(context);
            }),
            centerTitle: true,
            elevation: 0.0,
            systemOverlayStyle: SystemUiOverlayStyle.light,
          ),
          body: Column(children: [

            Expanded(
                child: SafeArea(
                  child: WebView(
                    initialUrl: this.url,
                    javascriptMode: JavascriptMode.unrestricted,
                    debuggingEnabled: true,
                  ),
                )
            )
          ])
      ),
    );
  }
}
arriff
  • 399
  • 1
  • 10
  • 30

1 Answers1

0

Lets say you have a set of data which is related to each Item in your list

You can have a Custom Widget as your List Item widget which accepts some extra information and also has a function which is responsible for loading data, for example:

class CardItem extends StatelessWidget {
  final int id;
  final String title;
  ...

  FoodItem({
    @required this.id,
    @required this.title,
    ...
  });
    
  void loadData() {
    var scheular = await db.getSchedulesById(id);
    ...
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        loadData();
      },
      child: Card(
        ...
      ),
    );
  }
}

Use this widget as your list item widget, when user taps on each item, the loadData() function will be called and the id of that item will be used

Another option is to have a field on your Item widget which accepts a function, then you can pass a function to that field from outside of your Item Widget, like this:

class CardItem extends StatelessWidget {
  final int id;
  final String title;
  final Function loadData;
  ...

  FoodItem({
    @required this.id,
    @required this.title,
    @required this.loadData,
    ...
  });


  void _loadData() {
    loadData(id);
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        _loadData(context);
      },
      child: Card(
        ...
      ),
    );
  }
}
Mahmoud_Mehri
  • 1,643
  • 2
  • 20
  • 38