diff --git a/.gitignore b/.gitignore index ee0d821..eea0c4a 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,6 @@ dist **/.idea scripts/ **/scripts/ -scripts/manual-notarize.js \ No newline at end of file +scripts/manual-notarize.js +autorun.bat +skibidi.vbs \ No newline at end of file diff --git a/README.md b/README.md index 47aeaf6..06cbae1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +# Changes I have done : +> - Changed Prompting for solving MCQs of topics related to OS,DBMS,Programming(even Syntax-based too) +> - Renders based on whether the question is a Coding problem or an MCQ (for MCQ it gives correct answer and explanation too) + # CodeInterviewAssist > ## ⚠️ IMPORTANT NOTICE TO THE COMMUNITY ⚠️ diff --git a/autorun.bat b/autorun.bat new file mode 100644 index 0000000..cb3b2c3 --- /dev/null +++ b/autorun.bat @@ -0,0 +1,3 @@ +@echo off +cd C:\Users\asmit\Downloads\interviewCoder\interview +stealth-run.bat \ No newline at end of file diff --git a/electron/ProcessingHelper.ts b/electron/ProcessingHelper.ts index 0dcd26f..f49830e 100644 --- a/electron/ProcessingHelper.ts +++ b/electron/ProcessingHelper.ts @@ -1,4 +1,4 @@ -// ProcessingHelper.ts +// ProcessingHelper.ts - UPDATED VERSION with Enhanced MCQ Detection import fs from "node:fs" import path from "node:path" import { ScreenshotHelper } from "./ScreenshotHelper" @@ -477,14 +477,14 @@ export class ProcessingHelper { const messages = [ { role: "system" as const, - content: "You are a coding challenge interpreter. Analyze the screenshot of the coding problem and extract all relevant information. Return the information in JSON format with these fields: problem_statement, constraints, example_input, example_output. Just return the structured JSON without any other text." + content: "You are an intelligent assistant that analyzes screenshots and determines if they contain coding problems or Multiple Choice Questions (MCQs).\n\n**IMPORTANT: Look carefully at the image content, including any code snippets, formatted text, or structured questions.**\n\n**If it's a CODING PROBLEM (like LeetCode, programming challenges):**\nReturn JSON format: {\"problem_statement\": \"...\", \"constraints\": \"...\", \"example_input\": \"...\", \"example_output\": \"...\"}\n\n**If it's an MCQ (Multiple Choice Question) - this includes:**\n- Questions with options A, B, C, D (even if formatted/colored)\n- Code-based MCQs with syntax highlighting\n- Questions asking \"What will be the output?\"\n- Questions about programming concepts, syntax, or theory\n- SQL queries asking \"What will this query do?\"\n- Java code asking \"What is the output?\"\n\nReturn in this EXACT format:\nMCQ_ANSWER: [A/B/C/D]\nEXPLANATION: [Detailed explanation of why this answer is correct, including step-by-step code analysis if applicable]\n\n**If it's neither:**\nReturn: UNSUPPORTED_FORMAT" }, { role: "user" as const, content: [ { type: "text" as const, - text: `Extract the coding problem details from these screenshots. Return in JSON format. Preferred coding language we gonna use for this problem is ${language}.` + text: `Analyze this screenshot. If it's a coding problem, return JSON format. If it's an MCQ about computer science topics (including code-based questions asking \"What will be the output?\" or \"What will this query do?\"), provide the MCQ answer and explanation as specified.` }, ...imageDataList.map(data => ({ type: "image_url" as const, @@ -505,7 +505,68 @@ export class ProcessingHelper { // Parse the response try { const responseText = extractionResponse.choices[0].message.content; - // Handle when OpenAI might wrap the JSON in markdown code blocks + + // Enhanced MCQ detection function + const isMCQResponse = (text: string): boolean => { + if (text.includes('MCQ_ANSWER:')) return true; + + const mcqIndicators = [ + 'what will be the output', + 'which of the following', + 'what is the result', + 'what will this query do', + 'what does the following' + ]; + + const lowerText = text.toLowerCase(); + return mcqIndicators.some(indicator => lowerText.includes(indicator)); + }; + + // Check if it's an MCQ response + if (isMCQResponse(responseText)) { + let answerMatch = responseText.match(/MCQ_ANSWER:\s*([A-D])/i); + + if (!answerMatch) { + answerMatch = responseText.match(/(?:answer\s*(?:is\s*)?):?\s*([A-D])/i); + } + + let explanationMatch = responseText.match(/EXPLANATION:\s*(.*)/is); + if (!explanationMatch) { + explanationMatch = [null, responseText]; + } + + const mcqResult = { + isMCQ: true, + answer: answerMatch ? answerMatch[1].toUpperCase() : 'Unknown', + explanation: explanationMatch ? explanationMatch[1].trim() : responseText.trim(), + fullResponse: responseText + }; + + // Update progress and send MCQ result to frontend + if (mainWindow) { + mainWindow.webContents.send("processing-status", { + message: "MCQ answered successfully", + progress: 100 + }); + + mainWindow.webContents.send( + this.deps.PROCESSING_EVENTS.SOLUTION_SUCCESS, + mcqResult + ); + } + + return { success: true, data: mcqResult }; + } + + // Handle unsupported format + if (responseText.includes('UNSUPPORTED_FORMAT')) { + return { + success: false, + error: "This appears to be neither a coding problem nor a supported MCQ. Please try a clearer screenshot." + }; + } + + // Handle as coding problem (existing logic) const jsonText = responseText.replace(/```json|```/g, '').trim(); problemInfo = JSON.parse(jsonText); } catch (error) { @@ -525,13 +586,44 @@ export class ProcessingHelper { } try { - // Create Gemini message structure + // Enhanced Gemini prompt for better code-based MCQ detection const geminiMessages: GeminiMessage[] = [ { role: "user", parts: [ { - text: `You are a coding challenge interpreter. Analyze the screenshots of the coding problem and extract all relevant information. Return the information in JSON format with these fields: problem_statement, constraints, example_input, example_output. Just return the structured JSON without any other text. Preferred coding language we gonna use for this problem is ${language}.` + text: `You are an intelligent assistant that analyzes screenshots and determines if they contain coding problems or Multiple Choice Questions (MCQs). + +**IMPORTANT: Look carefully at the image content, including any code snippets, formatted text, or structured questions.** + +**If it's a CODING PROBLEM (like LeetCode, programming challenges):** +Return JSON format: {"problem_statement": "...", "constraints": "...", "example_input": "...", "example_output": "..."} +Preferred coding language: ${language} + +**If it's an MCQ (Multiple Choice Question) - this includes:** +- Questions with options A, B, C, D (even if formatted/colored) +- Code-based MCQs with syntax highlighting +- Questions asking "What will be the output?" +- Questions about programming concepts, syntax, or theory +- SQL queries asking "What will this query do?" +- Java code asking "What is the output?" +- Any question with lettered options asking about code behavior + +Return in this EXACT format: +MCQ_ANSWER: [A/B/C/D] +EXPLANATION: [Detailed explanation of why this answer is correct, including step-by-step code analysis if applicable] + +**Examples of MCQs to detect:** +- "What will be the output of this Java code?" +- "Which SQL query will do X?" +- "What will the following SQL query do?" +- "What is the result of this code snippet?" +- Any question with lettered options (A, B, C, D) + +**If it's neither:** +Return: UNSUPPORTED_FORMAT + +Analyze this screenshot carefully and respond appropriately:` }, ...imageDataList.map(data => ({ inlineData: { @@ -563,10 +655,103 @@ export class ProcessingHelper { } const responseText = responseData.candidates[0].content.parts[0].text; + + // Enhanced MCQ detection function + // Enhanced MCQ detection function +const isMCQResponse = (text: string): boolean => { + if (text.includes('MCQ_ANSWER:')) return true; + + const mcqIndicators = [ + 'what will be the output', + 'which of the following', + 'what is the result', + 'what will this query do', + 'what does the following', + 'the correct answer is', + 'answer is' + ]; + + const lowerText = text.toLowerCase(); + return mcqIndicators.some(indicator => lowerText.includes(indicator)); +}; + +// Check if it's an MCQ response +if (isMCQResponse(responseText)) { + // Try multiple patterns to extract the answer + let answerMatch = responseText.match(/MCQ_ANSWER:\s*([A-D])/i); + + if (!answerMatch) { + // Try "Answer: B" pattern + answerMatch = responseText.match(/(?:answer\s*(?:is\s*)?):?\s*([A-D])/i); + } + + if (!answerMatch) { + // Try "The answer is B" pattern + answerMatch = responseText.match(/(?:the\s+answer\s+is\s+)([A-D])/i); + } + + if (!answerMatch) { + // Try "Correct answer: B" pattern + answerMatch = responseText.match(/(?:correct\s+answer\s*:?\s*)([A-D])/i); + } + + if (!answerMatch) { + // Try standalone letter pattern (look for isolated A, B, C, or D) + answerMatch = responseText.match(/\b([A-D])\b/); + } + + // Try multiple explanation patterns + let explanationMatch = responseText.match(/EXPLANATION:\s*(.*)/is); + if (!explanationMatch) { + explanationMatch = responseText.match(/(?:explanation|because|reason):\s*(.*)/is); + } + if (!explanationMatch) { + // If no explicit explanation found, use the full response + explanationMatch = [null, responseText]; + } + + const mcqResult = { + isMCQ: true, + answer: answerMatch ? answerMatch[1].toUpperCase() : 'Unknown', + explanation: explanationMatch ? explanationMatch[1].trim() : responseText.trim(), + fullResponse: responseText + }; + + + if (mainWindow) { + mainWindow.webContents.send("processing-status", { + message: "MCQ answered successfully", + progress: 100 + }); + + mainWindow.webContents.send( + this.deps.PROCESSING_EVENTS.SOLUTION_SUCCESS, + mcqResult + ); + } + + return { success: true, data: mcqResult }; + } + + // Handle unsupported format + if (responseText.includes('UNSUPPORTED_FORMAT')) { + return { + success: false, + error: "This appears to be neither a coding problem nor a supported MCQ. Please try a clearer screenshot." + }; + } - // Handle when Gemini might wrap the JSON in markdown code blocks - const jsonText = responseText.replace(/```json|```/g, '').trim(); - problemInfo = JSON.parse(jsonText); + // Handle as coding problem (existing logic) + try { + const jsonText = responseText.replace(/```json|```/g, '').trim(); + problemInfo = JSON.parse(jsonText); + } catch (parseError) { + console.error("Error parsing JSON from Gemini response:", parseError); + return { + success: false, + error: "Failed to parse problem information. Please try again or use clearer screenshots." + }; + } } catch (error) { console.error("Error using Gemini API:", error); return { @@ -1314,4 +1499,4 @@ If you include code examples, use proper markdown code blocks with language spec mainWindow.webContents.send(this.deps.PROCESSING_EVENTS.NO_SCREENSHOTS) } } -} +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index da87e3a..82aa250 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,6 +37,7 @@ "react-syntax-highlighter": "^15.6.1", "screenshot-desktop": "^1.15.0", "tailwind-merge": "^2.5.5", + "tesseract.js": "^6.0.1", "uuid": "^11.0.3" }, "devDependencies": { @@ -4056,6 +4057,12 @@ "bluebird": "^3.5.5" } }, + "node_modules/bmp-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", + "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==", + "license": "MIT" + }, "node_modules/boolean": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", @@ -7308,6 +7315,12 @@ "node": ">=0.10.0" } }, + "node_modules/idb-keyval": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.2.tgz", + "integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==", + "license": "Apache-2.0" + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -7526,6 +7539,12 @@ "node": ">=8" } }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "license": "MIT" + }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -9314,6 +9333,15 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "license": "MIT" }, + "node_modules/opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "license": "MIT", + "bin": { + "opencollective-postinstall": "index.js" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -11294,6 +11322,36 @@ "rimraf": "bin.js" } }, + "node_modules/tesseract.js": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/tesseract.js/-/tesseract.js-6.0.1.tgz", + "integrity": "sha512-/sPvMvrCtgxnNRCjbTYbr7BRu0yfWDsMZQ2a/T5aN/L1t8wUQN6tTWv6p6FwzpoEBA0jrN2UD2SX4QQFRdoDbA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "bmp-js": "^0.1.0", + "idb-keyval": "^6.2.0", + "is-url": "^1.2.4", + "node-fetch": "^2.6.9", + "opencollective-postinstall": "^2.0.3", + "regenerator-runtime": "^0.13.3", + "tesseract.js-core": "^6.0.0", + "wasm-feature-detect": "^1.2.11", + "zlibjs": "^0.3.1" + } + }, + "node_modules/tesseract.js-core": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tesseract.js-core/-/tesseract.js-core-6.0.0.tgz", + "integrity": "sha512-1Qncm/9oKM7xgrQXZXNB+NRh19qiXGhxlrR8EwFbK5SaUbPZnS5OMtP/ghtqfd23hsr1ZvZbZjeuAGcMxd/ooA==", + "license": "Apache-2.0" + }, + "node_modules/tesseract.js/node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "license": "MIT" + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -11781,6 +11839,12 @@ "node": ">=12.0.0" } }, + "node_modules/wasm-feature-detect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.8.0.tgz", + "integrity": "sha512-zksaLKM2fVlnB5jQQDqKXXwYHLQUVH9es+5TOOHwGOVJOCeRBCiPjwSg+3tN2AdTCzjgli4jijCH290kXb/zWQ==", + "license": "Apache-2.0" + }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", @@ -12125,6 +12189,15 @@ "node": ">= 10" } }, + "node_modules/zlibjs": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/zlibjs/-/zlibjs-0.3.1.tgz", + "integrity": "sha512-+J9RrgTKOmlxFSDHo0pI1xM6BLVUv+o0ZT9ANtCxGkjIVCCUdx9alUF8Gm+dGLKbkkkidWIHFDZHDMpfITt4+w==", + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", diff --git a/package.json b/package.json index 1fffcfb..40456ae 100644 --- a/package.json +++ b/package.json @@ -150,6 +150,7 @@ "react-syntax-highlighter": "^15.6.1", "screenshot-desktop": "^1.15.0", "tailwind-merge": "^2.5.5", + "tesseract.js": "^6.0.1", "uuid": "^11.0.3" }, "devDependencies": { diff --git a/skibidi.vbs b/skibidi.vbs new file mode 100644 index 0000000..836143d --- /dev/null +++ b/skibidi.vbs @@ -0,0 +1,3 @@ +Set WshShell = CreateObject("WScript.Shell") +WshShell.Run chr(34) & "C:\Users\asmit\OneDrive\Desktop\interview\autorun.bat" & chr(34), 0 +Set WshShell = Nothing diff --git a/src/_pages/Solutions.tsx b/src/_pages/Solutions.tsx index e193945..0cd7e74 100644 --- a/src/_pages/Solutions.tsx +++ b/src/_pages/Solutions.tsx @@ -12,6 +12,24 @@ import Debug from "./Debug" import { useToast } from "../contexts/toast" import { COMMAND_KEY } from "../utils/platform" +// Define proper types for solution data +interface MCQSolutionData { + isMCQ: true + answer: string + explanation: string + fullResponse: string +} + +interface CodeSolutionData { + isMCQ: false | undefined + code: string + thoughts: string[] + time_complexity: string + space_complexity: string +} + +type SolutionData = MCQSolutionData | CodeSolutionData | null + export const ContentSection = ({ title, content, @@ -38,6 +56,7 @@ export const ContentSection = ({ )} ) + const SolutionSection = ({ title, content, @@ -171,6 +190,7 @@ export interface SolutionsProps { currentLanguage: string setLanguage: (language: string) => void } + const Solutions: React.FC = ({ setView, credits, @@ -183,14 +203,13 @@ const Solutions: React.FC = ({ const [debugProcessing, setDebugProcessing] = useState(false) const [problemStatementData, setProblemStatementData] = useState(null) - const [solutionData, setSolutionData] = useState(null) + + // Fix the type definition for solutionData + const [solutionData, setSolutionData] = useState(null) + const [thoughtsData, setThoughtsData] = useState(null) - const [timeComplexityData, setTimeComplexityData] = useState( - null - ) - const [spaceComplexityData, setSpaceComplexityData] = useState( - null - ) + const [timeComplexityData, setTimeComplexityData] = useState(null) + const [spaceComplexityData, setSpaceComplexityData] = useState(null) const [isTooltipVisible, setIsTooltipVisible] = useState(false) const [tooltipHeight, setTooltipHeight] = useState(0) @@ -307,16 +326,11 @@ const Solutions: React.FC = ({ window.electronAPI.onSolutionError((error: string) => { showToast("Processing Failed", error, "error") // Reset solutions in the cache (even though this shouldn't ever happen) and complexities to previous states - const solution = queryClient.getQueryData(["solution"]) as { - code: string - thoughts: string[] - time_complexity: string - space_complexity: string - } | null + const solution = queryClient.getQueryData(["solution"]) as CodeSolutionData | null if (!solution) { setView("queue") } - setSolutionData(solution?.code || null) + setSolutionData(solution) setThoughtsData(solution?.thoughts || null) setTimeComplexityData(solution?.time_complexity || null) setSpaceComplexityData(solution?.space_complexity || null) @@ -329,19 +343,39 @@ const Solutions: React.FC = ({ return } console.log({ data }) - const solutionData = { - code: data.code, - thoughts: data.thoughts, - time_complexity: data.time_complexity, - space_complexity: data.space_complexity + + // Check if it's an MCQ result + if (data.isMCQ) { + // Handle MCQ data + const mcqData: MCQSolutionData = { + isMCQ: true, + answer: data.answer, + explanation: data.explanation, + fullResponse: data.fullResponse + } + + queryClient.setQueryData(["solution"], mcqData) + setSolutionData(mcqData) + setThoughtsData(null) + setTimeComplexityData(null) + setSpaceComplexityData(null) + } else { + // Handle regular coding solution data + const codeSolutionData: CodeSolutionData = { + isMCQ: false, + code: data.code, + thoughts: data.thoughts, + time_complexity: data.time_complexity, + space_complexity: data.space_complexity + } + + queryClient.setQueryData(["solution"], codeSolutionData) + setSolutionData(codeSolutionData) + setThoughtsData(codeSolutionData.thoughts || null) + setTimeComplexityData(codeSolutionData.time_complexity || null) + setSpaceComplexityData(codeSolutionData.space_complexity || null) } - - queryClient.setQueryData(["solution"], solutionData) - setSolutionData(solutionData.code || null) - setThoughtsData(solutionData.thoughts || null) - setTimeComplexityData(solutionData.time_complexity || null) - setSpaceComplexityData(solutionData.space_complexity || null) - + // Fetch latest screenshots when solution is successful const fetchScreenshots = async () => { try { @@ -412,17 +446,22 @@ const Solutions: React.FC = ({ ) } if (event?.query.queryKey[0] === "solution") { - const solution = queryClient.getQueryData(["solution"]) as { - code: string - thoughts: string[] - time_complexity: string - space_complexity: string - } | null - - setSolutionData(solution?.code ?? null) - setThoughtsData(solution?.thoughts ?? null) - setTimeComplexityData(solution?.time_complexity ?? null) - setSpaceComplexityData(solution?.space_complexity ?? null) + const solution = queryClient.getQueryData(["solution"]) as SolutionData + + if (solution && !solution.isMCQ) { + // Only update these for code solutions + const codeSolution = solution as CodeSolutionData + setSolutionData(solution) + setThoughtsData(codeSolution.thoughts ?? null) + setTimeComplexityData(codeSolution.time_complexity ?? null) + setSpaceComplexityData(codeSolution.space_complexity ?? null) + } else { + // For MCQ solutions, just set the solution data + setSolutionData(solution) + setThoughtsData(null) + setTimeComplexityData(null) + setSpaceComplexityData(null) + } } }) return () => unsubscribe() @@ -463,6 +502,16 @@ const Solutions: React.FC = ({ } } + // Helper function to check if solutionData is MCQ + const isMCQSolution = (data: SolutionData): data is MCQSolutionData => { + return data !== null && data.isMCQ === true + } + + // Helper function to check if solutionData is Code solution + const isCodeSolution = (data: SolutionData): data is CodeSolutionData => { + return data !== null && !data.isMCQ + } + return ( <> {!isResetting && queryClient.getQueryData(["new_solution"]) ? ( @@ -523,40 +572,62 @@ const Solutions: React.FC = ({ {solutionData && ( <> - -
- {thoughtsData.map((thought, index) => ( -
-
-
{thought}
-
- ))} -
+ {/* Check if it's MCQ data */} + {isMCQSolution(solutionData) ? ( + // MCQ Display +
+
+

MCQ Answer

+
+ + {solutionData.answer} + + Correct Answer
- ) - } - isLoading={!thoughtsData} - /> - - - - +
+

{solutionData.explanation}

+
+
+
+ ) : isCodeSolution(solutionData) ? ( + // Regular Coding Solution Display + <> + +
+ {thoughtsData.map((thought, index) => ( +
+
+
{thought}
+
+ ))} +
+
+ ) + } + isLoading={!thoughtsData} + /> + + + + + + ) : null} )}
@@ -569,4 +640,4 @@ const Solutions: React.FC = ({ ) } -export default Solutions +export default Solutions \ No newline at end of file