diff --git a/assets/images/ic_splash.svg b/assets/images/ic_splash.svg
new file mode 100644
index 0000000..d614fc8
--- /dev/null
+++ b/assets/images/ic_splash.svg
@@ -0,0 +1,7 @@
+
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 238dcf3..bafc646 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -32,4 +32,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796
-COCOAPODS: 1.16.2
+COCOAPODS: 1.15.2
diff --git a/lib/component/bottom_navigation_bar.dart b/lib/component/bottom_navigation_bar.dart
index 8c582d8..8c3ba06 100644
--- a/lib/component/bottom_navigation_bar.dart
+++ b/lib/component/bottom_navigation_bar.dart
@@ -48,13 +48,13 @@ class EasierDodamBottomNavigationBar extends StatelessWidget {
context,
icon: 'assets/images/ic_moon_plus.svg',
label: '심야자습',
- index: 3,
+ index: 2,
),
_buildNavItem(
context,
icon: 'assets/images/ic_gear.svg',
label: '설정',
- index: 2,
+ index: 3,
),
],
),
@@ -75,17 +75,14 @@ class EasierDodamBottomNavigationBar extends StatelessWidget {
icon,
height: isSelected ? 30 : 24,
width: isSelected ? 30 : 24,
- colorFilter: ColorFilter.mode(
- isSelected ? Colors.blue : Colors.grey,
- BlendMode.srcIn,
- ),
+ color: isSelected ? Colors.blue : Colors.grey,
),
const SizedBox(height: 4),
Text(
label,
style: TextStyle(
color: isSelected ? Colors.blue : Colors.grey,
- fontSize: isSelected ? 13 : 12,
+ fontSize: isSelected ? 14 : 12,
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
),
),
diff --git a/lib/component/modal_bottom_sheet_container.dart b/lib/component/modal_bottom_sheet_container.dart
index 90b9cf6..5ff9b80 100644
--- a/lib/component/modal_bottom_sheet_container.dart
+++ b/lib/component/modal_bottom_sheet_container.dart
@@ -1,5 +1,4 @@
import 'package:easier_dodam/component/theme/color.dart';
-import 'package:easier_dodam/component/theme/style.dart';
import 'package:flutter/material.dart';
class ModalBottomSheetContainer extends StatelessWidget {
diff --git a/lib/feature/logout/logout.dart b/lib/feature/logout/logout.dart
index e9de9e9..58e73cc 100644
--- a/lib/feature/logout/logout.dart
+++ b/lib/feature/logout/logout.dart
@@ -10,6 +10,7 @@ import '../../feature/out/out_navigation.dart';
import '../../feature/out_sleeping/out_sleeping_navigation.dart';
import '../logout/logout_viewmodel.dart';
import 'item/setting_item.dart';
+import 'logout_navigation.dart';
class SettingScreen extends StatefulWidget {
const SettingScreen({super.key});
@@ -33,9 +34,10 @@ class _SettingScreenState extends State {
Navigator.pushReplacementNamed(context, outRoute);
break;
case 2:
+ Navigator.pushReplacementNamed(context, nightStudyRoute);
break;
case 3:
- Navigator.pushReplacementNamed(context, nightStudyRoute);
+ Navigator.pushReplacementNamed(context, logoutRoute);
break;
}
});
diff --git a/lib/feature/night_study/item/night_study_item.dart b/lib/feature/night_study/item/night_study_item.dart
new file mode 100644
index 0000000..c411c8e
--- /dev/null
+++ b/lib/feature/night_study/item/night_study_item.dart
@@ -0,0 +1,184 @@
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+
+import '../../../component/theme/color.dart';
+import '../../../component/theme/style.dart';
+import '../../../utiles/utile.dart';
+
+enum TagType { PENDING, APPROVE, REJECT }
+enum PlaceType { PROGRAMMING_1, PROGRAMMING_2, PROGRAMMING_3 }
+
+extension PlaceTypeExtension on PlaceType {
+ String get name {
+ switch (this) {
+ case PlaceType.PROGRAMMING_1:
+ return "프로그래밍1실";
+ case PlaceType.PROGRAMMING_2:
+ return "프로그래밍2실";
+ case PlaceType.PROGRAMMING_3:
+ return "프로그래밍3실";
+ }
+ }
+}
+
+ class NightStudyItem extends StatelessWidget {
+
+ final TagType tagType;
+ final Function() onClickTrash;
+ final String? rejectReason;
+ final DateTime startAt;
+ final DateTime endAt;
+
+ const NightStudyItem({
+ super.key,
+ required this.tagType,
+ required this.onClickTrash,
+ this.rejectReason,
+ required this.startAt,
+ required this.endAt,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+
+ final hour = dateDifferenceInDays(DateTime.now(), endAt) ~/ 60;
+ final minute = dateDifferenceInDays(DateTime.now(), endAt) % 60;
+
+ return Container(
+ decoration: BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.all(Radius.circular(10)),
+ boxShadow: [
+ BoxShadow(
+ color: Colors.black.withOpacity(0.08),
+ spreadRadius: 0,
+ blurRadius: 4,
+ offset: const Offset(0, 4), // changes position of shadow
+ ),
+ ],
+ ),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(
+ vertical: 8,
+ horizontal: 12,
+ ),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ Container(
+ decoration: BoxDecoration(
+ color: switch (tagType) {
+ TagType.PENDING => EasierDodamColors.gray600,
+ TagType.APPROVE => EasierDodamColors.primary300,
+ TagType.REJECT => EasierDodamColors.staticRed
+ },
+ borderRadius: BorderRadius.circular(12),
+ ),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(
+ vertical: 4.0,
+ horizontal: 10.0,
+ ),
+ child: Text(
+ switch (tagType) {
+ TagType.PENDING => "대기중",
+ TagType.APPROVE => "수락됨",
+ TagType.REJECT => "거절됨",
+ },
+ style: EasierDodamStyles.label1.copyWith(
+ fontSize: 12.0,
+ color: EasierDodamColors.staticWhite,
+ ),
+ ),
+ ),
+ ),
+ Material(
+ color: EasierDodamColors.staticWhite,
+ child: InkWell(
+ onTap: onClickTrash,
+ child: SizedBox(
+ width: 24,
+ height: 24,
+ child: Image.asset("assets/images/ic_trash.png"),
+ ),
+ ),
+ )
+ ],
+ ),
+ const SizedBox(
+ height: 12,
+ ),
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.end,
+ children: [
+ Text(
+ hour > 0 ? "$hour시간" : "$minute분",
+ style: EasierDodamStyles.label2,
+ ),
+ SizedBox(
+ width: 2,
+ ),
+ Text(
+ "남음",
+ style: EasierDodamStyles.label2.copyWith(
+ fontSize: 12.0,
+ ),
+ )
+ ],
+ ),
+ const SizedBox(
+ height: 12,
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ Text(
+ "시작",
+ style: EasierDodamStyles.label2.copyWith(
+ fontSize: 12.0,
+ ),
+ ),
+ const SizedBox(
+ width: 2,
+ ),
+ Text(
+ "${startAt.year}-${startAt.month}-${startAt.day}일",
+ style: EasierDodamStyles.label2,
+ ),
+ ],
+ ),
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ Text(
+ "복귀",
+ style: EasierDodamStyles.label2.copyWith(
+ fontSize: 12.0,
+ ),
+ ),
+ const SizedBox(
+ width: 2,
+ ),
+ Text(
+ "${endAt.year}-${endAt.month}-${endAt.day}일",
+ style: EasierDodamStyles.label2,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/feature/night_study/item/night_study_preset_item.dart b/lib/feature/night_study/item/night_study_preset_item.dart
new file mode 100644
index 0000000..c3f5808
--- /dev/null
+++ b/lib/feature/night_study/item/night_study_preset_item.dart
@@ -0,0 +1,111 @@
+import 'package:easier_dodam/feature/night_study/item/night_study_item.dart';
+import 'package:flutter/material.dart';
+
+import '../../../component/theme/color.dart';
+import '../../../component/theme/style.dart';
+
+class NightStudyPresetItem extends StatelessWidget {
+ final String presetTitle;
+ final PlaceType place;
+ final String content;
+ final bool doNeedPhone;
+ final String phoneReason;
+ final String startDate;
+ final String endDate;
+ final Function() onTrashClick;
+ final Function() onClickCreate;
+
+ const NightStudyPresetItem({
+ super.key,
+ required this.presetTitle,
+ required this.place,
+ required this.content,
+ required this.doNeedPhone,
+ required this.phoneReason,
+ required this.startDate,
+ required this.endDate,
+ required this.onTrashClick,
+ required this.onClickCreate,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return Material(
+ color: EasierDodamColors.staticWhite,
+ child: InkWell(
+ onTap: onClickCreate,
+ child: Padding(
+ padding: EdgeInsets.all(8.0),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ presetTitle,
+ style: EasierDodamStyles.body2
+ .copyWith(color: EasierDodamColors.gray700),
+ ),
+ SizedBox(
+ height: 4,
+ ),
+ Text(
+ "사유 : $context",
+ style: EasierDodamStyles.body2
+ .copyWith(color: EasierDodamColors.gray600),
+ ),
+ SizedBox(
+ height: 4,
+ ),
+ Row(
+ children: [
+ Text(
+ "시작",
+ style:
+ EasierDodamStyles.body2.copyWith(fontSize: 12.0),
+ ),
+ Text(
+ " $startDate",
+ style:
+ EasierDodamStyles.body2.copyWith(fontSize: 14.0),
+ ),
+ Expanded(child: SizedBox()),
+ Text(
+ "종료",
+ style:
+ EasierDodamStyles.body2.copyWith(fontSize: 12.0),
+ ),
+ Text(
+ " $endDate",
+ style:
+ EasierDodamStyles.body2.copyWith(fontSize: 14.0),
+ ),
+ ],
+ )
+ ],
+ ),
+ ),
+ SizedBox(
+ width: 4,
+ ),
+ SizedBox(
+ width: 24,
+ height: 24,
+ child: InkWell(
+ onTap: onTrashClick,
+ child: Image.asset(
+ "assets/images/ic_trash.png",
+ color: EasierDodamColors.gray700,
+ ),
+ ),
+ )
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/feature/night_study/night_study.dart b/lib/feature/night_study/night_study.dart
index bbd6f56..b93f477 100644
--- a/lib/feature/night_study/night_study.dart
+++ b/lib/feature/night_study/night_study.dart
@@ -1,11 +1,21 @@
import 'package:easier_dodam/component/appbar.dart';
import 'package:easier_dodam/component/bottom_navigation_bar.dart';
+import 'package:easier_dodam/component/modal_bottom_sheet_container.dart';
import 'package:easier_dodam/component/theme/color.dart';
import 'package:easier_dodam/component/theme/style.dart';
-import 'package:easier_dodam/feature/night_study/night_study_viewmodel.dart';
+import 'package:easier_dodam/feature/night_study/item/night_study_item.dart';
+import 'package:easier_dodam/feature/night_study/item/night_study_preset_item.dart';
+import 'package:easier_dodam/remote/night_study/response/night_study_response.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
+import '../logout/logout_navigation.dart';
+import '../night_study_create/night_study_create_navigation.dart';
+import '../out/out_navigation.dart';
+import '../out_sleeping/out_sleeping_navigation.dart';
+import 'night_study_navigation.dart';
+import 'night_study_viewmodel.dart';
+
class NightStudyScreen extends StatefulWidget {
const NightStudyScreen({super.key});
@@ -14,36 +24,30 @@ class NightStudyScreen extends StatefulWidget {
}
class _NightStudyScreenState extends State {
- final TextEditingController _reasonTextFieldController = TextEditingController();
+ final TextEditingController _reasonTextFieldController =
+ TextEditingController();
- int _selectedIndex = 0;
+ int _selectedIndex = 2;
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
- }
- void _onPlusClick() {
- showDialog(
- context: context,
- builder: (context) => AlertDialog(
- title: Text("심자 추가"),
- content: Text("심자를 추가하시겠습니까?"),
- actions: [
- TextButton(
- onPressed: () => Navigator.of(context).pop(),
- child: Text("취소"),
- ),
- TextButton(
- onPressed: () {
- Navigator.of(context).pop();
- },
- child: Text("확인"),
- ),
- ],
- ),
- );
+ switch (index) {
+ case 0:
+ Navigator.pushReplacementNamed(context, outSleepingRoute);
+ break;
+ case 1:
+ Navigator.pushReplacementNamed(context, outRoute);
+ break;
+ case 2:
+ Navigator.pushReplacementNamed(context, nightStudyRoute);
+ break;
+ case 3:
+ Navigator.pushReplacementNamed(context, logoutRoute);
+ break;
+ }
}
@override
@@ -54,44 +58,294 @@ class _NightStudyScreenState extends State {
@override
Widget build(BuildContext context) {
- return Scaffold(
- appBar: PreferredSize(
- preferredSize: Size.fromHeight(60),
- child: EasierDodamDefaultAppbar(
- title: '심자',
- onPlusClick: _onPlusClick,
+ return Consumer(
+ builder:
+ (BuildContext context, NightStudyViewmodel viewModel, Widget? child) {
+ return Scaffold(
+ appBar: PreferredSize(
+ preferredSize: Size.fromHeight(60),
+ child: EasierDodamDefaultAppbar(
+ title: '심자',
+ onPlusClick: () {
+ showModalBottomSheet(
+ context: context,
+ builder: (context) {
+ return ChangeNotifierProvider.value(
+ value: viewModel,
+ child: Consumer(
+ builder: (
+ BuildContext context,
+ NightStudyViewmodel value,
+ Widget? child,
+ ) {
+ return _bottomWidget(context, viewModel);
+ },
+ ),
+ );
+ },
+ );
+ },
+ ),
),
- ),
- body: SafeArea(
- child: ChangeNotifierProvider(
- create: (_) => NightStudyViewmodel(),
- child: Consumer(
- builder: (context, provider, child) {
- return Container(
+ body: SafeArea(
+ child: RefreshIndicator(
+ onRefresh: () async {
+ return viewModel.getMyNightStudies();
+ },
+ child: Consumer(
+ builder: (context, provider, child) {
+ return Container(
+ color: EasierDodamColors.staticWhite,
+ margin: const EdgeInsets.symmetric(horizontal: 16),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ viewModel.isLoading ? "" : "현재 신청된 심자",
+ style: EasierDodamStyles.body1,
+ textAlign: TextAlign.start,
+ ),
+ _loading(viewModel.isLoading),
+ _notExitsNightStudy(
+ viewModel.nightStudyResponses.isEmpty &&
+ !viewModel.isLoading,
+ () {
+ viewModel.getMyNightStudies();
+ },
+ ),
+ ..._nightStudyItemsView(
+ viewModel.nightStudyResponses,
+ viewModel.isLoading,
+ (item) => {viewModel.deleteMyOut(item.id)},
+ ),
+ ],
+ ),
+ );
+ },
+ ),
+ ),
+ ),
+ bottomNavigationBar: SafeArea(
+ child: EasierDodamBottomNavigationBar(
+ selectedIndex: _selectedIndex,
+ onItemTapped: _onItemTapped,
+ ),
+ ),
+ );
+ });
+ }
+
+ Widget _bottomWidget(BuildContext context, NightStudyViewmodel viewModel) {
+ return ModalBottomSheetContainer(
+ child: Padding(
+ padding: const EdgeInsets.symmetric(
+ horizontal: 16,
+ ),
+ child: SingleChildScrollView(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Container(
+ height: 44,
+ width: 380,
+ child: Padding(
+ padding: const EdgeInsets.symmetric(
+ horizontal: 8,
+ ),
+ child: Text("심자 신청하기", style: EasierDodamStyles.title1),
+ ),
+ ),
+ SizedBox(
+ height: 8,
+ ),
+ ...viewModel.nightStudyEntities
+ .map(
+ (data) => NightStudyPresetItem(
+ presetTitle: data.title,
+ place: data.place,
+ content: data.content,
+ doNeedPhone: data.doNeedPhone,
+ phoneReason: data.reasonForPhone,
+ startDate: "${data.startAt} ${data.startAt.minute}",
+ endDate: "${data.endAt.hour} ${data.endAt.minute}",
+ onTrashClick: () {
+ viewModel.removeEntity(data.id ?? 0);
+ },
+ onClickCreate: () async {
+ Navigator.pop(context);
+ await viewModel.nightStudy(data);
+ },
+ ),
+ )
+ .toList(),
+ SizedBox(
+ height: 8,
+ ),
+ Divider(
+ height: 1,
+ color: EasierDodamColors.gray600,
+ ),
+ SizedBox(
+ height: 8,
+ ),
+ Material( //프리셋 생성 시작
color: EasierDodamColors.staticWhite,
- margin: const EdgeInsets.symmetric(horizontal: 16),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- SizedBox(height: 23),
- Text(
- "현재 신청된 심자",
- style: EasierDodamStyles.body1,
- textAlign: TextAlign.start,
+ child: InkWell(
+ onTap: () {
+ Navigator.pushReplacementNamed(
+ context,
+ nightStudyCreateRoute,
+ );
+ },
+ child: Padding(
+ padding: const EdgeInsets.symmetric(
+ horizontal: 8,
+ ),
+ child: Row(
+ children: [
+ Image.asset(
+ width: 24,
+ height: 24,
+ "assets/images/ic_plus.png",
+ color: EasierDodamColors.gray700,
+ ),
+ SizedBox(
+ width: 8,
+ ),
+ Text(
+ "새로운 프리셋 만들기",
+ style: EasierDodamStyles.body2,
+ )
+ ],
),
- SizedBox(),
- // You can add more content here
- ],
+ ),
),
- );
- },
+ ),
+ ],
),
),
),
- bottomNavigationBar: EasierDodamBottomNavigationBar(
- selectedIndex: _selectedIndex,
- onItemTapped: _onItemTapped,
- ),
);
}
-}
\ No newline at end of file
+
+ Widget _loading(bool isLoading) {
+ if (isLoading) {
+ return Center(
+ child: Container(
+ width: 50,
+ height: 50,
+ child: CircularProgressIndicator(
+ backgroundColor: EasierDodamColors.staticWhite,
+ color: EasierDodamColors.primary300,
+ ),
+ ),
+ );
+ } else {
+ return SizedBox();
+ }
+ }
+
+ Widget _notExitsNightStudy(bool isExit, Function() onClick) {
+ if (isExit) {
+ return Container(
+ decoration: BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.all(Radius.circular(10)),
+ boxShadow: [
+ BoxShadow(
+ color: Colors.black.withOpacity(0.08),
+ spreadRadius: 0,
+ blurRadius: 4,
+ offset: const Offset(0, 4),
+ ),
+ ],
+ ),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(
+ vertical: 8,
+ horizontal: 12,
+ ),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ SizedBox(
+ width: 40,
+ height: 40,
+ child: Image.asset("assets/images/ic_happy.png"),
+ ),
+ SizedBox(
+ height: 12,
+ ),
+ Text(
+ "현재 신청된 심자가 없어요",
+ style: EasierDodamStyles.label1,
+ ),
+ SizedBox(
+ height: 12,
+ ),
+ Material(
+ color: EasierDodamColors.staticWhite,
+ child: InkWell(
+ onTap: onClick,
+ child: Container(
+ width: double.infinity,
+ height: 42,
+ decoration: BoxDecoration(
+ border: const Border.fromBorderSide(
+ BorderSide(
+ width: 1.0, color: EasierDodamColors.gray500),
+ ),
+ borderRadius: BorderRadius.circular(8.0),
+ ),
+ child: Center(
+ child: Text(
+ "새로고침",
+ style: EasierDodamStyles.label1,
+ ),
+ ),
+ ),
+ ),
+ )
+ ],
+ ),
+ ),
+ );
+ } else {
+ return SizedBox();
+ }
+ }
+
+ List _nightStudyItemsView(
+ List items,
+ bool isLoading,
+ Function(NightStudyResponse) onClickTrash,
+ ) {
+ if (isLoading) {
+ return List.empty();
+ }
+ return items
+ .map((item) => Column(
+ children: [
+ SizedBox(
+ height: 12,
+ ),
+ NightStudyItem(
+ tagType: switch (item.status) {
+ Status.ALLOWED => TagType.APPROVE,
+ Status.PENDING => TagType.PENDING,
+ Status.REJECTED => TagType.REJECT,
+ },
+ onClickTrash: () {
+ onClickTrash(item);
+ },
+ startAt: item.startAt,
+ endAt: item.endAt,
+ ),
+ ],
+ ))
+ .toList();
+ }
+
+}
+
diff --git a/lib/feature/night_study/night_study_viewmodel.dart b/lib/feature/night_study/night_study_viewmodel.dart
index fed089b..ac3e1cd 100644
--- a/lib/feature/night_study/night_study_viewmodel.dart
+++ b/lib/feature/night_study/night_study_viewmodel.dart
@@ -1,32 +1,87 @@
-import 'package:easier_dodam/remote/night_study/night_study_data_source.dart';
-import 'package:easier_dodam/remote/night_study/response/night_study_response.dart';
+import 'dart:async';
+
+import 'package:easier_dodam/feature/night_study/item/night_study_item.dart';
import 'package:flutter/cupertino.dart';
+import '../../local/database_manager.dart';
+import '../../local/entity/night_study_entity.dart';
import '../../remote/core/base_response.dart';
+import '../../remote/night_study/night_study_data_source.dart';
+import '../../remote/night_study/response/night_study_response.dart';
-class NightStudyViewmodel with ChangeNotifier{
+class NightStudyViewmodel with ChangeNotifier {
late NightStudyDataSource _nightStudyDataSource;
- String _testState = "";
- String get testState => _testState;
+ bool _isLoading = false;
+ bool get isLoading => _isLoading;
+
+ List _nightStudyEntities = List.empty();
+ List get nightStudyEntities => _nightStudyEntities;
+
+ List _nightStudyResponses = List.empty();
+ List get nightStudyResponses => _nightStudyResponses;
- NightStudyViewmodel(){
+ StreamSubscription>? _nightStudyStreamSubscription;
+
+ NightStudyViewmodel() {
_nightStudyDataSource = NightStudyDataSource();
+ getMyNightStudies();
+ _getNightStudyEntities();
+ }
+
+ void _getNightStudyEntities() async {
+ final database = await DatabaseManager.getDatabase();
+ _nightStudyStreamSubscription
+ = database.nightStudyDao.findAllEntitiesWithStream().listen((data) {
+ _nightStudyEntities = data;
+ notifyListeners();
+ });
+ }
+
+ void removeEntity(int id) async {
+ final database = await DatabaseManager.getDatabase();
+ await database.nightStudyDao.deleteNightStudyEntityById(id);
+ notifyListeners();
}
- Future nightStudy(
- String place,
- String content,
- bool doNeedPhone,
- String reasonForPhone,
- String startAt,
- String endAt
- ) async {
- final BaseResponse response =
- await _nightStudyDataSource.nightStudy(place, content, doNeedPhone, reasonForPhone, startAt, endAt);
+ Future getMyNightStudies() async {
+ setIsLoading(true);
+ final nightStudies = await _nightStudyDataSource.getMyNightStudies();
+ setIsLoading(false);
+ _nightStudyResponses = nightStudies;
notifyListeners();
- return true;
}
+ void deleteMyOut(int id) async {
+ setIsLoading(true);
+ await _nightStudyDataSource.deleteMyNightStudy(id);
+ _nightStudyResponses.removeWhere((data) => data.id == id);
+ setIsLoading(false);
+ notifyListeners();
+ }
+
+ Future nightStudy(NightStudyEntity nightStudyEntity) async {
+ await _nightStudyDataSource.postNightStudy(
+ nightStudyEntity.place,
+ nightStudyEntity.content,
+ nightStudyEntity.doNeedPhone,
+ nightStudyEntity.reasonForPhone,
+ nightStudyEntity.startAt,
+ nightStudyEntity.endAt
+ );
+
+ getMyNightStudies();
+ return true;
+ }
+ void setIsLoading(bool isLoading) {
+ _isLoading = isLoading;
+ notifyListeners();
+ }
+
+ @override
+ void dispose() {
+ _nightStudyStreamSubscription?.cancel();
+ super.dispose();
+ }
}
\ No newline at end of file
diff --git a/lib/feature/night_study_create/item/night_study_create_time_item.dart b/lib/feature/night_study_create/item/night_study_create_time_item.dart
new file mode 100644
index 0000000..edeb332
--- /dev/null
+++ b/lib/feature/night_study_create/item/night_study_create_time_item.dart
@@ -0,0 +1,55 @@
+import 'package:easier_dodam/component/theme/color.dart';
+import 'package:easier_dodam/component/theme/style.dart';
+import 'package:flutter/material.dart';
+
+class NightStudyCreateTimeItem extends StatelessWidget {
+ final String title;
+ final String buttonText;
+ final Function() onButtonClick;
+
+ const NightStudyCreateTimeItem(
+ {super.key,
+ required this.title,
+ required this.buttonText,
+ required this.onButtonClick});
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ title,
+ style: EasierDodamStyles.label1.copyWith(
+ height: 1.5,
+ color: EasierDodamColors.gray500,
+ ),
+ ),
+ InkWell(
+ onTap: onButtonClick,
+ child: Container(
+ decoration: BoxDecoration(
+ border: const Border.fromBorderSide(
+ BorderSide(width: 1.0, color: EasierDodamColors.gray500),
+ ),
+ borderRadius: BorderRadius.circular(10.0),
+ ),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(
+ vertical: 15,
+ horizontal: 34.5,
+ ),
+ child: Text(
+ buttonText,
+ style: EasierDodamStyles.label1.copyWith(
+ height: 1.5,
+ color: EasierDodamColors.staticBlack,
+ ),
+ ),
+ ),
+ ),
+ )
+ ],
+ );
+ }
+}
diff --git a/lib/feature/night_study_create/night_study_create.dart b/lib/feature/night_study_create/night_study_create.dart
new file mode 100644
index 0000000..d2aec2f
--- /dev/null
+++ b/lib/feature/night_study_create/night_study_create.dart
@@ -0,0 +1,224 @@
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+import '../../../component/preset_appbar.dart';
+import '../../../component/textfield.dart';
+import '../../../component/theme/color.dart';
+import '../../../component/theme/style.dart';
+import '../night_study/item/night_study_item.dart';
+import 'item/night_study_create_time_item.dart';
+import 'night_study_create_viewmodel.dart';
+
+class NightStudyCreateScreen extends StatefulWidget {
+ const NightStudyCreateScreen({super.key});
+
+ @override
+ State createState() => _NightStudyCreateState();
+}
+
+class _NightStudyCreateState extends State {
+ final TextEditingController _titleTextFieldController = TextEditingController();
+ final TextEditingController _contentTextFieldController = TextEditingController();
+ final TextEditingController _reasonTextFieldController = TextEditingController();
+
+ DateTime startAt = DateTime.now();
+ DateTime endAt = adjustDateTime(DateTime.now(), hoursToAdd: 3);
+
+ PlaceType? selectedPlace;
+ bool doNeedPhone = false;
+
+ @override
+ void dispose() {
+ _titleTextFieldController.dispose();
+ _contentTextFieldController.dispose();
+ _reasonTextFieldController.dispose();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return ChangeNotifierProvider(
+ create: (_) => NightStudyCreateViewModel(),
+ child: Consumer(
+ builder: (context, provider, child) {
+ return Scaffold(
+ appBar: PreferredSize(
+ preferredSize: const Size.fromHeight(60),
+ child: EasierDodamDefaultPresetAppbar(
+ title: "심자 프리셋 생성하기",
+ onLeftArrowClick: () {
+ Navigator.pop(context);
+ },
+ ),
+ ),
+ body: SafeArea(
+ child: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ child: Column(
+ children: [
+ EasierDodamTextField(
+ labelText: "프리셋 제목",
+ hintText: "프리셋 제목을 입력해주세요.",
+ controller: _titleTextFieldController,
+ ),
+ const SizedBox(height: 12),
+ EasierDodamTextField(
+ labelText: "사유",
+ hintText: "사유를 입력해주세요.",
+ controller: _contentTextFieldController,
+ ),
+ const SizedBox(height: 12),
+ DropdownButton(
+ value: selectedPlace,
+ hint: const Text("장소를 선택하세요"),
+ items: PlaceType.values.map((place) {
+ return DropdownMenuItem(
+ value: place,
+ child: Text(place.name),
+ );
+ }).toList(),
+ onChanged: (PlaceType? value) {
+ setState(() {
+ selectedPlace = value;
+ });
+ },
+ dropdownColor: EasierDodamColors.staticWhite,
+ ),
+ const SizedBox(height: 12),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ const Text("휴대폰 필요 여부", style: TextStyle(fontSize: 16)),
+ Checkbox(
+ value: doNeedPhone,
+ onChanged: (value) {
+ setState(() {
+ doNeedPhone = value!;
+ if (!doNeedPhone) {
+ _reasonTextFieldController.clear();
+ }
+ });
+ },
+ activeColor: EasierDodamColors.primary300,
+ checkColor: EasierDodamColors.staticWhite,
+ side: BorderSide(
+ color: EasierDodamColors.gray200,
+ width: 2.0,
+ ),
+ ),
+ ],
+ ),
+ if (doNeedPhone)
+ EasierDodamTextField(
+ hintText: "휴대폰이 필요한 이유를 입력해주세요.",
+ controller: _reasonTextFieldController,
+ ),
+ const SizedBox(height: 12),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ Expanded(
+ child: NightStudyCreateTimeItem(
+ title: "심자 시작 날짜",
+ buttonText: "${startAt.year}년 ${startAt.month}월 ${startAt.day}일",
+ onButtonClick: () async {
+ final date = await showDatePicker(
+ context: context,
+ initialDate: startAt,
+ firstDate: DateTime(2000),
+ lastDate: DateTime(2100),
+ );
+ if (date != null) {
+ setState(() {
+ startAt = date;
+ if (startAt.isAfter(endAt)) {
+ endAt = startAt;
+ }
+ });
+ }
+ },
+ ),
+ ),
+ SizedBox(width: 8), // 간격 추가
+ Expanded(
+ child: NightStudyCreateTimeItem(
+ title: "심자 종료 날짜",
+ buttonText: "${endAt.year}년 ${endAt.month}월 ${endAt.day}일",
+ onButtonClick: () async {
+ final date = await showDatePicker(
+ context: context,
+ initialDate: endAt,
+ firstDate: DateTime(2000),
+ lastDate: DateTime(2100),
+ );
+ if (date != null) {
+ setState(() {
+ endAt = date;
+ });
+ }
+ },
+ ),
+ ),
+ ],
+ ),
+ const Spacer(),
+ SizedBox(
+ width: double.infinity,
+ height: 56.0,
+ child: MaterialButton(
+ height: 56.0,
+ color: EasierDodamColors.primary300,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(12.0),
+ ),
+ child: const Text(
+ "생성하기",
+ style: EasierDodamStyles.body2,
+ ),
+ textColor: EasierDodamColors.staticWhite,
+ onPressed: () async {
+ if (selectedPlace == null) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ const SnackBar(content: Text("장소를 선택해주세요.")),
+ );
+ return;
+ }
+ if (doNeedPhone && _reasonTextFieldController.text.isEmpty) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ const SnackBar(content: Text("휴대폰 필요 사유를 입력해주세요.")),
+ );
+ return;
+ }
+ await provider.createNightStudy(
+ title: _titleTextFieldController.text,
+ place: selectedPlace!,
+ content: _contentTextFieldController.text,
+ doNeedPhone: doNeedPhone,
+ reasonForPhone: _reasonTextFieldController.text,
+ startAt: startAt,
+ endAt: endAt,
+ );
+ Navigator.pop(context);
+ },
+ ),
+ ),
+ const SizedBox(
+ height: 8
+ ),
+ ],
+ ),
+ ),
+ ),
+ );
+ },
+ ),
+ );
+ }
+
+ static DateTime adjustDateTime(DateTime time, {required int hoursToAdd}) {
+ final adjustedTime = time.add(Duration(hours: hoursToAdd));
+
+ return adjustedTime;
+ }
+}
\ No newline at end of file
diff --git a/lib/feature/night_study_create/night_study_create_navigation.dart b/lib/feature/night_study_create/night_study_create_navigation.dart
new file mode 100644
index 0000000..55938e3
--- /dev/null
+++ b/lib/feature/night_study_create/night_study_create_navigation.dart
@@ -0,0 +1 @@
+const nightStudyCreateRoute = "night_study_create";
\ No newline at end of file
diff --git a/lib/feature/night_study_create/night_study_create_viewmodel.dart b/lib/feature/night_study_create/night_study_create_viewmodel.dart
new file mode 100644
index 0000000..a3e93d3
--- /dev/null
+++ b/lib/feature/night_study_create/night_study_create_viewmodel.dart
@@ -0,0 +1,33 @@
+import 'package:easier_dodam/local/database_manager.dart';
+import 'package:easier_dodam/local/entity/night_study_entity.dart';
+import 'package:flutter/material.dart';
+
+import '../night_study/item/night_study_item.dart';
+
+
+class NightStudyCreateViewModel with ChangeNotifier {
+ Future createNightStudy({
+ required PlaceType place,
+ required String title,
+ required String content,
+ required bool doNeedPhone,
+ required String reasonForPhone,
+ required DateTime startAt,
+ required DateTime endAt
+ }) async {
+ final database = await DatabaseManager.getDatabase();
+ await database.nightStudyDao.insertNightStudyEntity(NightStudyEntity(
+ title: title,
+ place: place,
+ content: content,
+ doNeedPhone: doNeedPhone,
+ reasonForPhone: reasonForPhone,
+ startAt: startAt,
+ endAt: endAt
+ ));
+
+ print(await database.nightStudyDao.findAllEntities());
+
+ return true;
+ }
+}
diff --git a/lib/feature/out/out.dart b/lib/feature/out/out.dart
index d2aa230..8380274 100644
--- a/lib/feature/out/out.dart
+++ b/lib/feature/out/out.dart
@@ -2,7 +2,9 @@ import 'package:easier_dodam/component/appbar.dart';
import 'package:easier_dodam/component/modal_bottom_sheet_container.dart';
import 'package:easier_dodam/component/theme/color.dart';
import 'package:easier_dodam/component/theme/style.dart';
+import 'package:easier_dodam/feature/night_study/night_study_navigation.dart';
import 'package:easier_dodam/feature/out/item/out_item.dart';
+import 'package:easier_dodam/feature/out/out_navigation.dart';
import 'package:easier_dodam/feature/out/out_viewmodel.dart';
import 'package:easier_dodam/feature/out_create/out_create_navigation.dart';
import 'package:easier_dodam/remote/out/response/out_response.dart';
@@ -10,6 +12,9 @@ import 'package:easier_dodam/utiles/utile.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
+import '../../component/bottom_navigation_bar.dart';
+import '../logout/logout_navigation.dart';
+import '../out_sleeping/out_sleeping_navigation.dart';
import 'item/out_preset_item.dart';
class OutScreen extends StatefulWidget {
@@ -20,6 +25,30 @@ class OutScreen extends StatefulWidget {
}
class _OutScreenState extends State with WidgetsBindingObserver {
+
+ int _selectedIndex = 1;
+
+ void _onItemTapped(int index) {
+ setState(() {
+ _selectedIndex = index;
+ });
+
+ switch (index) {
+ case 0:
+ Navigator.pushReplacementNamed(context, outSleepingRoute);
+ break;
+ case 1:
+ Navigator.pushReplacementNamed(context, outRoute);
+ break;
+ case 2:
+ Navigator.pushReplacementNamed(context, nightStudyRoute);
+ break;
+ case 3:
+ Navigator.pushReplacementNamed(context, logoutRoute);
+ break;
+ }
+ }
+
@override
void initState() {
super.initState();
@@ -109,6 +138,12 @@ class _OutScreenState extends State with WidgetsBindingObserver {
),
),
),
+ bottomNavigationBar: SafeArea(
+ child: EasierDodamBottomNavigationBar(
+ selectedIndex: _selectedIndex,
+ onItemTapped: _onItemTapped,
+ ),
+ ),
);
},
);
diff --git a/lib/feature/out_sleeping/out_sleeping.dart b/lib/feature/out_sleeping/out_sleeping.dart
index 8716989..98ef54b 100644
--- a/lib/feature/out_sleeping/out_sleeping.dart
+++ b/lib/feature/out_sleeping/out_sleeping.dart
@@ -5,6 +5,7 @@ import 'package:easier_dodam/component/theme/style.dart';
import 'package:easier_dodam/feature/logout/logout_navigation.dart';
import 'package:easier_dodam/feature/night_study/night_study_navigation.dart';
import 'package:easier_dodam/feature/out_sleeping/item/out_sleeping_item.dart';
+import 'package:easier_dodam/feature/out_sleeping/out_sleeping_navigation.dart';
import 'package:easier_dodam/feature/out_sleeping/out_sleeping_viewmodel.dart';
import 'package:easier_dodam/feature/out_sleeping_create/out_sleeping_create_navigation.dart';
import 'package:easier_dodam/remote/out_sleeping/response/out_sleeping_response.dart';
@@ -38,15 +39,16 @@ class _OutSleepingScreenState extends State
switch (index) {
case 0:
+ Navigator.pushReplacementNamed(context, outSleepingRoute);
break;
case 1:
Navigator.pushReplacementNamed(context, outRoute);
break;
case 2:
- Navigator.pushReplacementNamed(context, logoutRoute);
+ Navigator.pushReplacementNamed(context, nightStudyRoute);
break;
case 3:
- Navigator.pushReplacementNamed(context, nightStudyRoute);
+ Navigator.pushReplacementNamed(context, logoutRoute);
break;
}
});
diff --git a/lib/local/conventer/place_type_converter.dart b/lib/local/conventer/place_type_converter.dart
new file mode 100644
index 0000000..bd6753a
--- /dev/null
+++ b/lib/local/conventer/place_type_converter.dart
@@ -0,0 +1,15 @@
+import 'package:floor/floor.dart';
+
+import '../../feature/night_study/item/night_study_item.dart';
+
+class PlaceTypeConverter extends TypeConverter {
+ @override
+ PlaceType decode(String databaseValue) {
+ return PlaceType.values.firstWhere((e) => e.toString() == 'PlaceType.' + databaseValue);
+ }
+
+ @override
+ String encode(PlaceType value) {
+ return value.toString().split('.').last;
+ }
+}
\ No newline at end of file
diff --git a/lib/local/dao/nigh_study_dao.dart b/lib/local/dao/nigh_study_dao.dart
new file mode 100644
index 0000000..5be7d4b
--- /dev/null
+++ b/lib/local/dao/nigh_study_dao.dart
@@ -0,0 +1,32 @@
+import 'package:floor/floor.dart';
+
+import '../entity/night_study_entity.dart';
+
+@dao
+abstract class NighStudyDao {
+ @Query('SELECT * FROM $_tableName WHERE id = :id')
+ Future findNightStudyEntityById(int id);
+
+ @Query('SELECT * FROM $_tableName')
+ Future> findAllEntities();
+
+ @Query('SELECT * FROM $_tableName')
+ Stream> findAllEntitiesWithStream();
+
+ @Query('DELETE FROM $_tableName WHERE id = :id')
+ Future deleteNightStudyEntityById(int id);
+
+ @insert
+ Future insertNightStudyEntity(NightStudyEntity nightStudyEntity);
+
+ @update
+ Future updateNightStudyEntity(NightStudyEntity nightStudyEntity);
+
+ @delete
+ Future deleteNightStudyEntity(NightStudyEntity nightStudyEntity);
+
+ @Query("DELETE FROM night_study")
+ Future deleteAllNightStudyEntities();
+
+ static const String _tableName = "night_study";
+}
\ No newline at end of file
diff --git a/lib/local/dao/out_dao.dart b/lib/local/dao/out_dao.dart
index 1d94913..9fd4035 100644
--- a/lib/local/dao/out_dao.dart
+++ b/lib/local/dao/out_dao.dart
@@ -1,5 +1,3 @@
-import 'dart:ffi';
-
import 'package:easier_dodam/local/entity/out_entity.dart';
import 'package:floor/floor.dart';
diff --git a/lib/local/easier_dodam_database.dart b/lib/local/easier_dodam_database.dart
index 189aefa..5675294 100644
--- a/lib/local/easier_dodam_database.dart
+++ b/lib/local/easier_dodam_database.dart
@@ -1,20 +1,24 @@
import 'dart:async';
-import 'package:easier_dodam/local/conventer/date_time_conveter.dart';
+import 'package:easier_dodam/local/dao/nigh_study_dao.dart';
import 'package:easier_dodam/local/dao/out_dao.dart';
-import 'package:easier_dodam/local/dao/out_sleeping_dao.dart';
import 'package:floor/floor.dart';
import 'package:sqflite/sqflite.dart' as sqflite;
+import 'conventer/date_time_conveter.dart';
+import 'conventer/place_type_converter.dart';
import 'conventer/time_of_day_converter.dart';
+import 'dao/out_sleeping_dao.dart';
+import 'entity/night_study_entity.dart';
import 'entity/out_entity.dart';
import 'entity/out_sleeping_entity.dart';
part "easier_dodam_database.g.dart";
-@TypeConverters([TimeOfDayConverter, DateTimeConverter])
-@Database(version: 1, entities: [OutEntity, OutSleepingEntity])
+@TypeConverters([TimeOfDayConverter, DateTimeConverter, PlaceTypeConverter])
+@Database(version: 1, entities: [OutEntity, NightStudyEntity, OutSleepingEntity])
abstract class EasierDodamDatabase extends FloorDatabase {
OutDao get outDao;
+ NighStudyDao get nightStudyDao;
OutSleepingDao get outSleepingDao;
}
diff --git a/lib/local/easier_dodam_database.g.dart b/lib/local/easier_dodam_database.g.dart
index 2f12fea..477e9d2 100644
--- a/lib/local/easier_dodam_database.g.dart
+++ b/lib/local/easier_dodam_database.g.dart
@@ -76,6 +76,8 @@ class _$EasierDodamDatabase extends EasierDodamDatabase {
OutDao? _outDaoInstance;
+ NighStudyDao? _nightStudyDaoInstance;
+
OutSleepingDao? _outSleepingDaoInstance;
Future open(
@@ -101,6 +103,8 @@ class _$EasierDodamDatabase extends EasierDodamDatabase {
onCreate: (database, version) async {
await database.execute(
'CREATE TABLE IF NOT EXISTS `out` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `title` TEXT NOT NULL, `reason` TEXT NOT NULL, `startAt` TEXT NOT NULL, `endAt` TEXT NOT NULL)');
+ await database.execute(
+ 'CREATE TABLE IF NOT EXISTS `night_study` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `title` TEXT NOT NULL, `place` TEXT NOT NULL, `content` TEXT NOT NULL, `doNeedPhone` INTEGER NOT NULL, `reasonForPhone` TEXT NOT NULL, `startAt` TEXT NOT NULL, `endAt` TEXT NOT NULL)');
await database.execute(
'CREATE TABLE IF NOT EXISTS `out_sleeping` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `title` TEXT NOT NULL, `reason` TEXT NOT NULL, `startAt` TEXT NOT NULL, `endAt` TEXT NOT NULL)');
@@ -115,6 +119,11 @@ class _$EasierDodamDatabase extends EasierDodamDatabase {
return _outDaoInstance ??= _$OutDao(database, changeListener);
}
+ @override
+ NighStudyDao get nightStudyDao {
+ return _nightStudyDaoInstance ??= _$NighStudyDao(database, changeListener);
+ }
+
@override
OutSleepingDao get outSleepingDao {
return _outSleepingDaoInstance ??=
@@ -239,6 +248,142 @@ class _$OutDao extends OutDao {
}
}
+class _$NighStudyDao extends NighStudyDao {
+ _$NighStudyDao(
+ this.database,
+ this.changeListener,
+ ) : _queryAdapter = QueryAdapter(database, changeListener),
+ _nightStudyEntityInsertionAdapter = InsertionAdapter(
+ database,
+ 'night_study',
+ (NightStudyEntity item) => {
+ 'id': item.id,
+ 'title': item.title,
+ 'place': _placeTypeConverter.encode(item.place),
+ 'content': item.content,
+ 'doNeedPhone': item.doNeedPhone ? 1 : 0,
+ 'reasonForPhone': item.reasonForPhone,
+ 'startAt': _dateTimeConverter.encode(item.startAt),
+ 'endAt': _dateTimeConverter.encode(item.endAt)
+ },
+ changeListener),
+ _nightStudyEntityUpdateAdapter = UpdateAdapter(
+ database,
+ 'night_study',
+ ['id'],
+ (NightStudyEntity item) => {
+ 'id': item.id,
+ 'title': item.title,
+ 'place': _placeTypeConverter.encode(item.place),
+ 'content': item.content,
+ 'doNeedPhone': item.doNeedPhone ? 1 : 0,
+ 'reasonForPhone': item.reasonForPhone,
+ 'startAt': _dateTimeConverter.encode(item.startAt),
+ 'endAt': _dateTimeConverter.encode(item.endAt)
+ },
+ changeListener),
+ _nightStudyEntityDeletionAdapter = DeletionAdapter(
+ database,
+ 'night_study',
+ ['id'],
+ (NightStudyEntity item) => {
+ 'id': item.id,
+ 'title': item.title,
+ 'place': _placeTypeConverter.encode(item.place),
+ 'content': item.content,
+ 'doNeedPhone': item.doNeedPhone ? 1 : 0,
+ 'reasonForPhone': item.reasonForPhone,
+ 'startAt': _dateTimeConverter.encode(item.startAt),
+ 'endAt': _dateTimeConverter.encode(item.endAt)
+ },
+ changeListener);
+
+ final sqflite.DatabaseExecutor database;
+
+ final StreamController changeListener;
+
+ final QueryAdapter _queryAdapter;
+
+ final InsertionAdapter _nightStudyEntityInsertionAdapter;
+
+ final UpdateAdapter _nightStudyEntityUpdateAdapter;
+
+ final DeletionAdapter _nightStudyEntityDeletionAdapter;
+
+ @override
+ Future findNightStudyEntityById(int id) async {
+ return _queryAdapter.query('SELECT * FROM night_study WHERE id = ?1',
+ mapper: (Map row) => NightStudyEntity(
+ id: row['id'] as int?,
+ title: row['title'] as String,
+ place: _placeTypeConverter.decode(row['place'] as String),
+ content: row['content'] as String,
+ doNeedPhone: (row['doNeedPhone'] as int) != 0,
+ reasonForPhone: row['reasonForPhone'] as String,
+ startAt: _dateTimeConverter.decode(row['startAt'] as String),
+ endAt: _dateTimeConverter.decode(row['endAt'] as String)),
+ arguments: [id]);
+ }
+
+ @override
+ Future> findAllEntities() async {
+ return _queryAdapter.queryList('SELECT * FROM night_study',
+ mapper: (Map row) => NightStudyEntity(
+ id: row['id'] as int?,
+ title: row['title'] as String,
+ place: _placeTypeConverter.decode(row['place'] as String),
+ content: row['content'] as String,
+ doNeedPhone: (row['doNeedPhone'] as int) != 0,
+ reasonForPhone: row['reasonForPhone'] as String,
+ startAt: _dateTimeConverter.decode(row['startAt'] as String),
+ endAt: _dateTimeConverter.decode(row['endAt'] as String)));
+ }
+
+ @override
+ Stream> findAllEntitiesWithStream() {
+ return _queryAdapter.queryListStream('SELECT * FROM night_study',
+ mapper: (Map row) => NightStudyEntity(
+ id: row['id'] as int?,
+ title: row['title'] as String,
+ place: _placeTypeConverter.decode(row['place'] as String),
+ content: row['content'] as String,
+ doNeedPhone: (row['doNeedPhone'] as int) != 0,
+ reasonForPhone: row['reasonForPhone'] as String,
+ startAt: _dateTimeConverter.decode(row['startAt'] as String),
+ endAt: _dateTimeConverter.decode(row['endAt'] as String)),
+ queryableName: 'night_study',
+ isView: false);
+ }
+
+ @override
+ Future deleteNightStudyEntityById(int id) async {
+ await _queryAdapter.queryNoReturn('DELETE FROM night_study WHERE id = ?1',
+ arguments: [id]);
+ }
+
+ @override
+ Future deleteAllNightStudyEntities() async {
+ await _queryAdapter.queryNoReturn('DELETE FROM night_study');
+ }
+
+ @override
+ Future insertNightStudyEntity(NightStudyEntity nightStudyEntity) async {
+ await _nightStudyEntityInsertionAdapter.insert(
+ nightStudyEntity, OnConflictStrategy.abort);
+ }
+
+ @override
+ Future updateNightStudyEntity(NightStudyEntity nightStudyEntity) async {
+ await _nightStudyEntityUpdateAdapter.update(
+ nightStudyEntity, OnConflictStrategy.abort);
+ }
+
+ @override
+ Future deleteNightStudyEntity(NightStudyEntity nightStudyEntity) async {
+ await _nightStudyEntityDeletionAdapter.delete(nightStudyEntity);
+ }
+}
+
class _$OutSleepingDao extends OutSleepingDao {
_$OutSleepingDao(
this.database,
@@ -363,3 +508,4 @@ class _$OutSleepingDao extends OutSleepingDao {
// ignore_for_file: unused_element
final _timeOfDayConverter = TimeOfDayConverter();
final _dateTimeConverter = DateTimeConverter();
+final _placeTypeConverter = PlaceTypeConverter();
diff --git a/lib/local/entity/night_study_entity.dart b/lib/local/entity/night_study_entity.dart
new file mode 100644
index 0000000..80452a9
--- /dev/null
+++ b/lib/local/entity/night_study_entity.dart
@@ -0,0 +1,64 @@
+import 'package:floor/floor.dart';
+
+import '../../feature/night_study/item/night_study_item.dart';
+
+@Entity(tableName: "night_study")
+class NightStudyEntity {
+ @PrimaryKey(autoGenerate: true)
+ final int? id;
+
+ final String title;
+
+ final PlaceType place;
+
+ final String content;
+
+ final bool doNeedPhone;
+
+ final String reasonForPhone;
+
+ final DateTime startAt;
+
+ final DateTime endAt;
+
+ NightStudyEntity({
+ this.id,
+ required this.title,
+ required this.place,
+ required this.content,
+ required this.doNeedPhone,
+ required this.reasonForPhone,
+ required this.startAt,
+ required this.endAt,
+ });
+
+ @override
+ bool operator ==(Object other) =>
+ identical(this, other) ||
+ other is NightStudyEntity &&
+ runtimeType == other.runtimeType &&
+ id == other.id &&
+ title == other.title &&
+ place == other.place &&
+ content == other.content &&
+ doNeedPhone == other.doNeedPhone &&
+ reasonForPhone == other.reasonForPhone &&
+ startAt == other.startAt &&
+ endAt == other.endAt;
+
+ @override
+ int get hashCode =>
+ id.hashCode ^
+ title.hashCode ^
+ place.hashCode ^
+ content.hashCode ^
+ doNeedPhone.hashCode ^
+ reasonForPhone.hashCode ^
+ startAt.hashCode ^
+ endAt.hashCode;
+
+ @override
+ String toString() {
+ return 'NightStudyEntity(id: $id, title: $title, place: $place, content: $content, doNeedPhone: $doNeedPhone, reasonForPhone: $reasonForPhone, startAt: $startAt, endAt: $endAt)';
+ }
+}
\ No newline at end of file
diff --git a/lib/local/storage_manager.dart b/lib/local/storage_manager.dart
index 29bb478..bd1861a 100644
--- a/lib/local/storage_manager.dart
+++ b/lib/local/storage_manager.dart
@@ -43,6 +43,11 @@ class StorageManager {
);
}
+ Future hasToken() async {
+ final tokenDto = await StorageManager.getUserToken();
+ return tokenDto.accessToken != null && tokenDto.accessToken!.isNotEmpty;
+ }
+
static get _idKey => "id";
static get _pwKey => "pw";
static get _accessTokenKey => "accessToken";
diff --git a/lib/main.dart b/lib/main.dart
index ad4ec95..eaac5e4 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,8 +1,10 @@
import 'package:easier_dodam/component/theme/color.dart';
+import 'package:easier_dodam/component/theme/style.dart';
import 'package:easier_dodam/feature/login/login_navigation.dart';
import 'package:easier_dodam/feature/logout/logout.dart';
import 'package:easier_dodam/feature/logout/logout_navigation.dart';
import 'package:easier_dodam/feature/logout/logout_viewmodel.dart';
+import 'package:easier_dodam/feature/night_study/night_study_viewmodel.dart';
import 'package:easier_dodam/feature/out/out.dart';
import 'package:easier_dodam/feature/out_create/out_create.dart';
import 'package:easier_dodam/feature/out_create/out_create_navigation.dart';
@@ -10,21 +12,29 @@ import 'package:easier_dodam/feature/out_sleeping/out_sleeping.dart';
import 'package:easier_dodam/feature/out_sleeping/out_sleeping_navigation.dart';
import 'package:easier_dodam/feature/out_sleeping/out_sleeping_viewmodel.dart';
import 'package:easier_dodam/feature/out_sleeping_create/out_sleeping_create.dart';
+import 'package:easier_dodam/remote/core/core_client.dart';
import 'package:flutter/material.dart';
import 'package:flutter_config/flutter_config.dart';
+import 'package:flutter_svg/svg.dart';
import 'package:provider/provider.dart';
import 'feature/login/login.dart';
import 'feature/night_study/night_study.dart';
import 'feature/night_study/night_study_navigation.dart';
+import 'feature/night_study_create/night_study_create.dart';
+import 'feature/night_study_create/night_study_create_navigation.dart';
import 'feature/out/out_navigation.dart';
import 'feature/out/out_viewmodel.dart';
import 'feature/out_sleeping_create/out_sleeping_create_navigation.dart';
+import 'local/storage_manager.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
- await FlutterConfig.loadEnvVariables();
-
+ try {
+ await FlutterConfig.loadEnvVariables();
+ } catch (e) {
+ debugPrint('Failed to load environment variables: $e');
+ }
runApp(const MyApp());
}
@@ -33,37 +43,85 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
- return MaterialApp(
- title: 'Flutter Demo',
- debugShowCheckedModeBanner: false,
- theme: ThemeData(
- colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
- useMaterial3: true,
- fontFamily: "Pretendard",
- scaffoldBackgroundColor: EasierDodamColors.staticWhite,
+ return MultiProvider(
+ providers: [
+ ChangeNotifierProvider(create: (_) => NightStudyViewmodel()),
+ ChangeNotifierProvider(create: (_) => OutViewModel()),
+ ],
+ child: MaterialApp(
+ title: 'Flutter Demo',
+ debugShowCheckedModeBanner: false,
+ theme: ThemeData(
+ colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
+ useMaterial3: true,
+ fontFamily: "Pretendard",
+ scaffoldBackgroundColor: EasierDodamColors.staticWhite,
+ ),
+ initialRoute: 'splash',
+ routes: {
+ 'splash': (context) => const SplashScreen(),
+ nightStudyRoute: (context) => NightStudyScreen(),
+ loginRoute: (context) => LoginScreen(),
+ logoutRoute: (context) => ChangeNotifierProvider(
+ create: (_) => SettingViewModel(),
+ child: SettingScreen(),
+ ),
+ outSleepingRoute: (context) => ChangeNotifierProvider(
+ create: (_) => OutSleepingViewModel(),
+ child: OutSleepingScreen(),
+ ),
+ outSleepingCreateRoute: (context) => OutSleepingCreateScreen(),
+ outRoute: (context) => ChangeNotifierProvider(
+ create: (_) => OutViewModel(),
+ child: OutScreen(),
+ ),
+ outCreateRoute: (context) => OutCreateScreen(),
+ nightStudyCreateRoute: (context) => NightStudyCreateScreen(),
+ },
),
- initialRoute: loginRoute,
- routes: {
- nightStudyRoute: (context) => NightStudyScreen(),
- loginRoute: (context) => LoginScreen(),
- logoutRoute: (context) => ChangeNotifierProvider(
- create: (_) => SettingViewModel(),
- child: SettingScreen(),
- ),
- outSleepingRoute: (context) => ChangeNotifierProvider(
- create: (_) => OutSleepingViewModel(),
- child: OutSleepingScreen(),
- ),
- outSleepingCreateRoute: (context) => OutSleepingCreateScreen(),
- outRoute: (context) => ChangeNotifierProvider(
- create: (_) => OutViewModel(),
- child: OutScreen(),
- ),
- outCreateRoute: (context) => OutCreateScreen(),
- "test": (context) => Scaffold(
- body: Text("test"),
- )
- },
);
}
}
+
+class SplashScreen extends StatelessWidget {
+ const SplashScreen({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ Future.delayed(const Duration(seconds: 1), () async {
+ if (await StorageManager().hasToken()) {
+ Navigator.pushReplacementNamed(context, outSleepingRoute);
+ } else {
+ Navigator.pushReplacementNamed(context, loginRoute);
+ }
+ });
+
+ return Scaffold(
+ body: Container(
+ decoration: BoxDecoration(
+ color: EasierDodamColors.staticWhite,
+ ),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ SvgPicture.asset(
+ 'assets/images/ic_splash.svg',
+ width: 200,
+ ),
+ const SizedBox(height: 16),
+ Text(
+ "도담도담을 쉽게",
+ style: EasierDodamStyles.title1.copyWith(fontSize: 30, color: EasierDodamColors.staticBlack),
+ ),
+ const SizedBox(height: 16),
+ ],
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/remote/core/core_client.dart b/lib/remote/core/core_client.dart
index ca07da5..a291c99 100644
--- a/lib/remote/core/core_client.dart
+++ b/lib/remote/core/core_client.dart
@@ -18,7 +18,7 @@ class CoreClient {
bool sendToken = true,
}) async {
final headers = {
- 'Content-Type': 'application/json',
+ 'Content-Type': 'application/json; charset=utf-8',
};
if (sendToken) {
headers["Authorization"] =
@@ -30,7 +30,8 @@ class CoreClient {
body: json.encode(body),
headers: headers,
);
- print(response.body);
+ final responseBody = utf8.decode(response.bodyBytes);
+ print(responseBody);
if (response.statusCode == 401 && sendToken) {
final accessToken = await _refresh();
@@ -70,8 +71,8 @@ class CoreClient {
Uri.parse(url),
headers: headers,
);
-
- print(response.body);
+ final responseBody = utf8.decode(response.bodyBytes);
+ print(responseBody);
if (response.statusCode == 401 && sendToken) {
final accessToken = await _refresh();
diff --git a/lib/remote/night_study/night_study_data_source.dart b/lib/remote/night_study/night_study_data_source.dart
index ccde3e2..6f87cf1 100644
--- a/lib/remote/night_study/night_study_data_source.dart
+++ b/lib/remote/night_study/night_study_data_source.dart
@@ -4,28 +4,52 @@ import 'package:easier_dodam/remote/core/url.dart';
import 'package:easier_dodam/remote/night_study/request/night_study_request.dart';
import 'package:easier_dodam/remote/night_study/response/night_study_response.dart';
+import '../../feature/night_study/item/night_study_item.dart';
+
class NightStudyDataSource{
- Future> nightStudy(
- String place,
+ Future postNightStudy(
+ PlaceType place,
String content,
bool doNeedPhone,
String reasonForPhone,
- String startAt,
- String endAt) async {
- return await CoreClient.post(
- url: EasierDodamUrl.NIGHT_STUDY,
- body: NightStudyRequest(
- place: place,
- content: content,
- doNeedPhone: doNeedPhone,
- reasonForPhone: reasonForPhone,
- endAt: endAt,
- startAt: startAt
- ).toJson(),
- decoder: NightStudyResponse.fromJson,
- sendToken: true
+ DateTime startAt,
+ DateTime endAt
+ ) async {
+ await CoreClient.post(
+ url: EasierDodamUrl.NIGHT_STUDY,
+ body: NightStudyRequest(
+ place: place.name.toString(),
+ content: content,
+ doNeedPhone: doNeedPhone,
+ reasonForPhone: reasonForPhone,
+ startAt: startAt,
+ endAt: endAt
+ ).toJson(),
);
+ return true;
+ }
+
+ Future> getMyNightStudies() async {
+ final response = await CoreClient.get>(
+ url: EasierDodamUrl.NIGHT_STUDY_MY,
+ listDecoder: (data) {
+ return data
+ .map((item) => NightStudyResponse.fromJson(item as Map))
+ .toList();
+ },
+ );
+ return response.data;
+ }
+
+ Future deleteMyNightStudy(int id) async {
+ final response = await CoreClient.delete(
+ url: EasierDodamUrl.NIGHT_STUDY + "/$id",
+ );
+
+ print(response.message);
+
+ return true;
}
}
\ No newline at end of file
diff --git a/lib/remote/night_study/request/night_study_request.dart b/lib/remote/night_study/request/night_study_request.dart
index 5900b05..5f3e54a 100644
--- a/lib/remote/night_study/request/night_study_request.dart
+++ b/lib/remote/night_study/request/night_study_request.dart
@@ -1,5 +1,7 @@
import 'package:json_annotation/json_annotation.dart';
+import '../../../feature/night_study/item/night_study_item.dart';
+
part 'night_study_request.g.dart';
@JsonSerializable()
@@ -8,8 +10,8 @@ class NightStudyRequest{
String content;
bool doNeedPhone;
String reasonForPhone;
- String startAt;
- String endAt;
+ DateTime startAt;
+ DateTime endAt;
NightStudyRequest(
{
diff --git a/lib/remote/night_study/request/night_study_request.g.dart b/lib/remote/night_study/request/night_study_request.g.dart
index 39de93e..441c280 100644
--- a/lib/remote/night_study/request/night_study_request.g.dart
+++ b/lib/remote/night_study/request/night_study_request.g.dart
@@ -12,8 +12,8 @@ NightStudyRequest _$NightStudyRequestFromJson(Map json) =>
content: json['content'] as String,
doNeedPhone: json['doNeedPhone'] as bool,
reasonForPhone: json['reasonForPhone'] as String,
- endAt: json['endAt'] as String,
- startAt: json['startAt'] as String,
+ endAt: DateTime.parse(json['endAt'] as String),
+ startAt: DateTime.parse(json['startAt'] as String),
);
Map _$NightStudyRequestToJson(NightStudyRequest instance) =>
@@ -22,6 +22,6 @@ Map _$NightStudyRequestToJson(NightStudyRequest instance) =>
'content': instance.content,
'doNeedPhone': instance.doNeedPhone,
'reasonForPhone': instance.reasonForPhone,
- 'startAt': instance.startAt,
- 'endAt': instance.endAt,
+ 'startAt': instance.startAt.toIso8601String(),
+ 'endAt': instance.endAt.toIso8601String(),
};
diff --git a/lib/remote/night_study/response/night_study_response.dart b/lib/remote/night_study/response/night_study_response.dart
index fe37e2c..de7746e 100644
--- a/lib/remote/night_study/response/night_study_response.dart
+++ b/lib/remote/night_study/response/night_study_response.dart
@@ -1,46 +1,45 @@
-import 'package:easier_dodam/remote/core/base_response.dart';
import 'package:easier_dodam/remote/student/reponse/student_response.dart';
import 'package:json_annotation/json_annotation.dart';
part 'night_study_response.g.dart';
+enum Status { ALLOWED, PENDING, REJECTED }
+
@JsonSerializable()
-class NightStudyResponse extends BaseObject{
+class NightStudyResponse {
int id;
String content;
- String allowCheck;
- bool isPhone;
- String reason;
+ Status status;
+ bool doNeedPhone;
+ String? reasonForPhone;
StudentResponse student;
+ String? rejectReason;
String place;
- String startAt;
- String endAt;
- String createdAt;
- String? checkedAt;
+ DateTime startAt;
+ DateTime endAt;
+ DateTime createdAt;
+ DateTime? modifiedAt;
NightStudyResponse(
{
required this.id,
required this.content,
- required this.allowCheck,
- required this.isPhone,
- required this.reason,
+ required this.status,
+ required this.doNeedPhone,
+ this.reasonForPhone,
required this.student,
+ this.rejectReason,
required this.place,
required this.startAt,
required this.endAt,
required this.createdAt,
- this.checkedAt
+ this.modifiedAt
}
);
factory NightStudyResponse.fromJson(Map json) =>
_$NightStudyResponseFromJson(json);
- @override
- NightStudyResponse fromJson(json) {
- return NightStudyResponse.fromJson(json);
- }
-
+ Map toJson() => _$NightStudyResponseToJson(this);
}
\ No newline at end of file
diff --git a/lib/remote/night_study/response/night_study_response.g.dart b/lib/remote/night_study/response/night_study_response.g.dart
index 80ade5e..7a520a1 100644
--- a/lib/remote/night_study/response/night_study_response.g.dart
+++ b/lib/remote/night_study/response/night_study_response.g.dart
@@ -10,29 +10,39 @@ NightStudyResponse _$NightStudyResponseFromJson(Map json) =>
NightStudyResponse(
id: (json['id'] as num).toInt(),
content: json['content'] as String,
- allowCheck: json['allowCheck'] as String,
- isPhone: json['isPhone'] as bool,
- reason: json['reason'] as String,
+ status: $enumDecode(_$StatusEnumMap, json['status']),
+ doNeedPhone: json['doNeedPhone'] as bool,
+ reasonForPhone: json['reasonForPhone'] as String?,
student:
StudentResponse.fromJson(json['student'] as Map),
+ rejectReason: json['rejectReason'] as String?,
place: json['place'] as String,
- startAt: json['startAt'] as String,
- endAt: json['endAt'] as String,
- createdAt: json['createdAt'] as String,
- checkedAt: json['checkedAt'] as String?,
+ startAt: DateTime.parse(json['startAt'] as String),
+ endAt: DateTime.parse(json['endAt'] as String),
+ createdAt: DateTime.parse(json['createdAt'] as String),
+ modifiedAt: json['modifiedAt'] == null
+ ? null
+ : DateTime.parse(json['modifiedAt'] as String),
);
Map _$NightStudyResponseToJson(NightStudyResponse instance) =>
{
'id': instance.id,
'content': instance.content,
- 'allowCheck': instance.allowCheck,
- 'isPhone': instance.isPhone,
- 'reason': instance.reason,
+ 'status': _$StatusEnumMap[instance.status]!,
+ 'doNeedPhone': instance.doNeedPhone,
+ 'reasonForPhone': instance.reasonForPhone,
'student': instance.student,
+ 'rejectReason': instance.rejectReason,
'place': instance.place,
- 'startAt': instance.startAt,
- 'endAt': instance.endAt,
- 'createdAt': instance.createdAt,
- 'checkedAt': instance.checkedAt,
+ 'startAt': instance.startAt.toIso8601String(),
+ 'endAt': instance.endAt.toIso8601String(),
+ 'createdAt': instance.createdAt.toIso8601String(),
+ 'modifiedAt': instance.modifiedAt?.toIso8601String(),
};
+
+const _$StatusEnumMap = {
+ Status.ALLOWED: 'ALLOWED',
+ Status.PENDING: 'PENDING',
+ Status.REJECTED: 'REJECTED',
+};
diff --git a/lib/remote/student/reponse/student_response.dart b/lib/remote/student/reponse/student_response.dart
index c5c5c85..d07b499 100644
--- a/lib/remote/student/reponse/student_response.dart
+++ b/lib/remote/student/reponse/student_response.dart
@@ -5,12 +5,13 @@ part 'student_response.g.dart';
@JsonSerializable()
class StudentResponse extends BaseObject{
+ int? id;
String name;
int grade;
int room;
int number;
- StudentResponse({required this.name, required this.grade, required this.room, required this.number});
+ StudentResponse({this.id, required this.name, required this.grade, required this.room, required this.number});
factory StudentResponse.fromJson(Map json) =>
_$StudentResponseFromJson(json);
diff --git a/lib/remote/student/reponse/student_response.g.dart b/lib/remote/student/reponse/student_response.g.dart
index 311246d..3b1e74e 100644
--- a/lib/remote/student/reponse/student_response.g.dart
+++ b/lib/remote/student/reponse/student_response.g.dart
@@ -8,6 +8,7 @@ part of 'student_response.dart';
StudentResponse _$StudentResponseFromJson(Map json) =>
StudentResponse(
+ id: (json['id'] as num?)?.toInt(),
name: json['name'] as String,
grade: (json['grade'] as num).toInt(),
room: (json['room'] as num).toInt(),
@@ -16,6 +17,7 @@ StudentResponse _$StudentResponseFromJson(Map json) =>
Map _$StudentResponseToJson(StudentResponse instance) =>
{
+ 'id': instance.id,
'name': instance.name,
'grade': instance.grade,
'room': instance.room,
diff --git a/lib/utiles/utile.dart b/lib/utiles/utile.dart
index 9d126ec..80f0c09 100644
--- a/lib/utiles/utile.dart
+++ b/lib/utiles/utile.dart
@@ -16,3 +16,10 @@ extension DateTimeToTimeOfDay on DateTime {
return TimeOfDay.fromDateTime(this);
}
}
+
+int dateDifferenceInDays(DateTime start, DateTime end) {
+ final difference = end.difference(start);
+
+ return difference.inDays;
+}
+
diff --git a/pubspec.lock b/pubspec.lock
index 83cc890..1d7fc13 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -295,10 +295,10 @@ packages:
dependency: "direct main"
description:
name: flutter_svg
- sha256: "578bd8c508144fdaffd4f77b8ef2d8c523602275cd697cc3db284dbd762ef4ce"
+ sha256: "936d9c1c010d3e234d1672574636f3352b4941ca3decaddd3cafaeb9ad49c471"
url: "https://pub.dev"
source: hosted
- version: "2.0.14"
+ version: "2.0.15"
flutter_test:
dependency: "direct dev"
description: flutter
@@ -372,10 +372,10 @@ packages:
dependency: transitive
description:
name: js
- sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
+ sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
url: "https://pub.dev"
source: hosted
- version: "0.6.7"
+ version: "0.7.1"
json_annotation:
dependency: "direct main"
description:
@@ -388,10 +388,10 @@ packages:
dependency: "direct main"
description:
name: json_serializable
- sha256: ea1432d167339ea9b5bb153f0571d0039607a873d6e04e0117af043f14a1fd4b
+ sha256: c2fcb3920cf2b6ae6845954186420fca40bc0a8abcc84903b7801f17d7050d7c
url: "https://pub.dev"
source: hosted
- version: "6.8.0"
+ version: "6.9.0"
leak_tracker:
dependency: transitive
description:
@@ -588,10 +588,10 @@ packages:
dependency: transitive
description:
name: shelf_web_socket
- sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611"
+ sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67
url: "https://pub.dev"
source: hosted
- version: "2.0.0"
+ version: "2.0.1"
sky_engine:
dependency: transitive
description: flutter
@@ -641,26 +641,26 @@ packages:
dependency: transitive
description:
name: sqflite_common
- sha256: "4468b24876d673418a7b7147e5a08a715b4998a7ae69227acafaab762e0e5490"
+ sha256: "761b9740ecbd4d3e66b8916d784e581861fd3c3553eda85e167bc49fdb68f709"
url: "https://pub.dev"
source: hosted
- version: "2.5.4+5"
+ version: "2.5.4+6"
sqflite_common_ffi:
dependency: transitive
description:
name: sqflite_common_ffi
- sha256: d316908f1537725427ff2827a5c5f3b2c1bc311caed985fe3c9b10939c9e11ca
+ sha256: b8ba78c1b72a9ee6c2323b06af95d43fd13e03d90c8369cb454fd7f629a72588
url: "https://pub.dev"
source: hosted
- version: "2.3.4"
+ version: "2.3.4+3"
sqflite_common_ffi_web:
dependency: transitive
description:
name: sqflite_common_ffi_web
- sha256: f540ad769e5fd31aabe77bfa6e774fdd36145a83e33cdc39239f310c5f8559c3
+ sha256: "61ea702e7aba727f28be7ead00b84c19c745cd4a4934d0c41473303df11ac9ea"
url: "https://pub.dev"
source: hosted
- version: "0.4.5+3"
+ version: "0.4.5+4"
sqflite_darwin:
dependency: transitive
description:
@@ -785,10 +785,10 @@ packages:
dependency: transitive
description:
name: vector_graphics
- sha256: "773c9522d66d523e1c7b25dfb95cc91c26a1e17b107039cfe147285e92de7878"
+ sha256: "27d5fefe86fb9aace4a9f8375b56b3c292b64d8c04510df230f849850d912cb7"
url: "https://pub.dev"
source: hosted
- version: "1.1.14"
+ version: "1.1.15"
vector_graphics_codec:
dependency: transitive
description: