From 3a22ea8d2d60e183dd1a56f27aeb100988efb92d Mon Sep 17 00:00:00 2001 From: Milind Mishra Date: Sun, 28 Apr 2024 12:36:28 +0530 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=A6=20NEW:=20add=20total=20roadmaps=20?= =?UTF-8?q?generated=20ticker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + pnpm-lock.yaml | 22 +++++++++++++ src/actions/roadmaps.ts | 5 +++ src/app/page.tsx | 2 -- src/components/landing/roadmap-hero.tsx | 16 +++++++++- src/components/marketing/text-ticker.tsx | 40 ++++++++++++++++++++++++ 6 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 src/components/marketing/text-ticker.tsx diff --git a/package.json b/package.json index d433e9f..8facc30 100644 --- a/package.json +++ b/package.json @@ -73,6 +73,7 @@ "dayjs": "^1.11.10", "dotenv": "^16.4.5", "embla-carousel-react": "^8.0.0", + "framer-motion": "^11.1.7", "html-to-image": "^1.11.11", "input-otp": "^1.2.0", "lucide-react": "^0.358.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ea1df8c..8656695 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -176,6 +176,9 @@ dependencies: embla-carousel-react: specifier: ^8.0.0 version: 8.0.0(react@18.2.0) + framer-motion: + specifier: ^11.1.7 + version: 11.1.7(react-dom@18.2.0)(react@18.2.0) html-to-image: specifier: ^1.11.11 version: 1.11.11 @@ -4235,6 +4238,25 @@ packages: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} dev: true + /framer-motion@11.1.7(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-cW11Pu53eDAXUEhv5hEiWuIXWhfkbV32PlgVISn7jRdcAiVrJ1S03YQQ0/DzoswGYYwKi4qYmHHjCzAH52eSdQ==} + peerDependencies: + '@emotion/is-prop-valid': '*' + react: ^18.0.0 + react-dom: ^18.0.0 + peerDependenciesMeta: + '@emotion/is-prop-valid': + optional: true + react: + optional: true + react-dom: + optional: true + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + tslib: 2.6.2 + dev: false + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} dev: true diff --git a/src/actions/roadmaps.ts b/src/actions/roadmaps.ts index ed33eb7..38ed6d5 100644 --- a/src/actions/roadmaps.ts +++ b/src/actions/roadmaps.ts @@ -389,3 +389,8 @@ export const findSavedNodeDetails = async ( throw new Error("Failed to find saved node details"); } }; + +export const getTotalRoadmapsGenerated = async () => { + const totalRoadmaps = await db.roadmap.count(); + return totalRoadmaps; +}; diff --git a/src/app/page.tsx b/src/app/page.tsx index 39d9817..0ac94f0 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,4 +1,3 @@ -// import Confetti from "@/components/landing/roadmap-confetti"; import RoadmapHero from "@/components/landing/roadmap-hero"; import RoadmapFeatures from "@/components/landing/roadmap-features"; import RoadmapTestimonial from "@/components/testimonials/roadmap-testimonial"; @@ -9,7 +8,6 @@ import RoadmapFooter from "@/components/landing/roadmap-footer"; export default function Home() { return ( <> - {/* */} diff --git a/src/components/landing/roadmap-hero.tsx b/src/components/landing/roadmap-hero.tsx index 5fe4c92..4d39bc6 100644 --- a/src/components/landing/roadmap-hero.tsx +++ b/src/components/landing/roadmap-hero.tsx @@ -1,5 +1,4 @@ import DotPattern from "@/components/ui/dot-pattern"; -import { buttonVariants } from "@/components/ui/button"; import MarqueeDemo from "@/components/ui/marque-wrapper"; import { cn } from "@/lib/utils"; import { clerkClient } from "@clerk/nextjs"; @@ -8,6 +7,20 @@ import Image from "next/image"; import Link from "next/link"; import { Link as LinkWithViewTransitions } from "next-view-transitions"; import NeubrutalismButton from "@/components/ui/neobrutalism-button"; +import TextTicker from "@/components/marketing/text-ticker"; +import { getTotalRoadmapsGenerated } from "@/actions/roadmaps"; + +async function ToalUserTicker() { + const totalRoadmapCount = await getTotalRoadmapsGenerated(); + return ( +
+
+ + Roadmaps Generated! +
+
+ ); +} async function UserAvatars() { const users = await clerkClient.users.getUserList(); @@ -98,6 +111,7 @@ export default function RoadmapHero() { ))} +

diff --git a/src/components/marketing/text-ticker.tsx b/src/components/marketing/text-ticker.tsx new file mode 100644 index 0000000..c9db9ac --- /dev/null +++ b/src/components/marketing/text-ticker.tsx @@ -0,0 +1,40 @@ +"use client"; + +import { useEffect, useRef } from "react"; +import { useInView, useMotionValue, useSpring } from "framer-motion"; + +export default function TextTicker({ + value, + direction = "up", +}: { + value: number; + direction?: "up" | "down"; +}) { + const ref = useRef(null); + const motionValue = useMotionValue(direction === "down" ? value : 0); + const springValue = useSpring(motionValue, { + damping: 100, + stiffness: 100, + }); + const isInView = useInView(ref, { once: true, margin: "-100px" }); + + useEffect(() => { + if (isInView) { + motionValue.set(direction === "down" ? 0 : value); + } + }, [motionValue, isInView]); + + useEffect( + () => + springValue.on("change", (latest) => { + if (ref.current) { + ref.current.textContent = Intl.NumberFormat("en-US").format( + latest.toFixed(0), + ); + } + }), + [springValue], + ); + + return ; +}