Home > Net >  Find closest date to today from API results
Find closest date to today from API results

Time:11-15

I've come across a problem which I cannot figure out. I'm trying to display single event on my home screen which is next upcoming by date. That event comes from list of events in the api. Currently I am using listview.builder to display those events however when I set item count to 1 I cannot get the next event by date to be displayed. I was trying to display all events in listview.builder and then filter but I couldn't get it to work.

I need to display events in that order but they need to be shown 1 by 1 based on todays time. So when current time is the same as the events time next event will be shown: firstImage

And this is what I'm getting when the itemCount is 1. This is the last event from the list

which I tried to reverse but no success. secondImage

This is code for the ListView.builder

ListView.builder(
        reverse: true,
        shrinkWrap: true,
        physics: ClampingScrollPhysics(),
        // itemCount: 1,
        itemCount: 1,
        itemBuilder: (context, index) {
          var x = eventController.event.value!.data![index];
          DateTime formattedStartDate = new DateFormat('yyyy-MM-dd hh:mm')
              .parse(eventController
                  .event.value!.data![index].eventStartDate
                  .toString());
          DateTime splitStartDate = new DateTime(
              formattedStartDate.year,
              formattedStartDate.month,
              formattedStartDate.day,
              formattedStartDate.hour,
              formattedStartDate.minute);

          DateTime today = DateTime.now();
          bool isAfter = splitStartDate.isAfter(today);
          
          return Column(
            children: [
              isAfter == true
                  ? GestureDetector(
                      onTap: () {
                        Navigator.push(
                            context,
                            MaterialPageRoute(
                                builder: (context) => EventDetails(
                                    event: eventController
                                        .event.value!.data![index])));
                      },
                      child: EventTileMain(
                          eventController.event.value!.data![index]))
                  : Container()
            ],
          );
        });

This is model calss of event:

    // To parse this JSON data, do
//
//     final event = eventFromJson(jsonString);

import 'dart:convert';

Event eventFromJson(String str) => Event.fromJson(json.decode(str));

String eventToJson(Event data) => json.encode(data.toJson());

class Event {
  Event({
    this.success,
    this.data,
    this.code,
    this.count,
  });

  bool? success;
  List<Datum>? data;
  int? code;
  int? count;

  factory Event.fromJson(Map<String, dynamic> json) => Event(
    success: json["success"],
    data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
    code: json["code"],
    count: json["count"],
  );

  Map<String, dynamic> toJson() => {
    "success": success,
    "data": List<dynamic>.from(data!.map((x) => x.toJson())),
    "code": code,
    "count": count,
  };
}

class Datum {
  Datum({
    this.id,
    this.postTitle,
    this.postContent,
    this.postName,
    this.postUrl,
    this.organizer,
    this.venue,
    this.category,
    this.speaker,
    this.eventStartDate,
    this.eventEndDate,
    this.eventDate,
    this.featuredImage,
  });

  String? id;
  String? postTitle;
  String? postContent;
  String? postName;
  String? postUrl;
  List<Category>? organizer;
  List<Category>? venue;
  List<Category>? category;
  dynamic speaker;
  String? eventStartDate;
  String? eventEndDate;
  DateTime? eventDate;
  String? featuredImage;

  factory Datum.fromJson(Map<String, dynamic> json) => Datum(
    id: json["ID"],
    postTitle: json["post_title"],
    postContent: json["post_content"],
    postName: json["post_name"],
    postUrl: json["post_url"],
    organizer: List<Category>.from(json["organizer"].map((x) => Category.fromJson(x))),
    venue: List<Category>.from(json["venue"].map((x) => Category.fromJson(x))),
    category: List<Category>.from(json["category"].map((x) => Category.fromJson(x))),
    speaker: json["speaker"],
    eventStartDate: json["event_start_date"],
    eventEndDate: json["event_end_date"],
    eventDate: DateTime.parse(json["event_date"]),
    featuredImage: json["featured_image"],
  );

  Map<String, dynamic> toJson() => {
    "ID": id,
    "post_title": postTitle,
    "post_content": postContent,
    "post_name": postName,
    "post_url": postUrl,
    "organizer": List<dynamic>.from(organizer!.map((x) => x.toJson())),
    "venue": List<dynamic>.from(venue!.map((x) => x.toJson())),
    "category": List<dynamic>.from(category!.map((x) => x.toJson())),
    "speaker": speaker,
    "event_start_date": eventStartDate,
    "event_end_date": eventEndDate,
    "event_date": eventDate!.toIso8601String(),
    "featured_image": featuredImage,
  };
}

class Category {
  Category({
    this.id,
    this.name,
  });

  int? id;
  Name? name;

  factory Category.fromJson(Map<String, dynamic> json) => Category(
    id: json["id"],
    name: nameValues.map[json["name"]],
  );

  Map<String, dynamic> toJson() => {
    "id": id,
    "name": nameValues.reverse![name],
  };
}

enum Name { AUDITORIUM, SEMINAR, XPOSURE, XPOSURE_INTERNATIONAL_PHOTOGRAPHY_FESTIVAL, TOR_SEIDEL, XPOSURE_AUDITORIUM }

final nameValues = EnumValues({
  "Auditorium": Name.AUDITORIUM,
  "Seminar": Name.SEMINAR,
  "Tor Seidel": Name.TOR_SEIDEL,
  "Xposure": Name.XPOSURE,
  "Xposure Auditorium": Name.XPOSURE_AUDITORIUM,
  "Xposure International Photography Festival": Name.XPOSURE_INTERNATIONAL_PHOTOGRAPHY_FESTIVAL
});

class EnumValues<T> {
  Map<String, T> map;
  Map<T, String>? reverseMap;

  EnumValues(this.map);

  Map<T, String>? get reverse {
    if (reverseMap == null) {
      reverseMap = map.map((k, v) => new MapEntry(v, k));
    }
    return reverseMap;
  }
}

API call

class EventApi {
  static var client = http.Client();
  static Future<Event?> fetchEvents() async {
    final response = await client.get(Uri.parse(
        'https://xposure.ae/api/v1/events/'));
        // 'https://xposure.ae/wp-json/wp/auditorium/v1/events'));
    if (response.statusCode == 200) {
      var jsonString = response.body;
      return eventFromJson(jsonString);
    } else {
      return null;
    }
  }
}

If you need more information please let me know.

CodePudding user response:

you can try this:

ListView.builder(
        reverse: true,
        shrinkWrap: true,
        physics: ClampingScrollPhysics(),
        // itemCount: 1,
        itemCount: 1,
        itemBuilder: (context, index) {

          var now = DateTime.now();
          Datum? closestEvent;
          eventController.event.value!.data!.forEach((element) {
            var elementDate =
               DateFormat('yyyy-MM-dd hh:mm').parse(element.eventStartDate);
            if (closestEvent == null) {
              if (elementDate.isAfter(now)) {
                 closestEvent = element;
              }
            } else {
               var closestDate = DateFormat('yyyy-MM-dd hh:mm').parse(closestEvent!.eventStartDate);
               if (elementDate.isAfter(now) && elementDate.isBefore(closestDate)) {
                   closestEvent = element;
               }
             }
          });

          return Column(
            children: [
              isAfter == true
                  ? GestureDetector(
                      onTap: () {
                        Navigator.push(
                            context,
                            MaterialPageRoute(
                                builder: (context) => EventDetails(
                                    event: closestEvent)));
                      },
                      child: EventTileMain(
                          closestEvent))
                  : Container()
            ],
          );
        });

you can simply make a widget function and remove your listview, like this:

Widget buildEventWidget(BuildContext context){

   var now = DateTime.now();
          Datum? closestEvent;
          eventController.event.value!.data!.forEach((element) {
            var elementDate =
               DateFormat('yyyy-MM-dd hh:mm').parse(element.eventStartDate);
            if (closestEvent == null) {
              if (elementDate.isAfter(now)) {
                 closestEvent = element;
              }
            } else {
               var closestDate = DateFormat('yyyy-MM-dd hh:mm').parse(closestEvent!.eventStartDate);
               if (elementDate.isAfter(now) && elementDate.isBefore(closestDate)) {
                   closestEvent = element;
               }
             }
          });

    return Column(
            children: [
              isAfter == true
                  ? GestureDetector(
                      onTap: () {
                        Navigator.push(
                            context,
                            MaterialPageRoute(
                                builder: (context) => EventDetails(
                                    event: closestEvent)));
                      },
                      child: EventTileMain(
                          closestEvent))
                  : Container()
            ],
          );

}
  • Related