diff --git a/app/lib/replay/Problems.ts b/app/lib/replay/Problems.ts index 797b2601..3f39b827 100644 --- a/app/lib/replay/Problems.ts +++ b/app/lib/replay/Problems.ts @@ -177,7 +177,10 @@ export async function deleteProblem(problemId: string): Promise { +export async function updateProblem( + problemId: string, + problem: BoltProblemInput, +): Promise { if (shouldUseSupabase()) { return supabaseUpdateProblem(problemId, problem); } diff --git a/app/lib/supabase/problems.ts b/app/lib/supabase/problems.ts index 5b568be1..05efe1ae 100644 --- a/app/lib/supabase/problems.ts +++ b/app/lib/supabase/problems.ts @@ -98,7 +98,7 @@ export async function supabaseGetProblem(problemId: string): Promise ({ id: comment.id, - createdAt: comment.created_at, + timestamp: comment.created_at, problemId: comment.problem_id, content: comment.content, username: comment.username, @@ -159,11 +159,11 @@ export async function supabaseDeleteProblem(problemId: string): Promise { +export async function supabaseUpdateProblem(problemId: string, problem: BoltProblemInput): Promise { try { if (!getNutIsAdmin()) { toast.error('Admin user required'); - return undefined; + return null; } // Extract comments to add separately if needed @@ -192,37 +192,53 @@ export async function supabaseUpdateProblem(problemId: string, problem: BoltProb * Create a unique identifier for each comment based on content and timestamp. * This allows us to use upsert with onConflict to avoid duplicates. */ - const commentInserts = comments.map((comment) => ({ - problem_id: problemId, - content: comment.content, - username: comment.username || getUsername() || 'Anonymous', + const commentInserts = comments.map((comment) => { + // Ensure timestamp is a valid number + const timestamp = + typeof comment.timestamp === 'number' && !isNaN(comment.timestamp) ? comment.timestamp : Date.now(); - /** - * Use timestamp as a unique identifier for the comment. - * This assumes that comments with the same timestamp are the same comment. - */ - created_at: new Date(comment.timestamp).toISOString(), - })); + return { + problem_id: problemId, + content: comment.content, + username: comment.username || getUsername() || 'Anonymous', + + /** + * Use timestamp as a unique identifier for the comment. + * This assumes that comments with the same timestamp are the same comment. + */ + created_at: new Date(timestamp).toISOString(), + }; + }); /** * Use upsert with onConflict to avoid duplicates. * This will insert new comments and ignore existing ones based on created_at. */ - const { error: commentsError } = await getSupabase().from('problem_comments').upsert(commentInserts, { - onConflict: 'created_at', - ignoreDuplicates: true, - }); + const { error: commentsError, data: commentsData } = await getSupabase() + .from('problem_comments') + .upsert(commentInserts, { + onConflict: 'created_at', + ignoreDuplicates: true, + }) + .select(); + + console.log('commentsData', commentsData); if (commentsError) { throw commentsError; } } + + // Fetch the updated problem with comments to return to the caller + const updatedProblem = await supabaseGetProblem(problemId); + + return updatedProblem; } catch (error) { console.error('Error updating problem', error); toast.error('Failed to update problem'); - } - return undefined; + return undefined; + } } export async function supabaseSubmitFeedback(feedback: any) { diff --git a/app/routes/problem.$id.tsx b/app/routes/problem.$id.tsx index 8f1cad50..82ed2fc1 100644 --- a/app/routes/problem.$id.tsx +++ b/app/routes/problem.$id.tsx @@ -24,7 +24,12 @@ function Comments({ comments }: { comments: BoltProblemComment[] }) {
{comment.username ?? 'Anonymous'} - {new Date(comment.timestamp).toLocaleString()} + + {(() => { + const date = new Date(comment.timestamp); + return date && !isNaN(date.getTime()) ? date.toLocaleString() : 'Unknown date'; + })()} +
{comment.content}
@@ -247,7 +252,13 @@ function ViewProblemPage() { const newProblem = callback(problemData); setProblemData(newProblem); console.log('BackendUpdateProblem', problemId, newProblem); - await backendUpdateProblem(problemId, newProblem); + + const updatedProblem = await backendUpdateProblem(problemId, newProblem); + + // If we got an updated problem back from the backend, use it to update the UI + if (updatedProblem && typeof updatedProblem !== 'undefined') { + setProblemData(updatedProblem); + } }, [problemData], ); diff --git a/package.json b/package.json index b0c285b7..e2d25d24 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,9 @@ "scripts": { "deploy": "vercel deploy --prod", "build": "npx remix vite:build", - "dev": "node pre-start.cjs && npx remix vite:dev", - "dev:supabase": "USE_SUPABASE=true node pre-start.cjs && npx remix vite:dev", - "dev:legacy": "USE_SUPABASE=false node pre-start.cjs && npx remix vite:dev", + "dev": "pnpm run dev:legacy", + "dev:supabase": "node pre-start.cjs && USE_SUPABASE=true npx remix vite:dev", + "dev:legacy": "node pre-start.cjs && USE_SUPABASE=false npx remix vite:dev", "test": "vitest --run --exclude tests/e2e", "test:watch": "vitest", "test:e2e": "playwright test",