Skip to content

Commit

Permalink
Merge pull request #28 from seochan99/feature/profile
Browse files Browse the repository at this point in the history
✨ Feat : 단어/음소/문장 데이터 불러오기
  • Loading branch information
bunju20 authored Feb 18, 2024
2 parents f4c83d9 + 8b4a9a1 commit 536cf58
Show file tree
Hide file tree
Showing 11 changed files with 134 additions and 34 deletions.
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],
),
);
}
}

0 comments on commit 536cf58

Please sign in to comment.