diff --git a/client/package.json b/client/package.json index fbc2d72..0bca9cf 100644 --- a/client/package.json +++ b/client/package.json @@ -9,14 +9,18 @@ "lint": "next lint" }, "dependencies": { + "@types/react-calendar-heatmap": "^1.6.7", "@vercel/analytics": "^1.3.1", "@vercel/speed-insights": "^1.0.12", "axios": "^1.7.3", + "html2canvas": "^1.4.1", "mongoose": "^8.5.2", "next": "14.2.5", "react": "^18", + "react-calendar-heatmap": "^1.9.0", "react-dom": "^18", - "react-toastify": "^10.0.5" + "react-toastify": "^10.0.5", + "react-tooltip": "^5.28.0" }, "devDependencies": { "@types/node": "^20", diff --git a/client/public/assets/icons/loading.svg b/client/public/assets/icons/loading.svg new file mode 100644 index 0000000..02e78c4 --- /dev/null +++ b/client/public/assets/icons/loading.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/client/public/assets/icons/money.svg b/client/public/assets/icons/money.svg new file mode 100644 index 0000000..1046586 --- /dev/null +++ b/client/public/assets/icons/money.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/client/public/assets/icons/money2.svg b/client/public/assets/icons/money2.svg new file mode 100644 index 0000000..8d454b3 --- /dev/null +++ b/client/public/assets/icons/money2.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/client/src/app/components/Card.tsx b/client/src/app/components/Card.tsx index 335ca72..073112c 100644 --- a/client/src/app/components/Card.tsx +++ b/client/src/app/components/Card.tsx @@ -36,6 +36,13 @@ export const data = { easySolved: 175, mediumSolved: 110, hardSolved: 21, + activeYears: [2021, 2024], + calendarData: { + userCalendar: { + streak: 39, + totalActiveDays: 89, + }, + }, }; export default function Card({ userData = data, index }: any) { diff --git a/client/src/app/components/Circle.tsx b/client/src/app/components/Circle.tsx index edc8eda..0700c54 100644 --- a/client/src/app/components/Circle.tsx +++ b/client/src/app/components/Circle.tsx @@ -29,7 +29,7 @@ const Circle = ({ total }: any) => { strokeWidth="5" strokeLinecap="round" stroke="#FFC11F" - className="cursor-pointer " + className="" strokeDasharray={`${dashLength} ${circumference}`} strokeDashoffset="0" data-difficulty="ALL" diff --git a/client/src/app/components/Heatmap.tsx b/client/src/app/components/Heatmap.tsx new file mode 100644 index 0000000..dddc084 --- /dev/null +++ b/client/src/app/components/Heatmap.tsx @@ -0,0 +1,480 @@ +"use client"; + +import React, { useState, useEffect, useRef } from "react"; +import dynamic from "next/dynamic"; +import Image from "next/image"; +import { toast, ToastContainer } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; +import { data as TempData } from "./Card"; +import Link from "next/link"; +import Circle from "./Circle"; +import Questions from "./Questions"; +import html2canvas from "html2canvas"; + +const CalendarHeatmap = dynamic(() => import("react-calendar-heatmap"), { + ssr: false, +}); + +function convertSubmissionCalendar(submissionCalendar: any) { + // Parse the JSON string to convert it into a JavaScript object + const submissionCalendarData = JSON.parse(submissionCalendar); + + return submissionCalendarData; +} + +const submissionCalendarData = { + "1704067200": 2, + "1704153600": 4, + "1704240000": 3, + "1704326400": 1, + "1704412800": 2, + "1704499200": 1, + "1704585600": 3, + "1704672000": 1, + "1704758400": 2, + "1704844800": 1, + "1704931200": 1, + "1705017600": 1, + "1705104000": 1, + "1705190400": 1, + "1705276800": 1, + "1705363200": 1, + "1705449600": 1, + "1705520000": 1, + "1705536000": 1, + "1705622400": 1, + "1705708800": 1, + "1705795200": 1, + "1705881600": 1, + "1705968000": 1, + "1706054400": 1, + "1706140800": 1, + "1706227200": 1, + + "1702080000": 8, + "1702166400": 4, + "1702252800": 2, + "1702339200": 1, + "1702425600": 1, + "1702512000": 1, + "1702598400": 1, + "1702684800": 1, + "1702771200": 1, + "1702857600": 1, + "1702944000": 1, + "1703030400": 1, + "1703116800": 1, + "1703203200": 1, + "1703289600": 1, + "1703376000": 1, + "1703402400": 1, + + // Random data for each month of 2024 + "1703443200": 3, + "1703529600": 5, + "1703616000": 2, + "1703702400": 4, + "1703788800": 1, + "1703875200": 2, + "1703961600": 6, + "1704048000": 3, + "1704134400": 5, + "1704220800": 2, + "1704307200": 4, + "1704393600": 1, + "1704480000": 3, + "1704566400": 5, + "1704652800": 2, + "1704739200": 4, + + "1704825600": 6, + "1704912000": 1, + "1704998400": 2, + "1705084800": 3, + "1705171200": 5, + "1705257600": 4, + "1705344000": 1, + "1705430400": 3, + "1705516800": 5, + "1705603200": 2, + "1705689600": 4, + "1705776000": 6, + "1705862400": 1, + "1705948800": 2, + "1706035200": 3, + + // More random values for the remaining months + "1706121600": 1, + "1706208000": 4, + "1706294400": 2, + "1706380800": 5, + "1706467200": 1, + "1706553600": 3, + "1706640000": 6, + "1706726400": 2, + "1706812800": 4, + "1706899200": 1, + "1706985600": 5, + "1707072000": 3, + "1707158400": 6, + "1707244800": 2, + "1707331200": 4, + "1707417600": 1, +}; + +function worthCalculator( + streak: number, + easySolved: number, + mediumSolved: number, + hardSolved: number, + activeYears: number, + totalActiveDays: number +) { + const easyPoints = 1; + const mediumPoints = 2; + const hardPoints = 5; + const streakPoints = streak >= 30 ? 10 : 5; + const activeYearPoints = 2; + const totalActiveDaysPoints = 10; + + return ( + easySolved * easyPoints + + mediumSolved * mediumPoints + + hardSolved * hardPoints + + streak * streakPoints + + activeYears * activeYearPoints + + totalActiveDays * totalActiveDaysPoints + ); +} + +export default function Heatmap() { + const [isMounted, setIsMounted] = useState(false); + const [username, setUsername] = useState(""); + const [submissionCalendar, setSubmissionCalendar] = useState( + submissionCalendarData + ); + const [loading, setLoading] = useState(false); + const [data, setData] = useState(TempData); + const [tooltip, setTooltip] = useState({ + show: false, + content: "", + x: 0, + y: 0, + }); + + useEffect(() => { + setIsMounted(true); + }, []); + + const generateStats = async (e: React.FormEvent) => { + setLoading(true); + e.preventDefault(); + + if (!username) { + return; + } + + try { + const res = await fetch("/api/" + username); + if (!res.ok) { + toast("👻 User not found"); + setLoading(false); + return; + } + + const data = await res.json(); + setData(data); + setSubmissionCalendar(convertSubmissionCalendar(data.submissionCalendar)); + toast("🫡 Stats generated successfully"); + } catch (error) { + console.error("An error occurred. Please try again later"); + toast("😞 An error occurred. Please try again later"); + } finally { + setLoading(false); + } + }; + + const today = new Date(); + const endDate = today; + const startDate = new Date( + today.getFullYear() - 1, + today.getMonth(), + today.getDate() + 1 + ); + + const values = Object.entries(submissionCalendar) + .map(([timestamp, count]) => ({ + date: new Date(parseInt(timestamp) * 1000), + count: count, + })) + .filter((value) => value.date >= startDate && value.date <= endDate); + + const formatDate = (date: Date) => { + const months = [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", + ]; + return `${ + months[date.getMonth()] + } ${date.getDate()}, ${date.getFullYear()}`; + }; + + const contentRef = useRef(null); + + const downloadAsImage = async () => { + if (contentRef.current) { + try { + // Apply a background color to the element before capturing + contentRef.current.style.backgroundColor = "#1c1c1c"; + contentRef.current.style.padding = "20px"; + contentRef.current.style.borderRadius = "10px"; + + const canvas = await html2canvas(contentRef.current, { + scale: 2, // Increase scale for better quality + useCORS: true, // This can help with loading cross-origin images + logging: true, // This can help debug issues + backgroundColor: "#1c1c1c", // Set the background color + }); + + // Reset the inline styles after capturing + contentRef.current.style.backgroundColor = ""; + contentRef.current.style.padding = ""; + contentRef.current.style.borderRadius = ""; + + const image = canvas.toDataURL("image/png"); + const link = document.createElement("a"); + link.href = image; + link.download = "leetcode-stats.png"; + link.click(); + toast("🖼️ Image downloaded successfully"); + } catch (error) { + console.error("Error generating image:", error); + toast("😞 Error generating image. Please try again."); + } + } + }; + + const handleMouseOver = (event: any, value: any) => { + if (value && value.date) { + const rect = event.target.getBoundingClientRect(); + setTooltip({ + show: true, + content: `${value.count} submission${ + value.count !== 1 ? "s" : "" + } on ${formatDate(value.date)}`, + x: rect.left + window.scrollX, + y: rect.top + window.scrollY - 40, + }); + } + }; + + const handleMouseLeave = () => { + setTooltip({ ...tooltip, show: false }); + }; + + if (!isMounted) return null; + + return ( + <> + + + + Estimate LeetCode Worth Generator + + + + + setUsername(e.target.value)} + type="text" + placeholder="Enter the leetcode username" + className="bg-[#1f1f1f] pl-10 max-w-[600px] w-[300px] md:w-[450px] lg:w-[500px] h-[40px] text-white rounded px-4 py-6 md:text-lg text-base focus:outline-none" + /> + + + + + + Generate + {" "} + Worth + + + Download Image + + + + + + + + + + + + {data.profileData.fullName} + + @{data.profileData.username} + + + + + {/* Circle */} + + + + + {/* Questions */} + + + + + + + + + + + + { + if (!value || value.count === 0) { + return "color-empty"; + } + return `color-github-${Math.min(value.count, 4)}`; + }} + onMouseOver={handleMouseOver} + onMouseLeave={handleMouseLeave} + gutterSize={2} + horizontal={true} + /> + + + + {worthCalculator( + data.easySolved, + data.mediumSolved, + data.hardSolved, + data?.activeYears.length, + data?.calendarData.userCalendar.streak, + data?.calendarData.userCalendar.totalActiveDays + )} + $ + + + Estimated Worth + + + + Get Yours at: + + leetcode-profiles-delta.vercel.app + + + + {tooltip.show && ( + + {tooltip.content} + + )} + + + + > + ); +} diff --git a/client/src/app/components/Navbar.tsx b/client/src/app/components/Navbar.tsx index 672831f..17c0eef 100644 --- a/client/src/app/components/Navbar.tsx +++ b/client/src/app/components/Navbar.tsx @@ -4,16 +4,25 @@ import Image from "next/image"; import Link from "next/link"; import React, { useState } from "react"; -type NavbarProps = { - search: string; - setSearch: React.Dispatch>; -}; +interface NavbarProps { + search?: string; + setSearch?: (search: string) => void; + searchBarPresent?: boolean; +} -const Navbar: React.FC = ({ search, setSearch }) => { +const Navbar: React.FC = ({ + search, + setSearch, + searchBarPresent, +}) => { const [hoveredItem, setHoveredItem] = useState(null); return ( - + {/* Logo */} = ({ search, setSearch }) => { {/* Search */} - - - setSearch(e.target.value)} - type="text" - placeholder="Search by username" - className="bg-[#1f1f1f] sm:w-[260px] w-[100px] font-sourcecodepro text-white rounded px-4 py-3 focus:outline-none pl-10" - /> - - - + {searchBarPresent && ( + + + setSearch && setSearch(e.target.value)} + type="text" + placeholder="Search by username" + className="bg-[#1f1f1f] sm:w-[260px] w-[100px] font-sourcecodepro text-white rounded px-4 py-3 focus:outline-none pl-10" + /> + + + + )} {/* Profile */} diff --git a/client/src/app/context/DataContext.tsx b/client/src/app/context/DataContext.tsx index 82d359c..86847d0 100644 --- a/client/src/app/context/DataContext.tsx +++ b/client/src/app/context/DataContext.tsx @@ -5,15 +5,20 @@ import { createContext, useState } from "react"; export const DataContext = createContext({ datas: [], setDatas: (datas: any) => {}, + search: "", + setSearch: (search: string) => {}, }); export const DataProvider = ({ children }: any) => { const [datas, setDatas] = useState(); + const [search, setSearch] = useState(""); return ( {children} diff --git a/client/src/app/globals.css b/client/src/app/globals.css index c28c3b3..1ce297c 100644 --- a/client/src/app/globals.css +++ b/client/src/app/globals.css @@ -137,3 +137,52 @@ body { left: 50px; top: 9px; } + +/* Leetcode Heatmap styles */ +.react-calendar-heatmap text { + font-size: 10px; + fill: #aaa; +} + +.react-calendar-heatmap .react-calendar-heatmap-small-text { + font-size: 5px; +} + +.react-calendar-heatmap rect:hover { + stroke: #555; + stroke-width: 1px; +} +.react-calendar-heatmap .color-empty { + fill: #393939; +} +.react-calendar-heatmap rect { + rx: 2px; + ry: 2px; +} +.react-calendar-heatmap .month-label { + fill: #9ca3af; +} + +.react-calendar-heatmap .color-filled { + fill: #8cc665; +} + +/* + * Github color scale + */ + +.react-calendar-heatmap .color-github-0 { + fill: #eeeeee; +} +.react-calendar-heatmap .color-github-1 { + fill: #d6e685; +} +.react-calendar-heatmap .color-github-2 { + fill: #8cc665; +} +.react-calendar-heatmap .color-github-3 { + fill: #44a340; +} +.react-calendar-heatmap .color-github-4 { + fill: #1e6823; +} diff --git a/client/src/app/page.tsx b/client/src/app/page.tsx index 32000ba..6763ff9 100644 --- a/client/src/app/page.tsx +++ b/client/src/app/page.tsx @@ -5,17 +5,17 @@ import Navbar from "./components/Navbar"; import Card from "./components/Card"; import Footer from "./components/Footer"; import GenerateStats from "./components/GenerateStats"; -import { use, useContext, useEffect, useState } from "react"; +import { useContext, useEffect, useState } from "react"; import PromotionCard from "./components/PromotionCard"; import { DataContext } from "./context/DataContext"; import { ToastContainer } from "react-toastify"; import "react-toastify/dist/ReactToastify.css"; import Skeleton from "./components/Skeleton"; +import Link from "next/link"; export default function Home() { - const { datas, setDatas } = useContext(DataContext); + const { datas, setDatas, search, setSearch } = useContext(DataContext); const [loading, setLoading] = useState(true); - const [search, setSearch] = useState(""); const [showStats, setShowStats] = useState(false); const [sortBy, setSortBy] = useState("default"); @@ -75,15 +75,27 @@ export default function Home() { /> - + - + + + + LeetCode Worth + Sort By Default Sort By Questions Solved diff --git a/client/src/app/worth/page.tsx b/client/src/app/worth/page.tsx new file mode 100644 index 0000000..625f8c3 --- /dev/null +++ b/client/src/app/worth/page.tsx @@ -0,0 +1,15 @@ +import "react-toastify/dist/ReactToastify.css"; +import Heatmap from "../components/Heatmap"; +import Navbar from "../components/Navbar"; + +const Page = () => { + return ( + + + + + + ); +}; + +export default Page; diff --git a/client/src/pages/api/[username].ts b/client/src/pages/api/[username].ts index e11d884..e21100d 100644 --- a/client/src/pages/api/[username].ts +++ b/client/src/pages/api/[username].ts @@ -91,18 +91,46 @@ export default async function handler(req: any, res: any) { username: username, }, }; + const payload3 = { + operationName: "userProfileCalendar", + query: ` + query userProfileCalendar($username: String!, $year: Int) { + matchedUser(username: $username) { + userCalendar(year: $year) { + activeYears + streak + totalActiveDays + dccBadges { + timestamp + badge { + name + icon + } + } + submissionCalendar + } + } + } + `, + variables: { + username: username, + }, + }; try { const response1 = await axios.post(url, payload1, { headers }); const response2 = await axios.post(url, payload2, { headers }); + const response3 = await axios.post(url, payload3, { headers }); const data1 = response1.data; const data2 = response2.data; + const data3 = response3.data; // Merge the data from both responses const combinedData = { userSessionProgress: data1.data, userPublicProfile: data2.data, + userProfileCalendar: data3.data, }; const total = combinedData.userSessionProgress.allQuestionsCount[0].count; @@ -151,6 +179,10 @@ export default async function handler(req: any, res: any) { }, }; + const calendarData = combinedData.userProfileCalendar.matchedUser; + const activeYears = calendarData.userCalendar.activeYears; + const submissionCalendar = calendarData.userCalendar.submissionCalendar; + res.status(200).json({ profileData, aboutData, @@ -162,6 +194,9 @@ export default async function handler(req: any, res: any) { easySolved, mediumSolved, hardSolved, + calendarData, + activeYears, + submissionCalendar, }); } catch (error) { console.error(error); diff --git a/client/yarn.lock b/client/yarn.lock index 653e795..9f75c2c 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -39,6 +39,26 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== +"@floating-ui/core@^1.6.0": + version "1.6.7" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.7.tgz#7602367795a390ff0662efd1c7ae8ca74e75fb12" + integrity sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g== + dependencies: + "@floating-ui/utils" "^0.2.7" + +"@floating-ui/dom@^1.6.1": + version "1.6.10" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.10.tgz#b74c32f34a50336c86dcf1f1c845cf3a39e26d6f" + integrity sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A== + dependencies: + "@floating-ui/core" "^1.6.0" + "@floating-ui/utils" "^0.2.7" + +"@floating-ui/utils@^0.2.7": + version "0.2.7" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.7.tgz#d0ece53ce99ab5a8e37ebdfe5e32452a2bfc073e" + integrity sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA== + "@humanwhocodes/config-array@^0.11.14": version "0.11.14" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" @@ -227,6 +247,13 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6" integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== +"@types/react-calendar-heatmap@^1.6.7": + version "1.6.7" + resolved "https://registry.yarnpkg.com/@types/react-calendar-heatmap/-/react-calendar-heatmap-1.6.7.tgz#dec75660db7abb9b87a9ce9688221623e849d97b" + integrity sha512-xWBS9iOvw+aCidPk8QwCH69OCO7jnj6/9TjooqGQ9W+rA5m1aw36GjQMlSYKAg86otDeg9dzA+hSAIcvw/y9Rg== + dependencies: + "@types/react" "*" + "@types/react-dom@^18": version "18.3.0" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.0.tgz#0cbc818755d87066ab6ca74fbedb2547d74a82b0" @@ -526,6 +553,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base64-arraybuffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#1c37589a7c4b0746e34bd1feb951da2df01c1bdc" + integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ== + binary-extensions@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" @@ -614,6 +646,11 @@ chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" +classnames@^2.3.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" + integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== + client-only@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" @@ -662,6 +699,13 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" +css-line-break@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-line-break/-/css-line-break-2.1.0.tgz#bfef660dfa6f5397ea54116bb3cb4873edbc4fa0" + integrity sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w== + dependencies: + utrie "^1.0.2" + cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" @@ -1457,6 +1501,14 @@ hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: dependencies: function-bind "^1.1.2" +html2canvas@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/html2canvas/-/html2canvas-1.4.1.tgz#7cef1888311b5011d507794a066041b14669a543" + integrity sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA== + dependencies: + css-line-break "^2.1.0" + text-segmentation "^1.0.3" + ignore@^5.2.0: version "5.3.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" @@ -1846,6 +1898,11 @@ lru-cache@^10.2.0: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== +memoize-one@^5.0.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" + integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== + memory-pager@^1.0.2: version "1.5.0" resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5" @@ -2251,7 +2308,7 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prop-types@^15.8.1: +prop-types@^15.6.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -2275,6 +2332,14 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +react-calendar-heatmap@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/react-calendar-heatmap/-/react-calendar-heatmap-1.9.0.tgz#b691310a150d9c52e4ede21ebaa79734fc170d18" + integrity sha512-mGed9any6QLOVckxwxC/eeP9s9wE8mTUW/FCE0V27xF9WOaCGuOftGSRH8DSDoSwgzMSVF6uuH7M1xvc+aZ8sg== + dependencies: + memoize-one "^5.0.0" + prop-types "^15.6.2" + react-dom@^18: version "18.3.1" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" @@ -2295,6 +2360,14 @@ react-toastify@^10.0.5: dependencies: clsx "^2.1.0" +react-tooltip@^5.28.0: + version "5.28.0" + resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-5.28.0.tgz#c7b5343ab2d740a428494a3d8315515af1f26f46" + integrity sha512-R5cO3JPPXk6FRbBHMO0rI9nkUG/JKfalBSQfZedZYzmqaZQgq7GLzF8vcCWx6IhUCKg0yPqJhXIzmIO5ff15xg== + dependencies: + "@floating-ui/dom" "^1.6.1" + classnames "^2.3.0" + react@^18: version "18.3.1" resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" @@ -2695,6 +2768,13 @@ tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== +text-segmentation@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/text-segmentation/-/text-segmentation-1.0.3.tgz#52a388159efffe746b24a63ba311b6ac9f2d7943" + integrity sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw== + dependencies: + utrie "^1.0.2" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -2841,6 +2921,13 @@ util-deprecate@^1.0.2: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +utrie@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/utrie/-/utrie-1.0.2.tgz#d42fe44de9bc0119c25de7f564a6ed1b2c87a645" + integrity sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw== + dependencies: + base64-arraybuffer "^1.0.2" + webidl-conversions@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a"
@{data.profileData.username}
+ Get Yours at: + + leetcode-profiles-delta.vercel.app + +