Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Feat : 단어/음소/문장 데이터 불러오기 #28

Merged
merged 5 commits into from
Feb 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified assets/images/study/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/images/study/2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/images/study/3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/images/study/4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>io.flutter.embedded_views_preview</key>
<true/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
Expand Down
5 changes: 5 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:earlips/main_app.dart';
import 'package:flutter/services.dart';

void main() async {
/* Open .env file */
await dotenv.load(fileName: "assets/config/.env");
await initializeDateFormatting();
await EasyLocalization.ensureInitialized();

await SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
Expand Down
8 changes: 6 additions & 2 deletions lib/models/word_card_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ class WordCard {
final String word;
final String speaker;
final String video;
final int type;

WordCard({
required this.id,
required this.word,
required this.speaker,
required this.video,
required this.type,
});

Map<String, dynamic> toMap() {
Expand All @@ -17,6 +19,7 @@ class WordCard {
'word': word,
'speaker': speaker,
'video': video,
'type': type,
};
}

Expand All @@ -26,22 +29,23 @@ class WordCard {
word: doc['word'],
speaker: doc['speaker'],
video: doc['video'],
type: doc['type'],
);
}

WordCard copyWith({
int? id,
String? word,
String? speaker,
bool? isDone,
String? doneDate,
String? video,
int? type,
}) {
return WordCard(
id: id ?? this.id,
word: word ?? this.word,
speaker: speaker ?? this.speaker,
video: video ?? this.video,
type: type ?? this.type,
);
}
}
56 changes: 49 additions & 7 deletions lib/viewModels/word/word_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,17 @@ import 'package:intl/intl.dart';
class WordViewModel extends GetxController {
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
final FirebaseAuth _auth = FirebaseAuth.instance;
final int type;

RxList<WordData> wordList = RxList<WordData>([]);
RxInt currentIndex = 0.obs;

WordViewModel({required this.type});

@override
void onInit() {
super.onInit();
fetchWords();
fetchWords();
fetchWords(type);
wordList.refresh();
}

Expand All @@ -26,11 +28,15 @@ class WordViewModel extends GetxController {
}

// 단어 데이터 가져오기
Future<void> fetchWords() async {
Future<void> fetchWords(int type) async {
final uid = _auth.currentUser?.uid;
if (uid != null) {
// 모든 단어 데이터 가져오기
final wordsQuery = await _firestore.collection('words').get();
final wordsQuery = await _firestore
.collection('words')
.where('type', isEqualTo: type)
.get();

final allWords = wordsQuery.docs
.map((doc) => WordCard.fromDocument(doc.data()))
.toList();
Expand Down Expand Up @@ -62,8 +68,10 @@ class WordViewModel extends GetxController {
// 단어 완료 처리
Future<void> markWordAsDone(WordCard word) async {
final uid = _auth.currentUser?.uid;
String currentDate = DateFormat('yyyy/MM/dd').format(DateTime.now());

if (uid != null) {
// Add or update data in the user's 'words' subcollection in Firestore
// 유저 단어 데이터 업데이트
await _firestore
.collection('users')
.doc(uid)
Expand All @@ -72,13 +80,47 @@ class WordViewModel extends GetxController {
.set({
'wordId': word.id,
'isDone': true,
'doneDate': DateFormat('yyyy/MM/dd').format(DateTime.now()),
'doneDate': currentDate,
});

// 유저 record 업데이트
DocumentReference recordRef = _firestore
.collection('users')
.doc(uid)
.collection('records')
.doc(DateFormat('yyyyMMdd').format(DateTime.now()));

try {
await _firestore.runTransaction((transaction) async {
// Get the current record
DocumentSnapshot recordSnapshot = await transaction.get(recordRef);

if (recordSnapshot.exists) {
String existingDate = recordSnapshot.get('date');
if (existingDate == currentDate) {
transaction.update(recordRef, {
'cnt': FieldValue.increment(1),
});
}
} else {
print('different date!!!!!!!!!!!!!');
transaction.set(recordRef, {
'cnt': 1,
'date': currentDate,
'dateFormat': DateTime.now(),
});
}
});
} catch (e) {
print("Transaction failed: $e");
}
// 로컬에서 단어 데이터 업데이트
final index =
wordList.indexWhere((element) => element.wordCard.id == word.id);

// 만약 로컬에서 단어를 찾지 못했을 경우를 대비
if (index != -1) {
// Handle the scenario where we don't find the card locally.
// 단어 데이터 업데이트
wordList[index] = WordData(
wordCard: word,
userWord: UserWord(
Expand Down
14 changes: 6 additions & 8 deletions lib/views/study/date_study_screen.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:earlips/views/base/default_back_appbar.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
// ViewModel import 경로는 실제 프로젝트 구조에 따라 달라질 수 있습니다.
Expand All @@ -13,14 +14,11 @@ class DateStudyScreen extends StatelessWidget {
final sessions = viewModel.getSessions();

return Scaffold(
appBar: AppBar(
title: Text(DateFormat('yyyy/MM/dd').format(date),
style: const TextStyle(
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.w500,
)), // 동적으로 날짜를 표시
centerTitle: true,
appBar: PreferredSize(
preferredSize: const Size.fromHeight(kToolbarHeight),
child: DefaultBackAppbar(
title: DateFormat('yyyy/MM/dd').format(date),
),
),
body: ListView.separated(
padding: const EdgeInsets.fromLTRB(25, 20, 25, 20),
Expand Down
16 changes: 9 additions & 7 deletions lib/views/word/widget/word_list_widget.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import 'package:earlips/models/word_card_model.dart';
import 'package:earlips/models/word_data_model.dart';
import 'package:earlips/utilities/style/color_styles.dart';
import 'package:earlips/viewModels/word/word_viewmodel.dart';
Expand All @@ -7,11 +6,15 @@ import 'package:get/get.dart';

class WordList extends StatefulWidget {
final List<WordData> wordDataList;
final int type;

PageController pageController;

WordList(
{super.key, required this.wordDataList, required this.pageController});
{super.key,
required this.wordDataList,
required this.pageController,
required this.type});

@override
_WordListState createState() => _WordListState();
Expand All @@ -38,7 +41,6 @@ class _WordListState extends State<WordList> {
setState(() {
wordViewModel.currentIndex.value = index;
});
print('currentIndex: ${wordViewModel.currentIndex.value}');
},
itemBuilder: (context, index) {
final wordData = widget.wordDataList[index];
Expand Down Expand Up @@ -102,17 +104,17 @@ class _WordListState extends State<WordList> {
tileColor: Colors.white,
title: Text(
wordData.wordCard.word,
style: const TextStyle(
fontSize: 24,
style: TextStyle(
fontSize: widget.type == 2 ? 19 : 24,
fontWeight: FontWeight.w600,
color: ColorSystem.black,
),
textAlign: TextAlign.center,
),
subtitle: Text(
wordData.wordCard.speaker,
style: const TextStyle(
fontSize: 16,
style: TextStyle(
fontSize: widget.type == 2 ? 16 : 20,
fontWeight: FontWeight.w600,
color: ColorSystem.gray4,
),
Expand Down
67 changes: 57 additions & 10 deletions lib/views/word/word_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ class WordScreen extends StatelessWidget {

@override
Widget build(BuildContext context) {
final wordViewModel = Get.put(WordViewModel());
final wordViewModel = Get.put(WordViewModel(
type: type,
));

final PageController pageController =
PageController(initialPage: wordViewModel.currentIndex.value);
Expand Down Expand Up @@ -43,6 +45,7 @@ class WordScreen extends StatelessWidget {
builder: (controller) => WordList(
// viewmodel
wordDataList: controller.wordList,
type: type,
pageController: pageController,
),
),
Expand All @@ -67,20 +70,40 @@ class WordScreen extends StatelessWidget {
],
),
),

const Spacer(),
// wordViewModel final String video로 영상 유튜브 링크를 바로 볼 수 있게 하기
const Padding(
padding: EdgeInsets.all(20.0),
// child: YoutubeWordPlayer(),
),
const Spacer(),
// wordViewModel final String video로 영상 유튜브 링크를 바로 볼 수 있게 하기
ElevatedButton(
onPressed: () {
Get.toNamed(
'/video',
arguments: wordViewModel
.wordList[wordViewModel.currentIndex.value]
.wordCard
.video,
onPressed: () async {
await wordViewModel.markWordAsDone(wordViewModel
.wordList[wordViewModel.currentIndex.value].wordCard);

// YouTubePlayer 위젯 추가
Get.dialog(
AlertDialog(
title: const Text('동영상 재생'),
content: Column(
children: [
YoutubePlayer(
controller: YoutubePlayerController(
initialVideoId: wordViewModel
.wordList[wordViewModel.currentIndex.value]
.wordCard
.video
.split('v=')[1],
),
),
],
),
),
);
},
child: const Text("영상 보기"),
child: const Text(""),
),
ElevatedButton(
onPressed: () async {
Expand Down Expand Up @@ -121,3 +144,27 @@ class WordScreen extends StatelessWidget {
);
}
}

class YoutubeWordPlayer extends StatefulWidget {
const YoutubeWordPlayer({super.key});

@override
State<YoutubeWordPlayer> createState() => _YoutubeWordPlayerState();
}

class _YoutubeWordPlayerState extends State<YoutubeWordPlayer> {
final wordViewModel = Get.find<WordViewModel>();

@override
Widget build(BuildContext context) {
print(
'video: ${wordViewModel.wordList[wordViewModel.currentIndex.value].wordCard.video}');
return YoutubePlayer(
controller: YoutubePlayerController(
initialVideoId: wordViewModel
.wordList[wordViewModel.currentIndex.value].wordCard.video
.split('v=')[1],
),
);
}
}
Loading