initial commit

This commit is contained in:
2023-08-31 18:07:19 +05:30
parent 18a5eca9ae
commit a70b6656a8
140 changed files with 5168 additions and 0 deletions

16
lib/constants.dart Normal file
View File

@@ -0,0 +1,16 @@
//ignore_for_file: constant_identifier_names
import 'package:flutter/material.dart';
const String breakfast = "Breakfast";
const String lunch = "Lunch";
const String snak = "Snacks";
const String dinner = "Dinner";
const String VEG = "VEG";
const String NONVEG = "NON";
const String EGG = "EGG";
const String EMPTY = "Mt";
const String storageKey = "FullMenu";
const Center noMenuWidget = Center(
child: Text("Menu not available for this session",
style: TextStyle(fontSize: 20, fontStyle: FontStyle.italic)));

28
lib/main.dart Normal file
View File

@@ -0,0 +1,28 @@
import 'package:flutter/material.dart';
import 'package:iiitb_menu/models/globalModel.dart';
import 'package:iiitb_menu/views/homePage.dart';
import 'package:provider/provider.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MainApp());
}
class MainApp extends StatelessWidget {
const MainApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// getData();
return ChangeNotifierProvider<GlobalModel>(
lazy: false,
create: (context) => GlobalModel(),
builder: (BuildContext context, child) {
return const MaterialApp(
home: HomePage(),
);
},
);
}
}

156
lib/models/globalModel.dart Normal file
View File

@@ -0,0 +1,156 @@
// ignore_for_file: unnecessary_this, file_names
import "dart:convert";
import "dart:io";
import "package:iiitb_menu/constants.dart";
// import "package:path_provider/path_provider.dart";
// import 'dart:io';
import "package:flutter/material.dart";
import "package:crypto/crypto.dart";
import "package:http/http.dart";
import "package:intl/intl.dart";
import "package:shared_preferences/shared_preferences.dart";
class GlobalModel extends ChangeNotifier {
late Map<dynamic, dynamic> mainData;
DateTime currentDate = DateTime.now();
String menuTime = breakfast;
bool menuAvailable = false;
GlobalModel() {
print("In constructor");
GlobalModel.loadData().then((value) {
mainData = value;
if (this.mainData["dates"].keys.contains(this.date)) {
this.menuAvailable = true;
}
// print(mainData);
notifyListeners();
});
}
static Future<String> getLatestHash() async {
const String hashLink = "http://10.0.2.2:8000/out.txt";
try {
Response ret = await get(Uri.parse(hashLink));
if (ret.statusCode == 200) {
return ret.body.replaceAll("\n", "");
} else {
return "";
}
} on SocketException catch (exce) {
print("Unable to download hash");
print(exce);
return "";
}
}
static Future<String> getLatestData() async {
const String dataLink = "http://10.0.2.2:8000/out.json";
try {
Response ret = await get(Uri.parse(dataLink));
return ret.body;
} on SocketException catch (exce) {
print("Unable to download any data");
print(exce);
return "";
}
}
static Future<Map> loadData() async {
late Map returnData;
// Directory appDir = await getApplicationDocumentsDirectory();
final SharedPreferences prefs = await SharedPreferences.getInstance();
String? rawData;
String rawHash;
// String fileName = "${appDir.path}/menu.json";
// print(fileName);
// File fileLink = File(fileName);
rawData = prefs.getString(storageKey);
print(rawData);
if (rawData != null) {
print("data found");
// rawData = localStor.getItem("fullMenu");
rawHash = md5.convert(utf8.encode(rawData)).toString();
print("Hash of Raw Data:");
print(rawHash);
// print("RawData: ");
// print(rawData);
returnData = jsonDecode(rawData);
// menuAvailable = true;
} else {
print("File Not Found");
returnData = {};
rawHash = "";
}
String remoteHash = await GlobalModel.getLatestHash();
if (remoteHash == "") {
} else if (remoteHash == rawHash) {
// print("Remote hash $remoteHash is same as local hash $rawHash");
} else {
// print("Remote hash $remoteHash is NOT the same as local hash $rawHash");
// print("Getting data from remote");
rawData = await getLatestData();
if (rawData == "") {
return {};
}
returnData = jsonDecode(rawData);
// fileLink.writeAsStringSync(rawData, mode: FileMode.write);
prefs.setString(storageKey, rawData);
}
return returnData;
}
String get date {
return DateFormat("dd-MM-yyyy").format(this.currentDate);
}
void incrDate() {
this.currentDate = this.currentDate.add(const Duration(days: 1));
this.isMenuAvailable();
notifyListeners();
}
void decrDate() {
this.currentDate = this.currentDate.add(const Duration(days: -1));
this.isMenuAvailable();
notifyListeners();
}
void setMenuTime(int time) {
switch (time) {
case 0:
this.menuTime = breakfast;
notifyListeners();
break;
case 1:
this.menuTime = lunch;
notifyListeners();
break;
case 2:
this.menuTime = snak;
notifyListeners();
break;
case 3:
this.menuTime = dinner;
notifyListeners();
break;
default:
}
}
void isMenuAvailable() {
if (this.mainData["dates"].keys.contains(this.date)) {
this.menuAvailable = true;
} else {
this.menuAvailable = false;
}
}
void setDateToToday() {
this.currentDate = DateTime.now();
this.isMenuAvailable();
notifyListeners();
}
}

94
lib/views/homePage.dart Normal file
View File

@@ -0,0 +1,94 @@
// ignore_for_file: file_names
import "package:flutter/material.dart";
import "package:iiitb_menu/constants.dart";
import "package:iiitb_menu/models/globalModel.dart";
import "package:iiitb_menu/views/menuListView.dart";
// import "package:iiitb_menu/widgets/itemCard.dart";
// import "package:intl/intl.dart";
import "package:provider/provider.dart";
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return SafeArea(
child: DefaultTabController(
length: 4,
child: Consumer<GlobalModel>(
builder: (BuildContext context, GlobalModel data, Widget? child) {
return Scaffold(
appBar: AppBar(
title: Text("Daily ${data.menuTime} Menu"),
bottom: TabBar(
indicator: const UnderlineTabIndicator(
insets: EdgeInsets.fromLTRB(10, 3, 10, 3)),
onTap: (int index) {
Provider.of<GlobalModel>(context, listen: false)
.setMenuTime(index);
},
tabs: const [
Tab(icon: Icon(Icons.breakfast_dining_outlined)),
Tab(icon: Icon(Icons.lunch_dining_outlined)),
Tab(icon: Icon(Icons.coffee_outlined)),
Tab(icon: Icon(Icons.dinner_dining_outlined))
]),
actions: [
InkWell(
onTap: () {
data.decrDate();
},
child: const Icon(
Icons.arrow_left_rounded,
size: 30,
)),
InkWell(
onLongPress: () {
showDatePicker(
context: context,
initialDate: data.currentDate,
firstDate:
data.currentDate.add(const Duration(days: -30)),
lastDate:
data.currentDate.add(const Duration(days: 30)));
},
onTap: () {
data.setDateToToday();
},
child: Center(
child: Text(
data.date,
),
),
),
InkWell(
onTap: () {
data.incrDate();
},
child: const Icon(
Icons.arrow_right_rounded,
size: 30,
)),
],
),
body: TabBarView(
children: data.menuAvailable
? const [
MenuListView(menuType: "bf"),
MenuListView(menuType: "ln"),
MenuListView(menuType: "sk"),
MenuListView(menuType: "dn"),
]
: [
noMenuWidget,
noMenuWidget,
noMenuWidget,
noMenuWidget,
]),
);
}),
),
);
}
}

View File

@@ -0,0 +1,36 @@
// ignore_for_file: unnecessary_this, file_names
import 'package:flutter/material.dart';
import 'package:iiitb_menu/models/globalModel.dart';
import 'package:iiitb_menu/widgets/itemCard.dart';
import 'package:provider/provider.dart';
class MenuListView extends StatelessWidget {
const MenuListView({super.key, required this.menuType});
final String menuType;
@override
Widget build(BuildContext context) {
return Consumer<GlobalModel>(
builder: (BuildContext context, GlobalModel data, Widget? child) {
// print(data.date);
// print(data.mainData["dates"][data.date]);
String menuIndex = data.mainData["dates"][data.date];
return ListView.builder(
itemCount: data.mainData["items"][this.menuType].length,
itemBuilder: (BuildContext context, int index) {
String itemType = data.mainData["items"][this.menuType][index];
String itemName = data.mainData["menu"][menuIndex][this.menuType]
[itemType]["name"];
String itemVeggness = data.mainData["menu"][menuIndex]
[this.menuType][itemType]["eggy"];
return ItemCard(
itemName: itemName,
itemType: itemType,
vegClass: itemVeggness,
);
});
},
);
}
}

58
lib/widgets/itemCard.dart Normal file
View File

@@ -0,0 +1,58 @@
// ignore_for_file: file_names, unnecessary_this
import "package:flutter/material.dart";
import "package:iiitb_menu/constants.dart";
import "package:iiitb_menu/widgets/vegIcons.dart";
class ItemCard extends StatelessWidget {
const ItemCard(
{super.key,
required this.itemName,
required this.itemType,
this.vegClass = VEG});
final String itemName;
final String itemType;
final String vegClass;
@override
Widget build(BuildContext context) {
Icon vegClassIcon;
Color borderColor;
switch (this.vegClass) {
case VEG:
vegClassIcon = vegIcon;
borderColor = Colors.green.shade600;
break;
case EGG:
vegClassIcon = eggIcon;
borderColor = Colors.orange.shade700;
break;
case NONVEG:
vegClassIcon = nonVegIcon;
borderColor = Colors.red.shade600;
break;
default:
vegClassIcon = vegIcon;
borderColor = Colors.green;
}
if (this.itemName == EMPTY) {
return Container();
}
return Container(
margin: const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
// gradient: LinearGradient(colors: []),
borderRadius: BorderRadius.circular(2),
border: Border.all(width: 0.5, color: borderColor),
),
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text(this.itemName, style: const TextStyle(fontSize: 25)),
Text(this.itemType, style: const TextStyle(fontSize: 15)),
]),
vegClassIcon,
]),
);
}
}

View File

@@ -0,0 +1,9 @@
//ignore_for_file: file_names
import 'package:flutter/material.dart';
Icon vegIcon = const Icon(Icons.grass_rounded, color: Colors.green);
Icon nonVegIcon = const Icon(Icons.set_meal_rounded, color: Colors.red);
Icon eggIcon = const Icon(Icons.egg_rounded, color: Colors.orange);