Skip to content

Add new quiz set attributes #3047

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

Merged
merged 48 commits into from
Jun 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
795bb8a
feat(Quizzes): Add create quizz set when finish creating quizzes - Ch…
Puppychan May 29, 2025
054cc4a
fix(Quiz Sets): Quizzes not displayed in Quiz Sets after finishing cr…
Puppychan May 29, 2025
727be5f
fix(Quiz Sets): Quizzes not displayed in Quiz Sets after finishing cr…
Puppychan May 29, 2025
ae8b50e
feat(quizset): add statistics page for each quiz set
Henry7482 May 30, 2025
96b89a0
feat (UI - Quizzes); display Quizzes following Quiz-sets, add post me…
Puppychan Jun 4, 2025
fc1939d
fix: move mutton for statistics
Henry7482 Jun 4, 2025
86c1590
feat(Taking Quiz): add taking page including backend routes, add temp…
Puppychan Jun 5, 2025
08eeb57
refractor(Taking Quiz): Clean files
Puppychan Jun 5, 2025
a062cbd
chore: remove unused components
Henry7482 Jun 6, 2025
80005e3
fix: temporarily bypass type error by casting workspace_quiz_attempts…
Henry7482 Jun 6, 2025
65ba00f
style: apply prettier formatting
Henry7482 Jun 6, 2025
7780c76
style: apply prettier formatting for feat/upskii/quiz-set-statistics …
vhpx Jun 6, 2025
f9ed408
feat (Taking Quiz); chang ebackend and frontend for more sets attributes
Puppychan Jun 8, 2025
5275499
fix(taking quizz): fix deploy
Puppychan Jun 8, 2025
2de148e
fix<(taking quizz): fix deploy
Puppychan Jun 8, 2025
2db25ca
devs(TakingQuiz); Fix deploy
Puppychan Jun 8, 2025
b3ae5e5
devs(TakingQuiz); Fix deploy
Puppychan Jun 8, 2025
06e1d54
style: apply prettier formatting
Puppychan Jun 8, 2025
f66ca3f
style: apply prettier formatting for feat/upskii/taking-quiz (#3058)
Puppychan Jun 8, 2025
c0fe66c
style: apply prettier formatting
Puppychan Jun 8, 2025
a412b36
style: apply prettier formatting for feat/upskii/taking-quiz (#3059)
vhpx Jun 9, 2025
6315b24
style: apply prettier formatting
vhpx Jun 9, 2025
aca2927
style: apply prettier formatting for feat/upskii/taking-quiz (#3060)
vhpx Jun 9, 2025
e655ec2
Merge branch 'feat/upskii/taking-quiz' into feat/upskii/quiz-set-stat…
Henry7482 Jun 9, 2025
84a5711
style: apply prettier formatting
Henry7482 Jun 9, 2025
ffeb594
Merge branch 'main' into feat/upskii/taking-quiz
vhpx Jun 9, 2025
f845860
chore(db): consolidate migration files
vhpx Jun 9, 2025
447ce10
fix (Taking Quiz): use client misused bug
Puppychan Jun 9, 2025
44831ea
style: apply prettier formatting
vhpx Jun 9, 2025
43edac1
style: apply prettier formatting for feat/upskii/taking-quiz (#3061)
vhpx Jun 9, 2025
678aeec
style: apply prettier formatting for feat/upskii/quiz-set-statistics …
vhpx Jun 9, 2025
ea2a4b4
style: apply prettier formatting
vhpx Jun 9, 2025
8d6238d
style: apply prettier formatting for feat/upskii/taking-quiz (#3065)
Puppychan Jun 9, 2025
a43abfd
refactor: update TakeQuiz component to use hooks and improve error ha…
vhpx Jun 9, 2025
dfedddd
Merge remote-tracking branch 'origin/feat/upskii/taking-quiz' into fe…
vhpx Jun 9, 2025
7bbd5c3
Merge branch 'feat/upskii/taking-quiz' into feat/upskii/quiz-set-stat…
vhpx Jun 9, 2025
01e4449
refactor: remove outdated file references in quiz set routes
vhpx Jun 9, 2025
c92c4dd
Merge branch 'feat/upskii/taking-quiz' into feat/upskii/quiz-set-stat…
vhpx Jun 9, 2025
29f86c6
refractor(Taking Quiz): Remove bug formatted comment
Puppychan Jun 9, 2025
b48d00b
style: apply prettier formatting
vhpx Jun 9, 2025
c05a751
Merge remote-tracking branch 'origin/fix/prettier-formatting-feat/ups…
Puppychan Jun 9, 2025
4351720
Merge branch 'main' into feat/upskii/taking-quiz
Puppychan Jun 9, 2025
30e8ddc
fix (Taking Quiz): fix deploy
Puppychan Jun 9, 2025
61733be
Merge remote-tracking branch 'origin/feat/upskii/taking-quiz' into fe…
Puppychan Jun 9, 2025
a977b5b
style: apply prettier formatting
Puppychan Jun 9, 2025
ae4a65d
style: apply prettier formatting for feat/upskii/taking-quiz (#3069)
Puppychan Jun 9, 2025
dd4a0b0
fix (Taking Quiz): error 404 in all pages
Puppychan Jun 9, 2025
0a15b8a
Merge remote-tracking branch 'origin/feat/upskii/taking-quiz' into fe…
Puppychan Jun 9, 2025
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
169 changes: 169 additions & 0 deletions apps/db/supabase/migrations/20250609092649_add_quiz_attempts.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
create table "public"."workspace_quiz_attempt_answers" (
"id" uuid not null default gen_random_uuid(),
"attempt_id" uuid not null,
"quiz_id" uuid not null,
"selected_option_id" uuid not null,
"is_correct" boolean not null,
"score_awarded" real not null
);


create table "public"."workspace_quiz_attempts" (
"id" uuid not null default gen_random_uuid(),
"user_id" uuid not null,
"set_id" uuid not null,
"attempt_number" integer not null,
"started_at" timestamp with time zone not null default now(),
"completed_at" timestamp with time zone,
"total_score" real
);


alter table "public"."workspace_quiz_sets" add column "attempt_limit" integer;

alter table "public"."workspace_quiz_sets" add column "time_limit_minutes" integer;

alter table "public"."workspace_quizzes" add column "score" integer not null default 1;

CREATE UNIQUE INDEX workspace_quiz_attempts_pkey ON public.workspace_quiz_attempts USING btree (id);

CREATE UNIQUE INDEX wq_answer_pkey ON public.workspace_quiz_attempt_answers USING btree (id);

CREATE UNIQUE INDEX wq_attempts_unique ON public.workspace_quiz_attempts USING btree (user_id, set_id, attempt_number);

alter table "public"."workspace_quiz_attempt_answers" add constraint "wq_answer_pkey" PRIMARY KEY using index "wq_answer_pkey";

alter table "public"."workspace_quiz_attempts" add constraint "workspace_quiz_attempts_pkey" PRIMARY KEY using index "workspace_quiz_attempts_pkey";

alter table "public"."workspace_quiz_attempt_answers" add constraint "wq_answer_attempt_fkey" FOREIGN KEY (attempt_id) REFERENCES workspace_quiz_attempts(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;

alter table "public"."workspace_quiz_attempt_answers" validate constraint "wq_answer_attempt_fkey";

alter table "public"."workspace_quiz_attempt_answers" add constraint "wq_answer_option_fkey" FOREIGN KEY (selected_option_id) REFERENCES quiz_options(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;

alter table "public"."workspace_quiz_attempt_answers" validate constraint "wq_answer_option_fkey";

alter table "public"."workspace_quiz_attempt_answers" add constraint "wq_answer_quiz_fkey" FOREIGN KEY (quiz_id) REFERENCES workspace_quizzes(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;

alter table "public"."workspace_quiz_attempt_answers" validate constraint "wq_answer_quiz_fkey";

alter table "public"."workspace_quiz_attempts" add constraint "wq_attempts_set_fkey" FOREIGN KEY (set_id) REFERENCES workspace_quiz_sets(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;

alter table "public"."workspace_quiz_attempts" validate constraint "wq_attempts_set_fkey";

alter table "public"."workspace_quiz_attempts" add constraint "wq_attempts_unique" UNIQUE using index "wq_attempts_unique";

alter table "public"."workspace_quiz_attempts" add constraint "wq_attempts_user_fkey" FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;

alter table "public"."workspace_quiz_attempts" validate constraint "wq_attempts_user_fkey";

grant delete on table "public"."workspace_quiz_attempt_answers" to "anon";

grant insert on table "public"."workspace_quiz_attempt_answers" to "anon";

grant references on table "public"."workspace_quiz_attempt_answers" to "anon";

grant select on table "public"."workspace_quiz_attempt_answers" to "anon";

grant trigger on table "public"."workspace_quiz_attempt_answers" to "anon";

grant truncate on table "public"."workspace_quiz_attempt_answers" to "anon";

grant update on table "public"."workspace_quiz_attempt_answers" to "anon";

grant delete on table "public"."workspace_quiz_attempt_answers" to "authenticated";

grant insert on table "public"."workspace_quiz_attempt_answers" to "authenticated";

grant references on table "public"."workspace_quiz_attempt_answers" to "authenticated";

grant select on table "public"."workspace_quiz_attempt_answers" to "authenticated";

grant trigger on table "public"."workspace_quiz_attempt_answers" to "authenticated";

grant truncate on table "public"."workspace_quiz_attempt_answers" to "authenticated";

grant update on table "public"."workspace_quiz_attempt_answers" to "authenticated";

grant delete on table "public"."workspace_quiz_attempt_answers" to "service_role";

grant insert on table "public"."workspace_quiz_attempt_answers" to "service_role";

grant references on table "public"."workspace_quiz_attempt_answers" to "service_role";

grant select on table "public"."workspace_quiz_attempt_answers" to "service_role";

grant trigger on table "public"."workspace_quiz_attempt_answers" to "service_role";

grant truncate on table "public"."workspace_quiz_attempt_answers" to "service_role";

grant update on table "public"."workspace_quiz_attempt_answers" to "service_role";

grant delete on table "public"."workspace_quiz_attempts" to "anon";

grant insert on table "public"."workspace_quiz_attempts" to "anon";

grant references on table "public"."workspace_quiz_attempts" to "anon";

grant select on table "public"."workspace_quiz_attempts" to "anon";

grant trigger on table "public"."workspace_quiz_attempts" to "anon";

grant truncate on table "public"."workspace_quiz_attempts" to "anon";

grant update on table "public"."workspace_quiz_attempts" to "anon";

grant delete on table "public"."workspace_quiz_attempts" to "authenticated";

grant insert on table "public"."workspace_quiz_attempts" to "authenticated";

grant references on table "public"."workspace_quiz_attempts" to "authenticated";

grant select on table "public"."workspace_quiz_attempts" to "authenticated";

grant trigger on table "public"."workspace_quiz_attempts" to "authenticated";

grant truncate on table "public"."workspace_quiz_attempts" to "authenticated";

grant update on table "public"."workspace_quiz_attempts" to "authenticated";

grant delete on table "public"."workspace_quiz_attempts" to "service_role";

grant insert on table "public"."workspace_quiz_attempts" to "service_role";

grant references on table "public"."workspace_quiz_attempts" to "service_role";

grant select on table "public"."workspace_quiz_attempts" to "service_role";

grant trigger on table "public"."workspace_quiz_attempts" to "service_role";

grant truncate on table "public"."workspace_quiz_attempts" to "service_role";

grant update on table "public"."workspace_quiz_attempts" to "service_role";

alter table "public"."workspace_quiz_sets" add column "allow_view_results" boolean not null default true;

alter table "public"."workspace_quiz_sets" add column "release_at" timestamp with time zone;

alter table "public"."workspace_quiz_sets" add column "release_points_immediately" boolean not null default true;

set check_function_bodies = off;

CREATE OR REPLACE FUNCTION public.sum_quiz_scores(p_set_id uuid)
RETURNS TABLE(sum numeric)
LANGUAGE sql
AS $function$
SELECT COALESCE(SUM(wq.score), 0)::numeric
FROM quiz_set_quizzes qsq
JOIN workspace_quizzes wq ON qsq.quiz_id = wq.id
WHERE qsq.set_id = p_set_id;
$function$
;

alter table "public"."workspace_quiz_sets" add column "due_date" timestamp with time zone not null default (now() + '7 days'::interval);

alter table "public"."workspace_quiz_sets" add column "results_released" boolean not null default false;

alter table "public"."workspace_quiz_sets" drop column "release_at";

alter table "public"."workspace_quiz_sets" drop column "results_released";
61 changes: 56 additions & 5 deletions apps/upskii/messages/en.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,43 @@
{
"quiz-set-statistics": {
"title": "Quiz Set Statistics",
"description": "View detailed statistics for your quizzes, including average scores, completion rates, and more.",
"average_pass_rate": "Average Pass Rate",
"average_score": "Average Score",
"total_participants": "Total Participants",
"total_quizzes": "Total Quizzes",
"active_quizzes": "Active quizzes in set",
"total_attempts": "Total Attempts",
"accross_all_quizzes": "Across all quizzes",
"individual_quiz_performance": "Individual Quiz Performance",
"back": "Back",
"pass_rate": "Pass Rate",
"active_students": "Active Students",
"unique_participants": "Unique participants",
"last_attempt": "Last Attempt",
"no_quizzes": "No Quiz Data Available",
"no_quizzes_description": "No quiz attempts found for this set. Students haven't started taking quizzes yet."
},
"home-hero": {
"welcome": "Welcome back, {username}!",
"badge": "Your AI-Enhanced Learning Experience",
"title": "Explore smart tools, interactive lessons, and seamless collaboration",
"cards": {
"courses": {
"title": "Courses",
"description": "Explore diverse subjects through structured lessons that build knowledge step-by-step."
"description": "Learn the fundamentals and advanced techniques of prompt engineering through step-by-step lessons and practical examples."
},
"quizzes": {
"title": "Quizzes",
"description": "Strengthen what you’ve learned with interactive quizzes across various topics."
"description": "Test your understanding with interactive quizzes designed to reinforce key concepts and sharpen your prompt design skills."
},
"challenges": {
"title": "Challenges",
"description": "Put your knowledge to the test with fun and creative real-world challenges."
"description": "Take on creative challenges that push your limits and inspire innovative prompt solutions using AI."
},
"ai-chat": {
"title": "AI Chat",
"description": "Chat with AI for instant help, study tips, and personalized learning support."
"description": "Engage in real-time conversations with AI to practice prompt engineering, get instant feedback, and refine your skills."
}
},
"get-certificate": "Get Your Certificate"
Expand Down Expand Up @@ -300,6 +319,7 @@
"events": "Events"
},
"common": {
"statistics": "Statistics",
"allow_manage_all_challenges": "Allow Manage All Challenges",
"name_placeholder": "Enter name",
"name": "Name",
Expand Down Expand Up @@ -3818,9 +3838,40 @@
"edit": "Edit quiz",
"question": "Question",
"answer": "Answer",
"question_status_title": "Question Progress",
"answered_status_short": "answered",
"quiz_progress_label": "Quiz Progress",
"question_navigation_label": "Question Navigation",
"jump_to_question_aria": "Question {{number}}, {{status}}",
"answered_state": "Answered",
"unanswered_state": "Unanswered",
"answered_icon": "✓",
"unanswered_icon": "⚪",
"time_elapsed": "Time Elapsed",
"hidden_time_elapsed": "Time Elapsed (hidden)",
"hidden_time_remaining": "Hidden Timer",
"edit_description": "Edit an existing quiz",
"generation_error": "An error has occured when generating quizzes.",
"generation_accepted": "AI-generated quizzes are accepted!"
"generation_accepted": "AI-generated quizzes are accepted!",
"please_answer_all": "Please answer all questions.",
"loading": "Loading...",
"results": "Results",
"attempt": "Attempt",
"of": "of",
"unlimited": "Unlimited Attempts",
"score": "Score",
"done": "Done",
"attempts": "Attempts",
"time_limit": "Time Limit",
"no_time_limit": "No Time Limit",
"minutes": "Minutes",
"take_quiz": "Take Quiz",
"time_remaining": "Time Remaining",
"points": "Points",
"submitting": "Submitting...",
"submit": "Submit",
"due_on": "Due on",
"quiz_past_due": "This quiz is past its due date."
},
"ws-reports": {
"report": "Report",
Expand Down
63 changes: 57 additions & 6 deletions apps/upskii/messages/vi.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,43 @@
{
"quiz-set-statistics": {
"title": "Thống Kê",
"description": "Xem thống kê chi tiết về các bài kiểm tra của bạn, bao gồm điểm trung bình, tỷ lệ hoàn thành và nhiều thông tin khác.",
"average_pass_rate": "Tỷ Lệ Đạt Trung Bình",
"average_score": "Điểm Trung Bình",
"total_participants": "Tổng Số Người Tham Gia",
"total_quizzes": "Tổng Số Bài Kiểm Tra",
"active_quizzes": "Bài kiểm tra hiện có",
"total_attempts": "Tổng Số Lượt Làm Bài",
"accross_all_quizzes": "Trên tất cả bài kiểm tra",
"individual_quiz_performance": "Số Liệu Từng Bài Kiểm Tra",
"back": "Quay Lại",
"pass_rate": "Tỷ Lệ Đạt",
"active_students": "Học Viên Đang Hoạt Động",
"unique_participants": "Người tham gia khác nhau",
"last_attempt": "Lần Làm Bài Gần Nhất",
"no_quizzes": "Không Có Dữ Liệu Bài Kiểm Tra",
"no_quizzes_description": "Không tìm thấy lượt làm bài nào cho bộ câu hỏi này. Học viên chưa bắt đầu làm bài kiểm tra."
},
"home-hero": {
"welcome": "Xin chào, {username}!",
"badge": "Trải nghiệm học tập nâng cao với AI",
"title": "Khám phá các công cụ hiện đại, bài học sinh động và cộng tác dễ dàng",
"cards": {
"courses": {
"title": "Khóa học",
"description": "Khám phá các chủ đề khác nhau qua các bài học được thiết kế từng bước rõ ràng."
"description": "Nắm vững các kỹ thuật thiết kế prompt từ cơ bản đến nâng cao thông qua bài học từng bước và ví dụ thực tiễn."
},
"quizzes": {
"title": "Trắc nghiệm",
"description": "Củng cố kiến thức qua các bài trắc nghiệm tương tác trên nhiều chủ đề."
"title": "Câu hỏi ôn tập",
"description": "Kiểm tra mức độ hiểu biết của bạn với các câu hỏi tương tác giúp củng cố kiến thức và nâng cao kỹ năng thiết kế prompt."
},
"challenges": {
"title": "Thử thách",
"description": "Vận dụng kiến thức với các thử thách thực tế sáng tạo và thú vị."
"description": "Tham gia các thử thách sáng tạo để vượt qua giới hạn khám phá các giải pháp prompt đột phá cùng AI."
},
"ai-chat": {
"title": "Trò chuyện với AI",
"description": "Trò chuyện cùng AI để nhận hỗ trợ học tập lời khuyên hữu ích."
"description": "Luyện tập kỹ năng thiết kế prompt qua các cuộc đối thoại thời gian thực với AI, nhận phản hồi ngay lập tức cải thiện hiệu quả."
}
},
"get-certificate": "Nhận chứng chỉ của bạn"
Expand Down Expand Up @@ -300,6 +319,7 @@
"events": "Sự kiện"
},
"common": {
"statistics": "Thống kê",
"allow_manage_all_challenges": "Cho phép quản lý tất cả các thử thách",
"name_placeholder": "Nhập tên",
"name": "Tên",
Expand Down Expand Up @@ -3819,9 +3839,40 @@
"edit": "Chỉnh sửa bộ trắc nghiệm",
"question": "Câu hỏi",
"answer": "Câu trả lời",
"question_status_title": "Tiến độ câu hỏi",
"answered_status_short": "đã trả lời",
"quiz_progress_label": "Tiến độ bài kiểm tra",
"question_navigation_label": "Điều hướng câu hỏi",
"jump_to_question_aria": "Câu hỏi {{number}}, {{status}}",
"answered_state": "Đã trả lời",
"unanswered_state": "Chưa trả lời",
"answered_icon": "✓",
"unanswered_icon": "⚪",
"time_elapsed": "Đã trôi qua",
"hidden_time_elapsed": "Đã ẩn thời gian",
"hidden_time_remaining": "Ẩn đếm ngược",
"edit_description": "Chỉnh sửa bài kiểm tra hiện có",
"generation_error": "Đã xảy ra lỗi khi tạo bộ câu hỏi.",
"generation_accepted": "Các bộ câu hỏi do AI tạo ra đã được chấp nhận!"
"generation_accepted": "Các bộ câu hỏi do AI tạo ra đã được chấp nhận!",
"please_answer_all": "Vui lòng trả lời tất cả các câu hỏi.",
"loading": "Đang tải...",
"results": "Kết quả",
"attempt": "Lần thử",
"of": "của",
"unlimited": "Không giới hạn số lần thi",
"score": "Điểm số",
"done": "Hoàn thành",
"attempts": "Số lần thử",
"time_limit": "Giới hạn thời gian",
"no_time_limit": "Không giới hạn thời gian",
"minutes": "Phút",
"take_quiz": "Làm bài kiểm tra",
"time_remaining": "Thời gian còn lại",
"points": "Điểm",
"submitting": "Đang gửi...",
"submit": "Nộp bài",
"due_on": "Hạn nộp",
"quiz_past_due": "Bài kiểm tra đã quá hạn"
},
"ws-reports": {
"report": "Báo cáo",
Expand Down
Loading