diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/layout.tsx b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/layout.tsx
index d66de056cd..4e7a3f27c0 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/layout.tsx
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/layout.tsx
@@ -7,7 +7,7 @@ interface LayoutProps {
}
export default function layout({children} : LayoutProps) {
return <>
-
+
{children}
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx
index dcf103e71d..3d4b591f9a 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx
@@ -1,27 +1,59 @@
-// import { getChallenges } from '../challenges';
+'use client';
+
+import { getChallenge } from '../challenges';
+import CustomizedHeader from './customizedHeader';
import ProblemComponent from './problem-component';
import PromptComponent from './prompt-component';
import TestCaseComponent from './test-case-component';
-import React from 'react';
+import React, { useState } from 'react';
interface Props {
- params: Promise<{
+ params: {
challengeId: string;
- }>;
+ };
}
-export default async function Page({ params }: Props) {
- const { challengeId } = await params;
+export default function Page({ params }: Props) {
+ const challenge = getChallenge(parseInt(params.challengeId));
+ const problems = challenge?.problems || [];
+
+ const [currentProblemIndex, setCurrentProblemIndex] = useState(0);
+
+ // Handle "Next" and "Previous" navigation
+ const nextProblem = () => {
+ setCurrentProblemIndex((prev) =>
+ prev < problems.length - 1 ? prev + 1 : prev
+ );
+ };
+
+ const prevProblem = () => {
+ setCurrentProblemIndex((prev) => (prev > 0 ? prev - 1 : prev));
+ };
return (
-
- {/* Left side: Problem & Test Cases */}
-
+ <>
+ {/* Header with navigation */}
+
+
+
+ {/* Left side: Problem & Test Cases */}
+
+ {problems.length > 0 ? (
+
+ ) : (
+
No problems available.
+ )}
+
+
-
-
+ {/* Right Side */}
+
+
+ >
);
}
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/problem-changer.tsx b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/problem-changer.tsx
index 3d115e4622..1e9c37f3b8 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/problem-changer.tsx
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/problem-changer.tsx
@@ -1,14 +1,28 @@
import { Button } from '@repo/ui/components/ui/button';
import React from 'react';
-export default function ProblemChanger() {
+interface Props {
+ proNum: number;
+ currentProblem: number;
+ onNext: () => void;
+ onPrev: () => void;
+}
+
+export default function ProblemChanger({
+ proNum,
+ onNext,
+ onPrev,
+ currentProblem,
+}: Props) {
return (
-
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/challenges.ts b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/challenges.ts
index 6008b3fbd1..1839711186 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/challenges.ts
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/challenges.ts
@@ -3,6 +3,13 @@ export interface Challenge {
title: string;
topic: string;
description: string;
+ problems: Problems[];
+}
+
+export interface Problems {
+ id: string;
+ title: string;
+ description: string;
exampleInput: string;
exampleOutput: string;
}
@@ -10,41 +17,89 @@ export interface Challenge {
const challenges: Challenge[] = [
{
id: 1,
- title: 'Text Summarization',
+ title: 'Text Suma',
topic: 'Summarization',
description:
- 'Create a prompt that summarizes a given text while maintaining key information and context.',
- exampleInput:
- 'The Industrial Revolution was a period of major industrialization and innovation during the late 18th and early 19th century. The Industrial Revolution began in Great Britain and quickly spread throughout the world. This time period saw the mechanization of agriculture and textile manufacturing and a revolution in power, including steam ships and railroads, that affected social, cultural and economic conditions.',
- exampleOutput:
- 'The Industrial Revolution, occurring in the late 18th and early 19th centuries, was a time of significant technological and societal change. It started in Great Britain and spread globally, bringing mechanization to agriculture and textiles, and innovations in power like steam ships and railroads. These advancements had far-reaching impacts on society, culture, and the economy.',
+ 'Create prompts that summarize text while maintaining key details and context.',
+ problems: [
+ {
+ id: '1a',
+ title: 'One-Sentence Summary',
+ description: 'Summarize a given text in just **one sentence**.',
+ exampleInput:
+ 'The Industrial Revolution was a period of major industrialization and innovation during the late 18th and early 19th century. It started in Great Britain and spread worldwide, introducing mechanized agriculture, textile manufacturing, and steam-powered transportation.',
+ exampleOutput:
+ 'The Industrial Revolution transformed industry with mechanization, starting in Britain and spreading globally.',
+ },
+ {
+ id: '1b',
+ title: 'Summarization While Keeping Dates',
+ description: 'Summarize a text without **removing key numbers or dates**.',
+ exampleInput:
+ 'In 2023, the global AI industry was valued at $150 billion, with an expected growth rate of 40% annually until 2030.',
+ exampleOutput:
+ 'In 2023, AI was a $150B industry, projected to grow 40% yearly until 2030.',
+ },
+ ],
},
{
id: 2,
title: 'Sentiment Analysis',
topic: 'Classification',
description:
- 'Design a prompt that analyzes the sentiment of a given text, classifying it as positive, negative, or neutral.',
- exampleInput:
- "I absolutely loved the new restaurant downtown. The food was delicious and the service was impeccable. I can't wait to go back!",
- exampleOutput:
- 'This text expresses a very positive sentiment. The author uses enthusiastic language such as "absolutely loved" and "can\'t wait to go back". They praise both the food ("delicious") and the service ("impeccable"), indicating a highly satisfactory experience. Overall, this review conveys strong approval and excitement about the restaurant.',
+ 'Analyze the sentiment of text and classify it as positive, negative, or neutral.',
+ problems: [
+ {
+ id: '2a',
+ title: 'Positive vs. Negative Sentiment',
+ description: 'Classify a given text as **positive or negative**.',
+ exampleInput:
+ "I love this phone! The battery lasts forever, and the camera is amazing.",
+ exampleOutput: 'Positive',
+ },
+ {
+ id: '2b',
+ title: 'Sarcasm Detection',
+ description: 'Identify whether a sentence is **sarcastic or not**.',
+ exampleInput: '"Oh great, another Monday! Just what I needed..."',
+ exampleOutput: 'Sarcastic',
+ },
+ ],
},
{
id: 3,
title: 'Code Explanation',
topic: 'Programming',
description:
- 'Create a prompt that explains a given piece of code in simple terms, suitable for beginners.',
- exampleInput: `
-def fibonacci(n):
- if n <= 1:
- return n
- else:
- return fibonacci(n-1) + fibonacci(n-2)
- `,
- exampleOutput:
- 'This code defines a function called "fibonacci" that calculates the nth number in the Fibonacci sequence. The Fibonacci sequence is a series of numbers where each number is the sum of the two preceding ones. The function uses recursion, which means it calls itself with smaller values until it reaches the base case (n <= 1). For larger values of n, it calculates the Fibonacci number by adding the two previous numbers in the sequence. This recursive approach, while simple to understand, can be inefficient for large values of n due to repeated calculations.',
+ 'Explain programming concepts in simple terms.',
+ problems: [
+ {
+ id: '3a',
+ title: 'Explain a For Loop',
+ description:
+ 'Explain the function of a **for loop** in a beginner-friendly way.',
+ exampleInput: `
+for (let i = 0; i < 5; i++) {
+ console.log(i);
+}
+ `,
+ exampleOutput:
+ 'This loop runs five times, printing numbers from 0 to 4. It starts at `i = 0`, increases `i` by 1 each time, and stops at `i = 5`.',
+ },
+ {
+ id: '3b',
+ title: 'Explain Recursion',
+ description: 'Explain **recursion** using a simple example.',
+ exampleInput: `
+function factorial(n) {
+ if (n === 1) return 1;
+ return n * factorial(n - 1);
+}
+ `,
+ exampleOutput:
+ 'This function calculates the factorial of a number by calling itself repeatedly until it reaches the base case (`n === 1`).',
+ },
+ ],
},
];
From 490b1eab6b3988e9512956c02c21ba9fc1b6b21d Mon Sep 17 00:00:00 2001
From: phatgg221 <129394719+phatgg221@users.noreply.github.com>
Date: Sat, 8 Feb 2025 14:56:24 +0700
Subject: [PATCH 05/36] fixed id promise bug
---
.../[wsId]/challenges/[challengeId]/page.tsx | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx
index 3d4b591f9a..b7b04d6e2b 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx
@@ -5,7 +5,7 @@ import CustomizedHeader from './customizedHeader';
import ProblemComponent from './problem-component';
import PromptComponent from './prompt-component';
import TestCaseComponent from './test-case-component';
-import React, { useState } from 'react';
+import React, { useState, useEffect } from 'react';
interface Props {
params: {
@@ -14,7 +14,18 @@ interface Props {
}
export default function Page({ params }: Props) {
- const challenge = getChallenge(parseInt(params.challengeId));
+ const [challenge, setChallenge] = useState
(null);
+
+ useEffect(() => {
+ // Wait for params to resolve
+ const fetchData = async () => {
+ const challengeData = await getChallenge(parseInt(params.challengeId));
+ setChallenge(challengeData);
+ };
+
+ fetchData();
+ }, [params]);
+
const problems = challenge?.problems || [];
const [currentProblemIndex, setCurrentProblemIndex] = useState(0);
From f3a683a00a92bbd17555b878218624d2323a4494 Mon Sep 17 00:00:00 2001
From: phatgg221 <129394719+phatgg221@users.noreply.github.com>
Date: Sat, 8 Feb 2025 15:08:23 +0700
Subject: [PATCH 06/36] chore: add real problem data
---
.../[challengeId]/problem-component.tsx | 48 +++++++++++--------
.../[wsId]/challenges/challenges.ts | 13 +++--
2 files changed, 36 insertions(+), 25 deletions(-)
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/problem-component.tsx b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/problem-component.tsx
index ca64b20995..2b2cf02adb 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/problem-component.tsx
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/problem-component.tsx
@@ -1,31 +1,37 @@
import { Card, CardContent } from '@repo/ui/components/ui/card';
import React from 'react';
-export default function ProblemComponent() {
+interface Problem {
+ id: string;
+ title: string;
+ description: string;
+ exampleInput: string;
+ exampleOutput: string;
+ constraints?: string[]; // Optional constraints field
+}
+
+export default function ProblemComponent({ problem }: { problem: Problem }) {
return (
-
- Title
- Description: The problem statement
+
+ {problem.title}
+ {problem.description}
Example:
-
- {`Input: s = "hello"\nOutput: "holle"`}
+
+ {`Input: s = "${problem.exampleInput}"\n\nOutput: "${problem.exampleOutput}"`}
- Constraints:
-
- - 1 ≤ s.length ≤ 3 * 10⁵
- - 1 ≤ s.length ≤ 3 * 10⁵
- - s consists of printable ASCII characters.
- - 1 ≤ s.length ≤ 3 * 10⁵
- - s consists of printable ASCII characters.
- - 1 ≤ s.length ≤ 3 * 10⁵
- - s consists of printable ASCII characters.
- - 1 ≤ s.length ≤ 3 * 10⁵
- - s consists of printable ASCII characters.
- - 1 ≤ s.length ≤ 3 * 10⁵
- - s consists of printable ASCII characters.
- - s consists of printable ASCII characters.
-
+
+ {/* Render constraints if available */}
+ {problem.constraints && problem.constraints.length > 0 && (
+ <>
+ Constraints:
+
+ {problem.constraints.map((constraint, index) => (
+ - {constraint}
+ ))}
+
+ >
+ )}
);
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/challenges.ts b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/challenges.ts
index 1839711186..ee51b9309f 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/challenges.ts
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/challenges.ts
@@ -4,6 +4,7 @@ export interface Challenge {
topic: string;
description: string;
problems: Problems[];
+ constraints?: string[];
}
export interface Problems {
@@ -30,11 +31,16 @@ const challenges: Challenge[] = [
'The Industrial Revolution was a period of major industrialization and innovation during the late 18th and early 19th century. It started in Great Britain and spread worldwide, introducing mechanized agriculture, textile manufacturing, and steam-powered transportation.',
exampleOutput:
'The Industrial Revolution transformed industry with mechanization, starting in Britain and spreading globally.',
+ constraints: [
+ '1 ≤ s.length ≤ 3 * 10⁵',
+ 's consists of printable ASCII characters.',
+ ],
},
{
id: '1b',
title: 'Summarization While Keeping Dates',
- description: 'Summarize a text without **removing key numbers or dates**.',
+ description:
+ 'Summarize a text without **removing key numbers or dates**.',
exampleInput:
'In 2023, the global AI industry was valued at $150 billion, with an expected growth rate of 40% annually until 2030.',
exampleOutput:
@@ -54,7 +60,7 @@ const challenges: Challenge[] = [
title: 'Positive vs. Negative Sentiment',
description: 'Classify a given text as **positive or negative**.',
exampleInput:
- "I love this phone! The battery lasts forever, and the camera is amazing.",
+ 'I love this phone! The battery lasts forever, and the camera is amazing.',
exampleOutput: 'Positive',
},
{
@@ -70,8 +76,7 @@ const challenges: Challenge[] = [
id: 3,
title: 'Code Explanation',
topic: 'Programming',
- description:
- 'Explain programming concepts in simple terms.',
+ description: 'Explain programming concepts in simple terms.',
problems: [
{
id: '3a',
From 3d078e88af0c5c8502c2c0f357aff297fcee60ba Mon Sep 17 00:00:00 2001
From: phatgg221 <129394719+phatgg221@users.noreply.github.com>
Date: Sat, 8 Feb 2025 15:11:04 +0700
Subject: [PATCH 07/36] fix: delete unused variables
---
.../[wsId]/challenges/[challengeId]/problem-component.tsx | 2 +-
.../app/[locale]/(dashboard)/[wsId]/challenges/challenges.ts | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/problem-component.tsx b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/problem-component.tsx
index 2b2cf02adb..90271cb030 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/problem-component.tsx
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/problem-component.tsx
@@ -1,4 +1,4 @@
-import { Card, CardContent } from '@repo/ui/components/ui/card';
+import { Card } from '@repo/ui/components/ui/card';
import React from 'react';
interface Problem {
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/challenges.ts b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/challenges.ts
index ee51b9309f..fa206c9fb3 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/challenges.ts
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/challenges.ts
@@ -4,7 +4,6 @@ export interface Challenge {
topic: string;
description: string;
problems: Problems[];
- constraints?: string[];
}
export interface Problems {
@@ -13,6 +12,7 @@ export interface Problems {
description: string;
exampleInput: string;
exampleOutput: string;
+ constraints?: string[];
}
const challenges: Challenge[] = [
From 363f63d5466c0962e5ab655f72f3ba81c390ba2c Mon Sep 17 00:00:00 2001
From: phatgg221 <129394719+phatgg221@users.noreply.github.com>
Date: Sat, 8 Feb 2025 15:15:50 +0700
Subject: [PATCH 08/36] fix!: await bugs for challenge Id
---
.../(dashboard)/[wsId]/challenges/[challengeId]/page.tsx | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx
index b7b04d6e2b..8a5e21f9a3 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx
@@ -5,7 +5,7 @@ import CustomizedHeader from './customizedHeader';
import ProblemComponent from './problem-component';
import PromptComponent from './prompt-component';
import TestCaseComponent from './test-case-component';
-import React, { useState, useEffect } from 'react';
+import React, { useEffect, useState } from 'react';
interface Props {
params: {
@@ -15,14 +15,15 @@ interface Props {
export default function Page({ params }: Props) {
const [challenge, setChallenge] = useState(null);
-
+
useEffect(() => {
// Wait for params to resolve
const fetchData = async () => {
- const challengeData = await getChallenge(parseInt(params.challengeId));
+ const { challengeId } = await params;
+ const challengeData = getChallenge(parseInt(challengeId));
setChallenge(challengeData);
};
-
+
fetchData();
}, [params]);
From 30a7775c83b559c23d99c409cd893df328c31dfc Mon Sep 17 00:00:00 2001
From: phatgg221 <129394719+phatgg221@users.noreply.github.com>
Date: Sat, 8 Feb 2025 15:19:25 +0700
Subject: [PATCH 09/36] fix: css styling
---
.../[wsId]/challenges/[challengeId]/problem-component.tsx | 2 +-
.../[wsId]/challenges/[challengeId]/test-case-component.tsx | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/problem-component.tsx b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/problem-component.tsx
index 90271cb030..805cd05668 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/problem-component.tsx
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/problem-component.tsx
@@ -13,7 +13,7 @@ interface Problem {
export default function ProblemComponent({ problem }: { problem: Problem }) {
return (
-
+
{problem.title}
{problem.description}
Example:
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/test-case-component.tsx b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/test-case-component.tsx
index af08e38185..5aed40aeba 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/test-case-component.tsx
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/test-case-component.tsx
@@ -4,7 +4,7 @@ import React from 'react';
export default function TestCaseComponent() {
return (
-
+
Test Case
In the case of business world, we have to do this to test out the
From fc8856ac2c1d3f805a677946da9dce6ab0937f47 Mon Sep 17 00:00:00 2001
From: phatgg221 <129394719+phatgg221@users.noreply.github.com>
Date: Sun, 9 Feb 2025 14:32:44 +0700
Subject: [PATCH 10/36] chore: AI prompt routes
---
apps/mira/src/app/api/ai/chat/google/route.ts | 1 -
.../src/app/api/ai/chat/google/new/route.ts | 0
apps/nova/src/app/api/ai/chat/google/route.ts | 61 +++++++++++++++++++
3 files changed, 61 insertions(+), 1 deletion(-)
create mode 100644 apps/nova/src/app/api/ai/chat/google/new/route.ts
create mode 100644 apps/nova/src/app/api/ai/chat/google/route.ts
diff --git a/apps/mira/src/app/api/ai/chat/google/route.ts b/apps/mira/src/app/api/ai/chat/google/route.ts
index 6abed3c22a..8e742f48d3 100644
--- a/apps/mira/src/app/api/ai/chat/google/route.ts
+++ b/apps/mira/src/app/api/ai/chat/google/route.ts
@@ -10,7 +10,6 @@ export const preferredRegion = 'sin1';
export async function POST(req: Request) {
const sbAdmin = await createAdminClient();
-
const {
id,
model = appConfig.defaultModel,
diff --git a/apps/nova/src/app/api/ai/chat/google/new/route.ts b/apps/nova/src/app/api/ai/chat/google/new/route.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/apps/nova/src/app/api/ai/chat/google/route.ts b/apps/nova/src/app/api/ai/chat/google/route.ts
new file mode 100644
index 0000000000..b6083d6bdd
--- /dev/null
+++ b/apps/nova/src/app/api/ai/chat/google/route.ts
@@ -0,0 +1,61 @@
+import { AppConfig, appConfig } from '@/constants/configs';
+import { createAdminClient, createClient } from '@/utils/supabase/server';
+import { google } from '@ai-sdk/google';
+import { CoreMessage, streamText } from 'ai';
+import { NextResponse } from 'next/server';
+
+export const runtime = 'edge';
+export const maxDuration = 60;
+export const preferredRegion = 'sin1';
+
+export async function POST(req: Request) {
+ const sbAdmin = await createAdminClient();
+ const {
+ id,
+ model = appConfig.defaultModel,
+ messages,
+ previewToken,
+ mode,
+ } = (await req.json()) as {
+ id?: string;
+ model?: string;
+ messages?: CoreMessage[];
+ previewToken?: string;
+ mode?: 'short' | 'medium' | 'long';
+ };
+
+ try {
+ if (!messages || messages.length === 0) {
+ return NextResponse.json(
+ { message: 'No messages provided.' },
+ { status: 400 }
+ );
+ }
+
+ // Stream AI response
+ const aiResponse = await streamText({
+ model: google(model),
+ messages,
+ mode,
+ });
+
+ // Optionally, save the conversation to Supabase if needed
+ if (id) {
+ await sbAdmin
+ .from('chat_sessions')
+ .update({ messages: [...messages, aiResponse] })
+ .eq('id', id);
+ }
+
+ return NextResponse.json({ response: aiResponse }, { status: 200 });
+ } catch (error: any) {
+ return NextResponse.json(
+ {
+ message: `## Edge API Failure\nCould not complete the request. Please view the **Stack trace** below.\n\`\`\`bash\n${error?.stack}`,
+ },
+ {
+ status: 500,
+ }
+ );
+ }
+}
From 5cbfcb64f56ce56f4c75a4a767f0bc094fbdf8d0 Mon Sep 17 00:00:00 2001
From: phatgg221 <129394719+phatgg221@users.noreply.github.com>
Date: Sun, 9 Feb 2025 19:16:14 +0700
Subject: [PATCH 11/36] update google api
---
.../challenges/[challengeId]/layout.tsx | 1 -
.../[wsId]/challenges/[challengeId]/page.tsx | 6 +-
.../[challengeId]/test-case-component.tsx | 6 +-
.../[wsId]/challenges/challenges.ts | 7 +++
apps/nova/src/app/api/ai/chat/google/route.ts | 55 ++++++++-----------
5 files changed, 36 insertions(+), 39 deletions(-)
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/layout.tsx b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/layout.tsx
index 4e7a3f27c0..507f2d64ff 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/layout.tsx
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/layout.tsx
@@ -1,4 +1,3 @@
-import Header from './customizedHeader';
import React from 'react';
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx
index 8a5e21f9a3..df7b8ef2e3 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx
@@ -41,7 +41,7 @@ export default function Page({ params }: Props) {
const prevProblem = () => {
setCurrentProblemIndex((prev) => (prev > 0 ? prev - 1 : prev));
};
-
+ // console.log(problems[currentProblemIndex].testcase), 'testcase ';
return (
<>
{/* Header with navigation */}
@@ -60,7 +60,9 @@ export default function Page({ params }: Props) {
) : (
No problems available.
)}
-
+
{/* Right Side */}
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/test-case-component.tsx b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/test-case-component.tsx
index 5aed40aeba..9c585d9e72 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/test-case-component.tsx
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/test-case-component.tsx
@@ -1,15 +1,13 @@
import { Card } from '@repo/ui/components/ui/card';
import React from 'react';
-export default function TestCaseComponent() {
+export default function TestCaseComponent({ testcase }: { testcase?: string }) {
return (
Test Case
- In the case of business world, we have to do this to test out the
- cases askjdnakjscnavkjn askjdn ak akjsnd jnasdknj acsjknakjnvqjnf jas
- kdn
+ {testcase}
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/challenges.ts b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/challenges.ts
index fa206c9fb3..9a0f32cb94 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/challenges.ts
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/challenges.ts
@@ -13,6 +13,7 @@ export interface Problems {
exampleInput: string;
exampleOutput: string;
constraints?: string[];
+ testcase?: string;
}
const challenges: Challenge[] = [
@@ -35,6 +36,7 @@ const challenges: Challenge[] = [
'1 ≤ s.length ≤ 3 * 10⁵',
's consists of printable ASCII characters.',
],
+ testcase: 'hehe this is the correct answer ',
},
{
id: '1b',
@@ -45,6 +47,7 @@ const challenges: Challenge[] = [
'In 2023, the global AI industry was valued at $150 billion, with an expected growth rate of 40% annually until 2030.',
exampleOutput:
'In 2023, AI was a $150B industry, projected to grow 40% yearly until 2030.',
+ testcase: 'hehe this is the correct answer ',
},
],
},
@@ -62,6 +65,7 @@ const challenges: Challenge[] = [
exampleInput:
'I love this phone! The battery lasts forever, and the camera is amazing.',
exampleOutput: 'Positive',
+ testcase: 'hehe this is the correct answer ',
},
{
id: '2b',
@@ -69,6 +73,7 @@ const challenges: Challenge[] = [
description: 'Identify whether a sentence is **sarcastic or not**.',
exampleInput: '"Oh great, another Monday! Just what I needed..."',
exampleOutput: 'Sarcastic',
+ testcase: 'hehe this is the correct answer ',
},
],
},
@@ -90,6 +95,7 @@ for (let i = 0; i < 5; i++) {
`,
exampleOutput:
'This loop runs five times, printing numbers from 0 to 4. It starts at `i = 0`, increases `i` by 1 each time, and stops at `i = 5`.',
+ testcase: 'hehe this is the correct answer ',
},
{
id: '3b',
@@ -103,6 +109,7 @@ function factorial(n) {
`,
exampleOutput:
'This function calculates the factorial of a number by calling itself repeatedly until it reaches the base case (`n === 1`).',
+ testcase: 'hehe this is the correct answer ',
},
],
},
diff --git a/apps/nova/src/app/api/ai/chat/google/route.ts b/apps/nova/src/app/api/ai/chat/google/route.ts
index b6083d6bdd..c244e92b5f 100644
--- a/apps/nova/src/app/api/ai/chat/google/route.ts
+++ b/apps/nova/src/app/api/ai/chat/google/route.ts
@@ -1,27 +1,23 @@
-import { AppConfig, appConfig } from '@/constants/configs';
-import { createAdminClient, createClient } from '@/utils/supabase/server';
-import { google } from '@ai-sdk/google';
-import { CoreMessage, streamText } from 'ai';
+import { GoogleGenerativeAI } from '@google/generative-ai';
import { NextResponse } from 'next/server';
+// Replace this with your actual API key
+const API_KEY = process.env.GOOGLE_GENERATIVE_AI_API_KEY;
+
+// Initialize Google Generative AI Client
+const genAI = new GoogleGenerativeAI(API_KEY);
+
export const runtime = 'edge';
export const maxDuration = 60;
export const preferredRegion = 'sin1';
export async function POST(req: Request) {
- const sbAdmin = await createAdminClient();
const {
- id,
- model = appConfig.defaultModel,
messages,
- previewToken,
- mode,
+ model = 'gemini-pro', // Use the appropriate model (e.g., 'gemini-pro', 'chat-bison-001')
} = (await req.json()) as {
- id?: string;
+ messages?: { role: string; content: string }[];
model?: string;
- messages?: CoreMessage[];
- previewToken?: string;
- mode?: 'short' | 'medium' | 'long';
};
try {
@@ -32,30 +28,25 @@ export async function POST(req: Request) {
);
}
- // Stream AI response
- const aiResponse = await streamText({
- model: google(model),
- messages,
- mode,
- });
-
- // Optionally, save the conversation to Supabase if needed
- if (id) {
- await sbAdmin
- .from('chat_sessions')
- .update({ messages: [...messages, aiResponse] })
- .eq('id', id);
- }
+ // Prepare messages for Google API (as text)
+ const userMessage = messages
+ .map((msg) => `${msg.role}: ${msg.content}`)
+ .join('\n');
- return NextResponse.json({ response: aiResponse }, { status: 200 });
+ // Get the model
+ const aiModel = genAI.getGenerativeModel({ model });
+
+ // Send the prompt to the Google API
+ const result = await aiModel.generateContent(userMessage);
+ const response = result.response;
+
+ return NextResponse.json({ response: response.text() }, { status: 200 });
} catch (error: any) {
return NextResponse.json(
{
- message: `## Edge API Failure\nCould not complete the request. Please view the **Stack trace** below.\n\`\`\`bash\n${error?.stack}`,
+ message: `API Failure\nCould not complete the request.\n\n${error?.stack}`,
},
- {
- status: 500,
- }
+ { status: 500 }
);
}
}
From 72979f25e75379def8a1b0161510d9d36d09b403 Mon Sep 17 00:00:00 2001
From: phatgg221 <129394719+phatgg221@users.noreply.github.com>
Date: Sun, 9 Feb 2025 21:14:53 +0700
Subject: [PATCH 12/36] feat: test the chatbot evaluation based on the example
problem and test case
---
apps/nova/src/app/api/ai/chat/google/route.ts | 34 ++++++++++++-------
1 file changed, 22 insertions(+), 12 deletions(-)
diff --git a/apps/nova/src/app/api/ai/chat/google/route.ts b/apps/nova/src/app/api/ai/chat/google/route.ts
index c244e92b5f..0a84c1d2b1 100644
--- a/apps/nova/src/app/api/ai/chat/google/route.ts
+++ b/apps/nova/src/app/api/ai/chat/google/route.ts
@@ -2,7 +2,7 @@ import { GoogleGenerativeAI } from '@google/generative-ai';
import { NextResponse } from 'next/server';
// Replace this with your actual API key
-const API_KEY = process.env.GOOGLE_GENERATIVE_AI_API_KEY;
+const API_KEY = process.env.GOOGLE_GENERATIVE_AI_API_KEY || '';
// Initialize Google Generative AI Client
const genAI = new GoogleGenerativeAI(API_KEY);
@@ -11,33 +11,43 @@ export const runtime = 'edge';
export const maxDuration = 60;
export const preferredRegion = 'sin1';
+// Static Problem and Test Case
+const problem = "Write a prompt that instructs an AI to generate a short, creative story involving a dragon and a wizard.";
+const testCase = "The AI should generate a story where a dragon and a wizard interact in a creative way, no longer than 200 words.";
+
export async function POST(req: Request) {
const {
- messages,
- model = 'gemini-pro', // Use the appropriate model (e.g., 'gemini-pro', 'chat-bison-001')
+ answer,
+ model = 'gemini-pro',
} = (await req.json()) as {
- messages?: { role: string; content: string }[];
+ answer?: string;
model?: string;
};
try {
- if (!messages || messages.length === 0) {
+ if (!answer) {
return NextResponse.json(
- { message: 'No messages provided.' },
+ { message: 'No answer provided.' },
{ status: 400 }
);
}
- // Prepare messages for Google API (as text)
- const userMessage = messages
- .map((msg) => `${msg.role}: ${msg.content}`)
- .join('\n');
+ // System Instruction for Evaluation
+ const systemInstruction = `You are an examiner in a prompt engineering competition.
+ You will be provided with the problem and its test case. The user will input an answer.
+ Based on the input, evaluate the answer and give a score out of ten.
+
+ Problem: ${problem}
+ Test Case: ${testCase}
+ User's Answer: ${answer}
+
+ Please provide a score from 1 to 10 and briefly explain why the answer received that score.`;
// Get the model
const aiModel = genAI.getGenerativeModel({ model });
- // Send the prompt to the Google API
- const result = await aiModel.generateContent(userMessage);
+ // Send the instruction to Google API
+ const result = await aiModel.generateContent(systemInstruction);
const response = result.response;
return NextResponse.json({ response: response.text() }, { status: 200 });
From 966418f41a0fc5f09a26478d7f8116c25d84bebc Mon Sep 17 00:00:00 2001
From: phatgg221 <129394719+phatgg221@users.noreply.github.com>
Date: Sun, 9 Feb 2025 21:20:04 +0700
Subject: [PATCH 13/36] fix: build errors
---
.../[challengeId]/components/chat-panel.tsx | 14 +++++++-------
.../[challengeId]/components/prompt-form.tsx | 2 +-
.../[wsId]/challenges/[challengeId]/page.tsx | 5 ++---
3 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/components/chat-panel.tsx b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/components/chat-panel.tsx
index db09e0e9b8..d8dc5e2619 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/components/chat-panel.tsx
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/components/chat-panel.tsx
@@ -1,9 +1,9 @@
-import React from 'react';
-import { Model } from '@/data/models';
-import { AIChat } from '@/types/db';
+// import React from 'react';
+// import { Model } from '@/data/models';
+// import { AIChat } from '@/types/db';
-export default function ChatPanel() {
- return
+// export default function ChatPanel() {
+// return
-
;
-}
+//
;
+// }
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/components/prompt-form.tsx b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/components/prompt-form.tsx
index 359ffd50e6..96bd0aacca 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/components/prompt-form.tsx
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/components/prompt-form.tsx
@@ -5,7 +5,7 @@ import { Input } from '@repo/ui/components/ui/input';
import React, { useEffect, useRef, useState } from 'react';
export default function ChatBox() {
- const [messages, setMessages] = useState<
+ const [messages, _setMessages] = useState<
{ text: string; sender: 'user' | 'ai' }[]
>([]);
const [input, setInput] = useState('');
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx
index df7b8ef2e3..fe9f093224 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx
@@ -8,9 +8,9 @@ import TestCaseComponent from './test-case-component';
import React, { useEffect, useState } from 'react';
interface Props {
- params: {
+ params: Promise<{
challengeId: string;
- };
+ }>;
}
export default function Page({ params }: Props) {
@@ -53,7 +53,6 @@ export default function Page({ params }: Props) {
/>
- {/* Left side: Problem & Test Cases */}
{problems.length > 0 ? (
From 1d536db94de73fae374f5c939b2b429b110bca51 Mon Sep 17 00:00:00 2001
From: phatgg221 <129394719+phatgg221@users.noreply.github.com>
Date: Mon, 10 Feb 2025 15:20:52 +0700
Subject: [PATCH 14/36] feat: AI chatbot Json format response
---
.../[challengeId]/components/prompt-form.tsx | 3 ++
apps/nova/src/app/api/ai/chat/google/route.ts | 33 +++++++++++++++----
2 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/components/prompt-form.tsx b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/components/prompt-form.tsx
index 96bd0aacca..2bdde87134 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/components/prompt-form.tsx
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/components/prompt-form.tsx
@@ -37,6 +37,9 @@ export default function ChatBox() {
{msg.text}
))}
+
+ You only have 5 tries for each question. [0/5]
+
diff --git a/apps/nova/src/app/api/ai/chat/google/route.ts b/apps/nova/src/app/api/ai/chat/google/route.ts
index 0a84c1d2b1..e5d1706fa5 100644
--- a/apps/nova/src/app/api/ai/chat/google/route.ts
+++ b/apps/nova/src/app/api/ai/chat/google/route.ts
@@ -32,7 +32,7 @@ export async function POST(req: Request) {
);
}
- // System Instruction for Evaluation
+ // System Instruction for Evaluation with strict JSON output
const systemInstruction = `You are an examiner in a prompt engineering competition.
You will be provided with the problem and its test case. The user will input an answer.
Based on the input, evaluate the answer and give a score out of ten.
@@ -41,16 +41,37 @@ export async function POST(req: Request) {
Test Case: ${testCase}
User's Answer: ${answer}
- Please provide a score from 1 to 10 and briefly explain why the answer received that score.`;
+ Please provide the evaluation in the following JSON format:
+ {
+ "score": [number from 1 to 10],
+ "feedback": "[brief explanation of the score]"
+ }
+
+ Do not include anything other than the JSON object in your response.`;
+
- // Get the model
const aiModel = genAI.getGenerativeModel({ model });
- // Send the instruction to Google API
+
const result = await aiModel.generateContent(systemInstruction);
- const response = result.response;
+ const response = result.response.text();
+
+
+ let parsedResponse;
+ try {
+ parsedResponse = JSON.parse(response);
+ } catch (parseError) {
+
+ return NextResponse.json(
+ {
+ message: 'AI response was not in valid JSON format.',
+ rawResponse: response,
+ },
+ { status: 200 }
+ );
+ }
- return NextResponse.json({ response: response.text() }, { status: 200 });
+ return NextResponse.json({ response: parsedResponse }, { status: 200 });
} catch (error: any) {
return NextResponse.json(
{
From 61399e8a8f57750cbee6adf2d2e70b0614691f80 Mon Sep 17 00:00:00 2001
From: phatgg221 <129394719+phatgg221@users.noreply.github.com>
Date: Tue, 11 Feb 2025 23:38:52 +0700
Subject: [PATCH 15/36] chore: set up routes for prompting history and
leaderboards
---
.../20250210094622_new_migration.sql | 62 ++++++++++++
.../20250210100212_new_migration.sql | 63 ++++++++++++
.../20250211163619_new_migration.sql | 5 +
.../[challengeId]/components/prompt-form.tsx | 8 +-
.../[wsId]/challenges/[challengeId]/page.tsx | 25 ++++-
.../[challengeId]/prompt-component.tsx | 8 +-
apps/nova/src/app/[locale]/login/form.tsx | 2 +-
.../[problemId]/nova/prompt/route.ts | 27 ++++++
packages/types/src/supabase.ts | 95 +++++++++++++++++++
9 files changed, 282 insertions(+), 13 deletions(-)
create mode 100644 apps/db/supabase/migrations/20250210094622_new_migration.sql
create mode 100644 apps/db/supabase/migrations/20250210100212_new_migration.sql
create mode 100644 apps/db/supabase/migrations/20250211163619_new_migration.sql
create mode 100644 apps/nova/src/app/api/workspace/[problemId]/nova/prompt/route.ts
diff --git a/apps/db/supabase/migrations/20250210094622_new_migration.sql b/apps/db/supabase/migrations/20250210094622_new_migration.sql
new file mode 100644
index 0000000000..5deefcb637
--- /dev/null
+++ b/apps/db/supabase/migrations/20250210094622_new_migration.sql
@@ -0,0 +1,62 @@
+create table "public"."nova_leaderboard" (
+ "id" uuid not null default gen_random_uuid(),
+ "created_at" timestamp with time zone not null default now(),
+ "userId" uuid,
+ "problemId" character varying,
+ "score" real
+);
+
+
+alter table "public"."nova_leaderboard" enable row level security;
+
+CREATE UNIQUE INDEX nova_leaderboard_pkey ON public.nova_leaderboard USING btree (id);
+
+alter table "public"."nova_leaderboard" add constraint "nova_leaderboard_pkey" PRIMARY KEY using index "nova_leaderboard_pkey";
+
+alter table "public"."nova_leaderboard" add constraint "nova_leaderboard_userId_fkey" FOREIGN KEY ("userId") REFERENCES workspace_users(id) not valid;
+
+alter table "public"."nova_leaderboard" validate constraint "nova_leaderboard_userId_fkey";
+
+grant delete on table "public"."nova_leaderboard" to "anon";
+
+grant insert on table "public"."nova_leaderboard" to "anon";
+
+grant references on table "public"."nova_leaderboard" to "anon";
+
+grant select on table "public"."nova_leaderboard" to "anon";
+
+grant trigger on table "public"."nova_leaderboard" to "anon";
+
+grant truncate on table "public"."nova_leaderboard" to "anon";
+
+grant update on table "public"."nova_leaderboard" to "anon";
+
+grant delete on table "public"."nova_leaderboard" to "authenticated";
+
+grant insert on table "public"."nova_leaderboard" to "authenticated";
+
+grant references on table "public"."nova_leaderboard" to "authenticated";
+
+grant select on table "public"."nova_leaderboard" to "authenticated";
+
+grant trigger on table "public"."nova_leaderboard" to "authenticated";
+
+grant truncate on table "public"."nova_leaderboard" to "authenticated";
+
+grant update on table "public"."nova_leaderboard" to "authenticated";
+
+grant delete on table "public"."nova_leaderboard" to "service_role";
+
+grant insert on table "public"."nova_leaderboard" to "service_role";
+
+grant references on table "public"."nova_leaderboard" to "service_role";
+
+grant select on table "public"."nova_leaderboard" to "service_role";
+
+grant trigger on table "public"."nova_leaderboard" to "service_role";
+
+grant truncate on table "public"."nova_leaderboard" to "service_role";
+
+grant update on table "public"."nova_leaderboard" to "service_role";
+
+
diff --git a/apps/db/supabase/migrations/20250210100212_new_migration.sql b/apps/db/supabase/migrations/20250210100212_new_migration.sql
new file mode 100644
index 0000000000..7444df9bb3
--- /dev/null
+++ b/apps/db/supabase/migrations/20250210100212_new_migration.sql
@@ -0,0 +1,63 @@
+create table "public"."nova_users_problem_history" (
+ "id" bigint generated by default as identity not null,
+ "created_at" timestamp with time zone not null default now(),
+ "problemId" uuid,
+ "userId" uuid,
+ "score" real,
+ "feedback" character varying
+);
+
+
+alter table "public"."nova_users_problem_history" enable row level security;
+
+CREATE UNIQUE INDEX nova_users_problem_history_pkey ON public.nova_users_problem_history USING btree (id);
+
+alter table "public"."nova_users_problem_history" add constraint "nova_users_problem_history_pkey" PRIMARY KEY using index "nova_users_problem_history_pkey";
+
+alter table "public"."nova_users_problem_history" add constraint "nova_users_problem_history_userId_fkey" FOREIGN KEY ("userId") REFERENCES workspace_users(id) not valid;
+
+alter table "public"."nova_users_problem_history" validate constraint "nova_users_problem_history_userId_fkey";
+
+grant delete on table "public"."nova_users_problem_history" to "anon";
+
+grant insert on table "public"."nova_users_problem_history" to "anon";
+
+grant references on table "public"."nova_users_problem_history" to "anon";
+
+grant select on table "public"."nova_users_problem_history" to "anon";
+
+grant trigger on table "public"."nova_users_problem_history" to "anon";
+
+grant truncate on table "public"."nova_users_problem_history" to "anon";
+
+grant update on table "public"."nova_users_problem_history" to "anon";
+
+grant delete on table "public"."nova_users_problem_history" to "authenticated";
+
+grant insert on table "public"."nova_users_problem_history" to "authenticated";
+
+grant references on table "public"."nova_users_problem_history" to "authenticated";
+
+grant select on table "public"."nova_users_problem_history" to "authenticated";
+
+grant trigger on table "public"."nova_users_problem_history" to "authenticated";
+
+grant truncate on table "public"."nova_users_problem_history" to "authenticated";
+
+grant update on table "public"."nova_users_problem_history" to "authenticated";
+
+grant delete on table "public"."nova_users_problem_history" to "service_role";
+
+grant insert on table "public"."nova_users_problem_history" to "service_role";
+
+grant references on table "public"."nova_users_problem_history" to "service_role";
+
+grant select on table "public"."nova_users_problem_history" to "service_role";
+
+grant trigger on table "public"."nova_users_problem_history" to "service_role";
+
+grant truncate on table "public"."nova_users_problem_history" to "service_role";
+
+grant update on table "public"."nova_users_problem_history" to "service_role";
+
+
diff --git a/apps/db/supabase/migrations/20250211163619_new_migration.sql b/apps/db/supabase/migrations/20250211163619_new_migration.sql
new file mode 100644
index 0000000000..4f44bb30a0
--- /dev/null
+++ b/apps/db/supabase/migrations/20250211163619_new_migration.sql
@@ -0,0 +1,5 @@
+alter table "public"."nova_leaderboard" disable row level security;
+
+alter table "public"."nova_users_problem_history" disable row level security;
+
+
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/components/prompt-form.tsx b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/components/prompt-form.tsx
index 2bdde87134..151057d613 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/components/prompt-form.tsx
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/components/prompt-form.tsx
@@ -1,10 +1,11 @@
'use client';
+import { Problems } from '../../challenges';
import { Button } from '@repo/ui/components/ui/button';
import { Input } from '@repo/ui/components/ui/input';
import React, { useEffect, useRef, useState } from 'react';
-export default function ChatBox() {
+export default function ChatBox({ problem }: { problem: Problems }) {
const [messages, _setMessages] = useState<
{ text: string; sender: 'user' | 'ai' }[]
>([]);
@@ -20,7 +21,7 @@ export default function ChatBox() {
Chat Box
- Try to figure out the best prompt here...
+ You only have 5 tries for each question. [0/5]
{/* Chat Messages - Grows to take up available space */}
@@ -37,9 +38,6 @@ export default function ChatBox() {
{msg.text}
))}
-
- You only have 5 tries for each question. [0/5]
-
diff --git a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx
index fe9f093224..5478dbb1b9 100644
--- a/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx
+++ b/apps/nova/src/app/[locale]/(dashboard)/[wsId]/challenges/[challengeId]/page.tsx
@@ -5,6 +5,9 @@ import CustomizedHeader from './customizedHeader';
import ProblemComponent from './problem-component';
import PromptComponent from './prompt-component';
import TestCaseComponent from './test-case-component';
+import { createClient } from '@/utils/supabase/client';
+import { useRouter } from 'next/navigation';
+// use useRouter for client-side redirection
import React, { useEffect, useState } from 'react';
interface Props {
@@ -15,6 +18,22 @@ interface Props {
export default function Page({ params }: Props) {
const [challenge, setChallenge] = useState(null);
+ const database = createClient();
+ const router = useRouter();
+
+ useEffect(() => {
+ const authCheck = async () => {
+ const {
+ data: { user },
+ } = await database.auth.getUser();
+
+ if (!user?.id) {
+ router.push('/login');
+ }
+ };
+
+ authCheck();
+ }, []);
useEffect(() => {
// Wait for params to resolve
@@ -31,7 +50,6 @@ export default function Page({ params }: Props) {
const [currentProblemIndex, setCurrentProblemIndex] = useState(0);
- // Handle "Next" and "Previous" navigation
const nextProblem = () => {
setCurrentProblemIndex((prev) =>
prev < problems.length - 1 ? prev + 1 : prev
@@ -41,7 +59,7 @@ export default function Page({ params }: Props) {
const prevProblem = () => {
setCurrentProblemIndex((prev) => (prev > 0 ? prev - 1 : prev));
};
- // console.log(problems[currentProblemIndex].testcase), 'testcase ';
+
return (
<>
{/* Header with navigation */}
@@ -64,8 +82,7 @@ export default function Page({ params }: Props) {
/>
- {/* Right Side */}
- No problems available.
)}