Skip to content

Add result monitoring for quiz sets #3010

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

Closed
wants to merge 38 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
38 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
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
1b1d941
fix: get results data from backend
Henry7482 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
44 changes: 44 additions & 0 deletions apps/upskii/messages/en.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,47 @@
{
"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."
},
Comment on lines +2 to +20
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Typo & Label Casing in "quiz-set-statistics"

  • Rename "accross_all_quizzes" to "across_all_quizzes" to correct spelling.
  • Consider capitalizing the value for "active_quizzes" to "Active Quizzes in Set" for consistency with other labels.
🤖 Prompt for AI Agents
In apps/upskii/messages/en.json between lines 2 and 20, correct the typo in the
key "accross_all_quizzes" by renaming it to "across_all_quizzes". Also, update
the value of "active_quizzes" to "Active Quizzes in Set" to maintain consistent
capitalization with other labels in the "quiz-set-statistics" section.

"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": "Learn the fundamentals and advanced techniques of prompt engineering through step-by-step lessons and practical examples."
},
"quizzes": {
"title": "Quizzes",
"description": "Test your understanding with interactive quizzes designed to reinforce key concepts and sharpen your prompt design skills."
},
"challenges": {
"title": "Challenges",
"description": "Take on creative challenges that push your limits and inspire innovative prompt solutions using AI."
},
"ai-chat": {
"title": "AI Chat",
"description": "Engage in real-time conversations with AI to practice prompt engineering, get instant feedback, and refine your skills."
}
},
"get-certificate": "Get Your Certificate"
},
"score-calculator": {
"title": "Score Calculator",
"subtitle": "Calculate your submission score based on test results and criteria evaluation",
Expand Down Expand Up @@ -276,6 +319,7 @@
"events": "Events"
},
"common": {
"statistics": "Statistics",
"allow_manage_all_challenges": "Allow Manage All Challenges",
"name_placeholder": "Enter name",
"name": "Name",
Expand Down
44 changes: 44 additions & 0 deletions apps/upskii/messages/vi.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,47 @@
{
"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."
},
Comment on lines +2 to +20
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Typo in key "accross_all_quizzes"
The key "accross_all_quizzes" is misspelled and should be "across_all_quizzes" to align with proper spelling and the English file.
Apply this diff:

-    "accross_all_quizzes": "Trên tất cả bài kiểm tra",
+    "across_all_quizzes": "Trên tất cả bài kiểm tra",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"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."
},
"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",
"across_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."
},
🤖 Prompt for AI Agents
In apps/upskii/messages/vi.json around lines 2 to 20, the key
"accross_all_quizzes" is misspelled. Rename the key to "across_all_quizzes" to
correct the spelling and maintain consistency with the English version.

"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": "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": "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": "Tham gia các thử thách sáng tạo để vượt qua giới hạn và 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": "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 và cải thiện hiệu quả."
}
},
"get-certificate": "Nhận chứng chỉ của bạn"
},
"score-calculator": {
"test_formula": "(Số Bài Đạt / Tổng Số Bài Kiểm Tra) × 10 × Trọng Số",
"criteria_formula": "(Tổng Điểm Tiêu Chí / (Tổng Số Tiêu Chí × 10)) × 10 × Trọng Số",
Expand Down Expand Up @@ -276,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
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import { Separator } from '@tuturuuu/ui/separator';
import { getTranslations } from 'next-intl/server';
import { notFound } from 'next/navigation';
import { ReactNode } from 'react';
import { Button } from "@tuturuuu/ui/button"
import Link from "next/link"
import { BarChart3 } from "@tuturuuu/ui/icons"



interface Props {
children: ReactNode;
Expand Down Expand Up @@ -64,6 +69,14 @@ export default async function QuizSetDetailsLayout({
</div>
</>
}
action={
<Button variant="outline" className="gap-2" asChild>
<Link href={`/${wsId}/quiz-sets/${setId}/statistics`}>
<BarChart3 className="h-4 w-4" />
{t("common.statistics")}
</Link>
</Button>
}
/>
<Separator className="my-4" />
{children}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,45 +1,44 @@
import { getWorkspaceQuizColumns } from './columns';
import QuizForm from './form';
import { CustomDataTable } from '@/components/custom-data-table';
import { createClient } from '@tuturuuu/supabase/next/server';
import { WorkspaceQuiz } from '@tuturuuu/types/db';
import FeatureSummary from '@tuturuuu/ui/custom/feature-summary';
import { Separator } from '@tuturuuu/ui/separator';
import { getTranslations } from 'next-intl/server';

import { CustomDataTable } from "@/components/custom-data-table"
import { createClient } from "@tuturuuu/supabase/next/server"
import type { WorkspaceQuiz } from "@tuturuuu/types/db"
import { Button } from "@tuturuuu/ui/button"
import FeatureSummary from "@tuturuuu/ui/custom/feature-summary"
import { BarChart3 } from "@tuturuuu/ui/icons"
import { Separator } from "@tuturuuu/ui/separator"
import { getTranslations } from "next-intl/server"
import Link from "next/link"
import { getWorkspaceQuizColumns } from "./columns"
import QuizForm from "./form"
interface SearchParams {
q?: string;
page?: string;
pageSize?: string;
includedTags?: string | string[];
excludedTags?: string | string[];
q?: string
page?: string
pageSize?: string
includedTags?: string | string[]
excludedTags?: string | string[]
}

interface Props {
params: Promise<{
wsId: string;
setId: string;
}>;
searchParams: Promise<SearchParams>;
wsId: string
setId: string
}>
searchParams: Promise<SearchParams>
}

export default async function WorkspaceQuizzesPage({
params,
searchParams,
}: Props) {
const t = await getTranslations();
const { wsId, setId } = await params;
export default async function WorkspaceQuizzesPage({ params, searchParams }: Props) {
const t = await getTranslations()
const { wsId, setId } = await params

const { data, count } = await getData(setId, await searchParams);
const { data, count } = await getData(setId, await searchParams)

return (
<>
<FeatureSummary
pluralTitle={t('ws-quizzes.plural')}
singularTitle={t('ws-quizzes.singular')}
description={t('ws-quizzes.description')}
createTitle={t('ws-quizzes.create')}
createDescription={t('ws-quizzes.create_description')}
pluralTitle={t("ws-quizzes.plural")}
singularTitle={t("ws-quizzes.singular")}
description={t("ws-quizzes.description")}
createTitle={t("ws-quizzes.create")}
createDescription={t("ws-quizzes.create_description")}
form={<QuizForm wsId={wsId} setId={setId} />}
/>
<Separator className="my-4" />
Expand All @@ -54,43 +53,43 @@ export default async function WorkspaceQuizzesPage({
}}
/>
</>
);
)
}

async function getData(
setId: string,
{
q,
page = '1',
pageSize = '10',
page = "1",
pageSize = "10",
retry = true,
}: { q?: string; page?: string; pageSize?: string; retry?: boolean } = {}
}: { q?: string; page?: string; pageSize?: string; retry?: boolean } = {},
) {
const supabase = await createClient();
const supabase = await createClient()

const queryBuilder = supabase
.from('quiz_set_quizzes')
.select('...workspace_quizzes(*, quiz_options(*))', {
count: 'exact',
.from("quiz_set_quizzes")
.select("...workspace_quizzes(*, quiz_options(*))", {
count: "exact",
})
.eq('set_id', setId)
.order('created_at', { ascending: false });
.eq("set_id", setId)
.order("created_at", { ascending: false })

if (q) queryBuilder.ilike('name', `%${q}%`);
if (q) queryBuilder.ilike("name", `%${q}%`)

if (page && pageSize) {
const parsedPage = parseInt(page);
const parsedSize = parseInt(pageSize);
const start = (parsedPage - 1) * parsedSize;
const end = parsedPage * parsedSize;
queryBuilder.range(start, end).limit(parsedSize);
const parsedPage = Number.parseInt(page)
const parsedSize = Number.parseInt(pageSize)
const start = (parsedPage - 1) * parsedSize
const end = parsedPage * parsedSize
queryBuilder.range(start, end).limit(parsedSize)
}

const { data, error, count } = await queryBuilder;
const { data, error, count } = await queryBuilder
if (error) {
if (!retry) throw error;
return getData(setId, { q, pageSize, retry: false });
if (!retry) throw error
return getData(setId, { q, pageSize, retry: false })
}

return { data, count } as { data: WorkspaceQuiz[]; count: number };
return { data, count } as { data: WorkspaceQuiz[]; count: number }
}
Loading
Loading