Showing
17 changed files
with
849 additions
and
160 deletions
.vscode/c_cpp_properties.json
0 → 100644
1 | +{ | ||
2 | + "configurations": [ | ||
3 | + { | ||
4 | + "name": "Win32", | ||
5 | + "includePath": [ | ||
6 | + "${workspaceFolder}/**" | ||
7 | + ], | ||
8 | + "defines": [ | ||
9 | + "_DEBUG", | ||
10 | + "UNICODE", | ||
11 | + "_UNICODE" | ||
12 | + ], | ||
13 | + "windowsSdkVersion": "10.0.18362.0", | ||
14 | + "compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.28.29910/bin/Hostx64/x64/cl.exe", | ||
15 | + "cStandard": "c17", | ||
16 | + "cppStandard": "c++17", | ||
17 | + "intelliSenseMode": "windows-msvc-x64" | ||
18 | + } | ||
19 | + ], | ||
20 | + "version": 4 | ||
21 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +{ | ||
2 | + "project_info": { | ||
3 | + "project_number": "515101468848", | ||
4 | + "project_id": "smartmedicinebox-e7163", | ||
5 | + "storage_bucket": "smartmedicinebox-e7163.appspot.com" | ||
6 | + }, | ||
7 | + "client": [ | ||
8 | + { | ||
9 | + "client_info": { | ||
10 | + "mobilesdk_app_id": "1:515101468848:android:ca3083a7ae6e9e83cff375", | ||
11 | + "android_client_info": { | ||
12 | + "package_name": "com.example.Smart_Medicine_Box" | ||
13 | + } | ||
14 | + }, | ||
15 | + "oauth_client": [ | ||
16 | + { | ||
17 | + "client_id": "515101468848-a5p2ifirr30l80fcetedid91vrcj1v8h.apps.googleusercontent.com", | ||
18 | + "client_type": 3 | ||
19 | + } | ||
20 | + ], | ||
21 | + "api_key": [ | ||
22 | + { | ||
23 | + "current_key": "AIzaSyCkglFpl-CsPetG2C--9BZjiXILK3-TZT0" | ||
24 | + } | ||
25 | + ], | ||
26 | + "services": { | ||
27 | + "appinvite_service": { | ||
28 | + "other_platform_oauth_client": [ | ||
29 | + { | ||
30 | + "client_id": "515101468848-a5p2ifirr30l80fcetedid91vrcj1v8h.apps.googleusercontent.com", | ||
31 | + "client_type": 3 | ||
32 | + } | ||
33 | + ] | ||
34 | + } | ||
35 | + } | ||
36 | + } | ||
37 | + ], | ||
38 | + "configuration_version": "1" | ||
39 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
... | @@ -15,7 +15,6 @@ | ... | @@ -15,7 +15,6 @@ |
15 | <application | 15 | <application |
16 | android:name="io.flutter.app.FlutterApplication" | 16 | android:name="io.flutter.app.FlutterApplication" |
17 | android:label="Smart_Medicine_Box" | 17 | android:label="Smart_Medicine_Box" |
18 | - android:requestLegacyExternalStorage="true" | ||
19 | android:icon="@mipmap/ic_launcher"> | 18 | android:icon="@mipmap/ic_launcher"> |
20 | <activity | 19 | <activity |
21 | android:name=".MainActivity" | 20 | android:name=".MainActivity" | ... | ... |
... | @@ -8,6 +8,7 @@ buildscript { | ... | @@ -8,6 +8,7 @@ buildscript { |
8 | dependencies { | 8 | dependencies { |
9 | classpath 'com.android.tools.build:gradle:3.5.0' | 9 | classpath 'com.android.tools.build:gradle:3.5.0' |
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" | 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" |
11 | + classpath 'com.google.gms:google-services:4.3.10' | ||
11 | } | 12 | } |
12 | } | 13 | } |
13 | 14 | ... | ... |
1 | +// Copyright (c) 2018, codegrue. All rights reserved. Use of this source code | ||
2 | +// is governed by the MIT license that can be found in the LICENSE file. | ||
3 | + | ||
4 | +import '../flutter_material_pickers.dart'; | ||
5 | +import 'package:flutter/material.dart'; | ||
6 | +import '../interfaces/common_dialog_properties.dart'; | ||
7 | + | ||
8 | +// copied from flutter calendar picker | ||
9 | +const Duration _dialogSizeAnimationDuration = Duration(milliseconds: 200); | ||
10 | + | ||
11 | +/// This is a support widget that returns an Dialog with checkboxes as a Widget. | ||
12 | +/// It is designed to be used in the showDialog method of other fields. | ||
13 | +class ResponsiveDialog extends StatefulWidget | ||
14 | + implements ICommonDialogProperties { | ||
15 | + ResponsiveDialog({ | ||
16 | + this.context, | ||
17 | + String title, | ||
18 | + Widget child, | ||
19 | + this.headerColor, | ||
20 | + this.headerTextColor, | ||
21 | + this.backgroundColor, | ||
22 | + this.buttonTextColor, | ||
23 | + this.forcePortrait = false, | ||
24 | + double maxLongSide, | ||
25 | + double maxShortSide, | ||
26 | + this.hideButtons = false, | ||
27 | + this.okPressed, | ||
28 | + this.cancelPressed, | ||
29 | + this.confirmText, | ||
30 | + this.cancelText, | ||
31 | + }) : title = title ?? "Title Here", | ||
32 | + child = child ?? Text("Content Here"), | ||
33 | + maxLongSide = maxLongSide ?? 600, | ||
34 | + maxShortSide = maxShortSide ?? 400; | ||
35 | + | ||
36 | + // Variables | ||
37 | + final BuildContext context; | ||
38 | + @override | ||
39 | + final String title; | ||
40 | + final Widget child; | ||
41 | + final bool forcePortrait; | ||
42 | + @override | ||
43 | + final Color headerColor; | ||
44 | + @override | ||
45 | + final Color headerTextColor; | ||
46 | + @override | ||
47 | + final Color backgroundColor; | ||
48 | + @override | ||
49 | + final Color buttonTextColor; | ||
50 | + @override | ||
51 | + final double maxLongSide; | ||
52 | + @override | ||
53 | + final double maxShortSide; | ||
54 | + final bool hideButtons; | ||
55 | + @override | ||
56 | + final String confirmText; | ||
57 | + @override | ||
58 | + final String cancelText; | ||
59 | + | ||
60 | + // Events | ||
61 | + final VoidCallback cancelPressed; | ||
62 | + final VoidCallback okPressed; | ||
63 | + | ||
64 | + @override | ||
65 | + _ResponsiveDialogState createState() => _ResponsiveDialogState(); | ||
66 | +} | ||
67 | + | ||
68 | +class _ResponsiveDialogState extends State<ResponsiveDialog> { | ||
69 | + Color _headerColor; | ||
70 | + Color _headerTextColor; | ||
71 | + Color _backgroundColor; | ||
72 | + Color _buttonTextColor; | ||
73 | + | ||
74 | + Widget header(BuildContext context, Orientation orientation) { | ||
75 | + return Container( | ||
76 | + color: _headerColor, | ||
77 | + height: (orientation == Orientation.portrait) | ||
78 | + ? kPickerHeaderPortraitHeight | ||
79 | + : null, | ||
80 | + width: (orientation == Orientation.landscape) | ||
81 | + ? kPickerHeaderLandscapeWidth | ||
82 | + : null, | ||
83 | + child: Center( | ||
84 | + child: Text( | ||
85 | + widget.title, | ||
86 | + style: TextStyle( | ||
87 | + color: _headerTextColor, | ||
88 | + fontSize: 23, | ||
89 | + fontFamily: 'Noto', | ||
90 | + fontWeight: FontWeight.bold), | ||
91 | + ), | ||
92 | + ), | ||
93 | + padding: EdgeInsets.all(20.0), | ||
94 | + ); | ||
95 | + } | ||
96 | + | ||
97 | + Widget actionBar(BuildContext context) { | ||
98 | + if (widget.hideButtons) return Container(); | ||
99 | + | ||
100 | + var localizations = MaterialLocalizations.of(context); | ||
101 | + | ||
102 | + return Container( | ||
103 | + height: kDialogActionBarHeight, | ||
104 | + child: Container( | ||
105 | + decoration: BoxDecoration( | ||
106 | + border: Border( | ||
107 | + top: BorderSide(width: 1.0, color: _headerColor), | ||
108 | + ), | ||
109 | + ), | ||
110 | + child: ButtonBar( | ||
111 | + children: <Widget>[ | ||
112 | + FlatButton( | ||
113 | + textColor: _buttonTextColor, | ||
114 | + child: Text('취소'), | ||
115 | + onPressed: () => (widget.cancelPressed == null) | ||
116 | + ? Navigator.of(context).pop() | ||
117 | + : widget.cancelPressed(), | ||
118 | + ), | ||
119 | + FlatButton( | ||
120 | + textColor: _buttonTextColor, | ||
121 | + child: Text('확인'), | ||
122 | + onPressed: () => (widget.okPressed == null) | ||
123 | + ? Navigator.of(context).pop() | ||
124 | + : widget.okPressed(), | ||
125 | + ), | ||
126 | + ], | ||
127 | + ), | ||
128 | + ), | ||
129 | + ); | ||
130 | + } | ||
131 | + | ||
132 | + @override | ||
133 | + Widget build(BuildContext context) { | ||
134 | + assert(context != null); | ||
135 | + | ||
136 | + var theme = Theme.of(context); | ||
137 | + _headerColor = widget.headerColor ?? theme.primaryColor; | ||
138 | + _headerTextColor = | ||
139 | + widget.headerTextColor ?? theme.primaryTextTheme.headline6.color; | ||
140 | + _buttonTextColor = widget.buttonTextColor ?? theme.textTheme.button.color; | ||
141 | + _backgroundColor = widget.backgroundColor ?? theme.dialogBackgroundColor; | ||
142 | + | ||
143 | + final Orientation orientation = MediaQuery.of(context).orientation; | ||
144 | + | ||
145 | + // constrain the dialog from expanding to full screen | ||
146 | + final Size dialogSize = (orientation == Orientation.portrait) | ||
147 | + ? Size(widget.maxShortSide, widget.maxLongSide) | ||
148 | + : Size(widget.maxLongSide, widget.maxShortSide); | ||
149 | + | ||
150 | + return Dialog( | ||
151 | + backgroundColor: _backgroundColor, | ||
152 | + child: AnimatedContainer( | ||
153 | + width: dialogSize.width, | ||
154 | + height: dialogSize.height * 0.8, | ||
155 | + duration: _dialogSizeAnimationDuration, | ||
156 | + child: OrientationBuilder( | ||
157 | + builder: (BuildContext context, Orientation orientation) { | ||
158 | + assert(orientation != null); | ||
159 | + assert(context != null); | ||
160 | + | ||
161 | + if (widget.forcePortrait) orientation = Orientation.portrait; | ||
162 | + | ||
163 | + switch (orientation) { | ||
164 | + case Orientation.portrait: | ||
165 | + return Column( | ||
166 | + children: <Widget>[ | ||
167 | + header(context, orientation), | ||
168 | + Expanded( | ||
169 | + child: Container( | ||
170 | + child: widget.child, | ||
171 | + ), | ||
172 | + ), | ||
173 | + actionBar(context), | ||
174 | + ], | ||
175 | + ); | ||
176 | + case Orientation.landscape: | ||
177 | + return Row( | ||
178 | + children: <Widget>[ | ||
179 | + header(context, orientation), | ||
180 | + Expanded( | ||
181 | + child: Column( | ||
182 | + children: <Widget>[ | ||
183 | + Expanded( | ||
184 | + child: widget.child, | ||
185 | + ), | ||
186 | + actionBar(context), | ||
187 | + ], | ||
188 | + ), | ||
189 | + ), | ||
190 | + ], | ||
191 | + ); | ||
192 | + } | ||
193 | + return null; | ||
194 | + }, | ||
195 | + ), | ||
196 | + ), | ||
197 | + ); | ||
198 | + } | ||
199 | +} |
1 | +// Copyright (c) 2018, codegrue. All rights reserved. Use of this source code | ||
2 | +// is governed by the MIT license that can be found in the LICENSE file. | ||
3 | + | ||
4 | +import 'package:flutter/material.dart'; | ||
5 | +import '../pickers/scroll_picker.dart'; | ||
6 | + | ||
7 | +import 'responsive_dialog.dart'; | ||
8 | +import '../interfaces/common_dialog_properties.dart'; | ||
9 | + | ||
10 | +/// This is a support widget that returns an Dialog with checkboxes as a Widget. | ||
11 | +/// It is designed to be used in the showDialog method of other fields. | ||
12 | +class ScrollPickerDialog extends StatefulWidget | ||
13 | + implements ICommonDialogProperties { | ||
14 | + ScrollPickerDialog({ | ||
15 | + this.title, | ||
16 | + this.items, | ||
17 | + this.initialItem, | ||
18 | + this.headerColor, | ||
19 | + this.headerTextColor, | ||
20 | + this.backgroundColor, | ||
21 | + this.buttonTextColor, | ||
22 | + this.maxLongSide, | ||
23 | + this.maxShortSide, | ||
24 | + this.confirmText, | ||
25 | + this.cancelText, | ||
26 | + }); | ||
27 | + | ||
28 | + // Variables | ||
29 | + final List<String> items; | ||
30 | + final String initialItem; | ||
31 | + @override | ||
32 | + final String title; | ||
33 | + @override | ||
34 | + final Color headerColor; | ||
35 | + @override | ||
36 | + final Color headerTextColor; | ||
37 | + @override | ||
38 | + final Color backgroundColor; | ||
39 | + @override | ||
40 | + final Color buttonTextColor; | ||
41 | + @override | ||
42 | + final double maxLongSide; | ||
43 | + @override | ||
44 | + final double maxShortSide; | ||
45 | + @override | ||
46 | + final String confirmText; | ||
47 | + @override | ||
48 | + final String cancelText; | ||
49 | + | ||
50 | + @override | ||
51 | + State<ScrollPickerDialog> createState() => | ||
52 | + _ScrollPickerDialogState(initialItem); | ||
53 | +} | ||
54 | + | ||
55 | +class _ScrollPickerDialogState extends State<ScrollPickerDialog> { | ||
56 | + _ScrollPickerDialogState(this.selectedItem); | ||
57 | + | ||
58 | + String selectedItem; | ||
59 | + | ||
60 | + @override | ||
61 | + Widget build(BuildContext context) { | ||
62 | + assert(context != null); | ||
63 | + | ||
64 | + return ResponsiveDialog( | ||
65 | + context: context, | ||
66 | + title: widget.title, | ||
67 | + headerColor: widget.headerColor, | ||
68 | + headerTextColor: widget.headerTextColor, | ||
69 | + backgroundColor: widget.backgroundColor, | ||
70 | + buttonTextColor: widget.buttonTextColor, | ||
71 | + maxLongSide: widget.maxLongSide, | ||
72 | + maxShortSide: widget.maxLongSide, | ||
73 | + confirmText: widget.confirmText, | ||
74 | + cancelText: widget.cancelText, | ||
75 | + child: ScrollPicker( | ||
76 | + items: widget.items, | ||
77 | + initialValue: selectedItem, | ||
78 | + onChanged: (value) => setState(() => selectedItem = value), | ||
79 | + ), | ||
80 | + okPressed: () => Navigator.of(context).pop(selectedItem), | ||
81 | + ); | ||
82 | + } | ||
83 | +} |
1 | +// Copyright (c) 2018, codegrue. All rights reserved. Use of this source code | ||
2 | +// is governed by the MIT license that can be found in the LICENSE file. | ||
3 | + | ||
4 | +/// Package for building card based settings forms | ||
5 | +library flutter_material_pickers; | ||
6 | + | ||
7 | +/// Helpers | ||
8 | + | ||
9 | +export 'package:Smart_Medicine_Box/helpers/show_scroll_picker.dart'; | ||
10 | + | ||
11 | +// Constants | ||
12 | +const double kPickerHeaderPortraitHeight = 80.0; | ||
13 | +const double kPickerHeaderLandscapeWidth = 168.0; | ||
14 | +const double kDialogActionBarHeight = 52.0; | ||
15 | +const double kDialogMargin = 30.0; |
1 | +// Copyright (c) 2018, codegrue. All rights reserved. Use of this source code | ||
2 | +// is governed by the MIT license that can be found in the LICENSE file. | ||
3 | + | ||
4 | +import 'package:flutter/material.dart'; | ||
5 | +import '../dialogs/scroll_picker_dialog.dart'; | ||
6 | + | ||
7 | +/// Allows selection of a string via a slot machine carousel | ||
8 | +void showMaterialScrollPicker({ | ||
9 | + BuildContext context, | ||
10 | + String title, | ||
11 | + List<String> items, | ||
12 | + String selectedItem, | ||
13 | + Color headerColor, | ||
14 | + Color headerTextColor, | ||
15 | + Color backgroundColor, | ||
16 | + Color buttonTextColor, | ||
17 | + String confirmText, | ||
18 | + String cancelText, | ||
19 | + double maxLongSide, | ||
20 | + double maxShortSide, | ||
21 | + ValueChanged<String> onChanged, | ||
22 | + VoidCallback onConfirmed, | ||
23 | + VoidCallback onCancelled, | ||
24 | +}) { | ||
25 | + showDialog<String>( | ||
26 | + context: context, | ||
27 | + builder: (BuildContext context) { | ||
28 | + return ScrollPickerDialog( | ||
29 | + items: items, | ||
30 | + title: title, | ||
31 | + initialItem: selectedItem, | ||
32 | + headerColor: headerColor, | ||
33 | + headerTextColor: headerTextColor, | ||
34 | + backgroundColor: backgroundColor, | ||
35 | + buttonTextColor: buttonTextColor, | ||
36 | + confirmText: confirmText, | ||
37 | + cancelText: cancelText, | ||
38 | + maxLongSide: maxLongSide, | ||
39 | + maxShortSide: maxLongSide, | ||
40 | + ); | ||
41 | + }, | ||
42 | + ).then((selection) { | ||
43 | + if (onChanged != null && selection != null) onChanged(selection); | ||
44 | + if (onCancelled != null && selection == null) onCancelled(); | ||
45 | + if (onConfirmed != null && selection != null) onConfirmed(); | ||
46 | + }); | ||
47 | +} |
1 | +import 'package:flutter/material.dart'; | ||
2 | + | ||
3 | +abstract class ICommonDialogProperties { | ||
4 | + final String title = null; | ||
5 | + final Color headerColor = null; | ||
6 | + final Color headerTextColor = null; | ||
7 | + final Color backgroundColor = null; | ||
8 | + final Color buttonTextColor = null; | ||
9 | + final double maxLongSide = null; | ||
10 | + final double maxShortSide = null; | ||
11 | + final String confirmText = null; | ||
12 | + final String cancelText = null; | ||
13 | +} |
1 | +// Copyright (c) 2018, codegrue. All rights reserved. Use of this source code | ||
2 | +// is governed by the MIT license that can be found in the LICENSE file. | ||
3 | + | ||
4 | +import 'package:flutter/material.dart'; | ||
5 | +import 'package:flutter/rendering.dart'; | ||
6 | + | ||
7 | +/// This helper widget manages the scrollable content inside a picker widget. | ||
8 | +class ScrollPicker extends StatefulWidget { | ||
9 | + ScrollPicker({ | ||
10 | + Key key, | ||
11 | + @required this.items, | ||
12 | + @required this.initialValue, | ||
13 | + @required this.onChanged, | ||
14 | + }) : assert(items != null), | ||
15 | + super(key: key); | ||
16 | + | ||
17 | + // Events | ||
18 | + final ValueChanged<String> onChanged; | ||
19 | + | ||
20 | + // Variables | ||
21 | + final List<String> items; | ||
22 | + final String initialValue; | ||
23 | + | ||
24 | + @override | ||
25 | + _ScrollPickerState createState() => _ScrollPickerState(initialValue); | ||
26 | +} | ||
27 | + | ||
28 | +class _ScrollPickerState extends State<ScrollPicker> { | ||
29 | + _ScrollPickerState(this.selectedValue); | ||
30 | + | ||
31 | + // Constants | ||
32 | + static const double itemHeight = 50.0; | ||
33 | + | ||
34 | + // Variables | ||
35 | + double widgetHeight; | ||
36 | + int numberOfVisibleItems; | ||
37 | + int numberOfPaddingRows; | ||
38 | + double visibleItemsHeight; | ||
39 | + double offset; | ||
40 | + | ||
41 | + String selectedValue; | ||
42 | + | ||
43 | + ScrollController scrollController; | ||
44 | + | ||
45 | + @override | ||
46 | + void initState() { | ||
47 | + super.initState(); | ||
48 | + | ||
49 | + int initialItem = widget.items.indexOf(selectedValue); | ||
50 | + scrollController = FixedExtentScrollController(initialItem: initialItem); | ||
51 | + } | ||
52 | + | ||
53 | + @override | ||
54 | + Widget build(BuildContext context) { | ||
55 | + final ThemeData themeData = Theme.of(context); | ||
56 | + TextStyle defaultStyle = themeData.textTheme.bodyText2; | ||
57 | + TextStyle selectedStyle = | ||
58 | + themeData.textTheme.headline5.copyWith(color: themeData.accentColor); | ||
59 | + | ||
60 | + return LayoutBuilder( | ||
61 | + builder: (BuildContext context, BoxConstraints constraints) { | ||
62 | + widgetHeight = constraints.maxHeight; | ||
63 | + | ||
64 | + return Stack( | ||
65 | + children: <Widget>[ | ||
66 | + GestureDetector( | ||
67 | + onTapUp: _itemTapped, | ||
68 | + child: ListWheelScrollView.useDelegate( | ||
69 | + childDelegate: ListWheelChildBuilderDelegate( | ||
70 | + builder: (BuildContext context, int index) { | ||
71 | + if (index < 0 || index > widget.items.length - 1) { | ||
72 | + return null; | ||
73 | + } | ||
74 | + | ||
75 | + var value = widget.items[index]; | ||
76 | + | ||
77 | + final TextStyle itemStyle = | ||
78 | + (value == selectedValue) ? selectedStyle : defaultStyle; | ||
79 | + | ||
80 | + return Center( | ||
81 | + child: Text(value, style: itemStyle), | ||
82 | + ); | ||
83 | + }), | ||
84 | + controller: scrollController, | ||
85 | + itemExtent: itemHeight, | ||
86 | + onSelectedItemChanged: _onSelectedItemChanged, | ||
87 | + physics: FixedExtentScrollPhysics(), | ||
88 | + ), | ||
89 | + ), | ||
90 | + Center(child: Divider()), | ||
91 | + Center( | ||
92 | + child: Container( | ||
93 | + height: itemHeight, | ||
94 | + decoration: BoxDecoration( | ||
95 | + border: Border( | ||
96 | + top: BorderSide(color: themeData.accentColor, width: 1.0), | ||
97 | + bottom: | ||
98 | + BorderSide(color: themeData.accentColor, width: 1.0), | ||
99 | + ), | ||
100 | + ), | ||
101 | + ), | ||
102 | + ) | ||
103 | + ], | ||
104 | + ); | ||
105 | + }, | ||
106 | + ); | ||
107 | + } | ||
108 | + | ||
109 | + void _itemTapped(TapUpDetails details) { | ||
110 | + Offset position = details.localPosition; | ||
111 | + double center = widgetHeight / 2; | ||
112 | + double changeBy = position.dy - center; | ||
113 | + double newPosition = scrollController.offset + changeBy; | ||
114 | + | ||
115 | + // animate to and center on the selected item | ||
116 | + scrollController.animateTo(newPosition, | ||
117 | + duration: Duration(milliseconds: 500), curve: Curves.easeInOut); | ||
118 | + } | ||
119 | + | ||
120 | + void _onSelectedItemChanged(int index) { | ||
121 | + String newValue = widget.items[index]; | ||
122 | + if (newValue != selectedValue) { | ||
123 | + selectedValue = newValue; | ||
124 | + widget.onChanged(newValue); | ||
125 | + } | ||
126 | + } | ||
127 | +} |
... | @@ -10,7 +10,7 @@ import 'models/Medicine.dart'; | ... | @@ -10,7 +10,7 @@ import 'models/Medicine.dart'; |
10 | import 'package:Smart_Medicine_Box/src/screens/SettingPage.dart'; | 10 | import 'package:Smart_Medicine_Box/src/screens/SettingPage.dart'; |
11 | import 'BottleList.dart'; | 11 | import 'BottleList.dart'; |
12 | import 'MainPage.dart'; | 12 | import 'MainPage.dart'; |
13 | -import 'Register/SearchMedicine.dart'; | 13 | +import 'FeedBack.dart'; |
14 | 14 | ||
15 | class DashBoard extends StatefulWidget { | 15 | class DashBoard extends StatefulWidget { |
16 | int pageNumber; | 16 | int pageNumber; |
... | @@ -60,7 +60,7 @@ class _DashBoardState extends State<DashBoard> { | ... | @@ -60,7 +60,7 @@ class _DashBoardState extends State<DashBoard> { |
60 | var _tabs = [ | 60 | var _tabs = [ |
61 | ineerInformationpage(context), | 61 | ineerInformationpage(context), |
62 | MainPage(), | 62 | MainPage(), |
63 | - feedBackPage(context), | 63 | + FeedbackPage(), |
64 | ]; | 64 | ]; |
65 | 65 | ||
66 | return WillPopScope( | 66 | return WillPopScope( |
... | @@ -502,149 +502,3 @@ Widget ineerInformationpage(BuildContext context) { | ... | @@ -502,149 +502,3 @@ Widget ineerInformationpage(BuildContext context) { |
502 | ), | 502 | ), |
503 | ); | 503 | ); |
504 | } | 504 | } |
505 | - | ||
506 | -Widget feedBackPage(BuildContext context) { | ||
507 | - Bottle _bottleinformation = new Bottle(); | ||
508 | - //get bottle | ||
509 | - Future<Bottle> _getbottle() async { | ||
510 | - String usertoken = await UserSecureStorage.getUserToken(); | ||
511 | - String bottleid = await UserSecureStorage.getBottleId(); | ||
512 | - Bottle _bottleinformation = new Bottle(); | ||
513 | - http.Response response = await http.get( | ||
514 | - Uri.encodeFull(DotEnv().env['SERVER_URL'] + 'bottle/' + bottleid), | ||
515 | - headers: {"authorization": usertoken}); | ||
516 | - | ||
517 | - if (response.statusCode == 200) { | ||
518 | - Map<String, dynamic> jsonData = jsonDecode(response.body); | ||
519 | - | ||
520 | - _bottleinformation = Bottle.fromJson(jsonData); | ||
521 | - } | ||
522 | - return _bottleinformation; | ||
523 | - } | ||
524 | - | ||
525 | - final Size size = MediaQuery.of(context).size; | ||
526 | - return Scaffold( | ||
527 | - backgroundColor: Colors.white, | ||
528 | - body: FutureBuilder( | ||
529 | - future: _getbottle(), | ||
530 | - builder: (BuildContext context, AsyncSnapshot snapshot) { | ||
531 | - if (snapshot.hasData == false) { | ||
532 | - return CircularProgressIndicator(); | ||
533 | - } else if (snapshot.hasError) { | ||
534 | - return Padding( | ||
535 | - padding: const EdgeInsets.all(8.0), | ||
536 | - child: Text( | ||
537 | - 'Error: ${snapshot.error}', | ||
538 | - style: TextStyle(fontSize: 15), | ||
539 | - ), | ||
540 | - ); | ||
541 | - } else { | ||
542 | - return Container( | ||
543 | - height: size.height * 0.9, | ||
544 | - margin: EdgeInsets.fromLTRB(0, 30, 0, 0), | ||
545 | - padding: EdgeInsets.fromLTRB(5, 0, 5, 5), | ||
546 | - child: Column( | ||
547 | - crossAxisAlignment: CrossAxisAlignment.center, | ||
548 | - children: <Widget>[ | ||
549 | - Container( | ||
550 | - padding: EdgeInsets.fromLTRB(5, 5, 5, 5), | ||
551 | - height: size.height * 0.08, | ||
552 | - width: size.width, | ||
553 | - child: Center( | ||
554 | - child: Text( | ||
555 | - 'Outside Information', | ||
556 | - textAlign: TextAlign.center, | ||
557 | - textScaleFactor: 1.0, | ||
558 | - style: TextStyle( | ||
559 | - color: Colors.black, | ||
560 | - fontSize: 32, | ||
561 | - fontFamily: 'NotoSansKR', | ||
562 | - fontWeight: FontWeight.w700), | ||
563 | - ), | ||
564 | - ), | ||
565 | - ), | ||
566 | - Container( | ||
567 | - padding: EdgeInsets.fromLTRB(5, 0, 5, 5), | ||
568 | - margin: EdgeInsets.fromLTRB(0, 10, 0, 0), | ||
569 | - height: size.height * 0.20, | ||
570 | - width: size.width, | ||
571 | - child: Column( | ||
572 | - children: <Widget>[ | ||
573 | - Flexible( | ||
574 | - child: Column( | ||
575 | - mainAxisAlignment: MainAxisAlignment.center, | ||
576 | - children: <Widget>[ | ||
577 | - Container( | ||
578 | - padding: EdgeInsets.fromLTRB(5, 5, 5, 0), | ||
579 | - width: size.width * 0.9, | ||
580 | - height: size.height * 0.18, | ||
581 | - decoration: BoxDecoration( | ||
582 | - color: Color(0xff8E97FD), | ||
583 | - borderRadius: BorderRadius.circular(10.0), | ||
584 | - ), | ||
585 | - child: Column( | ||
586 | - children: [ | ||
587 | - Container( | ||
588 | - width: size.width, | ||
589 | - height: size.height * 0.05, | ||
590 | - child: Center( | ||
591 | - child: Text( | ||
592 | - '권장 약 복용량', | ||
593 | - textAlign: TextAlign.center, | ||
594 | - textScaleFactor: 1.0, | ||
595 | - style: TextStyle( | ||
596 | - color: Colors.white, | ||
597 | - fontSize: 28, | ||
598 | - fontFamily: 'NotoSansKR', | ||
599 | - fontWeight: FontWeight.w800), | ||
600 | - ), | ||
601 | - ), | ||
602 | - ), | ||
603 | - Container( | ||
604 | - width: size.width, | ||
605 | - height: size.height * 0.12, | ||
606 | - child: Row( | ||
607 | - mainAxisAlignment: | ||
608 | - MainAxisAlignment.center, | ||
609 | - children: [ | ||
610 | - Text( | ||
611 | - snapshot.data.dosage == null | ||
612 | - ? '-' | ||
613 | - : snapshot.data.dosage | ||
614 | - .toString(), | ||
615 | - textAlign: TextAlign.center, | ||
616 | - textScaleFactor: 1.0, | ||
617 | - style: TextStyle( | ||
618 | - color: Colors.white, | ||
619 | - fontSize: 80, | ||
620 | - fontFamily: 'NotoSansKR', | ||
621 | - fontWeight: FontWeight.w800), | ||
622 | - ), | ||
623 | - Text( | ||
624 | - ' 개', | ||
625 | - textScaleFactor: 1.0, | ||
626 | - style: TextStyle( | ||
627 | - color: Colors.white, | ||
628 | - fontSize: 64, | ||
629 | - fontFamily: 'NotoSansKR', | ||
630 | - fontWeight: FontWeight.w800), | ||
631 | - ) | ||
632 | - ], | ||
633 | - ), | ||
634 | - ), | ||
635 | - ], | ||
636 | - ), | ||
637 | - ), | ||
638 | - ], | ||
639 | - ), | ||
640 | - ), | ||
641 | - ], | ||
642 | - ), | ||
643 | - ), | ||
644 | - ], | ||
645 | - ), | ||
646 | - ); | ||
647 | - } | ||
648 | - }), | ||
649 | - ); | ||
650 | -} | ... | ... |
1 | +import 'package:flutter/material.dart'; | ||
2 | +import '../utils/user_secure_stoarge.dart'; | ||
3 | + | ||
4 | +import 'models/Medicine.dart'; | ||
5 | +import 'dart:convert'; | ||
6 | +import 'package:http/http.dart' as http; | ||
7 | +import 'package:flutter_dotenv/flutter_dotenv.dart'; | ||
8 | +import './models/Doctor.dart'; | ||
9 | +import './models/BottleMedicine.dart'; | ||
10 | + | ||
11 | +class FeedbackPage extends StatefulWidget { | ||
12 | + @override | ||
13 | + _FeedbackPageState createState() => _FeedbackPageState(); | ||
14 | +} | ||
15 | + | ||
16 | +class _FeedbackPageState extends State<FeedbackPage> { | ||
17 | + Widget build(BuildContext context) { | ||
18 | + Medicine _medicineInformation = new Medicine(); | ||
19 | + | ||
20 | + List<Doctor> _doctorlist = new List<Doctor>(); | ||
21 | + List<int> _hublist = new List<int>(); | ||
22 | + | ||
23 | + Future<String> getHubList() async { | ||
24 | + String usertoken = await UserSecureStorage.getUserToken(); | ||
25 | + http.Response response = await http.get( | ||
26 | + Uri.encodeFull(DotEnv().env['SERVER_URL'] + 'hub'), | ||
27 | + headers: {"authorization": usertoken}, | ||
28 | + ); | ||
29 | + List<dynamic> values = new List<dynamic>(); | ||
30 | + if (_hublist.length != 0) { | ||
31 | + _hublist.clear(); | ||
32 | + } | ||
33 | + if (response.statusCode == 200) { | ||
34 | + values = json.decode(response.body); | ||
35 | + for (int i = 0; i < values.length; i++) { | ||
36 | + _hublist.add(values[i]['hubId']); | ||
37 | + } | ||
38 | + return "get완료"; | ||
39 | + } else if (response.statusCode == 404) { | ||
40 | + return "Not Found"; | ||
41 | + } else { | ||
42 | + return "Error"; | ||
43 | + } | ||
44 | + } | ||
45 | + | ||
46 | + final Size size = MediaQuery.of(context).size; | ||
47 | + return Scaffold( | ||
48 | + backgroundColor: Colors.white, | ||
49 | + body: FutureBuilder( | ||
50 | + future: getHubList(), | ||
51 | + builder: (BuildContext context, AsyncSnapshot snapshot) { | ||
52 | + if (snapshot.hasData == false) { | ||
53 | + return CircularProgressIndicator(); | ||
54 | + } else if (snapshot.hasError) { | ||
55 | + return Padding( | ||
56 | + padding: const EdgeInsets.all(8.0), | ||
57 | + child: Text( | ||
58 | + 'Error: ${snapshot.error}', | ||
59 | + style: TextStyle(fontSize: 15), | ||
60 | + ), | ||
61 | + ); | ||
62 | + } else { | ||
63 | + return Container( | ||
64 | + height: size.height * 0.9, | ||
65 | + margin: EdgeInsets.fromLTRB(0, 30, 0, 0), | ||
66 | + padding: EdgeInsets.fromLTRB(5, 0, 5, 5), | ||
67 | + child: Column( | ||
68 | + crossAxisAlignment: CrossAxisAlignment.center, | ||
69 | + children: <Widget>[ | ||
70 | + Container( | ||
71 | + width: size.width * 0.81, | ||
72 | + height: size.height * 0.1, | ||
73 | + decoration: BoxDecoration(border: Border.all()), | ||
74 | + child: Row( | ||
75 | + children: [ | ||
76 | + Container( | ||
77 | + padding: const EdgeInsets.fromLTRB(10, 5, 10, 10), | ||
78 | + width: size.width * 0.2, | ||
79 | + decoration: BoxDecoration( | ||
80 | + border: Border( | ||
81 | + right: BorderSide(color: Colors.black))), | ||
82 | + child: Column( | ||
83 | + children: [ | ||
84 | + Container( | ||
85 | + child: Icon( | ||
86 | + Icons.circle, | ||
87 | + color: Colors.blue, | ||
88 | + ), | ||
89 | + ), | ||
90 | + SizedBox(height: 1), | ||
91 | + Container( | ||
92 | + child: Text('권고', | ||
93 | + style: TextStyle( | ||
94 | + color: Colors.black, | ||
95 | + fontSize: 16, | ||
96 | + fontFamily: 'Noto', | ||
97 | + fontWeight: FontWeight.bold))) | ||
98 | + ], | ||
99 | + ), | ||
100 | + ), | ||
101 | + Container( | ||
102 | + padding: const EdgeInsets.fromLTRB(10, 5, 10, 10), | ||
103 | + width: size.width * 0.2, | ||
104 | + decoration: BoxDecoration( | ||
105 | + border: Border( | ||
106 | + right: BorderSide(color: Colors.black))), | ||
107 | + child: Column( | ||
108 | + children: [ | ||
109 | + Container( | ||
110 | + child: Icon( | ||
111 | + Icons.circle, | ||
112 | + color: Colors.orange, | ||
113 | + ), | ||
114 | + ), | ||
115 | + SizedBox(height: 1), | ||
116 | + Container( | ||
117 | + child: Text('주의', | ||
118 | + style: TextStyle( | ||
119 | + color: Colors.black, | ||
120 | + fontSize: 16, | ||
121 | + fontFamily: 'Noto', | ||
122 | + fontWeight: FontWeight.bold))) | ||
123 | + ], | ||
124 | + ), | ||
125 | + ), | ||
126 | + Container( | ||
127 | + padding: const EdgeInsets.fromLTRB(10, 5, 10, 10), | ||
128 | + width: size.width * 0.2, | ||
129 | + decoration: BoxDecoration( | ||
130 | + border: Border( | ||
131 | + right: BorderSide(color: Colors.black))), | ||
132 | + child: Column( | ||
133 | + children: [ | ||
134 | + Container( | ||
135 | + child: Icon( | ||
136 | + Icons.circle, | ||
137 | + color: Colors.red, | ||
138 | + ), | ||
139 | + ), | ||
140 | + SizedBox(height: 1), | ||
141 | + Container( | ||
142 | + child: Text('경고', | ||
143 | + style: TextStyle( | ||
144 | + color: Colors.black, | ||
145 | + fontSize: 16, | ||
146 | + fontFamily: 'Noto', | ||
147 | + fontWeight: FontWeight.bold))) | ||
148 | + ], | ||
149 | + ), | ||
150 | + ), | ||
151 | + Container( | ||
152 | + padding: const EdgeInsets.fromLTRB(10, 5, 10, 10), | ||
153 | + width: size.width * 0.2, | ||
154 | + child: Column( | ||
155 | + children: [ | ||
156 | + Container( | ||
157 | + child: Icon( | ||
158 | + Icons.circle, | ||
159 | + color: Colors.black, | ||
160 | + ), | ||
161 | + ), | ||
162 | + SizedBox(height: 1), | ||
163 | + Container( | ||
164 | + child: Text('치명', | ||
165 | + style: TextStyle( | ||
166 | + color: Colors.black, | ||
167 | + fontSize: 16, | ||
168 | + fontFamily: 'Noto', | ||
169 | + fontWeight: FontWeight.bold))) | ||
170 | + ], | ||
171 | + ), | ||
172 | + ), | ||
173 | + ], | ||
174 | + ), | ||
175 | + ), | ||
176 | + SizedBox(height: 20), | ||
177 | + Expanded( | ||
178 | + child: ListView.separated( | ||
179 | + padding: const EdgeInsets.all(20), | ||
180 | + itemCount: _hublist.length, | ||
181 | + itemBuilder: (BuildContext context, int index) { | ||
182 | + return Container( | ||
183 | + padding: EdgeInsets.all(3.0), | ||
184 | + decoration: BoxDecoration( | ||
185 | + border: Border.all(), | ||
186 | + borderRadius: | ||
187 | + BorderRadius.all(Radius.circular(20.0)), | ||
188 | + ), | ||
189 | + child: ListTile( | ||
190 | + title: Text( | ||
191 | + '담당의 : ' + '${_hublist[index]}', | ||
192 | + style: TextStyle( | ||
193 | + color: Colors.black, | ||
194 | + fontSize: 20, | ||
195 | + fontFamily: 'Noto', | ||
196 | + fontWeight: FontWeight.bold), | ||
197 | + ), | ||
198 | + trailing: Icon( | ||
199 | + Icons.circle, | ||
200 | + color: Colors.red, | ||
201 | + ), | ||
202 | + onTap: () async { | ||
203 | + showDialog( | ||
204 | + context: context, | ||
205 | + builder: (BuildContext context) { | ||
206 | + return AlertDialog( | ||
207 | + title: new Text('피드백 내용'), | ||
208 | + content: new Text('대충 피드백 내용'), | ||
209 | + actions: <Widget>[ | ||
210 | + new FlatButton( | ||
211 | + child: new Text('닫기'), | ||
212 | + onPressed: () { | ||
213 | + Navigator.of(context).pop(); | ||
214 | + }) | ||
215 | + ], | ||
216 | + ); | ||
217 | + }); | ||
218 | + }, | ||
219 | + ), | ||
220 | + ); | ||
221 | + }, | ||
222 | + separatorBuilder: (BuildContext contetx, int index) => | ||
223 | + const Divider(), | ||
224 | + ), | ||
225 | + ), | ||
226 | + ], | ||
227 | + ), | ||
228 | + ); | ||
229 | + } | ||
230 | + }), | ||
231 | + ); | ||
232 | + } | ||
233 | +} | ... | ... |
... | @@ -8,7 +8,7 @@ import '../utils/user_secure_stoarge.dart'; | ... | @@ -8,7 +8,7 @@ import '../utils/user_secure_stoarge.dart'; |
8 | import 'models/Medicine.dart'; | 8 | import 'models/Medicine.dart'; |
9 | 9 | ||
10 | import 'Register/SearchMedicine.dart'; | 10 | import 'Register/SearchMedicine.dart'; |
11 | -//import 'package:flutter_material_pickers/flutter_material_pickers.dart'; | 11 | +import '../../flutter_material_pickers.dart'; |
12 | 12 | ||
13 | class MainPage extends StatefulWidget { | 13 | class MainPage extends StatefulWidget { |
14 | @override | 14 | @override |
... | @@ -16,11 +16,11 @@ class MainPage extends StatefulWidget { | ... | @@ -16,11 +16,11 @@ class MainPage extends StatefulWidget { |
16 | } | 16 | } |
17 | 17 | ||
18 | class _MainPageState extends State<MainPage> { | 18 | class _MainPageState extends State<MainPage> { |
19 | + String _seletedDoctor = ''; | ||
19 | Widget build(BuildContext context) { | 20 | Widget build(BuildContext context) { |
20 | Medicine _medicineInformation = new Medicine(); | 21 | Medicine _medicineInformation = new Medicine(); |
21 | List<String> doctorlist = ['temp1', 'temp2', 'temp3', 'temp4']; | 22 | List<String> doctorlist = ['temp1', 'temp2', 'temp3', 'temp4']; |
22 | 23 | ||
23 | - String seletedDoctor = ''; | ||
24 | Future<Medicine> _getmedicine() async { | 24 | Future<Medicine> _getmedicine() async { |
25 | String usertoken = await UserSecureStorage.getUserToken(); | 25 | String usertoken = await UserSecureStorage.getUserToken(); |
26 | String medicineid = await UserSecureStorage.getMedicineId(); | 26 | String medicineid = await UserSecureStorage.getMedicineId(); |
... | @@ -106,7 +106,7 @@ class _MainPageState extends State<MainPage> { | ... | @@ -106,7 +106,7 @@ class _MainPageState extends State<MainPage> { |
106 | Text( | 106 | Text( |
107 | _medicineInformation.company == null | 107 | _medicineInformation.company == null |
108 | ? '-' | 108 | ? '-' |
109 | - : '대강 처방의 이름', | 109 | + : _seletedDoctor, |
110 | style: TextStyle( | 110 | style: TextStyle( |
111 | color: Colors.black, | 111 | color: Colors.black, |
112 | fontSize: 16, | 112 | fontSize: 16, |
... | @@ -272,14 +272,15 @@ class _MainPageState extends State<MainPage> { | ... | @@ -272,14 +272,15 @@ class _MainPageState extends State<MainPage> { |
272 | child: FlatButton( | 272 | child: FlatButton( |
273 | padding: EdgeInsets.fromLTRB(0, 5, 0, 5), | 273 | padding: EdgeInsets.fromLTRB(0, 5, 0, 5), |
274 | onPressed: () async { | 274 | onPressed: () async { |
275 | - /*showMaterialScrollPicker( | 275 | + await showMaterialScrollPicker( |
276 | context: context, | 276 | context: context, |
277 | title: '처방의', | 277 | title: '처방의', |
278 | items: doctorlist, | 278 | items: doctorlist, |
279 | - selectedItem: seletedDoctor, | 279 | + selectedItem: _seletedDoctor, |
280 | - onChanged: (value) => | 280 | + onChanged: (value) => setState(() { |
281 | - setState(() => seletedDoctor = value), | 281 | + _seletedDoctor = value; |
282 | - );*/ | 282 | + }), |
283 | + ); | ||
283 | }, | 284 | }, |
284 | child: Text( | 285 | child: Text( |
285 | '처방의 변경', | 286 | '처방의 변경', | ... | ... |
... | @@ -407,12 +407,9 @@ class _AlarmnState extends State<Alarm> { | ... | @@ -407,12 +407,9 @@ class _AlarmnState extends State<Alarm> { |
407 | times[index - 1] = timeString; | 407 | times[index - 1] = timeString; |
408 | timesHours[index - 1] = timeHour; | 408 | timesHours[index - 1] = timeHour; |
409 | timesMinutes[index - 1] = timesMinite; | 409 | timesMinutes[index - 1] = timesMinite; |
410 | - | ||
411 | _prefs.setString('time' + (saveIndex[index - 1]).toString(), | 410 | _prefs.setString('time' + (saveIndex[index - 1]).toString(), |
412 | savetimeStrings); | 411 | savetimeStrings); |
413 | - | ||
414 | print(savetimeStrings); | 412 | print(savetimeStrings); |
415 | - | ||
416 | setState(() { | 413 | setState(() { |
417 | savetimeStrings = savetimeStrings; | 414 | savetimeStrings = savetimeStrings; |
418 | }); | 415 | }); | ... | ... |
1 | +class BottleMedicine { | ||
2 | + int dosage; | ||
3 | + int bottleId; | ||
4 | + int medicineId; | ||
5 | + String doctorId; | ||
6 | + String doctorName; | ||
7 | + DateTime regDtm; | ||
8 | + | ||
9 | + BottleMedicine( | ||
10 | + {this.dosage, | ||
11 | + this.bottleId, | ||
12 | + this.medicineId, | ||
13 | + this.doctorId, | ||
14 | + this.doctorName, | ||
15 | + this.regDtm}); | ||
16 | + | ||
17 | + factory BottleMedicine.fromJson(Map<String, dynamic> parsedJson) { | ||
18 | + return BottleMedicine( | ||
19 | + dosage: parsedJson['dosage'], | ||
20 | + bottleId: parsedJson['bottleId'], | ||
21 | + medicineId: parsedJson['medicineId'], | ||
22 | + doctorId: parsedJson['doctorId'], | ||
23 | + regDtm: DateTime.parse(parsedJson['regDtm']).toLocal(), | ||
24 | + ); | ||
25 | + } | ||
26 | + | ||
27 | + Map<String, dynamic> toJson() => { | ||
28 | + "dosage": dosage, | ||
29 | + "bottleId": bottleId, | ||
30 | + "medicineId": medicineId, | ||
31 | + "doctorId": doctorId, | ||
32 | + "doctorName": doctorName, | ||
33 | + "regDtm": regDtm | ||
34 | + }; | ||
35 | +} |
1 | +import 'BottleMedicine.dart'; | ||
2 | + | ||
3 | +class Doctor { | ||
4 | + String fdbType; | ||
5 | + String doctorId; | ||
6 | + String feedback; | ||
7 | + DateTime fdbDtm; | ||
8 | + BottleMedicine bmId; | ||
9 | + | ||
10 | + Doctor({this.fdbType, this.doctorId, this.feedback, this.fdbDtm, this.bmId}); | ||
11 | + | ||
12 | + factory Doctor.fromJson(Map<String, dynamic> parsedJson) { | ||
13 | + var list = parsedJson['bmId'] as List; | ||
14 | + List<BottleMedicine> data = | ||
15 | + list.map((i) => BottleMedicine.fromJson(i)).toList(); | ||
16 | + | ||
17 | + return Doctor( | ||
18 | + fdbType: parsedJson['fdbType'], | ||
19 | + doctorId: parsedJson['doctorId'], | ||
20 | + feedback: parsedJson['feedback'], | ||
21 | + fdbDtm: DateTime.parse(parsedJson['fdbDtm']).toLocal(), | ||
22 | + bmId: data[0], | ||
23 | + ); | ||
24 | + } | ||
25 | +} |
File mode changed
-
Please register or login to post a comment