Skip to content

Commit

Permalink
Feature: Threads (#44)
Browse files Browse the repository at this point in the history
Signed-off-by: Rhon <68691486+draqunov10@users.noreply.github.com>
  • Loading branch information
draqunov10 authored Apr 23, 2024
1 parent 095f7ab commit 531cc74
Show file tree
Hide file tree
Showing 13 changed files with 163 additions and 75 deletions.
22 changes: 14 additions & 8 deletions lib/core/models/firestore_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:scholars_guide/core/models/question_model.dart';

class FireStore {
//* Collection names in the Firestore
static const usersCollection = 'users';
static const solutionsCollection = 'solutions';
static const commentsCollection = 'comments';
static const additionalQuestionDataRef = 'additionalQuestionsData';
Expand All @@ -18,26 +19,31 @@ class FireStore {
//* Field names of each document in the Firestore
// Question related fields
static const String question = 'question';
static const String solutionRef = 'solutionsRef';
static const String solutionData = 'solutionData';
static const String options = 'choices';
static const String correctIndex = 'correctChoiceKey';
// static const String questionReference = 'additionalQuestionDataRef';
// static const String isVerified = 'isVerified';

// User related fields
// Solutions related fields
static const String solutionRef = 'solutionsRef';
static const String solutionData = 'solutionData';

// Comment related fields
static const String commentRef = 'commentsRef';
static const String commentArray = 'commentsArray';
static const String commentData = 'commentData';
static const String commentInitials = 'commentInitials';
static const String commentName = 'commentName';
static const String upvotes = 'upvotesCount';

// General fields
static const String createdAt = 'createdAt';
static const String createdBy = 'createdByRef';
static const String updatedAt = 'updatedAt';
static const String updatedBy = 'lastUpdatedByRef';
static const String verifiedAt = 'verifiedAt';
static const String verifiedBy = 'verifiedByRef';

// Review related fields
static const String solutions = 'solutionsRefs';
static const String comments = 'commentsRef';
static const String upvotes = 'upvotesCount';

static String SUBJ2subject(SUBJ subj) {
return subjects[subj] as String;
}
Expand Down
4 changes: 4 additions & 0 deletions lib/core/models/question_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class Question {
this.id = '',
this.solution = '',
this.solutionRef,
this.commentRef,
this.createdBy,
});

Expand All @@ -26,6 +27,7 @@ class Question {
String id;
String solution;
DocumentReference? solutionRef;
DocumentReference? commentRef;

DocumentReference? createdBy;
final FieldValue createdAt = FieldValue.serverTimestamp();
Expand Down Expand Up @@ -57,6 +59,7 @@ class Question {
subject: subject,
question: data[FireStore.question],
solutionRef: data[FireStore.solutionRef],
commentRef: data[FireStore.commentRef],
options: temp,
correctIndex: temp.indexWhere((element) => element == temp2),
createdBy: data[FireStore.createdBy]);
Expand All @@ -74,6 +77,7 @@ class Question {
},
FireStore.correctIndex: correctIndex.toString(),
FireStore.solutionRef: solutionRef,
FireStore.commentRef: commentRef,
FireStore.createdBy: createdBy,
FireStore.createdAt: createdAt,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// import 'package:scholars_guide/service_locator/service_locator.dart';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:scholars_guide/core/models/firestore_model.dart';
import 'package:scholars_guide/core/models/question_model.dart';
import 'package:scholars_guide/features/quiz_mode/domain/repositories_contract/quiz_mode_repository_contract.dart';
Expand All @@ -17,12 +18,27 @@ class QuizModeRepositoryImpl implements QuizModeRepositoryContract {
final dbService = services<FirebaseFirestore>();
List<Question> questions = [];

// * Fetching the questions from the Firestore
// * Fetching all questions of the chosen subject from the Firestore
await dbService
.collection(FireStore.SUBJ2subject(subj))
.get()
.then((snapshot) {
print("GETTING QUESTIONS");
.then((snapshot) async {
// * In case the question does not have a comment reference yet for old questions
for (var e in snapshot.docs) {
Map<String, dynamic> data = e.data();
if (!data.containsKey(FireStore.commentRef)) {
print("CREATING COMMENT REFERENCE TO: ${data[FireStore.question]}");
// Uploading a comment section of this post to the database
DocumentReference comRef =
await dbService.collection(FireStore.commentsCollection).add({
FireStore.commentArray: [],
});
// Updating the question reference with the comment reference
e.reference.update({FireStore.commentRef: comRef});
}
}

// * Mapping the fetched data to the Question model and adding it to the list
snapshot.docs
.map((e) => questions.add(Question.fromMap(e.id, e.data(), subj)))
.toList();
Expand All @@ -38,17 +54,37 @@ class QuizModeRepositoryImpl implements QuizModeRepositoryContract {
}

@override
Future<List> collectComments({required String questionId}) async {
final dbService = services<FirebaseFirestore>();
List comments = [];
Future<List> collectComments({required DocumentReference docRef}) async {
List<Map> comments = [];

// await dbService
// .collection(FireStore.question2comments(questionId))
// .get()
// .then((snapshot) {
// snapshot.docs.map((e) => comments.add(e.data())).toList();
// });
await docRef.get().then((value) {
value[FireStore.commentArray].forEach((element) {
comments.add(element);
});
});

return comments;
}

void addComment(
{required DocumentReference docRef, required String comment}) {
final authService = services<FirebaseAuth>();
final dbService = services<FirebaseFirestore>();

final DocumentReference userRef = dbService
.collection(FireStore.usersCollection)
.doc(authService.currentUser?.uid);

docRef.update({
FireStore.commentArray: FieldValue.arrayUnion([
{
FireStore.commentData: comment,
FireStore.createdAt: Timestamp.now(),
FireStore.createdBy: userRef,
FireStore.commentInitials: userRef.id.substring(0, 2),
FireStore.commentName: userRef.id.substring(0, 5),
}
])
});
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import 'package:cloud_firestore/cloud_firestore.dart';

import '../../../../core/models/question_model.dart';

abstract class QuizModeRepositoryContract {
const QuizModeRepositoryContract();

Future<List<Question>> collectQuestions({required SUBJ subj});

Future<List> collectComments({required String questionId});
Future<List> collectComments({required DocumentReference docRef});
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class _SolutionsQuizPageState extends State<SolutionsQuizPage> {
answer: questions[index]
.optionsArray[questions[index].correctIndex],
solution: questions[index].solution,
commentRef: questions[index].commentRef,
),
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// ignore_for_file: prefer_const_constructors

import 'package:bloc/bloc.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:equatable/equatable.dart';
import 'package:scholars_guide/features/quiz_mode/presentation/state_management/quiz_card/quiz_card_cubit.dart';
import '../../../../../core/models/question_model.dart';
Expand All @@ -27,7 +28,8 @@ class QuizBloc extends Bloc<QuizEvent, QuizState> {
correctIndex: e.correctIndex,
optionsArray: e.options,
question: e.question,
solution: e.solution))
solution: e.solution,
commentRef: e.commentRef as DocumentReference))
.toList());
});
} else {
Expand All @@ -41,7 +43,8 @@ class QuizBloc extends Bloc<QuizEvent, QuizState> {
correctIndex: e.correctIndex,
optionsArray: e.options,
question: e.question,
solution: e.solution))
solution: e.solution,
commentRef: e.commentRef as DocumentReference))
.toList()
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:bloc/bloc.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:equatable/equatable.dart';

part 'quiz_card_state.dart';
Expand All @@ -9,12 +10,14 @@ class QuizCardCubit extends Cubit<QuizCardState> {
required this.optionsArray,
required this.question,
required this.solution,
required this.commentRef,
}) : super(QuizCardUnanswered());

final int correctIndex;
final List<String> optionsArray;
final String question;
final String solution;
final DocumentReference commentRef;

void chooseOption({required int index}) {
emit(QuizCardUnanswered());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ class ConfirmCancelQuizDialogue extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
TextButton(
child: const Text('Continue Quiz'),
child: const Text('Go Back'),
onPressed: () {
Navigator.of(context).pop();
GoRouter.of(context).go('/quiz-mode');
},
),
TextButton(
child: const Text('Go Back'),
child: const Text('Continue Quiz'),
onPressed: () {
Navigator.of(context).pop();
GoRouter.of(context).go('/quiz-mode');
},
),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ class ConfirmSubmitQuizDialogue extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
TextButton(
child: const Text('Go Back'),
onPressed: () {
Navigator.of(context).pop();
},
),
TextButton(
child: const Text('Submit Quiz'),
onPressed: () {
Expand All @@ -44,12 +50,6 @@ class ConfirmSubmitQuizDialogue extends StatelessWidget {
});
},
),
TextButton(
child: const Text('Go Back'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@ class SubjectChosenDialogue extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
TextButton(
child: const Text('Start'),
child: const Text('Go Back'),
onPressed: () {
Navigator.of(context).pop();
GoRouter.of(context).go('/quiz-mode/start-quiz',
extra: Question.string2SUBJ(subjectTest));
},
),
TextButton(
child: const Text('Go Back'),
child: const Text('Start'),
onPressed: () {
Navigator.of(context).pop();
GoRouter.of(context).go('/quiz-mode/start-quiz',
extra: Question.string2SUBJ(subjectTest));
},
),
],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
// ignore_for_file: prefer_const_constructors, prefer_const_literals_to_create_immutables

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:flutter_markdown_latex/flutter_markdown_latex.dart';
import 'package:markdown/markdown.dart' as md;
import 'package:scholars_guide/features/quiz_mode/data/repositories/quiz_mode_repository_impl.dart';
import 'package:scholars_guide/features/quiz_mode/domain/repositories_contract/quiz_mode_repository_contract.dart';
import 'package:scholars_guide/features/quiz_mode/presentation/widgets/quiz_page_widgets/question_loading_display.dart';
import 'package:scholars_guide/features/quiz_mode/presentation/widgets/solution_quiz_page_widgets/solution_comment_modal.dart';

class SolutionCardDisplay extends StatefulWidget {
const SolutionCardDisplay(
{super.key,
required this.question,
required this.answer,
required this.solution});
required this.solution,
required this.commentRef});

final String question;
final String answer;
final String solution;
final DocumentReference commentRef;

@override
State<SolutionCardDisplay> createState() => _SolutionCardDisplayState();
Expand Down Expand Up @@ -62,24 +68,31 @@ class _SolutionCardDisplayState extends State<SolutionCardDisplay> {
),
),
),
TextTitle(title: "Comments"),
TextMarkdown(
// ! To Remove
text: "Coming soon!",
styleSheet: MarkdownStyleSheet(
textAlign: WrapAlignment.center,
p: const TextStyle(fontSize: 18),
),
),
ElevatedButton(
onPressed: () {
showModalBottomSheet(
context: context,
showDragHandle: true,
builder: (BuildContext context) => SolutionCommentModal(),
builder: (BuildContext context) => FutureBuilder(
future: QuizModeRepositoryImpl()
.collectComments(docRef: widget.commentRef),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return QuestionLoadingDisplay();
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
return SolutionCommentModal(
docRef: widget.commentRef,
comments: snapshot.data,
);
}
},
),
);
},
child: Text("Experimental"),
child: TextTitle(title: "Comments"),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
Expand Down
Loading

0 comments on commit 531cc74

Please sign in to comment.