From 9eb188750e903d616a453192d50ecd4c392cbe8e Mon Sep 17 00:00:00 2001 From: Kohminchae <72334086+Kohminchae@users.noreply.github.com> Date: Sat, 5 Oct 2024 23:09:01 +0900 Subject: [PATCH] feat(fe): add code manually save button (#2095) * feat(fe): add code manually save button * feat(fe): modify localStorage key * fix(fe): fix to localstorage * chore(fe): fix toast message * fix(fe): remove code context * chore(fe): fix code based on review * chore(fe): add useEffect dependency --- apps/frontend/components/EditorHeader.tsx | 72 +++++++++++++++++-- .../components/EditorResizablePanel.tsx | 17 +---- apps/frontend/components/auth/SignIn.tsx | 6 +- apps/frontend/stores/editor.ts | 42 ++++++----- 4 files changed, 99 insertions(+), 38 deletions(-) diff --git a/apps/frontend/components/EditorHeader.tsx b/apps/frontend/components/EditorHeader.tsx index 7275d4bca8..46a0061a07 100644 --- a/apps/frontend/components/EditorHeader.tsx +++ b/apps/frontend/components/EditorHeader.tsx @@ -24,7 +24,13 @@ import { auth } from '@/lib/auth' import { fetcherWithAuth } from '@/lib/utils' import submitIcon from '@/public/submit.svg' import useAuthModalStore from '@/stores/authModal' -import { CodeContext, useLanguageStore } from '@/stores/editor' +import { + useLanguageStore, + getKey, + setItem, + getItem, + CodeContext +} from '@/stores/editor' import type { Language, ProblemDetail, @@ -32,10 +38,11 @@ import type { Template } from '@/types/type' import JSConfetti from 'js-confetti' +import { Save } from 'lucide-react' import type { Route } from 'next' import Image from 'next/image' import { useRouter } from 'next/navigation' -import { useContext, useEffect, useState } from 'react' +import { useContext, useEffect, useRef, useState } from 'react' import { BsTrash3 } from 'react-icons/bs' //import { IoPlayCircleOutline } from 'react-icons/io5' import { useInterval } from 'react-use' @@ -60,8 +67,12 @@ export default function Editor({ const [loading, setLoading] = useState(false) const [submissionId, setSubmissionId] = useState(null) const [templateCode, setTemplateCode] = useState(null) + const [userName, setUserName] = useState('') const router = useRouter() const confetti = typeof window !== 'undefined' ? new JSConfetti() : null + const storageKey = useRef(getKey(language, problem.id, userName, contestId)) + const { currentModal, showSignIn } = useAuthModalStore((state) => state) + useInterval( async () => { const res = await fetcherWithAuth(`submission/${submissionId}`, { @@ -90,14 +101,15 @@ export default function Editor({ loading && submissionId ? 500 : null ) - const { showSignIn } = useAuthModalStore((state) => state) useEffect(() => { auth().then((session) => { if (!session) { - toast.info('Log in to use submission & auto save feature') + toast.info('Log in to use submission & save feature') + } else { + setUserName(session.user.username) } }) - }, []) + }, [currentModal]) useEffect(() => { if (!templateString) return @@ -109,6 +121,11 @@ export default function Editor({ setTemplateCode(filteredTemplate[0].code[0].text) }, [language]) + useEffect(() => { + storageKey.current = getKey(language, problem.id, userName, contestId) + getLocalstorageCode() + }, [userName, problem, contestId, language, templateCode]) + const submit = async () => { if (code === '') { toast.error('Please write code before submission') @@ -136,6 +153,7 @@ export default function Editor({ } }) if (res.ok) { + saveCode() const submission: Submission = await res.json() setSubmissionId(submission.id) } else { @@ -147,6 +165,40 @@ export default function Editor({ } } + const saveCode = async () => { + const session = await auth() + if (!session) { + toast.error('Log in first to save your code') + } else { + if (storeCodeToLocalstorage()) + toast.success('Successfully saved the code') + else toast.error('Failed to save the code') + } + } + + const storeCodeToLocalstorage = () => { + if (storageKey.current !== undefined) { + setItem(storageKey.current, code) + return true + } + return false + } + + const getLocalstorageCode = () => { + if (storageKey.current !== undefined) { + const storedCode = getItem(storageKey.current) ?? '' + setCode(storedCode ? JSON.parse(storedCode) : templateCode) + } + } + + const resetCode = () => { + if (storageKey.current !== undefined) { + setItem(storageKey.current, templateCode ?? '') + setCode(templateCode ?? '') + toast.success('Successfully reset the code') + } else toast.error('Failed to reset the code') + } + return (
@@ -173,7 +225,7 @@ export default function Editor({ Cancel setCode(templateCode ?? '')} + onClick={resetCode} > Reset @@ -182,6 +234,14 @@ export default function Editor({
+ {/* TODO: Add Test function