initial commit
This commit is contained in:
16
lib/constants.dart
Normal file
16
lib/constants.dart
Normal 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
28
lib/main.dart
Normal 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
156
lib/models/globalModel.dart
Normal 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
94
lib/views/homePage.dart
Normal 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,
|
||||
]),
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
36
lib/views/menuListView.dart
Normal file
36
lib/views/menuListView.dart
Normal 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
58
lib/widgets/itemCard.dart
Normal 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,
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
||||
9
lib/widgets/vegIcons.dart
Normal file
9
lib/widgets/vegIcons.dart
Normal 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);
|
||||
Reference in New Issue
Block a user