10 Commits

Author SHA1 Message Date
  Oniel Mendez 8ee4aed109 sprint 3 carlos integrado 4 years ago
  Oniel Mendez 6e8275bf04 sprint 3 hector integrado 4 years ago
  Oniel Mendez f7c056870e union sprint 1 carlos 4 years ago
  Oniel Mendez 0876c368c6 Union Sprint 3 Carlos 4 years ago
  Carlos 4196d234c5 Primer Commit 4 years ago
  Oniel Mendez 96444c6161 Update home.dart 4 years ago
  Oniel Mendez 7926ff616f Update pubspec.lock 4 years ago
  Oniel Mendez bc738eed7c Merge branch 'sprint2oniel' into sprint3 4 years ago
  JorgeIan 2569ee7c9d Sprint 3 4 years ago
  Oniel Mendez 44ad4ba069 Added: click en una Oficina de la lista te lleva a una pagina para ver su informacion 4 years ago
39 changed files with 2902 additions and 536 deletions
  1. 1
    1
      fast_med_flutter/android/app/build.gradle
  2. 17
    0
      fast_med_flutter/lib/classes/language.dart
  3. 15
    0
      fast_med_flutter/lib/languages/en.json
  4. 15
    0
      fast_med_flutter/lib/languages/es.json
  5. 42
    0
      fast_med_flutter/lib/localization/language_constants.dart
  6. 51
    0
      fast_med_flutter/lib/localization/localization.dart
  7. 10
    1
      fast_med_flutter/lib/main.dart
  8. 66
    0
      fast_med_flutter/lib/model/event.dart
  9. 26
    0
      fast_med_flutter/lib/pages/about_page.dart
  10. 217
    0
      fast_med_flutter/lib/pages/home_page.dart
  11. 24
    0
      fast_med_flutter/lib/pages/not_found_page.dart
  12. 54
    0
      fast_med_flutter/lib/pages/settings_page.dart
  13. 6
    0
      fast_med_flutter/lib/res/event_firestore_service.dart
  14. 21
    0
      fast_med_flutter/lib/router/custom_router.dart
  15. 3
    0
      fast_med_flutter/lib/router/route_constants.dart
  16. 60
    0
      fast_med_flutter/lib/routes/OfficeScreen.dart
  17. 69
    0
      fast_med_flutter/lib/routes/Offices.dart
  18. 85
    0
      fast_med_flutter/lib/routes/album.dart
  19. 135
    0
      fast_med_flutter/lib/routes/appointments.dart
  20. 159
    277
      fast_med_flutter/lib/routes/calendario.dart
  21. 39
    0
      fast_med_flutter/lib/routes/dynamic.dart
  22. 109
    0
      fast_med_flutter/lib/routes/especialidades.dart
  23. 14
    62
      fast_med_flutter/lib/routes/home.dart
  24. 88
    0
      fast_med_flutter/lib/routes/navigation.dart
  25. 226
    0
      fast_med_flutter/lib/routes/profileinfo.dart
  26. 217
    104
      fast_med_flutter/lib/routes/register.dart
  27. 81
    0
      fast_med_flutter/lib/routes/translation.dart
  28. 302
    0
      fast_med_flutter/lib/routes/ver_oficina.dart
  29. 15
    27
      fast_med_flutter/lib/routes/ver_oficinas.dart
  30. 68
    33
      fast_med_flutter/lib/routes/welcome.dart
  31. 231
    0
      fast_med_flutter/lib/ui/pages/add_event.dart
  32. 30
    0
      fast_med_flutter/lib/ui/pages/view_event.dart
  33. 32
    0
      fast_med_flutter/lib/widgets/DataTableMySqlDemo/Especialista.dart
  34. 29
    0
      fast_med_flutter/lib/widgets/DataTableMySqlDemo/Horario.dart
  35. 18
    2
      fast_med_flutter/lib/widgets/DataTableMySqlDemo/Oficina.dart
  36. 77
    19
      fast_med_flutter/lib/widgets/DataTableMySqlDemo/Services.dart
  37. 54
    0
      fast_med_flutter/lib/widgets/functions.dart
  38. 184
    6
      fast_med_flutter/pubspec.lock
  39. 12
    4
      fast_med_flutter/pubspec.yaml

+ 1
- 1
fast_med_flutter/android/app/build.gradle View File

@@ -39,7 +39,7 @@ android {
39 39
     defaultConfig {
40 40
         // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
41 41
         applicationId "com.example.fast_med_flutter"
42
-        minSdkVersion 16
42
+        minSdkVersion 23
43 43
         targetSdkVersion 29
44 44
         versionCode flutterVersionCode.toInteger()
45 45
         versionName flutterVersionName

+ 17
- 0
fast_med_flutter/lib/classes/language.dart View File

@@ -0,0 +1,17 @@
1
+class Language {
2
+  final int id;
3
+  final String flag;
4
+  final String name;
5
+  final String languageCode;
6
+
7
+  Language(this.id, this.flag, this.name, this.languageCode);
8
+
9
+  static List<Language> languageList() {
10
+    return <Language>[
11
+      Language(1, "🇦🇫", "فارسی", "fa"),
12
+      Language(2, "🇺🇸", "English", "en"),
13
+      Language(3, "🇺🇸", "Español", "es"),
14
+      Language(4, "🇮🇳", "हिंदी", "hi"),
15
+    ];
16
+  }
17
+}

+ 15
- 0
fast_med_flutter/lib/languages/en.json View File

@@ -0,0 +1,15 @@
1
+{
2
+  "home_page": "Home Page",
3
+  "personal_information": "Personal Information",
4
+  "name": "Name",
5
+  "name_hint": "Enter your name",
6
+  "email": "Email",
7
+  "email_hint": "Enter your email",
8
+  "date_of_birth": "Date of Birth",
9
+  "required_field": "Required Field",
10
+  "submit_info": "Submit Info",
11
+  "about_us": "About Us",
12
+  "settings": "Settings",
13
+  "change_language": "Change Language",
14
+  "about": "This user story translate for our FastMed app in CCOM4030."
15
+}

+ 15
- 0
fast_med_flutter/lib/languages/es.json View File

@@ -0,0 +1,15 @@
1
+{
2
+  "home_page": "Pagina Inicio",
3
+  "personal_information": "Informacion Personal",
4
+  "name": "Nombre",
5
+  "name_hint": "Entra tu nombre",
6
+  "email": "Correo electronico",
7
+  "email_hint": "Entra tu correo electronico",
8
+  "date_of_birth": "Fecha de nacimiento",
9
+  "required_field": "Campo requerido",
10
+  "submit_info": "Somete informacion",
11
+  "about_us": "Acerca de nosotros",
12
+  "settings": "Configuracion",
13
+  "change_language": "Cambia el lenguaje",
14
+  "about": "Este user story traduce para nuestro FastMed app en CCOM4030."
15
+}

+ 42
- 0
fast_med_flutter/lib/localization/language_constants.dart View File

@@ -0,0 +1,42 @@
1
+import 'package:flutter/material.dart';
2
+import '../localization/localization.dart';
3
+import 'package:shared_preferences/shared_preferences.dart';
4
+
5
+const String LAGUAGE_CODE = 'languageCode';
6
+
7
+//languages code
8
+const String ENGLISH = 'en';
9
+const String FARSI = 'fa';
10
+const String SPANISH = 'es';
11
+const String HINDI = 'hi';
12
+
13
+Future<Locale> setLocale(String languageCode) async {
14
+  SharedPreferences _prefs = await SharedPreferences.getInstance();
15
+  await _prefs.setString(LAGUAGE_CODE, languageCode);
16
+  return _locale(languageCode);
17
+}
18
+
19
+Future<Locale> getLocale() async {
20
+  SharedPreferences _prefs = await SharedPreferences.getInstance();
21
+  String languageCode = _prefs.getString(LAGUAGE_CODE) ?? "en";
22
+  return _locale(languageCode);
23
+}
24
+
25
+Locale _locale(String languageCode) {
26
+  switch (languageCode) {
27
+    case ENGLISH:
28
+      return Locale(ENGLISH, 'US');
29
+    case FARSI:
30
+      return Locale(FARSI, "IR");
31
+    case SPANISH:
32
+      return Locale(SPANISH, "SP");
33
+    case HINDI:
34
+      return Locale(HINDI, "IN");
35
+    default:
36
+      return Locale(ENGLISH, 'US');
37
+  }
38
+}
39
+
40
+String getTranslated(BuildContext context, String key) {
41
+  return DemoLocalization.of(context).translate(key);
42
+}

+ 51
- 0
fast_med_flutter/lib/localization/localization.dart View File

@@ -0,0 +1,51 @@
1
+import 'dart:convert';
2
+
3
+import 'package:flutter/material.dart';
4
+import 'package:flutter/services.dart';
5
+
6
+class DemoLocalization {
7
+  DemoLocalization(this.locale);
8
+
9
+  final Locale locale;
10
+  static DemoLocalization of(BuildContext context) {
11
+    return Localizations.of<DemoLocalization>(context, DemoLocalization);
12
+  }
13
+
14
+  Map<String, String> _localizedValues;
15
+
16
+  Future<void> load() async {
17
+    String jsonStringValues =
18
+    await rootBundle.loadString('lib/languages/${locale.languageCode}.json');
19
+    Map<String, dynamic> mappedJson = json.decode(jsonStringValues);
20
+    _localizedValues =
21
+        mappedJson.map((key, value) => MapEntry(key, value.toString()));
22
+  }
23
+
24
+  String translate(String key) {
25
+    return _localizedValues[key];
26
+  }
27
+
28
+  // static member to have simple access to the delegate from Material App
29
+  static const LocalizationsDelegate<DemoLocalization> delegate =
30
+  _DemoLocalizationsDelegate();
31
+}
32
+
33
+class _DemoLocalizationsDelegate
34
+    extends LocalizationsDelegate<DemoLocalization> {
35
+  const _DemoLocalizationsDelegate();
36
+
37
+  @override
38
+  bool isSupported(Locale locale) {
39
+    return ['en', 'es', 'fa', 'hi'].contains(locale.languageCode);
40
+  }
41
+
42
+  @override
43
+  Future<DemoLocalization> load(Locale locale) async {
44
+    DemoLocalization localization = new DemoLocalization(locale);
45
+    await localization.load();
46
+    return localization;
47
+  }
48
+
49
+  @override
50
+  bool shouldReload(LocalizationsDelegate<DemoLocalization> old) => false;
51
+}

+ 10
- 1
fast_med_flutter/lib/main.dart View File

@@ -1,19 +1,28 @@
1 1
 import 'package:fast_med_flutter/routes/home.dart';
2 2
 import 'package:fast_med_flutter/routes/ver_oficinas.dart';
3
+import 'package:fast_med_flutter/routes/ver_oficina.dart';
3 4
 import 'package:fast_med_flutter/routes/calendario.dart';
4 5
 import 'package:fast_med_flutter/routes/main.dart';
5 6
 import 'package:fast_med_flutter/routes/register.dart';
6 7
 import 'package:fast_med_flutter/routes/welcome.dart';
8
+import 'package:fast_med_flutter/routes/album.dart';
7 9
 import 'package:flutter/material.dart';
10
+import 'package:fast_med_flutter/routes/especialidades.dart';
11
+import 'routes/translation.dart';
8 12
 
9 13
 void main() => runApp(MaterialApp(
10
-    initialRoute: '/home',
14
+    initialRoute: '/welcome',
11 15
     routes: {
12 16
       '/home': (context) => Home(),
13 17
       '/verOficinas': (context) => VerOficinas(),
18
+      '/ver/oficina': (context) => VerOficina(),
14 19
       '/calendario': (context) => Calendario(),
15 20
       '/welcome': (context) => WelcomePage(),
16 21
       '/register': (context) => RegisterPage(),
17 22
       '/MyApp': (context) => MyApp(),
23
+      '/album': (context) => album(),
24
+      '/especialidades': (context) => especialidades(),
25
+      '/translation': (context) => translation(),
26
+
18 27
     }
19 28
 ));

+ 66
- 0
fast_med_flutter/lib/model/event.dart View File

@@ -0,0 +1,66 @@
1
+import 'package:firebase_helpers/firebase_helpers.dart';
2
+
3
+//En esta Area definimos todas las variables y parametros utilizadas en las
4
+//funciones de los otros files.
5
+
6
+//Son las mismas variables usadas para enviar al servidor y recibir de vuelta
7
+// a la aplicacion.
8
+
9
+class EventModel extends DatabaseItem{
10
+  final String id;
11
+  final String title;
12
+  final String description;
13
+  final DateTime eventDate;
14
+  final String name;
15
+  final String number;
16
+  final String reason;
17
+  final DateTime eventTime;
18
+
19
+
20
+  EventModel({this.id,this.title, this.description, this.eventDate, this.name, this.number, this.reason, this.eventTime}):super(id);
21
+
22
+  factory EventModel.fromMap(Map data) {
23
+    return EventModel(
24
+      title: data['title'],
25
+      description: data['description'],
26
+      name: data['name'],
27
+      number: data['number'],
28
+      reason: data['reason'],
29
+      eventDate: data['event_date'],
30
+      eventTime: data['event_time'],
31
+    );
32
+  }
33
+
34
+  factory EventModel.fromDS(String id, Map<String,dynamic> data) {
35
+    return EventModel(
36
+      id: id,
37
+      title: data['title'],
38
+      description: data['description'],
39
+      number: data['number'],
40
+      reason: data['reason'],
41
+      eventDate: data['event_date'].toDate(),
42
+      eventTime: data['event_time'].toTime(),
43
+    );
44
+  }
45
+
46
+  final Map<DateTime, List> _holidays = {
47
+    DateTime(2020, 11, 6): ['No Hay Citas'],
48
+    DateTime(2020, 11, 3): ['Dia Elecciones'],
49
+    DateTime(2020, 12, 25): ['Chrismas'],
50
+    DateTime(2020, 12, 31): ['Despedida del anyo nuevo'],
51
+  };
52
+
53
+
54
+  Map<String,dynamic> toMap() {
55
+    return {
56
+      "title":title,
57
+      "description": description,
58
+      "event_date":eventDate,
59
+      "id":id,
60
+      "name":name,
61
+      "number":number,
62
+      "reason":reason,
63
+      "event_time":eventTime,
64
+    };
65
+  }
66
+}

+ 26
- 0
fast_med_flutter/lib/pages/about_page.dart View File

@@ -0,0 +1,26 @@
1
+import 'package:flutter/material.dart';
2
+import '../localization/language_constants.dart';
3
+
4
+class AboutPage extends StatefulWidget {
5
+  AboutPage({Key key}) : super(key: key);
6
+
7
+  @override
8
+  _AboutPageState createState() => _AboutPageState();
9
+}
10
+
11
+class _AboutPageState extends State<AboutPage> {
12
+  @override
13
+  Widget build(BuildContext context) {
14
+    return Scaffold(
15
+      appBar: AppBar(
16
+        title: Text(getTranslated(context, 'about_us')),
17
+      ),
18
+      body: Container(
19
+        padding: EdgeInsets.all(20),
20
+        child: Center(
21
+          child: Text(getTranslated(context, 'about')),
22
+        ),
23
+      ),
24
+    );
25
+  }
26
+}

+ 217
- 0
fast_med_flutter/lib/pages/home_page.dart View File

@@ -0,0 +1,217 @@
1
+import 'package:flutter/material.dart';
2
+import '../classes/language.dart';
3
+import '../localization/language_constants.dart';
4
+import '../routes/translation.dart';
5
+import '../router/route_constants.dart';
6
+
7
+class HomePage extends StatefulWidget {
8
+  HomePage({Key key}) : super(key: key);
9
+
10
+  @override
11
+  _HomePageState createState() => _HomePageState();
12
+}
13
+
14
+class _HomePageState extends State<HomePage> {
15
+  final GlobalKey<FormState> _key = GlobalKey<FormState>();
16
+  void _changeLanguage(Language language) async {
17
+    Locale _locale = await setLocale(language.languageCode);
18
+    translation.setLocale(context, _locale);
19
+  }
20
+
21
+  void _showSuccessDialog() {
22
+    showTimePicker(context: context, initialTime: TimeOfDay.now());
23
+  }
24
+
25
+  @override
26
+  Widget build(BuildContext context) {
27
+    return Scaffold(
28
+      appBar: AppBar(
29
+        title: Text(getTranslated(context, 'home_page')),
30
+        actions: <Widget>[
31
+          Padding(
32
+            padding: const EdgeInsets.all(8.0),
33
+            child: DropdownButton<Language>(
34
+              underline: SizedBox(),
35
+              icon: Icon(
36
+                Icons.language,
37
+                color: Colors.white,
38
+              ),
39
+              onChanged: (Language language) {
40
+                _changeLanguage(language);
41
+              },
42
+              items: Language.languageList()
43
+                  .map<DropdownMenuItem<Language>>(
44
+                    (e) => DropdownMenuItem<Language>(
45
+                  value: e,
46
+                  child: Row(
47
+                    mainAxisAlignment: MainAxisAlignment.spaceAround,
48
+                    children: <Widget>[
49
+                      Text(
50
+                        e.flag,
51
+                        style: TextStyle(fontSize: 30),
52
+                      ),
53
+                      Text(e.name)
54
+                    ],
55
+                  ),
56
+                ),
57
+              )
58
+                  .toList(),
59
+            ),
60
+          ),
61
+        ],
62
+      ),
63
+      drawer: Drawer(
64
+        child: _drawerList(),
65
+      ),
66
+      body: Container(
67
+        padding: EdgeInsets.all(20),
68
+        child: _mainForm(context),
69
+      ),
70
+    );
71
+  }
72
+
73
+  Form _mainForm(BuildContext context) {
74
+    return Form(
75
+      key: _key,
76
+      child: Column(
77
+        children: <Widget>[
78
+          Container(
79
+            height: MediaQuery.of(context).size.height / 4,
80
+            child: Center(
81
+              child: Text(
82
+                getTranslated(context, 'personal_information'),
83
+                // DemoLocalization.of(context).translate('personal_information'),
84
+                textAlign: TextAlign.center,
85
+                style: TextStyle(
86
+                  fontSize: 30,
87
+                  fontWeight: FontWeight.bold,
88
+                ),
89
+              ),
90
+            ),
91
+          ),
92
+          TextFormField(
93
+            validator: (val) {
94
+              if (val.isEmpty) {
95
+                return getTranslated(context, 'required_field');
96
+                // return DemoLocalization.of(context).translate('required_fiedl');
97
+              }
98
+              return null;
99
+            },
100
+            decoration: InputDecoration(
101
+              border: OutlineInputBorder(),
102
+              labelText: getTranslated(context, 'name'),
103
+              hintText: getTranslated(context, 'name_hint'),
104
+            ),
105
+          ),
106
+          SizedBox(
107
+            height: 10,
108
+          ),
109
+          TextFormField(
110
+            validator: (val) {
111
+              if (val.isEmpty) {
112
+                return getTranslated(context, 'required_field');
113
+              }
114
+              return null;
115
+            },
116
+            decoration: InputDecoration(
117
+              border: OutlineInputBorder(),
118
+              labelText: getTranslated(context, 'email'),
119
+              hintText: getTranslated(context, 'email_hint'),
120
+            ),
121
+          ),
122
+          SizedBox(
123
+            height: 10,
124
+          ),
125
+          TextFormField(
126
+            decoration: InputDecoration(
127
+                border: OutlineInputBorder(),
128
+                hintText: getTranslated(context, 'date_of_birth')),
129
+            onTap: () async {
130
+              FocusScope.of(context).requestFocus(FocusNode());
131
+              await showDatePicker(
132
+                context: context,
133
+                initialDate: DateTime.now(),
134
+                firstDate: DateTime(DateTime.now().year),
135
+                lastDate: DateTime(DateTime.now().year + 20),
136
+              );
137
+            },
138
+          ),
139
+          SizedBox(
140
+            height: 10,
141
+          ),
142
+          MaterialButton(
143
+            onPressed: () {
144
+              if (_key.currentState.validate()) {
145
+                _showSuccessDialog();
146
+              }
147
+            },
148
+            height: 50,
149
+            shape: StadiumBorder(),
150
+            color: Theme.of(context).primaryColor,
151
+            child: Center(
152
+              child: Text(
153
+                getTranslated(context, 'submit_info'),
154
+                style: TextStyle(color: Colors.white, fontSize: 20),
155
+              ),
156
+            ),
157
+          )
158
+        ],
159
+      ),
160
+    );
161
+  }
162
+
163
+  Container _drawerList() {
164
+    TextStyle _textStyle = TextStyle(
165
+      color: Colors.white,
166
+      fontSize: 24,
167
+    );
168
+    return Container(
169
+      color: Theme.of(context).primaryColor,
170
+      child: ListView(
171
+        padding: EdgeInsets.zero,
172
+        children: <Widget>[
173
+          DrawerHeader(
174
+            child: Container(
175
+              height: 100,
176
+              child: CircleAvatar(),
177
+            ),
178
+          ),
179
+          ListTile(
180
+            leading: Icon(
181
+              Icons.info,
182
+              color: Colors.white,
183
+              size: 30,
184
+            ),
185
+            title: Text(
186
+              getTranslated(context, 'about_us'),
187
+              style: _textStyle,
188
+            ),
189
+            onTap: () {
190
+              // To close the Drawer
191
+              Navigator.pop(context);
192
+              // Navigating to About Page
193
+              Navigator.pushNamed(context, aboutRoute);
194
+            },
195
+          ),
196
+          ListTile(
197
+            leading: Icon(
198
+              Icons.settings,
199
+              color: Colors.white,
200
+              size: 30,
201
+            ),
202
+            title: Text(
203
+              getTranslated(context, 'settings'),
204
+              style: _textStyle,
205
+            ),
206
+            onTap: () {
207
+              // To close the Drawer
208
+              Navigator.pop(context);
209
+              // Navigating to About Page
210
+              Navigator.pushNamed(context, settingsRoute);
211
+            },
212
+          ),
213
+        ],
214
+      ),
215
+    );
216
+  }
217
+}

+ 24
- 0
fast_med_flutter/lib/pages/not_found_page.dart View File

@@ -0,0 +1,24 @@
1
+import 'package:flutter/material.dart';
2
+
3
+class NotFoundPage extends StatefulWidget {
4
+  NotFoundPage({Key key}) : super(key: key);
5
+
6
+  @override
7
+  _NotFoundPageState createState() => _NotFoundPageState();
8
+}
9
+
10
+class _NotFoundPageState extends State<NotFoundPage> {
11
+  @override
12
+  Widget build(BuildContext context) {
13
+    return Scaffold(
14
+      appBar: AppBar(
15
+        title: Text("Not Found"),
16
+      ),
17
+      body: Container(
18
+        child: Center(
19
+          child: Text("Sorry, We couldn't found your page"),
20
+        ),
21
+      ),
22
+    );
23
+  }
24
+}

+ 54
- 0
fast_med_flutter/lib/pages/settings_page.dart View File

@@ -0,0 +1,54 @@
1
+import 'package:flutter/material.dart';
2
+import '../classes/language.dart';
3
+import '../localization/language_constants.dart';
4
+import '../routes/translation.dart';
5
+
6
+class SettingsPage extends StatefulWidget {
7
+  SettingsPage({Key key}) : super(key: key);
8
+
9
+  @override
10
+  _SettingsPageState createState() => _SettingsPageState();
11
+}
12
+
13
+class _SettingsPageState extends State<SettingsPage> {
14
+  void _changeLanguage(Language language) async {
15
+    Locale _locale = await setLocale(language.languageCode);
16
+    translation.setLocale(context, _locale);
17
+  }
18
+
19
+  @override
20
+  Widget build(BuildContext context) {
21
+    return Scaffold(
22
+      appBar: AppBar(
23
+        title: Text(getTranslated(context, 'settings')),
24
+      ),
25
+      body: Container(
26
+        child: Center(
27
+            child: DropdownButton<Language>(
28
+              iconSize: 30,
29
+              hint: Text(getTranslated(context, 'change_language')),
30
+              onChanged: (Language language) {
31
+                _changeLanguage(language);
32
+              },
33
+              items: Language.languageList()
34
+                  .map<DropdownMenuItem<Language>>(
35
+                    (e) => DropdownMenuItem<Language>(
36
+                  value: e,
37
+                  child: Row(
38
+                    mainAxisAlignment: MainAxisAlignment.spaceAround,
39
+                    children: <Widget>[
40
+                      Text(
41
+                        e.flag,
42
+                        style: TextStyle(fontSize: 30),
43
+                      ),
44
+                      Text(e.name)
45
+                    ],
46
+                  ),
47
+                ),
48
+              )
49
+                  .toList(),
50
+            )),
51
+      ),
52
+    );
53
+  }
54
+}

+ 6
- 0
fast_med_flutter/lib/res/event_firestore_service.dart View File

@@ -0,0 +1,6 @@
1
+import 'package:firebase_helpers/firebase_helpers.dart';
2
+import '../model/event.dart';
3
+
4
+DatabaseService<EventModel> eventDBS = DatabaseService<EventModel>
5
+  ("events",fromDS: (id,data) => EventModel.fromDS(id, data), toMap:
6
+    (event) => event.toMap());

+ 21
- 0
fast_med_flutter/lib/router/custom_router.dart View File

@@ -0,0 +1,21 @@
1
+import 'package:flutter/material.dart';
2
+import '../pages/about_page.dart';
3
+import '../pages/home_page.dart';
4
+import '../pages/not_found_page.dart';
5
+import '../pages/settings_page.dart';
6
+import '../router/route_constants.dart';
7
+
8
+class CustomRouter {
9
+  static Route<dynamic> generatedRoute(RouteSettings settings) {
10
+    switch (settings.name) {
11
+      case homeRoute:
12
+        return MaterialPageRoute(builder: (_) => HomePage());
13
+      case aboutRoute:
14
+        return MaterialPageRoute(builder: (_) => AboutPage());
15
+      case settingsRoute:
16
+        return MaterialPageRoute(builder: (_) => SettingsPage());
17
+      default:
18
+        return MaterialPageRoute(builder: (_) => NotFoundPage());
19
+    }
20
+  }
21
+}

+ 3
- 0
fast_med_flutter/lib/router/route_constants.dart View File

@@ -0,0 +1,3 @@
1
+const String homeRoute = "home";
2
+const String aboutRoute = "about";
3
+const String settingsRoute = "settings";

+ 60
- 0
fast_med_flutter/lib/routes/OfficeScreen.dart View File

@@ -0,0 +1,60 @@
1
+import 'package:flutter/material.dart';
2
+import 'dart:convert';
3
+import 'Offices.dart';
4
+import 'appointments.dart';
5
+import 'package:flutter/foundation.dart';
6
+
7
+
8
+class OfficesScreen extends StatelessWidget {
9
+  final List<Offices> off;
10
+  Offices ofi;
11
+  // final Offices Of;
12
+  // final offlist = List<Offices>.generate(
13
+  //   2,
14
+  //       (i) => Offices(
15
+  //         'Office $i',
16
+  //         docs[i], spec[i], addrs[i],
17
+  //   ),
18
+  // );
19
+
20
+  var docs = ["Collazo", "Albizu"];
21
+  var spec = ["General", "Pediatra"];
22
+  var addrs = ["Bo. Montellano, Cayey", "Las Dalias, Mayagüez"];
23
+
24
+  //requiring the list of todos
25
+  OfficesScreen({Key key, @required this.off}) : super(key: key);
26
+
27
+  @override
28
+  Widget build(BuildContext context) {
29
+    // print(docs[0]);
30
+
31
+    final offlist = List<Offices>.generate(
32
+      2,
33
+          (i) => Offices(
34
+            'Office $i',
35
+            // "sds", "gfdf", "fvfgv",
36
+            docs[i], spec[i], addrs[i]
37
+      ),
38
+    );
39
+    return Scaffold(
40
+
41
+      appBar: AppBar(
42
+        title: Text('Todos'),
43
+      ),
44
+      //passing in the ListView.builder
45
+      body: ListView.builder(
46
+        itemCount: offlist.length,
47
+        itemBuilder: (context, index) {
48
+          return ListTile(
49
+              title: Text(offlist[index].office),
50
+              onTap: (){
51
+                Navigator.push(context, MaterialPageRoute(builder: (context) => 
52
+                AppointmentPage(O: offlist[index])),
53
+                );
54
+              },
55
+          );
56
+        },
57
+      ),
58
+    );
59
+  }
60
+}

+ 69
- 0
fast_med_flutter/lib/routes/Offices.dart View File

@@ -0,0 +1,69 @@
1
+// import 'package:flutter/material.dart';
2
+// import 'dart:convert';
3
+// import 'package:flutter/foundation.dart';
4
+// import 'OfficeScreen.dart';
5
+// import 'appointments.dart';
6
+//
7
+// class Officess {
8
+//   final String office;
9
+//   final String doctor;
10
+//   final String specialty;
11
+//   final String address;
12
+//
13
+//   Officess({this.office, this.doctor, this.specialty, this.address});
14
+//
15
+//   factory Officess.fromJson(Map<String, dynamic> json) {
16
+//     return Officess(
17
+//       office: json['office'],
18
+//       doctor: json['doctor'],
19
+//       specialty: json['id'],
20
+//       address: json['title'],
21
+//     );
22
+//   }
23
+// }
24
+
25
+class Offices {
26
+  final String office;
27
+  final String doctor;
28
+  final String specialty;
29
+  final String address;
30
+
31
+  var variable = 32;
32
+
33
+  var docs = ["Collazo", "Albizu"];
34
+  var spec = ["General", "Pediatra"];
35
+  var addrs = ["Bo. Montellano, Cayey", "Las Dalias, Mayagüez"];
36
+
37
+  Offices(this.office, this.doctor, this.specialty, this.address);
38
+
39
+
40
+}
41
+// var docs = List<String> ("juan", "pedro");
42
+
43
+
44
+// final off = List<Offices>.generate(
45
+//   2,
46
+//       (i) => Offices(
47
+//     'Office $i',
48
+//     docs[i], spec[i], addrs[i],
49
+//   ),
50
+// );
51
+
52
+
53
+
54
+
55
+
56
+
57
+// final off = List<Offices>.generate(
58
+//   2,
59
+//       (i) => Offices(
60
+//     'Office $i',
61
+//     docs[i],
62
+//     spec[i],
63
+//     addrs[i],
64
+//   ),
65
+// );
66
+
67
+
68
+
69
+

+ 85
- 0
fast_med_flutter/lib/routes/album.dart View File

@@ -0,0 +1,85 @@
1
+import 'dart:async';
2
+import 'dart:convert';
3
+import 'dart:io';
4
+
5
+import 'package:flutter/material.dart';
6
+import 'package:flutter/services.dart';
7
+import 'package:http/http.dart' as http;
8
+
9
+Future<Oficina> fetchOficina() async {
10
+  final response =
11
+  await http.get('https://ada.uprrp.edu/~oniel.mendez2/json/getOficinas.php');
12
+
13
+  if (response.statusCode == 200) {
14
+    return Oficina.fromJson(jsonDecode(response.body));
15
+  } else {
16
+    throw Exception('Failed to load album');
17
+  }
18
+}
19
+
20
+class Oficina {
21
+  String id;
22
+  String name;
23
+
24
+  Oficina({this.id, this.name});
25
+
26
+  factory Oficina.fromJson(Map<String, dynamic> json) {
27
+    return Oficina (
28
+      id :json['id'],
29
+      name: json['name'],
30
+    );
31
+  }
32
+}
33
+
34
+
35
+Future<void> main() async {
36
+  runApp(album());
37
+}
38
+class album extends StatefulWidget {
39
+
40
+  album({Key key}) : super(key: key);
41
+
42
+  @override
43
+  _MyAppState2 createState() => _MyAppState2();
44
+}
45
+
46
+
47
+class _MyAppState2 extends State<album> {
48
+  Future<Oficina> futureOficina;
49
+
50
+  @override
51
+  void initState() {
52
+    super.initState();
53
+    futureOficina = fetchOficina();
54
+  }
55
+
56
+  @override
57
+  Widget build(BuildContext context) {
58
+    return MaterialApp(
59
+      title: 'Fetch Data Example',
60
+      theme: ThemeData(
61
+        primarySwatch: Colors.blue,
62
+      ),
63
+      home: Scaffold(
64
+        appBar: AppBar(
65
+          title: Text('Fetch Data Example'),
66
+        ),
67
+        body: Center(
68
+          child: FutureBuilder<Oficina>(
69
+            future: futureOficina,
70
+            builder: (context, snapshot) {
71
+              if (snapshot.hasData) {
72
+                return Text(snapshot.data.name);
73
+              } else if (snapshot.hasError) {
74
+                return Text("${snapshot.error}");
75
+              }
76
+
77
+              // By default, show a loading spinner.
78
+              return CircularProgressIndicator();
79
+            },
80
+          ),
81
+        ),
82
+      ),
83
+    );
84
+  }
85
+}

+ 135
- 0
fast_med_flutter/lib/routes/appointments.dart View File

@@ -0,0 +1,135 @@
1
+import 'package:flutter/cupertino.dart';
2
+import 'package:flutter_login/flutter_login.dart';
3
+import 'package:flutter/material.dart';
4
+import 'package:google_fonts/google_fonts.dart';
5
+import 'Offices.dart';
6
+import 'dynamic.dart';
7
+import 'Offices.dart';
8
+import 'OfficeScreen.dart';
9
+import 'package:flutter/foundation.dart';
10
+import 'package:http/http.dart' as http;
11
+
12
+//This page only works when called by other OfficeScreenPage()
13
+//Need to add the functionality to work on its own
14
+
15
+
16
+class AppointmentPage extends StatelessWidget {
17
+
18
+
19
+  final Offices O;
20
+  AppointmentPage({Key key, @required this.O}) :super(key: key);
21
+  // AppointmentPage({Key key, @required this.O}) : super(key: key);
22
+
23
+  // final String title;
24
+  //
25
+  // Future<http.Response> fetchAlbum() {
26
+  //   return http.get('https://ada.uprrp.edu/~hector.sierra/FastMed/API/API/getcitas.php');
27
+  // }
28
+
29
+
30
+
31
+  // List<dynamicWidget> listDynamic = [];
32
+  // List<String> data = [];
33
+  // Icon floatingIcon = new Icon(Icons.add);
34
+  //
35
+  // addDynamic() {
36
+  //   if (data.length != 0) {
37
+  //     floatingIcon = new Icon(Icons.add);
38
+  //     data = [];
39
+  //     listDynamic = [];
40
+  //     print('if');
41
+  //   }
42
+  //   setState(() {});
43
+  //   if (listDynamic.length >= 5) {
44
+  //     return;
45
+  //   }
46
+  //   listDynamic.add(new dynamicWidget());
47
+  // }
48
+  //
49
+
50
+  // var docs = ["Collazo", "Albizu"];
51
+  // var spec = ["General", "Pediatra"];
52
+  // var addrs = ["Bo. Montellano, Cayey", "Las Dalias, Mayagüez"];
53
+
54
+
55
+  @override
56
+  Widget card() {
57
+  return SizedBox(
58
+    width: 380,
59
+    height: 150,
60
+      child: Card(
61
+        child: Column(
62
+          mainAxisSize: MainAxisSize.min,
63
+            children: <Widget>[
64
+              ListTile(
65
+
66
+                leading: Icon(
67
+                  Icons.check,
68
+                  color: Colors.green,
69
+                  size: 60,
70
+              ),
71
+                title: Text( O.doctor + "\n" + O.specialty, textScaleFactor: 1.5,),
72
+                subtitle: Text(O.address, textScaleFactor: 1.45,),
73
+                trailing: Text("\n10:45 - 11:45      ", textScaleFactor: 1.30,),
74
+
75
+              ),
76
+              // ListTile(
77
+              //   leading: Icon(
78
+              //     Icons.check,
79
+              //     color: Colors.green,
80
+              //     size: 60,
81
+              //   ),
82
+              //   title: Text("Figueroa" + "\n" + "Gastrointerologo", textScaleFactor: 1.5,),
83
+              //   subtitle: Text("Las Dalias, Mayagüez", textScaleFactor: 1.45,),
84
+              //   trailing: Text("\n10:45 - 11:45      ", textScaleFactor: 1.30,),
85
+              //
86
+              // )
87
+           ],
88
+          ),
89
+        ),
90
+      );
91
+    }
92
+
93
+  @override
94
+  Widget build(BuildContext context) {
95
+    final height = MediaQuery.of(context).size.height;
96
+    return Scaffold(
97
+
98
+        body: Container(
99
+          height: height,
100
+          child:Container(
101
+            width: MediaQuery.of(context).size.width,
102
+            padding: EdgeInsets.symmetric(horizontal: 20),
103
+            // height: MediaQuery.of(context).size.height,
104
+            decoration: BoxDecoration(
105
+                borderRadius: BorderRadius.all(Radius.circular(4)),
106
+                boxShadow: [
107
+                  BoxShadow(
108
+                      color: Colors.white,
109
+                      offset: Offset(0,3),
110
+                      blurRadius: 5,
111
+                      spreadRadius: 2)
112
+                ]
113
+
114
+            ),
115
+            child: SingleChildScrollView(
116
+                child: Column(
117
+                  crossAxisAlignment: CrossAxisAlignment.center,
118
+                  mainAxisAlignment: MainAxisAlignment.center,
119
+                  children: <Widget> [
120
+                    SizedBox(
121
+                      height: 80,
122
+                    ),
123
+                    card(),
124
+                    SizedBox(
125
+                      height: 25,
126
+                    ),
127
+                    // card(docs[1], spec[1], addrs[1]),
128
+                  ],
129
+                )
130
+            ),
131
+          ),
132
+        )
133
+    );
134
+  }
135
+}

+ 159
- 277
fast_med_flutter/lib/routes/calendario.dart View File

@@ -1,19 +1,36 @@
1 1
 import 'package:flutter/material.dart';
2
-import 'package:intl/date_symbol_data_local.dart';
2
+import 'package:fast_med_flutter/ui/pages/add_event.dart';
3
+import 'package:fast_med_flutter/ui/pages/view_event.dart';
3 4
 import 'package:table_calendar/table_calendar.dart';
5
+import 'package:http/http.dart' as http;
6
+
7
+import 'package:fast_med_flutter/model/event.dart';
8
+
9
+// Dias de Citas No Disponibles
4 10
 
5
-// Dias sin Citas Disponibles
6 11
 final Map<DateTime, List> _holidays = {
7 12
   DateTime(2020, 11, 6): ['No Hay Citas'],
8 13
   DateTime(2020, 11, 3): ['Dia Elecciones'],
9
-
14
+  DateTime(2020, 12, 25): ['Christmas'],
15
+  DateTime(2020, 12, 31): ['Despedida del anyo nuevo'],
16
+  DateTime(2021, 01, 01): ['Anyo Nuevo'],
10 17
 };
11 18
 
12
-void main() {
13
-  initializeDateFormatting().then((_) => runApp(Calendario()));
14
-}
19
+//Iniciar la Seccion de las Citas
20
+
21
+void main() async{
15 22
 
23
+  //Comunicacion con el servidor antes de iniciar el app
16 24
 
25
+  var url = 'https://ada.uprrp.edu/~jorge.lopez19/FastMed/API/InsertEvent.php';
26
+  WidgetsFlutterBinding.ensureInitialized();
27
+  final data = await http.post(url, body: {
28
+  });
29
+  runApp(Calendario());
30
+
31
+}
32
+
33
+//Inicio del Area de las Citas Disponibles
17 34
 
18 35
 class Calendario extends StatelessWidget {
19 36
   @override
@@ -23,56 +40,72 @@ class Calendario extends StatelessWidget {
23 40
       theme: ThemeData(
24 41
         primarySwatch: Colors.blue,
25 42
       ),
26
-      home: MyHomePage(title: 'Citas Disponibles'),
43
+      home: MyHomePage(),
44
+      routes: {
45
+        "add_event": (_) => AddEventPage(),
46
+      },
27 47
     );
28 48
   }
29 49
 }
30 50
 
31
-class MyHomePage extends StatefulWidget {
32
-  MyHomePage({Key key, this.title}) : super(key: key);
33 51
 
34
-  final String title;
52
+// Define el homepage para el area de citas
35 53
 
54
+class MyHomePage extends StatefulWidget {
36 55
   @override
37 56
   _MyHomePageState createState() => _MyHomePageState();
38 57
 }
39 58
 
40
-class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
41
-  Map<DateTime, List> _events;
42
-  List _selectedEvents;
43
-  AnimationController _animationController;
44
-  CalendarController _calendarController;
59
+class _MyHomePageState extends State<MyHomePage> {
60
+  CalendarController _controller;
61
+  Map<DateTime, List<dynamic>> _events;
62
+  List<dynamic> _selectedEvents;
45 63
 
46 64
   @override
47 65
   void initState() {
48 66
     super.initState();
49 67
     final _selectedDay = DateTime.now();
50
-
68
+    _controller = CalendarController();
51 69
     _events = {
52
-
53
-      _selectedDay.add(Duration(days: 3)): Set.from([ 'Cita Cardiologo', 'Cita Dentista']).toList(),
54
-      _selectedDay.add(Duration(days: 22)): ['Cita Cardiologo', 'Cita Dentista'],
55
-
70
+      //Ejemplos de Citas Previamente Hechas de Prueba Para los Recordatorios
71
+      _selectedDay.add(Duration(days: 3)): Set.from(
72
+          [ 'Cita Cardiologo', 'Cita Dentista']).toList(),
73
+      _selectedDay.add(Duration(days: 22)): [
74
+        'Cita Cardiologo',
75
+        'Cita Dentista'
76
+      ],
56 77
     };
57
-
58 78
     _selectedEvents = _events[_selectedDay] ?? [];
59
-    _calendarController = CalendarController();
60
-
61
-    _animationController = AnimationController(
62
-      vsync: this,
63
-      duration: const Duration(milliseconds: 400),
64
-    );
79
+    void _onDaySelected(DateTime day, List events, List holidays) {
80
+      print('CALLBACK: _onDaySelected');
81
+      setState(() {
82
+        _selectedEvents = _events[_selectedDay] ?? [];
83
+      });
84
+    }
85
+  }
65 86
 
66
-    _animationController.forward();
87
+  Map<String, dynamic> encodeMap(Map<DateTime, dynamic> map) {
88
+    Map<String, dynamic> newMap = {};
89
+    map.forEach((key, value) {
90
+      newMap[key.toString()] = map[key];
91
+    });
92
+    return newMap;
67 93
   }
68 94
 
69
-  @override
70
-  void dispose() {
71
-    _animationController.dispose();
72
-    _calendarController.dispose();
73
-    super.dispose();
95
+  Map<DateTime, List<dynamic>> _groupEvents(List<EventModel> events) {
96
+    Map<DateTime, List<dynamic>> data = {};
97
+    events.forEach((event) {
98
+      DateTime date = DateTime(event.eventDate.year, event.eventDate.month,
99
+          event.eventDate.day, 12);
100
+      if (data[date] == null) data[date] = [];
101
+      data[date].add(event);
102
+    });
103
+    return data;
74 104
   }
75 105
 
106
+
107
+  @override
108
+//Marca en el calendario los dias que no esta disponibles para hacer horarios
76 109
   void _onDaySelected(DateTime day, List events, List holidays) {
77 110
     print('CALLBACK: _onDaySelected');
78 111
     setState(() {
@@ -80,268 +113,117 @@ class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
80 113
     });
81 114
   }
82 115
 
83
-  void _onVisibleDaysChanged(DateTime first, DateTime last, CalendarFormat format) {
116
+  void _onVisibleDaysChanged(DateTime first, DateTime last,
117
+      CalendarFormat format) {
84 118
     print('CALLBACK: _onVisibleDaysChanged');
85 119
   }
86 120
 
87
-  void _onCalendarCreated(DateTime first, DateTime last, CalendarFormat format) {
121
+  void _onCalendarCreated(DateTime first, DateTime last,
122
+      CalendarFormat format) {
88 123
     print('CALLBACK: _onCalendarCreated');
89 124
   }
90 125
 
126
+//Definimos los detalles del area de las citas
91 127
   @override
92 128
   Widget build(BuildContext context) {
93 129
     return Scaffold(
94 130
       appBar: AppBar(
95
-        title: Text(widget.title),
96
-      ),
97
-      body: Column(
98
-        mainAxisSize: MainAxisSize.max,
99
-        children: <Widget>[
100
-          // Switch out 2 lines below to play with TableCalendar's settings
101
-          //-----------------------
102
-          _buildTableCalendar(),
103
-          // _buildTableCalendarWithBuilders(),
104
-          const SizedBox(height: 8.0),
105
-          _buildButtons(),
106
-          const SizedBox(height: 8.0),
107
-          Expanded(child: _buildEventList()),
108
-        ],
109
-      ),
110
-    );
111
-  }
112
-  //Back button
113
-  Widget BackButton(BuildContext context){
114
-    return InkWell(
115
-      onTap: (){
116
-        Navigator.pop(context);
117
-      },
118
-      child: Row(
119
-          children: <Widget>[
120
-            Container(
121
-              padding: EdgeInsets.only(left: 0, top:10, bottom: 10),
122
-              child: Icon(Icons.arrow_back_ios, color: Colors.black),
123
-            ),
124
-            Text("Black",
125
-                style: TextStyle(fontSize: 12, fontWeight: FontWeight.w500))
126
-          ]
127
-      ),
128
-    );
129
-  }
130
-
131
-  // Simple TableCalendar configuration (using Styles)
132
-  Widget _buildTableCalendar() {
133
-    return TableCalendar(
134
-      calendarController: _calendarController,
135
-      events: _events,
136
-      holidays: _holidays,
137
-      startingDayOfWeek: StartingDayOfWeek.monday,
138
-      calendarStyle: CalendarStyle(
139
-        selectedColor: Colors.lightBlueAccent,
140
-        todayColor: Colors.blueAccent,
141
-        markersColor: Colors.brown,
142
-        outsideDaysVisible: false,
131
+        title: Text('Citas Disponibles'),
143 132
       ),
144
-      headerStyle: HeaderStyle(
145
-        formatButtonTextStyle: TextStyle().copyWith(color: Colors.white, fontSize: 15.0),
146
-        formatButtonDecoration: BoxDecoration(
147
-          color: Colors.lightBlue,
148
-          borderRadius: BorderRadius.circular(16.0),
149
-        ),
150
-      ),
151
-      onDaySelected: _onDaySelected,
152
-      onVisibleDaysChanged: _onVisibleDaysChanged,
153
-      onCalendarCreated: _onCalendarCreated,
154
-    );
155
-  }
156
-
157
-  // More advanced TableCalendar configuration (using Builders & Styles)
158
-  Widget _buildTableCalendarWithBuilders() {
159
-    return TableCalendar(
160
-      locale: 'pl_PL',
161
-      calendarController: _calendarController,
162
-      events: _events,
163
-      holidays: _holidays,
164
-      initialCalendarFormat: CalendarFormat.month,
165
-      formatAnimation: FormatAnimation.slide,
166
-      startingDayOfWeek: StartingDayOfWeek.sunday,
167
-      availableGestures: AvailableGestures.all,
168
-      availableCalendarFormats: const {
169
-        CalendarFormat.month: '',
170
-        CalendarFormat.week: '',
171
-      },
172
-      calendarStyle: CalendarStyle(
173
-        outsideDaysVisible: false,
174
-        weekendStyle: TextStyle().copyWith(color: Colors.blue),
175
-        holidayStyle: TextStyle().copyWith(color: Colors.blue),
176
-      ),
177
-      daysOfWeekStyle: DaysOfWeekStyle(
178
-        weekendStyle: TextStyle().copyWith(color: Colors.blue),
179
-      ),
180
-      headerStyle: HeaderStyle(
181
-        centerHeaderTitle: true,
182
-        formatButtonVisible: false,
183
-      ),
184
-      builders: CalendarBuilders(
185
-        selectedDayBuilder: (context, date, _) {
186
-          return FadeTransition(
187
-            opacity: Tween(begin: 0.0, end: 1.0).animate(_animationController),
188
-            child: Container(
189
-              margin: const EdgeInsets.all(4.0),
190
-              padding: const EdgeInsets.only(top: 5.0, left: 6.0),
191
-              color: Colors.green,
192
-              width: 100,
193
-              height: 100,
194
-              child: Text(
195
-                '${date.day}',
196
-                style: TextStyle().copyWith(fontSize: 16.0),
197
-              ),
198
-            ),
199
-          );
200
-        },
201
-        todayDayBuilder: (context, date, _) {
202
-          return Container(
203
-            margin: const EdgeInsets.all(4.0),
204
-            padding: const EdgeInsets.only(top: 5.0, left: 6.0),
205
-            color: Colors.amber,
206
-            width: 100,
207
-            height: 100,
208
-            child: Text(
209
-              '${date.day}',
210
-              style: TextStyle().copyWith(fontSize: 16.0),
211
-            ),
212
-          );
213
-        },
214
-        markersBuilder: (context, date, events, holidays) {
215
-          final children = <Widget>[];
216
-
217
-          if (events.isNotEmpty) {
218
-            children.add(
219
-              Positioned(
220
-                right: 1,
221
-                bottom: 1,
222
-                child: _buildEventsMarker(date, events),
223
-              ),
224
-            );
225
-          }
226
-
227
-          if (holidays.isNotEmpty) {
228
-            children.add(
229
-              Positioned(
230
-                right: -2,
231
-                top: -2,
232
-                child: _buildHolidaysMarker(),
133
+      body: StreamBuilder<List<EventModel>>(
134
+        // stream: eventDBS.streamList(),
135
+          builder: (context, snapshot) {
136
+            if (snapshot.hasData) {
137
+              List<EventModel> allEvents = snapshot.data;
138
+              if (allEvents.isNotEmpty) {
139
+                _events = _groupEvents(allEvents);
140
+              }
141
+            }
142
+
143
+            return SingleChildScrollView(
144
+              child: Column(
145
+                crossAxisAlignment: CrossAxisAlignment.start,
146
+                children: <Widget>[
147
+                  TableCalendar(
148
+                    events: _events,
149
+                    holidays: _holidays,
150
+                    initialCalendarFormat: CalendarFormat.month,
151
+                    calendarStyle: CalendarStyle(
152
+                        canEventMarkersOverflow: true,
153
+                        todayColor: Colors.orange,
154
+                        selectedColor: Theme
155
+                            .of(context)
156
+                            .primaryColor,
157
+                        todayStyle: TextStyle(
158
+                            fontWeight: FontWeight.bold,
159
+                            fontSize: 18.0,
160
+                            color: Colors.white)),
161
+                    headerStyle: HeaderStyle(
162
+                      centerHeaderTitle: true,
163
+                      formatButtonDecoration: BoxDecoration(
164
+                        color: Colors.orange,
165
+                        borderRadius: BorderRadius.circular(20.0),
166
+                      ),
167
+                      formatButtonTextStyle: TextStyle(color: Colors.white),
168
+                      formatButtonShowsNext: false,
169
+                    ),
170
+                    startingDayOfWeek: StartingDayOfWeek.monday,
171
+                    onVisibleDaysChanged: _onVisibleDaysChanged,
172
+                    onCalendarCreated: _onCalendarCreated,
173
+
174
+                    builders: CalendarBuilders(
175
+                      selectedDayBuilder: (context, date, events) =>
176
+                          Container(
177
+                              margin: const EdgeInsets.all(4.0),
178
+                              alignment: Alignment.center,
179
+                              decoration: BoxDecoration(
180
+                                  color: Theme
181
+                                      .of(context)
182
+                                      .primaryColor,
183
+                                  borderRadius: BorderRadius.circular(10.0)),
184
+                              child: Text(
185
+                                date.day.toString(),
186
+                                style: TextStyle(color: Colors.white),
187
+                              )),
188
+                      todayDayBuilder: (context, date, events) =>
189
+                          Container(
190
+                              margin: const EdgeInsets.all(4.0),
191
+                              alignment: Alignment.center,
192
+                              decoration: BoxDecoration(
193
+                                  color: Colors.orange,
194
+                                  borderRadius: BorderRadius.circular(10.0)),
195
+                              child: Text(
196
+                                date.day.toString(),
197
+                                style: TextStyle(color: Colors.white),
198
+                              )),
199
+                    ),
200
+                    calendarController: _controller,
201
+                  ),
202
+                  ..._selectedEvents.map((event) =>
203
+                      ListTile(
204
+                        title: Text(event.title),
205
+                        onTap: () {
206
+                          Navigator.push(
207
+                              context,
208
+                              MaterialPageRoute(
209
+                                  builder: (_) =>
210
+                                      EventDetailsPage(
211
+                                        event: event,
212
+                                      )));
213
+                        },
214
+                      )),
215
+                ],
233 216
               ),
234 217
             );
235 218
           }
236
-
237
-          return children;
238
-        },
239
-      ),
240
-      onDaySelected: (date, events, holidays) {
241
-        _onDaySelected(date, events, holidays);
242
-        _animationController.forward(from: 0.0);
243
-      },
244
-      onVisibleDaysChanged: _onVisibleDaysChanged,
245
-      onCalendarCreated: _onCalendarCreated,
246
-    );
247
-  }
248
-
249
-  Widget _buildEventsMarker(DateTime date, List events) {
250
-    return AnimatedContainer(
251
-      duration: const Duration(milliseconds: 300),
252
-      decoration: BoxDecoration(
253
-        shape: BoxShape.rectangle,
254
-        color: _calendarController.isSelected(date)
255
-            ? Colors.brown[500]
256
-            : _calendarController.isToday(date) ? Colors.brown : Colors.blue,
257 219
       ),
258
-      width: 16.0,
259
-      height: 16.0,
260
-      child: Center(
261
-        child: Text(
262
-          '${events.length}',
263
-          style: TextStyle().copyWith(
264
-            color: Colors.green,
265
-            fontSize: 12.0,
266
-          ),
267
-        ),
220
+      floatingActionButton: FloatingActionButton(
221
+        child: Icon(Icons.add),
222
+        onPressed: () => Navigator.pushNamed(context, 'add_event'),
268 223
       ),
269 224
     );
270 225
   }
226
+}
271 227
 
272
-  Widget _buildHolidaysMarker() {
273
-    return Icon(
274
-      Icons.add_box,
275
-      size: 20.0,
276
-      color: Colors.blueGrey,
277
-    );
278
-  }
279
-
280
-  Widget _buildButtons() {
281
-    final dateTime = _events.keys.elementAt(_events.length - 2);
282
-
283
-    return Column(
284
-      children: <Widget>[
285
-        Row(
286
-          mainAxisSize: MainAxisSize.max,
287
-          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
288
-          children: <Widget>[
289
-            RaisedButton(
290
-              child: Text('Mes'),
291
-              onPressed: () {
292
-                setState(() {
293
-                  _calendarController.setCalendarFormat(CalendarFormat.month);
294
-                });
295
-              },
296
-            ),
297
-            RaisedButton(
298
-              child: Text('2 Semanas'),
299
-              onPressed: () {
300
-                setState(() {
301
-                  _calendarController.setCalendarFormat(CalendarFormat.twoWeeks);
302
-                });
303
-              },
304
-            ),
305
-            RaisedButton(
306
-              child: Text('Semana'),
307
-              onPressed: () {
308
-                setState(() {
309
-                  _calendarController.setCalendarFormat(CalendarFormat.week);
310
-                });
311
-              },
312
-            ),
313
-          ],
314
-        ),
315
-        const SizedBox(height: 8.0),
316
-        RaisedButton(
317
-          child: Text('Recuerde Cita ${dateTime.day}-${dateTime.month}-${dateTime.year}'),
318
-          onPressed: () {
319
-            _calendarController.setSelectedDay(
320
-              DateTime(dateTime.year, dateTime.month, dateTime.day),
321
-              runCallback: true,
322
-            );
323
-          },
324
-        ),
325
-      ],
326
-    );
327
-  }
328 228
 
329 229
 
330
-  Widget _buildEventList() {
331
-    return ListView(
332
-      children: _selectedEvents
333
-          .map((event) => Container(
334
-        decoration: BoxDecoration(
335
-          border: Border.all(width: 0.8),
336
-          borderRadius: BorderRadius.circular(12.0),
337
-        ),
338
-        margin: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
339
-        child: ListTile(
340
-          title: Text(event.toString()),
341
-          onTap: () => print('$event tapped!'),
342
-        ),
343
-      ))
344
-          .toList(),
345
-    );
346
-  }
347
-}

+ 39
- 0
fast_med_flutter/lib/routes/dynamic.dart View File

@@ -0,0 +1,39 @@
1
+import 'package:flutter/material.dart';
2
+
3
+
4
+class dynamicWidget extends StatelessWidget {
5
+  TextEditingController Product = new TextEditingController();
6
+  TextEditingController Price = new TextEditingController();
7
+
8
+  @override
9
+  Widget build(BuildContext context) {
10
+
11
+    Widget card() {
12
+      return SizedBox(
13
+        width: 380,
14
+        height: 140,
15
+        child: Card(
16
+          child: Column(
17
+            mainAxisSize: MainAxisSize.min,
18
+            children: <Widget>[
19
+              const ListTile(
20
+
21
+                leading: Icon(
22
+                  Icons.check,
23
+                  color: Colors.green,
24
+                  size: 60,
25
+                ),
26
+                title: Text("\nVacunación\nDr. Jímenez", textScaleFactor: 1.15,),
27
+                subtitle: Text("Bo. Montellano, Cayey", textScaleFactor: 1.25,),
28
+                trailing: Text("\n10:45 - 11:45      ", textScaleFactor: 1.30,),
29
+
30
+              ),
31
+            ],
32
+          ),
33
+        ),
34
+      );
35
+    }
36
+
37
+  }
38
+
39
+}

+ 109
- 0
fast_med_flutter/lib/routes/especialidades.dart View File

@@ -0,0 +1,109 @@
1
+import 'package:flutter/material.dart';
2
+import 'dart:convert';
3
+import 'package:json_table/json_table.dart';
4
+
5
+class SimpleTable extends StatefulWidget {
6
+  @override
7
+  _SimpleTableState createState() => _SimpleTableState();
8
+}
9
+
10
+class _SimpleTableState extends State<SimpleTable> {
11
+  final String jsonSample =
12
+      '[{"id":"0","name":"Dr.Collazo","Oficina":"A","Phone":"787-522-0123","Espe":"Dentist"},{"id":"1","name":"Dr.Lelolelo","Oficina":"B","Phone":"787-533-4567","Espe":"Dentist"},{"id":"2","name":"Dr.Pepo","Oficina":"C","Phone":"787-544-8910","Espe":"otorrinolaringologo"}]';
13
+  bool toggle = true;
14
+
15
+  @override
16
+  Widget build(BuildContext context) {
17
+    var json = jsonDecode(jsonSample);
18
+    return Scaffold(
19
+      body: Container(
20
+        padding: EdgeInsets.all(16.0),
21
+        child: toggle
22
+            ? Column(
23
+          children: [
24
+            JsonTable(
25
+              json,
26
+              showColumnToggle: true,
27
+              tableHeaderBuilder: (String header) {
28
+                return Container(
29
+                  padding: EdgeInsets.symmetric(
30
+                      horizontal: 8.0, vertical: 4.0),
31
+                  decoration: BoxDecoration(
32
+                      border: Border.all(width: 0.5),
33
+                      color: Colors.grey[300]),
34
+                  child: Text(
35
+                    header,
36
+                    textAlign: TextAlign.center,
37
+                    style: Theme.of(context).textTheme.display1.copyWith(
38
+                        fontWeight: FontWeight.w700,
39
+                        fontSize: 14.0,
40
+                        color: Colors.black87),
41
+                  ),
42
+                );
43
+              },
44
+              tableCellBuilder: (value) {
45
+                return Container(
46
+                  padding: EdgeInsets.symmetric(
47
+                      horizontal: 4.0, vertical: 2.0),
48
+                  decoration: BoxDecoration(
49
+                      border: Border.all(
50
+                          width: 0.5,
51
+                          color: Colors.grey.withOpacity(0.5))),
52
+                  child: Text(
53
+                    value,
54
+                    textAlign: TextAlign.center,
55
+                    style: Theme.of(context).textTheme.display1.copyWith(
56
+                        fontSize: 14.0, color: Colors.grey[900]),
57
+                  ),
58
+                );
59
+              },
60
+              allowRowHighlight: true,
61
+              rowHighlightColor: Colors.yellow[500].withOpacity(0.7),
62
+              paginationRowCount: 20,
63
+            ),
64
+            SizedBox(
65
+              height: 20.0,
66
+            ),
67
+            Text("Tabla Oficinas")
68
+          ],
69
+        )
70
+            : Center(
71
+          child: Text(getPrettyJSONString(jsonSample)),
72
+        ),
73
+      ),
74
+      floatingActionButton: FloatingActionButton(
75
+          child: Icon(Icons.grid_on),
76
+          onPressed: () {
77
+            setState(
78
+                  () {
79
+                toggle = !toggle;
80
+              },
81
+            );
82
+          }),
83
+    );
84
+  }
85
+
86
+  String getPrettyJSONString(jsonObject) {
87
+    JsonEncoder encoder = new JsonEncoder.withIndent('  ');
88
+    String jsonString = encoder.convert(json.decode(jsonObject));
89
+    return jsonString;
90
+  }
91
+}
92
+
93
+void main() => runApp(especialidades());
94
+
95
+class especialidades extends StatelessWidget {
96
+  @override
97
+  Widget build(BuildContext context) {
98
+    return MaterialApp(
99
+      title: 'Flutter Demo',
100
+      theme: ThemeData(
101
+        primarySwatch: Colors.blue,
102
+      ),
103
+      home: SimpleTable(),
104
+    );
105
+  }
106
+}
107
+
108
+
109
+

+ 14
- 62
fast_med_flutter/lib/routes/home.dart View File

@@ -1,10 +1,14 @@
1 1
 import 'package:flutter/material.dart';
2
+import '../widgets/functions.dart';
2 3
 
3 4
 class Home extends StatefulWidget{
4 5
   @override
5 6
   _HomeState createState() => _HomeState();
6 7
 }
7 8
 
9
+
10
+
11
+
8 12
 class _HomeState extends State<Home>{
9 13
   @override
10 14
   Widget build(BuildContext context){
@@ -14,69 +18,17 @@ class _HomeState extends State<Home>{
14 18
         centerTitle: true,
15 19
       ),
16 20
       body: Center(
17
-        child: Column(
18
-          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
21
+        child: ListView(
22
+          //mainAxisAlignment: MainAxisAlignment.spaceEvenly,
19 23
           children: [
20
-            new FlatButton(
21
-              minWidth: 300.0,
22
-              height: 100.0,
23
-              onPressed: (){
24
-                Navigator.pushNamed(context, '/verOficinas');
25
-              },
26
-              child: Text('Ver Oficinas',
27
-                style: TextStyle(fontSize: 36),
28
-              ),
29
-              color: Colors.purple,
30
-
31
-            ),
32
-            new FlatButton(
33
-              minWidth: 300.0,
34
-              height: 100.0,
35
-              onPressed: (){
36
-                Navigator.pushNamed(context, '/calendario');
37
-              },
38
-              child: Text('Calendario',
39
-                style: TextStyle(fontSize: 36),
40
-              ),
41
-              color: Colors.purple,
42
-
43
-            ),
44
-            new FlatButton(
45
-              minWidth: 300.0,
46
-              height: 100.0,
47
-              onPressed: (){
48
-                Navigator.pushNamed(context, '/register');
49
-              },
50
-              child: Text('register',
51
-                style: TextStyle(fontSize: 36),
52
-              ),
53
-              color: Colors.purple,
54
-
55
-            ),
56
-            new FlatButton(
57
-              minWidth: 300.0,
58
-              height: 100.0,
59
-              onPressed: (){
60
-                Navigator.pushNamed(context, '/welcome');
61
-              },
62
-              child: Text('welcome',
63
-                style: TextStyle(fontSize: 36),
64
-              ),
65
-              color: Colors.purple,
66
-
67
-            ),
68
-            new FlatButton(
69
-              minWidth: 300.0,
70
-              height: 100.0,
71
-              onPressed: (){
72
-                Navigator.pushNamed(context, '/MyApp');
73
-              },
74
-              child: Text('MyApp',
75
-                style: TextStyle(fontSize: 36),
76
-              ),
77
-              color: Colors.purple,
78
-
79
-            ),
24
+            newButton(context,'/verOficinas','Ver Oficinas'),
25
+            spaceBetween(),
26
+            newButton(context,'/calendario','Calendario'),
27
+            spaceBetween(),
28
+            newButton(context,'/especialidades','especialidades'),
29
+            spaceBetween(),
30
+            newButton(context,'/translation','translation'),
31
+            spaceBetween(),
80 32
             ],
81 33
         ),
82 34
 

+ 88
- 0
fast_med_flutter/lib/routes/navigation.dart View File

@@ -0,0 +1,88 @@
1
+
2
+import 'package:flutter_login/flutter_login.dart';
3
+import 'package:flutter/material.dart';
4
+import 'package:google_fonts/google_fonts.dart';
5
+import 'register.dart';
6
+import 'welcome.dart';
7
+import 'profileinfo.dart';
8
+import 'appointments.dart';
9
+import 'package:http/http.dart' as http;
10
+import 'OfficeScreen.dart';
11
+import 'Offices.dart';
12
+import 'package:fast_med_flutter/routes/home.dart';
13
+
14
+
15
+class NavigationPage extends StatefulWidget{
16
+
17
+  NavigationPage({Key key, this.title}) : super(key: key);
18
+  final String title;
19
+
20
+  @override
21
+  _NavigationPageState createState() => _NavigationPageState();
22
+}
23
+
24
+class _NavigationPageState extends State<NavigationPage>{
25
+
26
+
27
+  int _selectedIndex = 0;
28
+
29
+  static const TextStyle optionStyle = TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
30
+
31
+  final _pageOptions = [
32
+    OfficesScreen(),
33
+    ProfilePage(),
34
+    Home()
35
+  ];
36
+
37
+  // static const List<Navigator> _widgetOptions = <Navigator>[
38
+  // //   Navigator.push(
39
+  // // context, MaterialPageRoute(builder: (context) => ProfilePage()));
40
+  // ];
41
+
42
+
43
+  // void _onItemTapped(int index) {
44
+  //   setState(() {
45
+  //     _selectedIndex = index;
46
+  //   });
47
+  // }
48
+  @override
49
+  Widget build(BuildContext context) {
50
+    final height = MediaQuery.of(context).size.height;
51
+    return Scaffold(
52
+      // appBar: AppBar(
53
+      //   title: Text("Title"),
54
+      // ),
55
+      body:  _pageOptions[_selectedIndex],
56
+      bottomNavigationBar: BottomNavigationBar(
57
+        onTap: (int index){
58
+          setState(() {
59
+            _selectedIndex = index;
60
+          });
61
+        },
62
+          selectedItemColor: Colors.red[800],
63
+        currentIndex: _selectedIndex,
64
+        // onTap: ,
65
+        // currentIndex: ,
66
+        // selectedItemColor: Colors.red, onTap: ,
67
+        //
68
+
69
+        items: [
70
+          BottomNavigationBarItem(icon: Icon(Icons.medical_services),
71
+              label: 'FastMed'),
72
+          BottomNavigationBarItem(icon: Icon(Icons.person_rounded),
73
+              label: 'Profile'),
74
+          BottomNavigationBarItem(icon: Icon(Icons.event_note_rounded),
75
+              label: 'Appointments')
76
+        ],
77
+
78
+      ),
79
+      // body: Container(
80
+      //
81
+      // ),
82
+    );
83
+    // TODO: implement build
84
+    throw UnimplementedError();
85
+  }
86
+
87
+
88
+}

+ 226
- 0
fast_med_flutter/lib/routes/profileinfo.dart View File

@@ -0,0 +1,226 @@
1
+
2
+
3
+import 'package:flutter_login/flutter_login.dart';
4
+import 'package:flutter/material.dart';
5
+import 'package:google_fonts/google_fonts.dart';
6
+import 'register.dart';
7
+import 'package:http/http.dart' as http;
8
+
9
+
10
+
11
+class ProfilePage extends StatefulWidget{
12
+
13
+  ProfilePage({Key key, this.title}) : super(key: key);
14
+  final String title;
15
+
16
+  @override
17
+  _ProfilePageState createState() => _ProfilePageState();
18
+}
19
+
20
+class _ProfilePageState extends State<ProfilePage>{
21
+  TextEditingController first_name = new TextEditingController();
22
+  TextEditingController last_name = new TextEditingController() ;
23
+  TextEditingController country = new TextEditingController();
24
+  TextEditingController city = new TextEditingController();
25
+  TextEditingController phone = new TextEditingController();
26
+  TextEditingController healthcare = new TextEditingController();
27
+
28
+  // trying to create a an array of controllers
29
+  // final List<TextEditingController> controllers = List();
30
+  // controllers.add(first_name);
31
+
32
+  Future<List> clear_controllers() async {
33
+    first_name.text = "";
34
+    last_name.text = "";
35
+    country.text = "";
36
+    city.text = "";
37
+    phone.text = "";
38
+    healthcare.text = "";
39
+  }
40
+
41
+
42
+  _Notice(BuildContext context, String message, int r, int g, int b){
43
+    showDialog<void>(
44
+        context: context,
45
+        barrierDismissible: false,
46
+        barrierColor: Colors.transparent,
47
+
48
+        builder: (BuildContext context){
49
+          Future.delayed(Duration(seconds: 3), () {
50
+            Navigator.of(context).pop(true);
51
+          });
52
+
53
+          return Material(
54
+              color: Colors.transparent,
55
+              child: InkResponse(
56
+                child: Container(
57
+
58
+                  alignment: Alignment.bottomCenter,
59
+                  padding: EdgeInsets.only(bottom: 130),
60
+                  child: Text(
61
+                    message,
62
+                    style: TextStyle(fontSize: 20, color: Color.fromARGB(255, r, g, b)),),
63
+
64
+                ),
65
+              )
66
+          );  
67
+        }
68
+      );
69
+  }
70
+  Future<List> send_data() async {
71
+
72
+
73
+    var url = 'https://ada.uprrp.edu/~hector.sierra/FastMed/UpdateProfile.php';
74
+    final data = await http.post(url, body: {
75
+      "first_name": first_name.text,
76
+      "last_name": last_name.text,
77
+      "country": country.text,
78
+      "city": city.text,
79
+      "phone": phone.text,
80
+      "healthcare": healthcare.text,
81
+    });
82
+    print(data.body);
83
+    if("User not registered" == data.body){
84
+      _Notice(context, "Error, unable to update profile", 255, 0, 0);
85
+    }
86
+    else{
87
+      _Notice(context, "Profile Updated", 0, 255, 0);
88
+    }
89
+
90
+  }
91
+
92
+  Widget _BackButton(BuildContext context) {
93
+    return InkWell(
94
+      onTap: () {
95
+        Navigator.pop(context);
96
+      },
97
+      child: Row(
98
+          children: <Widget>[
99
+            Container(
100
+              padding: EdgeInsets.only(left: 0, top: 10, bottom: 10),
101
+              child: Icon(Icons.arrow_back_ios, color: Colors.black),
102
+            ),
103
+            Text("Back",
104
+                style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500))
105
+          ]
106
+      ),
107
+    );
108
+  }
109
+
110
+
111
+  Widget _SubmitButton(BuildContext context) {
112
+    return InkResponse(
113
+      onTap: () {
114
+        send_data();
115
+        // clear_controllers();
116
+      },
117
+      child: Material(
118
+        borderRadius: BorderRadius.circular(30),
119
+        elevation: 3,
120
+        child: Container(
121
+          padding: EdgeInsets.symmetric(vertical: 10),
122
+          width: 250,
123
+          alignment: Alignment.center,
124
+          decoration: BoxDecoration(
125
+            color: Colors.red,
126
+            borderRadius: BorderRadius.circular(30),
127
+          ),
128
+
129
+          child: Text(
130
+            "Update",
131
+            style: TextStyle(fontSize: 22, color: Colors.white),
132
+          ),
133
+        ),
134
+      ),
135
+    );
136
+  }
137
+
138
+  Widget _Fills() {
139
+    return Column(
140
+        children: <Widget>[
141
+          _EntryField("First Name", first_name),
142
+          _EntryField("Last Name", last_name),
143
+          _EntryField("Country", country),
144
+          _EntryField("City", city),
145
+          _EntryField("Phone Number", phone),
146
+          _EntryField("Healthcare Provider", healthcare),
147
+        ]
148
+    );
149
+  }
150
+
151
+  Widget _EntryField(String title, TextEditingController controller,
152
+      {bool pass = false}) {
153
+    return Container(
154
+      padding: EdgeInsets.only(left: 0, top: 10, bottom: 10),
155
+      child: Column(
156
+          crossAxisAlignment: CrossAxisAlignment.start,
157
+
158
+          children: <Widget>[
159
+            Text(
160
+              title,
161
+              style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
162
+            ),
163
+            SizedBox(
164
+                height: 30
165
+            ),
166
+            TextField(
167
+              controller: controller,
168
+              obscureText: pass,
169
+              decoration: InputDecoration(
170
+                border: (
171
+                    UnderlineInputBorder()
172
+                ),
173
+              ),
174
+            )
175
+          ]
176
+      ),
177
+
178
+    );
179
+  }
180
+
181
+
182
+
183
+  @override
184
+  Widget build(BuildContext context) {
185
+    final height = MediaQuery.of(context).size.height;
186
+    return Scaffold(
187
+        body: Container(
188
+          height: height,
189
+          child: Stack(
190
+
191
+            children: <Widget>[
192
+              Container(
193
+                  padding: EdgeInsets.symmetric(horizontal: 20),
194
+                  child: SingleChildScrollView(
195
+                    child: Column(
196
+                      crossAxisAlignment: CrossAxisAlignment.center,
197
+                      mainAxisAlignment: MainAxisAlignment.center,
198
+                      children: <Widget>[
199
+                        SizedBox(
200
+                          height: 60,
201
+                        ),
202
+                        _Fills(),
203
+                        //Add code to verify if password and confirm password match
204
+                        SizedBox(
205
+                          height: 80,
206
+                        ),
207
+                        _SubmitButton(context),
208
+                        SizedBox(
209
+                          height: 50,
210
+                        ),
211
+                        // ElevatedButton(
212
+                        //     onPressed: send_data, child: Text("Register")),
213
+                      ],
214
+                    ),
215
+                  )
216
+              ),
217
+              // Positioned(
218
+              //   top: 15, left: 20, child: _BackButton(context),
219
+              // ),
220
+            ],
221
+
222
+          ),
223
+        )
224
+    );
225
+  }
226
+}

+ 217
- 104
fast_med_flutter/lib/routes/register.dart View File

@@ -1,13 +1,19 @@
1
+import 'dart:convert';
2
+
1 3
 import 'package:flutter_login/flutter_login.dart';
2 4
 import 'package:flutter/material.dart';
3 5
 import 'package:google_fonts/google_fonts.dart';
6
+import 'package:http/http.dart' as http;
7
+import 'dart:convert' as convert;
8
+
9
+
4 10
 
5 11
 //
6 12
 //Still to add: 
7 13
 //  Email verification, that the input has "@" and "."
8
-//  Send email and password to database
9
-//
10
-//
14
+//  Hash the passwords
15
+//  Allow users to login
16
+//  Verify password and confirm password match
11 17
 //
12 18
 
13 19
 class RegisterPage extends StatefulWidget{
@@ -20,48 +26,138 @@ class RegisterPage extends StatefulWidget{
20 26
 }
21 27
 
22 28
 class _RegisterPageState extends State<RegisterPage> {
29
+  // TextEditingController name = new TextEditingController();
30
+  TextEditingController email = new TextEditingController();
31
+  TextEditingController password = new TextEditingController() ;
32
+  TextEditingController confirmpass = new TextEditingController();
23 33
 
24
-  TextEditingController email;
25
-  TextEditingController password;
26
-  TextEditingController confirmpass;
27 34
 
28
-  // Future<List> send_data() async {
29
-  //   final data = await
30
-  // }
35
+  Future<List> send_data() async {
31 36
 
32
-  String _SamePass(){
33
-    if(password == confirmpass){
34
-      return "Same password";
37
+
38
+    var url = 'https://ada.uprrp.edu/~hector.sierra/FastMed/API/insertuser.php';
39
+    final data = await http.post(url, body: {
40
+        "email": email.text,
41
+        "password": password.text,
42
+      });
43
+    print(data.body);
44
+    if("user not registered" == data.body){
45
+      print("maybe we use this");
35 46
     }
36
-    else{
37
-      return "Different passwords";
47
+
48
+  }
49
+
50
+  bool _SamePass() {
51
+    if (password.text == confirmpass.text) {
52
+      return true;
53
+    }
54
+    else {
55
+      return false;
38 56
     }
39 57
   }
40 58
 
41
-  Widget _BackButton(BuildContext context){
59
+  _Alerts(BuildContext context){
60
+
61
+    TextEditingController msg = new TextEditingController();
62
+
63
+
64
+   //
65
+   //Useful code for adding pop up messages with animations
66
+   //
67
+   //
68
+
69
+    // Navigator.of(context).push(
70
+    //
71
+    //   PageRouteBuilder(
72
+    //       transitionDuration: Duration(seconds: 2),
73
+    //       pageBuilder: (context, animation, secAnimation ) => AlertDialog(
74
+    //         title: Text("Testing"),
75
+    //         elevation: 1,
76
+    //         backgroundColor: Colors.transparent,
77
+    //
78
+    //       ),
79
+    //       opaque: false,
80
+    //   )
81
+    //
82
+    // );
83
+
84
+    showDialog<void>(
85
+      context: context,
86
+      barrierDismissible: false,
87
+      barrierColor: Colors.transparent,
88
+
89
+      builder: (BuildContext context){
90
+        Future.delayed(Duration(seconds: 2), () {
91
+          Navigator.of(context).pop(true);
92
+        });
93
+
94
+        return Material(
95
+          color: Colors.transparent,
96
+          child: InkResponse(
97
+            child: Container(
98
+
99
+              alignment: Alignment.bottomCenter,
100
+              padding: EdgeInsets.only(bottom: 30),
101
+              child: Text(
102
+                  "Email address is already registered",
103
+                  style: TextStyle(fontSize: 18, color: Colors.red),),
104
+
105
+            ),
106
+          )
107
+        );
108
+
109
+        // return Banner(
110
+        //   location: BannerLocation.bottomEnd,
111
+        //   message: "Hello there",
112
+        //
113
+        // );
114
+
115
+        // // allows the message to disappear
116
+        // Future.delayed(Duration(seconds: 2), () {
117
+        //   Navigator.of(context).pop(true);
118
+        // });
119
+        // return AlertDialog(
120
+        //   buttonPadding: ,
121
+        //   title: Text("Testing"),
122
+        //   elevation: 1,
123
+        //   backgroundColor: Colors.transparent,
124
+        // );
125
+      }
126
+    );
127
+  }
128
+
129
+
130
+
131
+  Widget _BackButton(BuildContext context) {
42 132
     return InkWell(
43
-      onTap: (){
133
+      onTap: () {
44 134
         Navigator.pop(context);
45 135
       },
46 136
       child: Row(
47
-        children: <Widget>[
48
-          Container(
49
-            padding: EdgeInsets.only(left: 0, top: 10, bottom: 10),
50
-            child: Icon(Icons.arrow_back_ios, color: Colors.black),
51
-          ),
52
-          Text("Back",
53
-          style: TextStyle(fontSize: 12, fontWeight: FontWeight.w500))
54
-        ]
137
+          children: <Widget>[
138
+            Container(
139
+              padding: EdgeInsets.only(left: 0, top: 10, bottom: 10),
140
+              child: Icon(Icons.arrow_back_ios, color: Colors.black),
141
+            ),
142
+            Text("Back",
143
+                style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500))
144
+          ]
55 145
       ),
56 146
     );
57 147
   }
58 148
 
59
-  Widget _SubmitButton(BuildContext context){
60
-    return InkWell(
61
-       onTap: (){
62
-
63
-       },
64
-      child: Container(
149
+  Widget _SubmitButton(BuildContext context) {
150
+    return InkResponse(
151
+      onTap: () {
152
+        send_data();
153
+        // _Alert(BuildContext);
154
+        // _Match(context);
155
+        _Alerts(context);
156
+      },
157
+      child: Material(
158
+        borderRadius: BorderRadius.circular(30),
159
+        elevation: 3,
160
+        child: Container(
65 161
         padding: EdgeInsets.symmetric(vertical: 10),
66 162
         width: 250,
67 163
         alignment: Alignment.center,
@@ -69,93 +165,110 @@ class _RegisterPageState extends State<RegisterPage> {
69 165
           color: Colors.red,
70 166
           borderRadius: BorderRadius.circular(30),
71 167
         ),
168
+
72 169
         child: Text(
73 170
           "Submit",
74 171
           style: TextStyle(fontSize: 22, color: Colors.white),
75 172
         ),
173
+        ),
76 174
       ),
77 175
     );
78 176
   }
79 177
 
80
-  Widget _EntryField(String title, TextEditingController controller, {bool pass = false}){
81
-    return Container(
82
-      padding: EdgeInsets.only(left: 0, top: 10, bottom: 10),
83
-      child: Column(
84
-        crossAxisAlignment: CrossAxisAlignment.start,
85
-      
86
-        children: <Widget> [
87
-          Text(
88
-            title,
89
-            style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
90
-          ),
91
-          SizedBox(
92
-            height: 30
93
-          ),
94
-          TextField(
95
-            controller: controller,
96
-            obscureText: pass,
97
-            decoration: InputDecoration(
98
-              border: (
99
-                  UnderlineInputBorder()
178
+    Widget _EntryField(String title, TextEditingController controller,
179
+        {bool pass = false}) {
180
+      return Container(
181
+        padding: EdgeInsets.only(left: 0, top: 10, bottom: 10),
182
+        child: Column(
183
+            crossAxisAlignment: CrossAxisAlignment.start,
184
+
185
+            children: <Widget>[
186
+              Text(
187
+                title,
188
+                style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
100 189
               ),
101
-            ),
102
-          )
103
-        ]
104
-      ),
105
-      
106
-    );
107
-  }
190
+              SizedBox(
191
+                  height: 30
192
+              ),
193
+              TextField(
194
+                controller: controller,
195
+                obscureText: pass,
196
+                decoration: InputDecoration(
197
+                  border: (
198
+                      UnderlineInputBorder()
199
+                  ),
200
+                ),
201
+              )
202
+            ]
203
+        ),
108 204
 
109
-  Widget _Fills(){
110
-    return Column(
111
-      children: <Widget> [
112
-      _EntryField("Email", email),
113
-      _EntryField("Password", password, pass: true),
114
-      _EntryField("Confirm Password", confirmpass, pass: true)
115
-    
116
-    ]
117
-    );
118
-  }
205
+      );
206
+    }
119 207
 
120
-//add column or stack
121
-  @override
122
-  Widget build(BuildContext context) {
123
-    final height = MediaQuery.of(context).size.height;
124
-    return Scaffold(
125
-      body: Container(
126
-        height: height,
127
-        child: Stack(
128
-          
208
+    Widget _Fills() {
209
+      return Column(
129 210
           children: <Widget>[
130
-            Container(
131
-              padding: EdgeInsets.symmetric(horizontal: 20),
132
-              child: SingleChildScrollView(
133
-                child: Column(
134
-                  crossAxisAlignment: CrossAxisAlignment.center,
135
-                  mainAxisAlignment: MainAxisAlignment.center,
136
-                  children: <Widget>[
137
-                     SizedBox(
138
-                      height: 200,
139
-                    ),
140
-                    _Fills(),
141
-                    //Add code to verify if password and confirm password match
142
-                    SizedBox(
143
-                      height: 20,
144
-                    ),
145
-                    _SubmitButton(context),
146
-                  ],
211
+            _EntryField("Email", email),
212
+            _EntryField("Password", password, pass: true),
213
+            _EntryField("Confirm Password", confirmpass, pass: true)
214
+
215
+          ]
216
+      );
217
+    }
218
+
219
+//add column or stack
220
+    @override
221
+    Widget build(BuildContext context) {
222
+      final height = MediaQuery
223
+          .of(context)
224
+          .size
225
+          .height;
226
+      return Scaffold(
227
+          body: Container(
228
+            height: height,
229
+            child: Stack(
230
+
231
+              children: <Widget>[
232
+                Container(
233
+                    padding: EdgeInsets.symmetric(horizontal: 20),
234
+                    child: SingleChildScrollView(
235
+                      child: Column(
236
+                        crossAxisAlignment: CrossAxisAlignment.center,
237
+                        mainAxisAlignment: MainAxisAlignment.center,
238
+                        children: <Widget>[
239
+                          // Text("Username", style: TextStyle(fontSize: 18.0),),
240
+                          // TextField(
241
+                          //   controller: name,
242
+                          //   decoration: InputDecoration(
243
+                          //       hintText: 'name'
244
+                          //   ),
245
+                          // ),
246
+                          SizedBox(
247
+                            height: 100,
248
+                          ),
249
+                          _Fills(),
250
+                          //Add code to verify if password and confirm password match
251
+                          SizedBox(
252
+                            height: 20,
253
+                          ),
254
+                          _SubmitButton(context),
255
+                          SizedBox(
256
+                            height: 10,
257
+                          ),
258
+                          // ElevatedButton(
259
+                          //     onPressed: send_data, child: Text("Register")),
260
+                        ],
261
+                      ),
262
+                    )
147 263
                 ),
148
-              )
264
+                Positioned(
265
+                  top: 15, left: 20, child: _BackButton(context),
266
+                ),
267
+              ],
268
+
149 269
             ),
150
-            Positioned(
151
-            top: 12, left: 20, child: _BackButton(context),
152
-          ),
153
-          ],
154
-          
155
-        ),
156
-      )
157
-    );
270
+          )
271
+      );
272
+    }
158 273
   }
159
-    
160
-}
161 274
 

+ 81
- 0
fast_med_flutter/lib/routes/translation.dart View File

@@ -0,0 +1,81 @@
1
+import 'package:flutter/material.dart';
2
+import '../localization/localization.dart';
3
+import '../router/custom_router.dart';
4
+import '../router/route_constants.dart';
5
+import 'package:flutter_localizations/flutter_localizations.dart';
6
+
7
+import '../localization/language_constants.dart';
8
+
9
+void main() => runApp(translation());
10
+
11
+class translation extends StatefulWidget {
12
+  const translation({Key key}) : super(key: key);
13
+  static void setLocale(BuildContext context, Locale newLocale) {
14
+    _MyAppState state = context.findAncestorStateOfType<_MyAppState>();
15
+    state.setLocale(newLocale);
16
+  }
17
+
18
+  @override
19
+  _MyAppState createState() => _MyAppState();
20
+}
21
+
22
+class _MyAppState extends State<translation> {
23
+  Locale _locale;
24
+  setLocale(Locale locale) {
25
+    setState(() {
26
+      _locale = locale;
27
+    });
28
+  }
29
+
30
+  @override
31
+  void didChangeDependencies() {
32
+    getLocale().then((locale) {
33
+      setState(() {
34
+        this._locale = locale;
35
+      });
36
+    });
37
+    super.didChangeDependencies();
38
+  }
39
+
40
+  @override
41
+  Widget build(BuildContext context) {
42
+    if (this._locale == null) {
43
+      return Container(
44
+        child: Center(
45
+          child: CircularProgressIndicator(
46
+              valueColor: AlwaysStoppedAnimation<Color>(Colors.blue[800])),
47
+        ),
48
+      );
49
+    } else {
50
+      return MaterialApp(
51
+        debugShowCheckedModeBanner: false,
52
+        title: "Flutter Localization Demo",
53
+        theme: ThemeData(primarySwatch: Colors.blue),
54
+        locale: _locale,
55
+        supportedLocales: [
56
+          Locale("en", "US"),
57
+          Locale("fa", "IR"),
58
+          Locale("es", "SP"),
59
+          Locale("hi", "IN")
60
+        ],
61
+        localizationsDelegates: [
62
+          DemoLocalization.delegate,
63
+          GlobalMaterialLocalizations.delegate,
64
+          GlobalWidgetsLocalizations.delegate,
65
+          GlobalCupertinoLocalizations.delegate,
66
+        ],
67
+        localeResolutionCallback: (locale, supportedLocales) {
68
+          for (var supportedLocale in supportedLocales) {
69
+            if (supportedLocale.languageCode == locale.languageCode &&
70
+                supportedLocale.countryCode == locale.countryCode) {
71
+              return supportedLocale;
72
+            }
73
+          }
74
+          return supportedLocales.first;
75
+        },
76
+        onGenerateRoute: CustomRouter.generatedRoute,
77
+        initialRoute: homeRoute,
78
+      );
79
+    }
80
+  }
81
+}

+ 302
- 0
fast_med_flutter/lib/routes/ver_oficina.dart View File

@@ -0,0 +1,302 @@
1
+import 'package:flutter/material.dart';
2
+import '../widgets/DataTableMySqlDemo/Oficina.dart';
3
+import '../widgets/DataTableMySqlDemo/Horario.dart';
4
+import '../widgets/DataTableMySqlDemo/Especialista.dart';
5
+import '../widgets/DataTableMySqlDemo/Services.dart';
6
+import 'dart:async';
7
+import '../widgets/functions.dart';
8
+import 'package:flutter/material.dart';
9
+import 'package:url_launcher/url_launcher.dart';
10
+
11
+
12
+class VerOficina extends StatefulWidget{
13
+  VerOficina() : super();
14
+  final String title = 'Oficina';
15
+  @override
16
+  State<StatefulWidget> viewOficina() {
17
+    //no se que hago, quizas no lo necesite
18
+    return null;
19
+  }
20
+  _VerOficinaState createState() => _VerOficinaState();
21
+}
22
+
23
+class _VerOficinaState extends State<VerOficina>{
24
+  Map post = {};
25
+  List<Oficina> _oficina;
26
+  List<Horario> _horario;
27
+  List<Especialista> _especialista;
28
+
29
+  @override
30
+  void initState() {
31
+    super.initState();
32
+    _oficina = [];
33
+    _getOficina();
34
+    _horario = [];
35
+    _getHorario();
36
+    _especialista = [];
37
+    _getEspecialista();
38
+  }
39
+
40
+  _getOficina() {
41
+    return _oficina;
42
+  }
43
+  _getHorario() {
44
+    return _horario;
45
+  }
46
+  _getEspecialista() {
47
+    return _especialista;
48
+  }
49
+
50
+  //funcion
51
+  //recibe Horario para regresar la horas de entrada y salida
52
+  String getHoras(Horario horario) {
53
+    var open_time = horario.open_time;
54
+    var close_time = horario.close_time;
55
+    if (open_time == close_time
56
+        && open_time == '00:00:00'){
57
+        return 'Cerrado';
58
+    }
59
+    var open_hour = int.parse(open_time.substring(0,2));
60
+    var open_minutes = open_time.substring(3,5);
61
+    //var open_minutes;
62
+    var close_hour = int.parse(close_time.substring(0,2));
63
+    var close_minutes = open_time.substring(3,5);
64
+
65
+    // ver si la hora de abrir es AM o PM
66
+    if (open_hour==12){
67
+      open_time = open_time.substring(0,5) + ' PM';
68
+    }else if (open_hour>12){
69
+      open_time = (open_hour % 12).toString() + ':' + open_minutes + ' PM';
70
+    }else{
71
+      open_time = (open_hour % 12).toString() + ':' + open_minutes + ' AM';
72
+    }
73
+
74
+    // ver si la hora de cerrar es AM o PM
75
+    if (close_hour==12){
76
+      close_time = close_time.substring(0,5) + ' PM';
77
+    }else if (close_hour>12){
78
+      close_time = (close_hour % 12).toString() + ':' + close_minutes + ' PM';
79
+    }else{
80
+      close_time = (close_hour % 12).toString() + ':' + close_minutes + ' AM';
81
+    }
82
+
83
+    return open_time + ' - ' + close_time;
84
+  }
85
+  String getEspecialistas(List especialistas) {
86
+    if(especialistas.length > 0 && especialistas[0].specialty.toString() != 'null'){
87
+      var str = "";
88
+      especialistas.forEach((especialista){
89
+        str = str + especialista.specialty.toString() + '\n';
90
+      });
91
+      return str;
92
+    }
93
+    return "No hay especialistas";
94
+  }
95
+
96
+  @override
97
+  Widget build(BuildContext context){
98
+    post = ModalRoute.of(context).settings.arguments;
99
+    Services.getOficina(post['id']).then((Oficina) {
100
+      setState(() {
101
+        _oficina = Oficina;
102
+      });
103
+    });
104
+    Services.getHorario(post['id']).then((Horario) {
105
+      setState(() {
106
+        _horario = Horario;
107
+      });
108
+    });
109
+    Services.getEspecialista(post['id']).then((Especialista) {
110
+      setState(() {
111
+        _especialista = Especialista;
112
+      });
113
+    });
114
+
115
+
116
+    List<Oficina> lista =  _oficina;
117
+    var name = 'Cargando...';
118
+    var telephone = 'Cargando...';
119
+    var address = 'Cargando...';
120
+    var email = 'Cargando...';
121
+    if (lista.length > 0){
122
+      name = lista[0].name;
123
+      telephone = lista[0].telephone;
124
+      address = lista[0].address;
125
+      email = lista[0].email;
126
+    }
127
+
128
+    List<Horario> horario =  _horario;
129
+    var domingo_horario = 'Cargando...';
130
+    var lunes_horario = 'Cargando...';
131
+    var martes_horario = 'Cargando...';
132
+    var miercoles_horario = 'Cargando...';
133
+    var jueves_horario = 'Cargando...';
134
+    var viernes_horario = 'Cargando...';
135
+    var sabado_horario = 'Cargando...';
136
+    if(horario.length == 7){
137
+      domingo_horario = getHoras(horario[0]);
138
+      lunes_horario = getHoras(horario[1]);
139
+      martes_horario = getHoras(horario[2]);
140
+      miercoles_horario = getHoras(horario[3]);
141
+      jueves_horario = getHoras(horario[4]);
142
+      viernes_horario = getHoras(horario[5]);
143
+      sabado_horario = getHoras(horario[6]);
144
+    }else{
145
+      domingo_horario = 'Error';
146
+      lunes_horario = 'Error';
147
+      martes_horario = 'Error';
148
+      miercoles_horario = 'Error';
149
+      jueves_horario = 'Error';
150
+      viernes_horario = 'Error';
151
+      sabado_horario = 'Error';
152
+    }
153
+
154
+
155
+    List<Especialista> especialista =  _especialista;
156
+    var especialistas = getEspecialistas(especialista);
157
+
158
+    return Scaffold(
159
+      appBar: AppBar(
160
+        title: Text(name),
161
+        centerTitle: true,
162
+      ),
163
+      body: Center(
164
+        child: ListView(
165
+          //mainAxisAlignment: MainAxisAlignment.spaceEvenly,
166
+          children: [
167
+            new Card(
168
+              color: Colors.red[300],
169
+
170
+              child: Column(
171
+                mainAxisSize: MainAxisSize.min,
172
+                children: <Widget>[
173
+                  ListTile(
174
+                    // leading: Icon(Icons.album),
175
+                    title: Text('Horario',style: TextStyle(fontWeight: FontWeight.bold,height: 2, fontSize: 36),textAlign: TextAlign.center),
176
+                    subtitle: Text(
177
+                        'Domingo: ' + '$domingo_horario'
178
+                        '\nLunes: ' + '$lunes_horario'
179
+                        '\nMartes: ' + '$martes_horario'
180
+                        '\nMiercoles: ' + '$miercoles_horario'
181
+                        '\nJueves: ' + '$jueves_horario'
182
+                        '\nViernes: ' + '$viernes_horario'
183
+                        '\nSabado: ' + '$sabado_horario',
184
+                        style: TextStyle(fontWeight: FontWeight.bold,height: 2, fontSize: 12),
185
+                        textAlign: TextAlign.center),
186
+                  ),
187
+                  Row(
188
+                    mainAxisAlignment: MainAxisAlignment.end,
189
+                    children: <Widget>[
190
+                      TextButton(
191
+                        child: const Text('Buscar Disponibilidad'),
192
+                        onPressed: () { /* ... */ },
193
+                      ),
194
+                      const SizedBox(width: 8),
195
+                    ],
196
+                  ),
197
+                ],
198
+              ),
199
+            ),
200
+            new Card(
201
+              color: Colors.red[300],
202
+
203
+              child: Column(
204
+                mainAxisSize: MainAxisSize.min,
205
+                children: <Widget>[
206
+                  Row(
207
+                    mainAxisAlignment: MainAxisAlignment.center,
208
+                    children: <Widget>[
209
+                      TextButton(
210
+                        child: const Text('Especialidades \ndisponibles',
211
+                            style: TextStyle(fontWeight: FontWeight.bold,height: 1.5, fontSize: 36),
212
+                            textAlign: TextAlign.center),
213
+                        onPressed: () { /* ... */ },
214
+                      ),
215
+                      const SizedBox(width: 8),
216
+                    ],
217
+                  ),
218
+                  ListTile(
219
+                    subtitle: Text(
220
+                        '$especialistas',
221
+                        style: TextStyle(fontWeight: FontWeight.bold,height: 2, fontSize: 12),
222
+                        textAlign: TextAlign.center),
223
+                  ),
224
+                ],
225
+              ),
226
+            ),
227
+            new Card(
228
+              color: Colors.red[300],
229
+
230
+              child: Column(
231
+                mainAxisSize: MainAxisSize.min,
232
+                children: <Widget>[
233
+                  ListTile(
234
+                    title: Text('Direccion',style: TextStyle(fontWeight: FontWeight.bold,height: 2, fontSize: 36),textAlign: TextAlign.center),
235
+                    subtitle: Text('$address',
236
+                        style: TextStyle(fontWeight: FontWeight.bold,height: 2, fontSize: 12),
237
+                        textAlign: TextAlign.center),
238
+                  ),
239
+                  Row(
240
+                    mainAxisAlignment: MainAxisAlignment.end,
241
+                    children: <Widget>[
242
+                      TextButton(
243
+                        child: const Text('Buscar en el mapa'),
244
+                        onPressed: () {
245
+                          setState(() async {
246
+                            String destinationLatitude = "18.39007092764153";
247
+                            String destinationLongitude = "-65.976216841223";
248
+                            String originlatitude = "18.418738017376207";
249
+                            String originlongitude = "-66.02565531285634";
250
+
251
+                            //const url = 'https://www.google.com/maps/@42.585444,13.007813,6z';
252
+                            const url = "https://www.google.com/maps/dir/?api=1&parameters&origin=18.418738017376207,-66.02565531285634&destination=18.39007092764153,-65.976216841223";
253
+                            if (await canLaunch(url)) {
254
+                              await launch(url);
255
+                            } else {
256
+                              throw 'Could not launch $url';
257
+                            }
258
+
259
+                            //String uri = "http://maps.google.com/maps?daddr=" + destinationLatitude + "," + destinationLongitude + " (" + "Doctor" + ")";
260
+                            //Intent intent;
261
+                            //intent.setAction(Action.ACTION_VIEW);
262
+                            //Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
263
+                            //intent.setPackage("com.google.android.apps.maps");
264
+                            //startActivity(intent);
265
+                            //UIApplication.shared.openURL(URL(string:"https://www.google.com/maps/@42.585444,13.007813,6z")!);
266
+                          });
267
+                          },
268
+                      ),
269
+                      const SizedBox(width: 8),
270
+                    ],
271
+                  ),
272
+                ],
273
+              ),
274
+            ),
275
+            new Card(
276
+              color: Colors.red[300],
277
+
278
+              child: Column(
279
+                mainAxisSize: MainAxisSize.min,
280
+                children: <Widget>[
281
+                  ListTile(
282
+                    title: Text('Contacto',style: TextStyle(fontWeight: FontWeight.bold,height: 2, fontSize: 36),textAlign: TextAlign.center),
283
+                    subtitle: Text("Telefono: \n "
284
+                        "$telephone \n "
285
+                        "\n"
286
+                        "Email:  \n  "
287
+                        "$email",
288
+                        style: TextStyle(fontWeight: FontWeight.bold,height: 2, fontSize: 12),
289
+                        textAlign: TextAlign.center),
290
+                  ),
291
+                ],
292
+              ),
293
+            ),
294
+          ],
295
+        ),
296
+
297
+      ),
298
+
299
+    );
300
+  }
301
+}
302
+

+ 15
- 27
fast_med_flutter/lib/routes/ver_oficinas.dart View File

@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
2 2
 import '../widgets/DataTableMySqlDemo/Oficina.dart';
3 3
 import '../widgets/DataTableMySqlDemo/Services.dart';
4 4
 import 'dart:async';
5
+import '../widgets/functions.dart';
5 6
 
6 7
 class VerOficinas extends StatefulWidget{
7 8
   VerOficinas() : super();
@@ -58,34 +59,21 @@ class _VerOficinasState extends State<VerOficinas>{
58 59
         backgroundColor: Colors.purple,
59 60
 
60 61
       ),
61
-      body: Center(
62
-          child: Column(
63
-            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
64
-            children: lista.map((Oficina data) {
65
-              return FlatButton(
66
-                minWidth: 300.0,
67
-                height: 100.0,
68
-                child: Text(data.name,
69
-                style: TextStyle(fontSize: 36),
70
-                ),
71
-                onPressed: () {
72
-                  print(data.name);
73
-                },
74
-                padding: new EdgeInsets.all(0.0),
75
-                color: Colors.purple,
76
-
77
-              );
78
-            }).toList(),
79
-          ),
80
-          // child: FlatButton(
81
-          //   onPressed: (){
82
-          //     _getOficinas();
83
-          //   },
84
-          //   child: Text('Ver Oficinas'),
85
-          //   color: Colors.purple,
86
-          // )
62
+      body: ListView.builder(
63
+        itemCount: lista.length,
64
+        itemBuilder: (context, index){
65
+          return Card(
66
+          child: ListTile(
67
+            onTap: () {
68
+              Navigator.pushNamed(context, "/ver/oficina", arguments:{
69
+                'id' : lista[index].id,
70
+              });
71
+            },
72
+            title: Text(lista[index].name),
73
+          )
74
+          );
75
+        }
87 76
       ),
88
-
89 77
     );
90 78
   }
91 79
 }

+ 68
- 33
fast_med_flutter/lib/routes/welcome.dart View File

@@ -1,10 +1,14 @@
1
-
2
-
1
+import 'dart:convert';
2
+// import 'dart:html';
3
+import 'dart:io';
4
+import 'package:flutter/cupertino.dart';
3 5
 import 'package:flutter_login/flutter_login.dart';
4 6
 import 'package:flutter/material.dart';
5 7
 import 'package:google_fonts/google_fonts.dart';
6 8
 import 'register.dart';
7
-
9
+import 'package:http/http.dart' as http;
10
+import 'dart:convert' as convert;
11
+import 'navigation.dart';
8 12
 
9 13
 
10 14
 
@@ -19,9 +23,34 @@ class WelcomePage extends StatefulWidget {
19 23
 }
20 24
 
21 25
 class _WelcomePageState extends State<WelcomePage> {
26
+  var Token;
27
+  TextEditingController email = new TextEditingController();
28
+  TextEditingController password = new TextEditingController();
29
+
30
+
31
+  Future<List> send_data() async {
32
+
33
+    var url = 'https://ada.uprrp.edu/~hector.sierra/FastMed/API/login.php';
34
+    http.Response response = await http.post(url, body: {
35
+      "email": email.text,
36
+      "password": password.text,
37
+    });
38
+    print(response.body);
39
+    print(response.statusCode);
40
+    print(HttpStatus.ok);
41
+    if("user not found" == response.body){
42
+      print("maybe we use this");
43
+    }
44
+    else{
45
+      print("User found");
46
+      Token = email.text;
47
+
48
+      Navigator.push(
49
+          context, MaterialPageRoute(builder: (context) => NavigationPage()));
50
+
51
+    }
52
+  }
22 53
 
23
-  TextEditingController email;
24
-  TextEditingController password;
25 54
 
26 55
   Widget _message(BuildContext context){
27 56
     return RichText(
@@ -59,7 +88,7 @@ class _WelcomePageState extends State<WelcomePage> {
59 88
           children: <Widget> [
60 89
             Text(
61 90
               title,
62
-              style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
91
+              style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
63 92
             ),
64 93
             SizedBox(
65 94
                 height: 30
@@ -81,6 +110,8 @@ class _WelcomePageState extends State<WelcomePage> {
81 110
     );
82 111
   }
83 112
 
113
+
114
+
84 115
   Widget _Fills(){
85 116
     return Column(
86 117
         children: <Widget> [
@@ -93,31 +124,31 @@ class _WelcomePageState extends State<WelcomePage> {
93 124
 
94 125
 
95 126
 
96
-  // Widget _LogInButton(BuildContext context){
97
-  //   return InkWell(
98
-  //     // onTap: () {
99
-  //     //   Navigator.push(context, MaterialPageRoute(builder: (context)) => __LoginPage())
100
-  //     // },
101
-  //     child: Container(
102
-  //       // width: MediaQuery.of(context).size.width,
103
-  //       width: 200,
104
-  //       // height: ,
105
-  //       padding: EdgeInsets.symmetric(vertical:8),
106
-  //       alignment: Alignment.center,
107
-  //       decoration: BoxDecoration(
108
-  //         color: Colors.red,
109
-  //         // shape:
110
-  //
111
-  //         borderRadius: BorderRadius.circular(30),
112
-  //       ),
113
-  //       child: Text(
114
-  //         "Login",
115
-  //         style: TextStyle(fontSize: 25, color: Colors.white),
116
-  //       ),
117
-  //
118
-  //     )
119
-  //   );
120
-  // }
127
+
128
+  Widget _SubmitButton(BuildContext context){
129
+    return InkResponse(
130
+      onTap: (){
131
+
132
+        send_data();
133
+
134
+
135
+      },
136
+      child: Container(
137
+        padding: EdgeInsets.symmetric(vertical: 10),
138
+        width: 180,
139
+        alignment: Alignment.center,
140
+        decoration: BoxDecoration(
141
+          color: Colors.red,
142
+          borderRadius: BorderRadius.circular(30),
143
+        ),
144
+        child: Text(
145
+          "Login",
146
+          style: TextStyle(fontSize: 22, color: Colors.white),
147
+        ),
148
+      ),
149
+    );
150
+  }
151
+
121 152
 
122 153
   Widget _RegisterButton(BuildContext context){
123 154
     return InkWell(
@@ -183,13 +214,17 @@ class _WelcomePageState extends State<WelcomePage> {
183 214
                     SizedBox(
184 215
                       height: 60,
185 216
                     ),
217
+                    _SubmitButton(context),
218
+                    SizedBox(
219
+                      height: 45,
220
+                    ),
186 221
                     _message(context),
187 222
                     SizedBox(
188
-                      height: 10,
223
+                      height: 15,
189 224
                     ),
190 225
                     _RegisterButton(context),
191 226
                     SizedBox(
192
-                      height: 10,
227
+                      height: 20,
193 228
                     )
194 229
                   ],
195 230
                 )

+ 231
- 0
fast_med_flutter/lib/ui/pages/add_event.dart View File

@@ -0,0 +1,231 @@
1
+import 'package:fast_med_flutter/model/event.dart';
2
+import 'package:flutter/material.dart';
3
+import 'package:fast_med_flutter/res/event_firestore_service.dart';
4
+import 'package:http/http.dart' as http;
5
+import 'dart:async';
6
+
7
+class AddEventPage extends StatefulWidget {
8
+  final EventModel note;
9
+
10
+  const AddEventPage({Key key, this.note}) : super(key: key);
11
+
12
+  @override
13
+  _AddEventPageState createState() => _AddEventPageState();
14
+}
15
+
16
+//Controles de cada Evento que usaremos en todos los files
17
+
18
+class _AddEventPageState extends State<AddEventPage> {
19
+  TextStyle style = TextStyle(fontFamily: 'Montserrat', fontSize: 20.0);
20
+  TextEditingController _title;
21
+  TextEditingController _description;
22
+  TextEditingController _number;
23
+  TextEditingController _name;
24
+  TextEditingController _reason;
25
+
26
+
27
+  DateTime _eventDate;
28
+  DateTime _eventTime;
29
+  DateTime selectedDate = DateTime.now();
30
+  List data;
31
+  List holidays;
32
+  final _formKey = GlobalKey<FormState>();
33
+  final _key = GlobalKey<ScaffoldState>();
34
+  bool processing;
35
+
36
+  @override
37
+  void initState() {
38
+    super.initState();
39
+    _title = TextEditingController(text: widget.note != null ? widget.note.title : "");
40
+    _description = TextEditingController(text:  widget.note != null ? widget.note.description : "");
41
+    _name = TextEditingController(text:  widget.note != null ? widget.note.name : "");
42
+    _number = TextEditingController(text:  widget.note != null ? widget.note.number : "");
43
+    _reason = TextEditingController(text:  widget.note != null ? widget.note.reason : "");
44
+    _eventDate = DateTime.now();
45
+    _eventTime = DateTime.now();
46
+    processing = false;
47
+  }
48
+
49
+// Definimos el Formulario con cada parametro para crear la cita
50
+
51
+  @override
52
+  Widget build(BuildContext context) {
53
+    return Scaffold(
54
+      appBar: AppBar(
55
+        title: Text(widget.note != null ? "Edit Note" : "Crear Su Cita"),
56
+      ),
57
+      key: _key,
58
+      body: Form(
59
+        key: _formKey,
60
+        child: Container(
61
+          alignment: Alignment.center,
62
+          child: ListView(
63
+            children: <Widget>[
64
+
65
+              // Area donde paciente anota su nombre. Si esta vacio no lo acepta.
66
+
67
+              Padding(
68
+                padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
69
+                child: TextFormField(
70
+                  controller: _name,
71
+                  validator: (value) =>
72
+                      (value.isEmpty) ? "Favor Anotar Nombre del Paciente" : null,
73
+                  style: style,
74
+                  decoration: InputDecoration(
75
+                      labelText: "Nombre completo del paciente",
76
+                      filled: true,
77
+                      fillColor: Colors.white,
78
+                      border: OutlineInputBorder(borderRadius: BorderRadius.circular(10))),
79
+                ),
80
+              ),
81
+
82
+              //Area donde el paciente debe anotar su numero de telefono. Si esta vacio no lo acepta.
83
+
84
+              Padding(
85
+                padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
86
+                child: TextFormField(
87
+                  controller: _number,
88
+                  validator: (value) =>
89
+                  (value.isEmpty) ? "Favor Anotar Numero de Telefono" : null,
90
+                  style: style,
91
+                  decoration: InputDecoration(
92
+                      labelText: "Numero de Telefono",
93
+                      border: OutlineInputBorder(borderRadius: BorderRadius.circular(10))),
94
+                ),
95
+              ),
96
+
97
+              //Area donde el paciente explica la razon de su cita medica. Si esta vacio no lo acepta
98
+
99
+              Padding(
100
+                padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
101
+                child: TextFormField(
102
+                  controller: _reason,
103
+                  minLines: 3,
104
+                  maxLines: 5,
105
+                  validator: (value) =>
106
+                      (value.isEmpty) ? "Favor Explicar Razon Para La Cita" : null,
107
+                  style: style,
108
+                  decoration: InputDecoration(
109
+                      labelText: "Razones para su cita",
110
+                      border: OutlineInputBorder(borderRadius: BorderRadius.circular(10))),
111
+                ),
112
+              ),
113
+              const SizedBox(height: 10.0),
114
+
115
+              //Area donde el paciente puede cambiar la fecha para la cita
116
+
117
+              ListTile(
118
+                title: Text("Date (YYYY-MM-DD)"),
119
+                subtitle: Text("${_eventDate.year} - ${_eventDate.month} - ${_eventDate.day}"),
120
+                onTap: ()async{
121
+                  DateTime picked = await showDatePicker(context: context, initialDate: _eventDate, firstDate: DateTime(_eventDate.year-5), lastDate: DateTime(_eventDate.year+5));
122
+                  if(picked != null) {
123
+                    setState(() {
124
+                      _eventDate = picked;
125
+                    });
126
+                  }
127
+                },
128
+              ),
129
+
130
+              //Area donde el paciente puede elegir y cambiar la hora para la cita
131
+
132
+              ListTile(
133
+                title: Text("Time (HH: mm)"),
134
+                subtitle: Text("${_eventDate.hour} - ${_eventDate.minute} - ${_eventDate.second}"),
135
+                onTap: ()async{
136
+                 final selectedTime = await _selectTime(context);
137
+                 if (selectedTime == null) return;
138
+                  print(selectedTime);
139
+
140
+                setState(() {
141
+                this.selectedDate = DateTime(
142
+                selectedTime.hour,
143
+                selectedTime.minute,
144
+                );
145
+                    });
146
+                  }
147
+                  ),
148
+              SizedBox(height: 10.0),
149
+
150
+              //Se define el envio de los parametros al usar el boton de Crear la Cita
151
+
152
+              processing
153
+                  ? Center(child: CircularProgressIndicator())
154
+                  : Padding(
155
+                padding: const EdgeInsets.symmetric(horizontal: 16.0),
156
+                child: Material(
157
+                  elevation: 5.0,
158
+                  borderRadius: BorderRadius.circular(30.0),
159
+                  color: Theme.of(context).primaryColor,
160
+                  child: MaterialButton(
161
+                    onPressed: () async {
162
+                      if (_formKey.currentState.validate()) {
163
+                        setState(() {
164
+                          processing = true;
165
+                        });
166
+                        if(widget.note != null) {
167
+                          await eventDBS.updateData(widget.note.id,{
168
+
169
+
170
+                          "title": _title.text,
171
+                          "number": _number.text,
172
+                          "reason": _reason.text,
173
+                          "event_date": widget.note.eventDate,
174
+                          "time": widget.note.eventTime,
175
+                          });
176
+                        }else{
177
+                          await eventDBS.createItem(EventModel(
178
+                              title: _title.text,
179
+                              description: _description.text,
180
+                              name: _name.text,
181
+                              number: _number.text,
182
+                              reason: _reason.text,
183
+                              eventDate: _eventDate
184
+
185
+                          ));
186
+                        }
187
+                        Navigator.pop(context);
188
+                        setState(() {
189
+                          processing = false;
190
+                        });
191
+                      }
192
+                    },
193
+                    child: Text(
194
+                      "Crear Su Cita Ahora",
195
+                      style: style.copyWith(
196
+                          color: Colors.white,
197
+                          fontWeight: FontWeight.bold),
198
+                    ),
199
+                  ),
200
+                ),
201
+              ),
202
+            ],
203
+          ),
204
+        ),
205
+      ),
206
+    );
207
+  }
208
+
209
+
210
+  @override
211
+  void dispose() {
212
+    _title.dispose();
213
+    _description.dispose();
214
+    _name.dispose();
215
+    _number.dispose();
216
+    _reason.dispose();
217
+    super.dispose();
218
+  }
219
+}
220
+
221
+// Funcionalidades para poder seleccionar horarios
222
+
223
+Future<TimeOfDay> _selectTime(BuildContext context) {
224
+  final now = DateTime.now();
225
+
226
+  return showTimePicker(
227
+    context: context,
228
+    initialTime: TimeOfDay(hour: now.hour, minute: now.minute),
229
+  );
230
+}
231
+

+ 30
- 0
fast_med_flutter/lib/ui/pages/view_event.dart View File

@@ -0,0 +1,30 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:fast_med_flutter/model/event.dart';
3
+
4
+// Implementacion para ver recordatorios de citas creadas
5
+
6
+class EventDetailsPage extends StatelessWidget {
7
+  final EventModel event;
8
+
9
+  const EventDetailsPage({Key key, this.event}) : super(key: key);
10
+
11
+  @override
12
+  Widget build(BuildContext context){
13
+    return Scaffold(
14
+      appBar: AppBar(
15
+        title: Text('Note details'),
16
+      ),
17
+      body: SingleChildScrollView(
18
+        padding: const EdgeInsets.all(16.0),
19
+        child: Column(
20
+          crossAxisAlignment: CrossAxisAlignment.start,
21
+          children: <Widget>[
22
+            Text(event.title, style: Theme.of(context).textTheme.display1,),
23
+            SizedBox(height: 20.0),
24
+            Text(event.description)
25
+          ],
26
+        ),
27
+      ),
28
+    );
29
+  }
30
+}

+ 32
- 0
fast_med_flutter/lib/widgets/DataTableMySqlDemo/Especialista.dart View File

@@ -0,0 +1,32 @@
1
+class Especialista {
2
+  String id;
3
+  String oficina_id;
4
+  String name;
5
+  String specialty;
6
+  String telephone;
7
+  String email;
8
+
9
+  Especialista({this.id, this.oficina_id, this.name, this.specialty, this.telephone, this.email});
10
+
11
+  factory Especialista.allFromJson(Map<String, dynamic> json) {
12
+    return Especialista (
13
+      id :json['id'] as String,
14
+      oficina_id: json['oficina_id'] as String,
15
+      name: json['name'] as String,
16
+      specialty: json['specialty'] as String,
17
+      telephone: json['telephone'] as String,
18
+      email: json['email'] as String,
19
+    );
20
+  }
21
+
22
+  factory Especialista.infoFromJson(Map<String, dynamic> json) {
23
+    return Especialista (
24
+      id :json['id'] as String,
25
+      oficina_id: json['oficina_id'] as String,
26
+      name: json['name'] as String,
27
+      specialty: json['specialty'] as String,
28
+      telephone: json['telephone'] as String,
29
+      email: json['email'] as String,
30
+    );
31
+  }
32
+}

+ 29
- 0
fast_med_flutter/lib/widgets/DataTableMySqlDemo/Horario.dart View File

@@ -0,0 +1,29 @@
1
+class Horario {
2
+  String id;
3
+  String oficina_id;
4
+  String dia_semana;
5
+  String open_time;
6
+  String close_time;
7
+
8
+  Horario({this.id, this.oficina_id, this.dia_semana, this.open_time, this.close_time});
9
+
10
+  factory Horario.allFromJson(Map<String, dynamic> json) {
11
+    return Horario (
12
+      id :json['id'] as String,
13
+      oficina_id: json['oficina_id'] as String,
14
+      dia_semana: json['dia_semana'] as String,
15
+      open_time: json['open_time'] as String,
16
+      close_time: json['close_time'] as String,
17
+    );
18
+  }
19
+
20
+  factory Horario.infoFromJson(Map<String, dynamic> json) {
21
+    return Horario (
22
+      id :json['id'] as String,
23
+      oficina_id: json['oficina_id'] as String,
24
+      dia_semana: json['dia_semana'] as String,
25
+      open_time: json['open_time'] as String,
26
+      close_time: json['close_time'] as String,
27
+    );
28
+  }
29
+}

+ 18
- 2
fast_med_flutter/lib/widgets/DataTableMySqlDemo/Oficina.dart View File

@@ -1,13 +1,29 @@
1 1
 class Oficina {
2 2
   String id;
3 3
   String name;
4
+  String address;
5
+  String telephone;
6
+  String email;
4 7
 
5
-  Oficina({this.id, this.name});
8
+  Oficina({this.id, this.name, this.address, this.telephone, this.email});
6 9
 
7
-  factory Oficina.fromJson(Map<String, dynamic> json) {
10
+  factory Oficina.allFromJson(Map<String, dynamic> json) {
8 11
     return Oficina (
9 12
       id :json['id'] as String,
10 13
       name: json['name'] as String,
14
+      address: json['address'] as String,
15
+      telephone: json['telephone'] as String,
16
+      email: json['email'] as String,
17
+    );
18
+  }
19
+
20
+  factory Oficina.infoFromJson(Map<String, dynamic> json) {
21
+    return Oficina (
22
+      id :json['id'] as String,
23
+      name: json['name'] as String,
24
+      address: json['address'] as String,
25
+      telephone: json['telephone'] as String,
26
+      email: json['email'] as String,
11 27
     );
12 28
   }
13 29
 }

+ 77
- 19
fast_med_flutter/lib/widgets/DataTableMySqlDemo/Services.dart View File

@@ -1,46 +1,104 @@
1 1
 import 'dart:convert';
2
+import 'package:fast_med_flutter/widgets/DataTableMySqlDemo/Horario.dart';
3
+import 'package:fast_med_flutter/widgets/DataTableMySqlDemo/Especialista.dart';
2 4
 import 'package:http/http.dart'
3 5
   as http;
4 6
 import 'Oficina.dart';
5 7
 
6 8
 class Services {
7
-  static const URL = 'https://ada.uprrp.edu/~oniel.mendez2/json/oficinas.php';
8
-  static const URL_GET_ALL = 'ada.uprrp.edu/~oniel.mendez2/json/getOficinas.php';
9
-  static const URL_LOCAL = 'http://localhost/test/getOficinas.json';
10
-  static const _GET_ALL = "GET_ALL";
9
+  static const URL_GET_ALL = 'http://ada.uprrp.edu/~oniel.mendez2/json/getOficinas.php';
10
+  static const URL_OFICINA_GET_BY_ID = 'https://ada.uprrp.edu/~oniel.mendez2/json/getOficinaByID.php';
11
+  static const URL_HORARIO = 'https://ada.uprrp.edu/~oniel.mendez2/json/getHorario.php';
12
+  static const URL_ESPECIALISTA = 'https://ada.uprrp.edu/~oniel.mendez2/json/getEspecialista.php';
13
+  //static const _GET_ALL = "GET_ALL";
11 14
 
12 15
   //get all oficinas
13 16
   static Future<List<Oficina>> getOficinas() async {
14 17
     try {
15
-      var map = Map<String, dynamic>();
16
-      map['action'] = _GET_ALL;
17
-      //print('antes');
18 18
       final response = await http.get(URL_GET_ALL);
19
-      // print('despues');
20
-      // print('getOficinas Response: ${response.body}');
21 19
       if (200 == response.statusCode) {
22
-        List<Oficina> list = parseResponse(response.body);
20
+        final parsed = json.decode(response.body).cast<Map<String, dynamic>>();
21
+        List<Oficina> list = parsed.map<Oficina>((json) => Oficina.allFromJson(json)).toList();
22
+        return list;
23
+      } else {
24
+        final response = '[{"id":"1","name":"error."},{"id":"2","name":"el codigo"},{"id":"3","name":"!=200"}]';
25
+        final parsed = json.decode(response).cast<Map<String, dynamic>>();
26
+        List<Oficina> list = parsed.map<Oficina>((json) => Oficina.allFromJson(json)).toList();
27
+        return list; // return an empty list on exception/error
28
+      }
29
+    } catch (e) {
30
+      final response = '[{"id":"1","name":"oficina 1,"telephone":"787","address":"Carretera ##","email":"email@domain.com""},'
31
+                        '{"id":"2","name":"oficina 2","telephone":"787","address":"Carretera ##","email":"email@domain.com"},'
32
+                        '{"id":"3","name":"oficina 3","telephone":"787","address":"Carretera ##","email":"email@domain.com"}]';
33
+      final parsed = json.decode(response).cast<Map<String, dynamic>>();
34
+      List<Oficina> list = parsed.map<Oficina>((json) => Oficina.allFromJson(json)).toList();
35
+      return list; // return an empty list on exception/error
36
+    }
37
+  }
23 38
 
39
+  static Future<List<Oficina>> getOficina(id) async {
40
+    try {
41
+      final response = await http.post(URL_OFICINA_GET_BY_ID, body: {'id': id});
42
+      if (200 == response.statusCode) {
43
+        final parsed = json.decode(response.body).cast<Map<String, dynamic>>();
44
+        List<Oficina> list = parsed.map<Oficina>((json) => Oficina.allFromJson(json)).toList();
24 45
         return list;
25 46
       } else {
26
-        final response = '[{"id":"1","name":"no"},{"id":"2","name":"respondio"},{"id":"3","name":"code: 200"}]';
27
-        List<Oficina> list = parseResponse(response);
47
+        final response = '[{"id":"1","name":"error.","telephone":"787","address":"Carretera ##","email":"email@domain.com"}]';
48
+        final parsed = json.decode(response).cast<Map<String, dynamic>>();
49
+        List<Oficina> list = parsed.map<Oficina>((json) => Oficina.allFromJson(json)).toList();
28 50
         return list; // return an empty list on exception/error
29 51
       }
30 52
     } catch (e) {
31
-      final response = '[{"id":"1","name":"este"},{"id":"2","name":"es el"},{"id":"3","name":"catch(e)"}]';
32
-      List<Oficina> list = parseResponse(response);
53
+      final response = '[{"id":"1","name":"oficina 1","telephone":"787","address":"Carretera ##","email":"email@domain.com"}]';
54
+      final parsed = json.decode(response).cast<Map<String, dynamic>>();
55
+      List<Oficina> list = parsed.map<Oficina>((json) => Oficina.allFromJson(json)).toList();
33 56
       return list; // return an empty list on exception/error
34 57
     }
35 58
   }
36 59
 
37
-  static List<Oficina> parseResponse(String responseBody) {
38
-    final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
39
-    return parsed.map<Oficina>((json) => Oficina.fromJson(json)).toList();
60
+  //para conseguir el horario de una oficina
61
+  static Future<List<Horario>> getHorario(id) async {
62
+    try {
63
+      final response = await http.post(URL_HORARIO, body: {'id': id});
64
+      if (200 == response.statusCode && response != null) {
65
+        final parsed = json.decode(response.body).cast<Map<String, dynamic>>();
66
+        List<Horario> list = parsed.map<Horario>((json) => Horario.allFromJson(json)).toList();
67
+        return list;
68
+      } else {
69
+        final response = '[{"id":"1","name":"error.","telephone":"787","address":"Carretera ##","email":"email@domain.com"}]';
70
+        final parsed = json.decode(response).cast<Map<String, dynamic>>();
71
+        List<Horario> list = parsed.map<Horario>((json) => Horario.allFromJson(json)).toList();
72
+        return list; // return an empty list on exception/error
73
+      }
74
+    } catch (e) {
75
+      final response = '[{"id":"1","name":"oficina 1","telephone":"787","address":"Carretera ##","email":"email@domain.com"}]';
76
+      final parsed = json.decode(response).cast<Map<String, dynamic>>();
77
+      List<Horario> list = parsed.map<Horario>((json) => Horario.allFromJson(json)).toList();
78
+      return list; // return an empty list on exception/error
79
+    }
40 80
   }
41 81
 
42
-  Future<http.Response> fetchAlbum() {
43
-    return http.get('https://jsonplaceholder.typicode.com/albums/1');
82
+  //para conseguir especialistas que trabajen en una oficina
83
+  static Future<List<Especialista>> getEspecialista(id) async {
84
+    try {
85
+      final response = await http.post(URL_ESPECIALISTA, body: {'id': id});
86
+      if (200 == response.statusCode && response != null) {
87
+        final parsed = json.decode(response.body).cast<Map<String, dynamic>>();
88
+        List<Especialista> list = parsed.map<Especialista>((json) => Especialista.allFromJson(json)).toList();
89
+        return list;
90
+      } else {
91
+        final response = '[{"id":"1","name":"error.","telephone":"787","address":"Carretera ##","email":"email@domain.com"}]';
92
+        final parsed = json.decode(response).cast<Map<String, dynamic>>();
93
+        List<Especialista> list = parsed.map<Especialista>((json) => Especialista.allFromJson(json)).toList();
94
+        return list; // return an empty list on exception/error
95
+      }
96
+    } catch (e) {
97
+      final response = '[{"id":"1","name":"oficina 1","telephone":"787","address":"Carretera ##","email":"email@domain.com"}]';
98
+      final parsed = json.decode(response).cast<Map<String, dynamic>>();
99
+      List<Especialista> list = parsed.map<Especialista>((json) => Especialista.allFromJson(json)).toList();
100
+      return list; // return an empty list on exception/error
101
+    }
44 102
   }
45 103
 
46 104
 }

+ 54
- 0
fast_med_flutter/lib/widgets/functions.dart View File

@@ -0,0 +1,54 @@
1
+import 'package:flutter/material.dart';
2
+
3
+FlatButton newButton(context,route,text){
4
+  return new FlatButton(
5
+    //minWidth: 300.0,
6
+    //height: 100.0,
7
+    onPressed: (){
8
+      Navigator.pushNamed(context, route);
9
+    },
10
+    child: Text(text,
11
+      style: TextStyle(fontSize: 36),
12
+    ),
13
+    color: Colors.purple,
14
+    //shape: new RoundedRectangleBorder(borderRadius: new BorderRadius.circular(50)),
15
+    padding: EdgeInsets.all(25),
16
+  );
17
+}
18
+FlatButton verOficinaButton(context,name){
19
+  return new FlatButton(
20
+        minWidth: 300.0,
21
+        height: 100.0,
22
+        child: Text(name,
23
+        style: TextStyle(fontSize: 36),
24
+        ),
25
+        onPressed: () {
26
+          print(name);
27
+        },
28
+        padding: new EdgeInsets.all(0.0),
29
+        color: Colors.purple,
30
+
31
+      );
32
+}
33
+
34
+SizedBox spaceBetween(){
35
+  return new SizedBox(height: 16);
36
+}
37
+List newButton2(context,route,text){
38
+  return [new FlatButton(
39
+          //minWidth: 300.0,
40
+          //height: 100.0,
41
+          onPressed: (){
42
+            Navigator.pushNamed(context, route);
43
+          },
44
+          child: Text(text,
45
+            style: TextStyle(fontSize: 36),
46
+          ),
47
+          color: Colors.purple,
48
+          //shape: new RoundedRectangleBorder(borderRadius: new BorderRadius.circular(50)),
49
+          padding: EdgeInsets.all(25),
50
+        )
51
+    ,
52
+    new SizedBox(height: 16)
53
+  ];
54
+}

+ 184
- 6
fast_med_flutter/pubspec.lock View File

@@ -36,6 +36,27 @@ packages:
36 36
       url: "https://pub.dartlang.org"
37 37
     source: hosted
38 38
     version: "1.1.0-nullsafety.1"
39
+  cloud_firestore:
40
+    dependency: "direct main"
41
+    description:
42
+      name: cloud_firestore
43
+      url: "https://pub.dartlang.org"
44
+    source: hosted
45
+    version: "0.13.7"
46
+  cloud_firestore_platform_interface:
47
+    dependency: transitive
48
+    description:
49
+      name: cloud_firestore_platform_interface
50
+      url: "https://pub.dartlang.org"
51
+    source: hosted
52
+    version: "1.1.2"
53
+  cloud_firestore_web:
54
+    dependency: transitive
55
+    description:
56
+      name: cloud_firestore_web
57
+      url: "https://pub.dartlang.org"
58
+    source: hosted
59
+    version: "0.1.1+2"
39 60
   collection:
40 61
     dependency: transitive
41 62
     description:
@@ -85,6 +106,48 @@ packages:
85 106
       url: "https://pub.dartlang.org"
86 107
     source: hosted
87 108
     version: "5.2.1"
109
+  firebase:
110
+    dependency: transitive
111
+    description:
112
+      name: firebase
113
+      url: "https://pub.dartlang.org"
114
+    source: hosted
115
+    version: "7.3.3"
116
+  firebase_core:
117
+    dependency: transitive
118
+    description:
119
+      name: firebase_core
120
+      url: "https://pub.dartlang.org"
121
+    source: hosted
122
+    version: "0.4.5"
123
+  firebase_core_platform_interface:
124
+    dependency: transitive
125
+    description:
126
+      name: firebase_core_platform_interface
127
+      url: "https://pub.dartlang.org"
128
+    source: hosted
129
+    version: "1.0.4"
130
+  firebase_core_web:
131
+    dependency: transitive
132
+    description:
133
+      name: firebase_core_web
134
+      url: "https://pub.dartlang.org"
135
+    source: hosted
136
+    version: "0.1.1+2"
137
+  firebase_helpers:
138
+    dependency: "direct main"
139
+    description:
140
+      name: firebase_helpers
141
+      url: "https://pub.dartlang.org"
142
+    source: hosted
143
+    version: "0.1.11"
144
+  firebase_storage:
145
+    dependency: transitive
146
+    description:
147
+      name: firebase_storage
148
+      url: "https://pub.dartlang.org"
149
+    source: hosted
150
+    version: "3.1.6"
88 151
   flushbar:
89 152
     dependency: transitive
90 153
     description:
@@ -97,6 +160,11 @@ packages:
97 160
     description: flutter
98 161
     source: sdk
99 162
     version: "0.0.0"
163
+  flutter_localizations:
164
+    dependency: "direct main"
165
+    description: flutter
166
+    source: sdk
167
+    version: "0.0.0"
100 168
   flutter_login:
101 169
     dependency: "direct main"
102 170
     description:
@@ -109,13 +177,18 @@ packages:
109 177
     description: flutter
110 178
     source: sdk
111 179
     version: "0.0.0"
180
+  flutter_web_plugins:
181
+    dependency: transitive
182
+    description: flutter
183
+    source: sdk
184
+    version: "0.0.0"
112 185
   font_awesome_flutter:
113 186
     dependency: transitive
114 187
     description:
115 188
       name: font_awesome_flutter
116 189
       url: "https://pub.dartlang.org"
117 190
     source: hosted
118
-    version: "8.10.0"
191
+    version: "8.11.0"
119 192
   google_fonts:
120 193
     dependency: "direct main"
121 194
     description:
@@ -144,6 +217,27 @@ packages:
144 217
       url: "https://pub.dartlang.org"
145 218
     source: hosted
146 219
     version: "0.16.1"
220
+  js:
221
+    dependency: transitive
222
+    description:
223
+      name: js
224
+      url: "https://pub.dartlang.org"
225
+    source: hosted
226
+    version: "0.6.2"
227
+  json_table:
228
+    dependency: "direct dev"
229
+    description:
230
+      name: json_table
231
+      url: "https://pub.dartlang.org"
232
+    source: hosted
233
+    version: "1.4.0"
234
+  json_utilities:
235
+    dependency: transitive
236
+    description:
237
+      name: json_utilities
238
+      url: "https://pub.dartlang.org"
239
+    source: hosted
240
+    version: "0.1.3"
147 241
   matcher:
148 242
     dependency: transitive
149 243
     description:
@@ -241,7 +335,7 @@ packages:
241 335
       name: provider
242 336
       url: "https://pub.dartlang.org"
243 337
     source: hosted
244
-    version: "4.3.2+2"
338
+    version: "4.3.2+3"
245 339
   quiver:
246 340
     dependency: transitive
247 341
     description:
@@ -249,13 +343,55 @@ packages:
249 343
       url: "https://pub.dartlang.org"
250 344
     source: hosted
251 345
     version: "2.1.5"
346
+  shared_preferences:
347
+    dependency: "direct main"
348
+    description:
349
+      name: shared_preferences
350
+      url: "https://pub.dartlang.org"
351
+    source: hosted
352
+    version: "0.5.12+4"
353
+  shared_preferences_linux:
354
+    dependency: transitive
355
+    description:
356
+      name: shared_preferences_linux
357
+      url: "https://pub.dartlang.org"
358
+    source: hosted
359
+    version: "0.0.2+4"
360
+  shared_preferences_macos:
361
+    dependency: transitive
362
+    description:
363
+      name: shared_preferences_macos
364
+      url: "https://pub.dartlang.org"
365
+    source: hosted
366
+    version: "0.0.1+11"
367
+  shared_preferences_platform_interface:
368
+    dependency: transitive
369
+    description:
370
+      name: shared_preferences_platform_interface
371
+      url: "https://pub.dartlang.org"
372
+    source: hosted
373
+    version: "1.0.4"
374
+  shared_preferences_web:
375
+    dependency: transitive
376
+    description:
377
+      name: shared_preferences_web
378
+      url: "https://pub.dartlang.org"
379
+    source: hosted
380
+    version: "0.1.2+7"
381
+  shared_preferences_windows:
382
+    dependency: transitive
383
+    description:
384
+      name: shared_preferences_windows
385
+      url: "https://pub.dartlang.org"
386
+    source: hosted
387
+    version: "0.0.1+3"
252 388
   simple_gesture_detector:
253 389
     dependency: transitive
254 390
     description:
255 391
       name: simple_gesture_detector
256 392
       url: "https://pub.dartlang.org"
257 393
     source: hosted
258
-    version: "0.1.4"
394
+    version: "0.1.6"
259 395
   sky_engine:
260 396
     dependency: transitive
261 397
     description: flutter
@@ -295,7 +431,7 @@ packages:
295 431
       name: table_calendar
296 432
       url: "https://pub.dartlang.org"
297 433
     source: hosted
298
-    version: "2.3.0"
434
+    version: "2.3.3"
299 435
   term_glyph:
300 436
     dependency: transitive
301 437
     description:
@@ -324,6 +460,48 @@ packages:
324 460
       url: "https://pub.dartlang.org"
325 461
     source: hosted
326 462
     version: "1.3.0-nullsafety.3"
463
+  url_launcher:
464
+    dependency: "direct main"
465
+    description:
466
+      name: url_launcher
467
+      url: "https://pub.dartlang.org"
468
+    source: hosted
469
+    version: "5.7.10"
470
+  url_launcher_linux:
471
+    dependency: transitive
472
+    description:
473
+      name: url_launcher_linux
474
+      url: "https://pub.dartlang.org"
475
+    source: hosted
476
+    version: "0.0.1+4"
477
+  url_launcher_macos:
478
+    dependency: transitive
479
+    description:
480
+      name: url_launcher_macos
481
+      url: "https://pub.dartlang.org"
482
+    source: hosted
483
+    version: "0.0.1+9"
484
+  url_launcher_platform_interface:
485
+    dependency: transitive
486
+    description:
487
+      name: url_launcher_platform_interface
488
+      url: "https://pub.dartlang.org"
489
+    source: hosted
490
+    version: "1.0.9"
491
+  url_launcher_web:
492
+    dependency: transitive
493
+    description:
494
+      name: url_launcher_web
495
+      url: "https://pub.dartlang.org"
496
+    source: hosted
497
+    version: "0.1.5+1"
498
+  url_launcher_windows:
499
+    dependency: transitive
500
+    description:
501
+      name: url_launcher_windows
502
+      url: "https://pub.dartlang.org"
503
+    source: hosted
504
+    version: "0.0.1+3"
327 505
   vector_math:
328 506
     dependency: transitive
329 507
     description:
@@ -337,7 +515,7 @@ packages:
337 515
       name: win32
338 516
       url: "https://pub.dartlang.org"
339 517
     source: hosted
340
-    version: "1.7.3"
518
+    version: "1.7.4"
341 519
   xdg_directories:
342 520
     dependency: transitive
343 521
     description:
@@ -347,4 +525,4 @@ packages:
347 525
     version: "0.1.2"
348 526
 sdks:
349 527
   dart: ">=2.10.0-110 <2.11.0"
350
-  flutter: ">=1.17.0 <2.0.0"
528
+  flutter: ">=1.22.0 <2.0.0"

+ 12
- 4
fast_med_flutter/pubspec.yaml View File

@@ -23,7 +23,13 @@ environment:
23 23
 dependencies:
24 24
   flutter:
25 25
     sdk: flutter
26
+  url_launcher: ^5.4.0
27
+  shared_preferences: ^0.5.4+5
26 28
 
29
+  firebase_helpers: ^0.1.8
30
+  cloud_firestore: ^0.13.5
31
+  flutter_localizations:
32
+    sdk: flutter
27 33
 
28 34
   # The following adds the Cupertino Icons font to your application.
29 35
   # Use with the CupertinoIcons class for iOS style icons.
@@ -34,10 +40,12 @@ dependencies:
34 40
 
35 41
   #
36 42
   http: ^0.12.2
37
-
43
+assets:
44
+  - assets/raw/certificate.pem
38 45
 dev_dependencies:
39 46
   flutter_test:
40 47
     sdk: flutter
48
+  json_table: 1.4.0
41 49
 
42 50
 # For information on the generic Dart part of this file, see the
43 51
 # following page: https://dart.dev/tools/pub/pubspec
@@ -51,9 +59,9 @@ flutter:
51 59
   uses-material-design: true
52 60
 
53 61
   # To add assets to your application, add an assets section, like this:
54
-  # assets:
55
-  #   - images/a_dot_burr.jpeg
56
-  #   - images/a_dot_ham.jpeg
62
+  assets:
63
+    - lib/languages/en.json
64
+    - lib/languages/es.json
57 65
 
58 66
   # An image asset can refer to one or more resolution-specific "variants", see
59 67
   # https://flutter.dev/assets-and-images/#resolution-aware.