Skip to content

Commit

Permalink
Merge pull request #27 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 62f8bdf + 3894def commit f4c83d9
Show file tree
Hide file tree
Showing 12 changed files with 445 additions and 171 deletions.
21 changes: 21 additions & 0 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,13 @@ PODS:
- nanopb (< 2.30910.0, >= 2.30908.0)
- FirebaseSharedSwift (10.21.0)
- Flutter (1.0.0)
- flutter_inappwebview (0.0.1):
- Flutter
- flutter_inappwebview/Core (= 0.0.1)
- OrderedSet (~> 5.0)
- flutter_inappwebview/Core (0.0.1):
- Flutter
- OrderedSet (~> 5.0)
- flutter_localization (0.0.1):
- Flutter
- flutter_native_splash (0.0.1):
Expand Down Expand Up @@ -813,6 +820,7 @@ PODS:
- nanopb/encode (= 2.30909.1)
- nanopb/decode (2.30909.1)
- nanopb/encode (2.30909.1)
- OrderedSet (5.0.0)
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
Expand All @@ -827,13 +835,17 @@ PODS:
- Flutter
- Try
- Try (2.1.1)
- video_player_avfoundation (0.0.1):
- Flutter
- FlutterMacOS

DEPENDENCIES:
- cloud_firestore (from `.symlinks/plugins/cloud_firestore/ios`)
- firebase_auth (from `.symlinks/plugins/firebase_auth/ios`)
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
- firebase_database (from `.symlinks/plugins/firebase_database/ios`)
- Flutter (from `Flutter`)
- flutter_inappwebview (from `.symlinks/plugins/flutter_inappwebview/ios`)
- flutter_localization (from `.symlinks/plugins/flutter_localization/ios`)
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
Expand All @@ -843,6 +855,7 @@ DEPENDENCIES:
- permission_handler (from `.symlinks/plugins/permission_handler/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- speech_to_text (from `.symlinks/plugins/speech_to_text/ios`)
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`)

SPEC REPOS:
trunk:
Expand All @@ -868,6 +881,7 @@ SPEC REPOS:
- GTMSessionFetcher
- leveldb-library
- nanopb
- OrderedSet
- PromisesObjC
- RecaptchaInterop
- Try
Expand All @@ -883,6 +897,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/firebase_database/ios"
Flutter:
:path: Flutter
flutter_inappwebview:
:path: ".symlinks/plugins/flutter_inappwebview/ios"
flutter_localization:
:path: ".symlinks/plugins/flutter_localization/ios"
flutter_native_splash:
Expand All @@ -901,6 +917,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
speech_to_text:
:path: ".symlinks/plugins/speech_to_text/ios"
video_player_avfoundation:
:path: ".symlinks/plugins/video_player_avfoundation/darwin"

SPEC CHECKSUMS:
abseil: 926fb7a82dc6d2b8e1f2ed7f3a718bce691d1e46
Expand All @@ -921,6 +939,7 @@ SPEC CHECKSUMS:
FirebaseFirestoreInternal: 7ac1e0c5b4e75aeb898dfe4b1d6d77abbac9eca3
FirebaseSharedSwift: 19b3f709993d6fa1d84941d41c01e3c4c11eab93
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_inappwebview: 3d32228f1304635e7c028b0d4252937730bbc6cf
flutter_localization: f43b18844a2b3d2c71fd64f04ffd6b1e64dd54d4
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
Expand All @@ -935,13 +954,15 @@ SPEC CHECKSUMS:
GTMSessionFetcher: 8a1b34ad97ebe6f909fb8b9b77fba99943007556
leveldb-library: e74c27d8fbd22854db7cb467968a0b8aa1db7126
nanopb: d4d75c12cd1316f4a64e3c6963f879ecd4b5e0d5
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
permission_handler: ccb20a9fad0ee9b1314a52b70b76b473c5f8dab0
PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4
RecaptchaInterop: 7d1a4a01a6b2cb1610a47ef3f85f0c411434cb21
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
speech_to_text: b43a7d99aef037bd758ed8e45d79bbac035d2dfe
Try: 5ef669ae832617b3cee58cb2c6f99fb767a4ff96
video_player_avfoundation: 02011213dab73ae3687df27ce441fbbcc82b5579

PODFILE CHECKSUM: 0b2c97823421f8b156b8e4753a469ac167670df8

Expand Down
Empty file removed lib/models/temp
Empty file.
27 changes: 27 additions & 0 deletions lib/models/user_word_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
class UserWord {
final int wordId;
final bool isDone;
final String? doneDate;

UserWord({
required this.wordId,
required this.isDone,
this.doneDate,
});

Map<String, dynamic> toMap() {
return {
'wordId': wordId,
'isDone': isDone,
'doneDate': doneDate,
};
}

factory UserWord.fromDocument(Map<String, dynamic> doc) {
return UserWord(
wordId: doc['wordId'],
isDone: doc['isDone'],
doneDate: doc['doneDate'],
);
}
}
47 changes: 47 additions & 0 deletions lib/models/word_card_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
class WordCard {
final int id;
final String word;
final String speaker;
final String video;

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

Map<String, dynamic> toMap() {
return {
'id': id,
'word': word,
'speaker': speaker,
'video': video,
};
}

factory WordCard.fromDocument(Map<String, dynamic> doc) {
return WordCard(
id: doc['id'],
word: doc['word'],
speaker: doc['speaker'],
video: doc['video'],
);
}

WordCard copyWith({
int? id,
String? word,
String? speaker,
bool? isDone,
String? doneDate,
String? video,
}) {
return WordCard(
id: id ?? this.id,
word: word ?? this.word,
speaker: speaker ?? this.speaker,
video: video ?? this.video,
);
}
}
12 changes: 12 additions & 0 deletions lib/models/word_data_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import 'package:earlips/models/user_word_model.dart';
import 'package:earlips/models/word_card_model.dart';

class WordData {
final WordCard wordCard;
final UserWord? userWord;

WordData({
required this.wordCard,
this.userWord,
});
}
1 change: 1 addition & 0 deletions lib/services/auth/auth_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class AuthService {

// 사용자 데이터
final userData = {
'uid': userCredential.user!.uid,
'systemLanguage': 'kr',
'learningLanguage': 'kr',
'nickname': extractNickname(googleUser!.email), // @ 앞까지만 추출
Expand Down
3 changes: 1 addition & 2 deletions lib/viewModels/auth/email_signup_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@ import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:earlips/utilities/validators/auth_validators.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:get/get.dart';

class EmailSignupViewModel extends GetxController {
final formKey = GlobalKey<FormState>();
final emailController = TextEditingController();
final passwordController = TextEditingController();
final FlutterSecureStorage _storage = const FlutterSecureStorage();

// Email Validator
String? emailValidator(String? value) {
Expand Down Expand Up @@ -44,6 +42,7 @@ class EmailSignupViewModel extends GetxController {

// 사용자 데이터
final userData = {
'uid': userCredential.user!.uid,
'systemLanguage': 'kr',
'learningLanguage': 'kr',
'nickname': extractNickname(emailController.text.trim()),
Expand Down
43 changes: 43 additions & 0 deletions lib/viewModels/user/user_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,40 @@ class UserViewModel extends GetxController {
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
final storage = const FlutterSecureStorage(); // Instance for secure storage

// final List<WordCard> wordList = [
// WordCard(
// id: 1,
// word: "강",
// speaker: "가-앙",
// video: "https://www.youtube.com/watch?v=OzHrIz-wMLA"),
// WordCard(
// id: 2,
// word: "서",
// speaker: "가-앙",
// video: "https://www.youtube.com/watch?v=OzHrIz-wMLA"),
// WordCard(
// id: 3,
// word: "희",
// speaker: "가-앙",
// video: "https://www.youtube.com/watch?v=OzHrIz-wMLA"),
// WordCard(
// id: 4,
// word: "찬",
// speaker: "차-안",
// video: "https://www.youtube.com/watch?v=OzHrIz-wMLA"),
// WordCard(
// id: 5,
// word: "캬",
// speaker: "캬",
// video: "https://www.youtube.com/watch?v=OzHrIz-wMLA"),
// ];

// for (final word in wordList) {
// await FirebaseFirestore.instance
// .collection('words')
// .doc(word.id.toString())
// .set(word.toMap());
// }
// User Profile Data
final Rx<User?> _firebaseUser = Rx<User?>(null);
String? get uid => _firebaseUser.value?.uid;
Expand All @@ -31,6 +65,15 @@ class UserViewModel extends GetxController {

Future<void> getUserData() async {
if (uid != null) {
// // users 컬렉션의 하위 컬렉션에 단어 완료 정보 삽입
// for (final word in wordList) {
// await FirebaseFirestore.instance
// .collection('users')
// .doc(uid)
// .collection('words')
// .doc(word.id.toString())
// .set(UserWord(wordId: word.id, isDone: false).toMap());
// }
final doc = await _firestore.collection('users').doc(uid).get();
userData.value = doc.data() ?? {};
nickname.value = userData.value['nickname'] ?? '';
Expand Down
94 changes: 94 additions & 0 deletions lib/viewModels/word/word_viewmodel.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:earlips/models/user_word_model.dart';
import 'package:earlips/models/word_card_model.dart';
import 'package:earlips/models/word_data_model.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';

class WordViewModel extends GetxController {
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
final FirebaseAuth _auth = FirebaseAuth.instance;

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

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

void updateCurrentIndex(int index) {
currentIndex.value = index;
}

// 단어 데이터 가져오기
Future<void> fetchWords() async {
final uid = _auth.currentUser?.uid;
if (uid != null) {
// 모든 단어 데이터 가져오기
final wordsQuery = await _firestore.collection('words').get();
final allWords = wordsQuery.docs
.map((doc) => WordCard.fromDocument(doc.data()))
.toList();

// 현재 사용자의 단어 데이터 가져오기
final userWordsQuery = await _firestore
.collection('users')
.doc(uid)
.collection('words')
.get();
final userWords = userWordsQuery.docs
.map((doc) => UserWord.fromDocument(doc.data()))
.toList();

// 모든 단어 데이터에 사용자의 단어 데이터를 추가
wordList.value = allWords.map((word) {
final matchingUserWord = userWords
.firstWhereOrNull((userWord) => userWord.wordId == word.id);

return WordData(
wordCard: word,
userWord: matchingUserWord,
);
}).toList();
update();
}
}

// 단어 완료 처리
Future<void> markWordAsDone(WordCard word) async {
final uid = _auth.currentUser?.uid;
if (uid != null) {
// Add or update data in the user's 'words' subcollection in Firestore
await _firestore
.collection('users')
.doc(uid)
.collection('words')
.doc(word.id.toString())
.set({
'wordId': word.id,
'isDone': true,
'doneDate': DateFormat('yyyy/MM/dd').format(DateTime.now()),
});

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(
wordId: word.id,
isDone: true,
doneDate: DateFormat('yyyy/MM/dd').format(DateTime.now()),
),
);
wordList.refresh();
}
}
}
}
Loading

0 comments on commit f4c83d9

Please sign in to comment.