Appointments system

This commit is contained in:
sewmina7@gmail.com 2023-08-14 17:11:11 +05:30
parent da15e3cda6
commit 50e9dda303
6 changed files with 167 additions and 62 deletions

View File

@ -1,4 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<application <application
android:label="queue_client" android:label="queue_client"
android:name="${applicationName}" android:name="${applicationName}"

View File

@ -24,6 +24,7 @@ class _DataManager{
_DataManager(); _DataManager();
List<dynamic> services = []; List<dynamic> services = [];
List<dynamic> joinedServices=[];
List<Map<String, dynamic>> AvailableServices = []; List<Map<String, dynamic>> AvailableServices = [];
List<Map<String, dynamic>> JoinedServices = []; List<Map<String, dynamic>> JoinedServices = [];
String Username = ""; String Username = "";
@ -74,34 +75,45 @@ class _DataManager{
Debug.LogError(e); Debug.LogError(e);
} }
ProcessServices();
await ProcessServices();
} }
void ProcessServices(){ Future<void> ProcessServices() async{
try{
var response = (await http.post(
Uri.parse('${API_ENDPOINT}get_joined_services.php'),
body: <String, String>{
'userId':userId.toString()
}));
Debug.LogResponse(response.body.toString());
joinedServices = jsonDecode(response.body.toString());
Debug.LogResponse(services);
}catch(e){
Debug.LogError(e);
}
AvailableServices=[]; AvailableServices=[];
JoinedServices=[]; JoinedServices=[];
for (var m_service in services) { for (var m_service in services) {
Map<String,dynamic> service= jsonDecode(m_service); Map<String,dynamic> service = jsonDecode(m_service);
if(DateTime.parse(service['end_time']).isBefore(DateTime.now())){ if(DateTime.parse(service['end_time']).isBefore(DateTime.now())){
continue; continue;
} }
List<String> members = service['members'].toString().split(','); bool joined = false;
for (var m_joinedService in joinedServices){
if(members.contains(userId.toString())){ if(service['id'] == jsonDecode(m_joinedService)['service_id']){
int tokenId = 0; //Joined this
for(int i=0;i<members.length; i++){ JoinedServices.add(jsonDecode(m_joinedService));
if(members[i] == userId.toString()){ joined=true;
tokenId = i; break;
break;
}
} }
service.putIfAbsent("tokenId", () => tokenId);
JoinedServices.add(service);
}else{
AvailableServices.add(service);
} }
m_service = jsonEncode(service); if(!joined){
AvailableServices.add(service);
}
} }
} }
@ -130,7 +142,7 @@ class _DataManager{
Debug.LogError(e); Debug.LogError(e);
} }
ProcessServices(); await ProcessServices();
} }
} }

View File

@ -15,6 +15,7 @@ class Debug{
static void LogError(Object? msg){ static void LogError(Object? msg){
if(!enableLogging){return;} if(!enableLogging){return;}
if(!enableErrorLoggin) {return;} if(!enableErrorLoggin) {return;}
print(StackTrace.current);
print('\x1B[31m$msg\x1B[0m'); print('\x1B[31m$msg\x1B[0m');
} }

View File

@ -3,6 +3,7 @@
import 'package:duration_picker/duration_picker.dart'; import 'package:duration_picker/duration_picker.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:queue_client/backend/DebugHelper.dart';
// import 'package:flutter_spinkit/flutter_spinkit.dart'; // import 'package:flutter_spinkit/flutter_spinkit.dart';
// import 'package:shared_preferences/shared_preferences.dart'; // import 'package:shared_preferences/shared_preferences.dart';
// import 'package:url_launcher/url_launcher.dart'; // import 'package:url_launcher/url_launcher.dart';
@ -41,8 +42,7 @@ class Dialogs{
} }
static bool showing = false; static bool showing = false;
static BuildContext? context; static waiting(BuildContext context){
static waiting(){
showing=true; showing=true;
// context=navigatorKey.currentContext; // context=navigatorKey.currentContext;
if(context!=null) { if(context!=null) {
@ -68,6 +68,39 @@ class Dialogs{
} }
} }
static Future<bool> AskQuestion(BuildContext context, String title, String message) async{
bool yes = false;
AlertDialog alert = AlertDialog(
backgroundColor: Color(0xFF1F1F1F),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)),
title: Text(title,textAlign: TextAlign.center,),
content: Text(message,textAlign: TextAlign.center,),
actions: [
TextButton(onPressed: (){
yes=true;
Navigator.pop(context);
}, child: Text("Yes")),
TextButton(onPressed: (){
Navigator.pop(context);
}, child: Text("No")),
],
);
// show the dialog
await showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
return yes;
}
static showDurationPicker(BuildContext context, String title) { static showDurationPicker(BuildContext context, String title) {
// set up the button // set up the button
Widget okButton = TextButton( Widget okButton = TextButton(
@ -97,11 +130,11 @@ class Dialogs{
}, },
); );
} }
// static hide(){ static hide(BuildContext context){
// showing=false; showing=false;
// Navigator.of(navigatorKey.currentContext!).popUntil((route){ Navigator.of(context).popUntil((route){
// return route.settings.name!="Progress"; return route.settings.name!="Progress";
// }); });
// } }
} }

View File

@ -1,7 +1,10 @@
import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:queue_client/backend/DataManager.dart'; import 'package:queue_client/backend/DataManager.dart';
import 'package:queue_client/backend/Dialogs.dart';
import 'package:queue_client/service_info.dart'; import 'package:queue_client/service_info.dart';
class HomePage extends StatefulWidget { class HomePage extends StatefulWidget {
@ -12,12 +15,32 @@ class HomePage extends StatefulWidget {
} }
class _HomePageState extends State<HomePage> { class _HomePageState extends State<HomePage> {
Timer timer = Timer(Duration(hours: 1), () { });
@override @override
void initState() { void initState() {
// TODO: implement initState // TODO: implement initState
super.initState(); super.initState();
timer = Timer.periodic(const Duration(seconds: 30), (timer) {
refresh();
});
refresh(); refreshInit();
}
void refreshInit() async{
// Dialogs.waiting(context);
await DataManager.instance().GetData();
// Dialogs.hide(context);
setState(() {});
}
@override
void dispose() {
// TODO: implement dispose
timer.cancel();
super.dispose();
} }
void refresh() async { void refresh() async {
@ -51,35 +74,38 @@ class _HomePageState extends State<HomePage> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Card( // Card(
child: Padding( // child: Padding(
padding: const EdgeInsets.all(8.0), // padding: const EdgeInsets.all(8.0),
child: Column( // child: Column(
children: [ // children: [
Row( // Row(
mainAxisAlignment: MainAxisAlignment.center, // mainAxisAlignment: MainAxisAlignment.center,
children: [ // children: [
Icon(Icons.token), // Icon(Icons.token),
Text(" Your Token ID") // Text(" Your Token ID")
], // ],
), // ),
Text(DataManager.instance().userId.toString(),style: TextStyle(fontSize: 45),) // Text(DataManager.instance().userId.toString(),style: TextStyle(fontSize: 45),)
], // ],
), // ),
), // ),
), // ),
// SizedBox(height: 30,),
Text("Joined"), Text("Joined"),
SizedBox(height: 10,), SizedBox(height: 10,),
GridView.count( GridView.count(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,
crossAxisCount: context.isSmall ? 1 : ( context.isTablet ? 4: 2), crossAxisCount: context.isSmall ? 1 : ( context.isTablet ? 4: 2),
children: List.generate( children: List.generate(
DataManager.instance().JoinedServices.length, (index) { DataManager.instance().JoinedServices.length, (index) {
Map<String, dynamic> service = Map<String, dynamic> service =
DataManager.instance().JoinedServices[index]; (DataManager.instance().JoinedServices[index]);
return ServiceCard( return ServiceCard(
tokenId: service['tokenId'], tokenId: int.parse(service['id']),
id: int.parse(service['id']), id: int.parse(service['service_id']),
sTime: DateTime.parse( sTime: DateTime.parse(
service['start_time'] ?? DateTime.now().toString()), service['start_time'] ?? DateTime.now().toString()),
eTime: DateTime.parse( eTime: DateTime.parse(
@ -98,10 +124,12 @@ class _HomePageState extends State<HomePage> {
// Map<String,dynamic> service= DataManager.instance().JoinedServices[index]; // Map<String,dynamic> service= DataManager.instance().JoinedServices[index];
// return ServiceCard(tokenId:service['tokenId'],id: int.parse(service['id']),sTime: DateTime.parse(service['start_time'] ?? DateTime.now().toString()), name: service['name']!, memberCount: service['members']!.split(',').length-1); // return ServiceCard(tokenId:service['tokenId'],id: int.parse(service['id']),sTime: DateTime.parse(service['start_time'] ?? DateTime.now().toString()), name: service['name']!, memberCount: service['members']!.split(',').length-1);
// }), // }),
SizedBox(height: 50), SizedBox(height: 20),
Text("Available"), Text("Available"),
SizedBox(height: 10,), SizedBox(height: 10,),
ListView.builder( ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,
itemCount: DataManager.instance().AvailableServices.length, itemCount: DataManager.instance().AvailableServices.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
@ -136,18 +164,25 @@ class _HomePageState extends State<HomePage> {
required Duration duration}) { required Duration duration}) {
DateTime eta = sTime.add(duration * tokenId); DateTime eta = sTime.add(duration * (tokenId > 0 ? tokenId : memberCount));
return InkWell( return InkWell(
onTap: () async { onTap: () async {
if(tokenId > 0){return;} if(tokenId > 0){return;}
await Navigator.of(context).push(MaterialPageRoute( // await Navigator.of(context).push(MaterialPageRoute(
builder: (context) => ServiceInfoPage( // builder: (context) => ServiceInfoPage(
id: id, // id: id,
tokenId: tokenId, // tokenId: tokenId,
))); // )));
bool confirmed = await Dialogs.AskQuestion(context, "Confirm", "Are you sure to join to this Queue?\n\nQueue Name : ${name}");
if(confirmed){
Dialogs.waiting(context);
await DataManager.instance().JoinService(id);
Dialogs.hide(context);
}
setState(() {}); setState(() {});
}, },
child: Card( child: Card(
@ -156,18 +191,29 @@ class _HomePageState extends State<HomePage> {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Center( Row(
child: Text( mainAxisAlignment: MainAxisAlignment.spaceBetween,
name, children: [
style: TextStyle(fontSize: 20), Text(
)), name,
style: TextStyle(fontSize: 20),
),
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Icon(Icons.people_alt_rounded,size: 25,),
Text(
" ${memberCount}",
style: TextStyle(fontSize: 25),
),
])
],
),
SizedBox(height: tokenId > 0 ? 0 : 10,), SizedBox(height: tokenId > 0 ? 0 : 10,),
(tokenId > 0) ? Column( (tokenId > 0) ? Column(
children: [ children: [
Row(mainAxisAlignment: MainAxisAlignment.center, children: [ Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Icon(Icons.people_alt_rounded,size: 25,), Icon(Icons.token,size: 25,),
Text( Text(
" $tokenId", " ${tokenId}",
style: TextStyle(fontSize: 40), style: TextStyle(fontSize: 40),
), ),
]), ]),

View File

@ -1,8 +1,10 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:queue_client/CustomWidgets.dart'; import 'package:queue_client/CustomWidgets.dart';
import 'package:queue_client/backend/DataManager.dart'; import 'package:queue_client/backend/DataManager.dart';
import 'package:queue_client/backend/Dialogs.dart'; import 'package:queue_client/backend/Dialogs.dart';
import 'package:queue_client/home.dart'; import 'package:queue_client/home.dart';
import 'package:shared_preferences/shared_preferences.dart';
class LoginPage extends StatefulWidget { class LoginPage extends StatefulWidget {
const LoginPage({Key? key}) : super(key: key); const LoginPage({Key? key}) : super(key: key);
@ -19,8 +21,17 @@ class _LoginPageState extends State<LoginPage> {
void initState() { void initState() {
// TODO: implement initState // TODO: implement initState
super.initState(); super.initState();
Reset();
// AutoLogin();
}
AutoLogin(); void Reset() async{
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.clear();
isLogging =false;
setState(() {
});
} }
void AutoLogin()async{ void AutoLogin()async{