diff --git a/android/build.gradle b/android/build.gradle index a054dd4..d2ffbff 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,8 +1,3 @@ -buildscript { - dependencies { - classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10' - } -} allprojects { repositories { google() diff --git a/lib/controller/announcement_controller.dart b/lib/controller/announcement_controller.dart new file mode 100644 index 0000000..ed30ae4 --- /dev/null +++ b/lib/controller/announcement_controller.dart @@ -0,0 +1,31 @@ +import 'package:get/get.dart'; +import '../models/announcement_response.dart'; +import '../services/api_service.dart'; +import '../utils/api_urls.dart'; + +class AnnouncementController extends GetxController { + final ApiService _apiClient = ApiService(); + RxList announcementsList = [].obs; + RxBool isLoading = false.obs; + + @override + void onInit() { + super.onInit(); + getAnnouncements(); + } + + Future getAnnouncements() async { + isLoading.value = true; + try { + final response = await _apiClient.get(ApiUrls.announcementUrl); + isLoading.value = false; + if (response.statusCode == 200) { + final List data = response.data; + announcementsList.value = data.map((item) => AnnouncementResponse.fromJson(item)).toList(); + } + } catch (e) { + isLoading.value = false; + Get.snackbar('Error', 'Failed to fetch announcements'); + } + } +} \ No newline at end of file diff --git a/lib/models/announcement_response.dart b/lib/models/announcement_response.dart new file mode 100644 index 0000000..1598777 --- /dev/null +++ b/lib/models/announcement_response.dart @@ -0,0 +1,43 @@ +class AnnouncementResponse { + String? id; + String? uniqueId; + List? sentTo; + String? message; + DateTime? createdAt; + DateTime? updatedAt; + int? v; + + AnnouncementResponse({ + this.id, + this.uniqueId, + this.sentTo, + this.message, + this.createdAt, + this.updatedAt, + this.v, + }); + + factory AnnouncementResponse.fromJson(Map json) { + return AnnouncementResponse( + id: json['_id'], + uniqueId: json['uniqueId'], + sentTo: json['sentTo'] != null ? List.from(json['sentTo']) : null, + message: json['message'], + createdAt: json['createdAt'] != null ? DateTime.parse(json['createdAt']) : null, + updatedAt: json['updatedAt'] != null ? DateTime.parse(json['updatedAt']) : null, + v: json['__v'], + ); + } + + Map toJson() { + return { + '_id': id, + 'uniqueId': uniqueId, + 'sentTo': sentTo, + 'message': message, + 'createdAt': createdAt?.toIso8601String(), + 'updatedAt': updatedAt?.toIso8601String(), + '__v': v, + }; + } +} \ No newline at end of file diff --git a/lib/screens/announment/announment_screen.dart b/lib/screens/announment/announment_screen.dart new file mode 100644 index 0000000..a5b2c59 --- /dev/null +++ b/lib/screens/announment/announment_screen.dart @@ -0,0 +1,131 @@ +import 'package:cheminova/widgets/my_drawer.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:intl/intl.dart'; +import '../../controller/announcement_controller.dart'; +import '../../models/announcement_response.dart'; +import '../../widgets/comman_background.dart'; +import '../../widgets/common_appbar.dart'; +import '../../widgets/common_elevated_button.dart'; + +class AnnouncementScreen extends StatelessWidget { + final AnnouncementController controller = Get.put(AnnouncementController()); + + AnnouncementScreen({super.key}); + + @override + Widget build(BuildContext context) { + return CommonBackground( + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: CommonAppBar( + title: const Text('Announcements', + style: TextStyle( + fontSize: 20, + color: Colors.black, + fontWeight: FontWeight.w400, + fontFamily: 'Anek')), + backgroundColor: Colors.transparent, + elevation: 0, + actions: [ + IconButton( + onPressed: () => Navigator.pop(context), + icon: SvgPicture.asset('assets/svg/back_arrow.svg'), + padding: const EdgeInsets.only(right: 20)) + ], + ), + drawer: const MyDrawer(), + body: Obx(() => controller.isLoading.value + ? const Center(child: CircularProgressIndicator()) + : MyListView(announcementList: controller.announcementsList)), + ), + ); + } +} + +Widget buildProductButton(String productName) { + return Padding( + padding: const EdgeInsets.only(bottom: 15), + child: CommonElevatedButton( + borderRadius: 30, + width: double.infinity, + height: kToolbarHeight - 10, + text: productName, + backgroundColor: const Color(0xff004791), + onPressed: () { + debugPrint('$productName pressed'); + }, + ), + ); +} + +class MyListView extends StatelessWidget { + final List announcementList; + + const MyListView({super.key, required this.announcementList}); + + @override + Widget build(BuildContext context) { + Map> groupedAnnouncements = {}; + + for (var announcement in announcementList) { + String date = DateFormat("dd MMM yyyy").format(announcement.createdAt ?? DateTime.now()); + if (!groupedAnnouncements.containsKey(date)) { + groupedAnnouncements[date] = []; + } + groupedAnnouncements[date]!.add(announcement); + } + + return ListView.builder( + padding: const EdgeInsets.only(top: 15), + itemCount: groupedAnnouncements.length, + itemBuilder: (context, index) { + String date = groupedAnnouncements.keys.elementAt(index); + List announcementsForDate = groupedAnnouncements[date]!; + + return Padding( + padding: const EdgeInsets.only(bottom: 10, left: 10, right: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 8.0), + child: Text( + date, + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + ), + ), + ...announcementsForDate.map((item) => Padding( + padding: const EdgeInsets.only(bottom: 10), + child: ExpansionTile( + collapsedBackgroundColor: Colors.white, + backgroundColor: Colors.white, + trailing: const SizedBox.shrink(), + title: const Text( + 'New Announcement', + style: TextStyle(fontSize: 17, fontWeight: FontWeight.w500), + ), + subtitle: Text(item.message ?? ''), + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Sent to: ${item.sentTo?.join(", ")}'), + const SizedBox(height: 8), + Text('Unique ID: ${item.uniqueId}'), + ], + ), + ), + ], + ), + )), + ], + ), + ); + }, + ); + } +} \ No newline at end of file diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index 072526e..361588d 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -1,10 +1,10 @@ import 'package:cheminova/controller/home_controller.dart'; +import 'package:cheminova/screens/announment/announment_screen.dart'; import 'package:cheminova/screens/inventory/inventory_management_screen.dart'; import 'package:cheminova/screens/order/order_tracking_screen.dart'; import 'package:cheminova/screens/order_management/order_management_screen.dart'; import 'package:cheminova/screens/product/product_catalog_screen.dart'; import 'package:cheminova/screens/report/notification_screen.dart'; -import 'package:cheminova/screens/retail/retail_distributer_on_boarding_screen.dart'; import 'package:cheminova/widgets/home_card.dart'; import 'package:cheminova/widgets/my_drawer.dart'; import 'package:flutter/material.dart'; @@ -150,8 +150,7 @@ class _HomeScreenState extends State { HomeCard( title: 'Announcement', onTap: () => Get.to( - () => - const RetailDistributerOnBoardingScreen(), // Navigates to RetailDistributerOnBoardingScreen. + () => AnnouncementScreen(), // Navigates to RetailDistributerOnBoardingScreen. ), ), ], diff --git a/lib/utils/api_urls.dart b/lib/utils/api_urls.dart index a35af11..0916956 100644 --- a/lib/utils/api_urls.dart +++ b/lib/utils/api_urls.dart @@ -15,5 +15,6 @@ class ApiUrls { static const String getSinglePlacedOrderUrl ='/api/get-single-placed-order-pd'; static const String placedOrderUrl ='${baseUrl}/api/order-place'; static const String inventoryManangementOrdersStock ='${baseUrl}/api/stock'; + static const String announcementUrl ='${baseUrl}/api/announcement/RDs'; }