From 914e99613f3901380b042c764927f0eefc0c8c3a Mon Sep 17 00:00:00 2001 From: Kagari <112100828+yangzhijiany@users.noreply.github.com> Date: Sun, 7 Dec 2025 20:48:46 -0600 Subject: [PATCH] Modified some frontend leetcode part. Edit some backend bugs and modified docker file to auto run the manage.py --- backend/leetcode/serializers.py | 2 +- backend/leetcode/views.py | 8 +- docker-compose.yml | 1 + frontend/vite-project/src/LeetCode.jsx | 299 ++++++++++++++++--------- 4 files changed, 204 insertions(+), 106 deletions(-) diff --git a/backend/leetcode/serializers.py b/backend/leetcode/serializers.py index 6cc2f41..c4bdae8 100644 --- a/backend/leetcode/serializers.py +++ b/backend/leetcode/serializers.py @@ -19,7 +19,7 @@ class UserProblemRecordSerializer(serializers.ModelSerializer): class Meta: model = UserProblemRecord - fields = ["problem", "solved_at"] + fields = ["problem", "problem_id", "solved_at"] def create(self, validated_data): return super().create(validated_data) diff --git a/backend/leetcode/views.py b/backend/leetcode/views.py index 86913db..bf3da3b 100644 --- a/backend/leetcode/views.py +++ b/backend/leetcode/views.py @@ -17,8 +17,12 @@ class UserProblemRecordViewSet(viewsets.ModelViewSet): permission_classes = [permissions.IsAuthenticated] def get_queryset(self): - # return user records - return UserProblemRecord.objects.filter(user=self.request.user).select_related("problem") + # return user records, ordered by problem_id + return ( + UserProblemRecord.objects.filter(user=self.request.user) + .select_related("problem") + .order_by("problem__problem_id") + ) def perform_create(self, serializer): serializer.save(user=self.request.user) diff --git a/docker-compose.yml b/docker-compose.yml index 2591156..869b742 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,6 +9,7 @@ services: command: > sh -c " python manage.py migrate && + python manage.py get_leetcode_problem && python manage.py runserver 0.0.0.0:8000 " volumes: diff --git a/frontend/vite-project/src/LeetCode.jsx b/frontend/vite-project/src/LeetCode.jsx index 63bc554..0483ab2 100644 --- a/frontend/vite-project/src/LeetCode.jsx +++ b/frontend/vite-project/src/LeetCode.jsx @@ -1,97 +1,146 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import { useNavigate } from "react-router-dom"; import "./LeetCode.css"; function LeetCode() { const navigate = useNavigate(); const [problemNumber, setProblemNumber] = useState(""); - const [records, setRecords] = useState([ - // Example placeholder record - { - id: 1, - number: 1, - name: "Two Sum", - difficulty: "Easy", - topics: ["Array", "Hash Table"], - completedAt: "2024-01-15 10:30:00", - }, - ]); + const [records, setRecords] = useState([]); const [error, setError] = useState(""); + const [loading, setLoading] = useState(false); + const [submitting, setSubmitting] = useState(false); - const handleSubmit = (e) => { + const fetchRecords = async (token) => { + setLoading(true); + try { + const response = await fetch("http://localhost:8000/leetcode/records/", { + method: "GET", + headers: { + Authorization: `Token ${token}`, + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + throw new Error("Failed to fetch records"); + } + + const responseData = await response.json(); + const recordsList = responseData.results || responseData; + const sortedRecords = Array.isArray(recordsList) + ? recordsList.sort( + (a, b) => a.problem.problem_id - b.problem.problem_id, + ) + : []; + setRecords(sortedRecords); + } catch (error) { + console.error("Error fetching records:", error); + setError("Failed to load records"); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + const token = localStorage.getItem("token"); + if (token) { + fetchRecords(token); + } else { + navigate("/login"); + } + }, [navigate]); + + const handleSubmit = async (e) => { e.preventDefault(); setError(""); + setSubmitting(true); const number = parseInt(problemNumber.trim()); if (isNaN(number) || number <= 0) { setError("Please enter a valid positive integer for the problem number."); + setSubmitting(false); return; } - if (records.some((record) => record.number === number)) { + const token = localStorage.getItem("token"); + if (!token) { + setError("Please login first."); + setSubmitting(false); + navigate("/login"); + return; + } + + if (records.some((record) => record.problem.problem_id === number)) { setError(`Problem #${number} already exists in your records.`); + setSubmitting(false); return; } - const exampleNames = [ - "Two Sum", - "Add Two Numbers", - "Longest Substring Without Repeating Characters", - "Median of Two Sorted Arrays", - "Longest Palindromic Substring", - "ZigZag Conversion", - "Reverse Integer", - "String to Integer (atoi)", - "Palindrome Number", - "Regular Expression Matching", - ]; - - const difficulties = ["Easy", "Medium", "Hard"]; - const allTopics = [ - "Array", - "Hash Table", - "Two Pointers", - "String", - "Dynamic Programming", - "Math", - "Tree", - "Graph", - "Backtracking", - "Greedy", - "Binary Search", - "Stack", - "Queue", - "Linked List", - ]; - - const randomName = - exampleNames[Math.floor(Math.random() * exampleNames.length)]; - const randomDifficulty = - difficulties[Math.floor(Math.random() * difficulties.length)]; - const topicCount = Math.floor(Math.random() * 3) + 1; // 1-3 topics - const shuffledTopics = [...allTopics].sort(() => 0.5 - Math.random()); - const randomTopics = shuffledTopics.slice(0, topicCount); - - const now = new Date(); - const completedAt = `${now.getFullYear()}-${String( - now.getMonth() + 1, - ).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")} ${String( - now.getHours(), - ).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}:${String( - now.getSeconds(), - ).padStart(2, "0")}`; - - const newRecord = { - id: Date.now(), - number: number, - name: randomName, - difficulty: randomDifficulty, - topics: randomTopics, - completedAt: completedAt, - }; - - setRecords([...records, newRecord].sort((a, b) => a.number - b.number)); - setProblemNumber(""); + try { + const recordResponse = await fetch( + "http://localhost:8000/leetcode/records/", + { + method: "POST", + headers: { + Authorization: `Token ${token}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ + problem_id: number, + }), + }, + ); + + if (!recordResponse.ok) { + let errorData; + try { + errorData = await recordResponse.json(); + } catch (e) { + errorData = {}; + } + + if (recordResponse.status === 400) { + let errorMsg = errorData.detail; + + if (!errorMsg && errorData.problem_id) { + if (Array.isArray(errorData.problem_id)) { + errorMsg = errorData.problem_id[0]; + } else { + errorMsg = errorData.problem_id; + } + } + + if (!errorMsg && errorData.non_field_errors) { + if (Array.isArray(errorData.non_field_errors)) { + errorMsg = errorData.non_field_errors[0]; + } else { + errorMsg = errorData.non_field_errors; + } + } + + if (!errorMsg) { + errorMsg = `Problem #${number} may already exist in your records, or does not exist in the database.`; + } + + setError(errorMsg); + } else if (recordResponse.status === 404) { + setError(`Problem #${number} does not exist in the database. Please ensure the problem is loaded.`); + } else { + setError(`Failed to create record (status: ${recordResponse.status}). Please try again later.`); + } + setSubmitting(false); + return; + } + + await fetchRecords(token); + setProblemNumber(""); + setError(""); + } catch (error) { + console.error("Error creating record:", error); + setError("Failed to create record. Please try again later."); + } finally { + setSubmitting(false); + } }; const getDifficultyColor = (difficulty) => { @@ -121,7 +170,7 @@ function LeetCode() {
Loading...
+Null
-Please enter the problem number.
+No records
+Please enter a problem number to add a record.