【02】从0到1构建AI生成思维导图应用 -- 编写主页

【02】从0到1构建AI生成思维导图应用 – 编写主页

大家好!最近自己做了一个完全免费的AI生成思维导图的网站,支持下载,编辑和对接微信公众号,可以在这里体验:https://lt2mind.zeabur.app/

上一章:https://blog.csdn.net/m0_56699208/article/details/140006789?spm=1001.2014.3001.5501

构建好nextjs,并配置了tailwindcss和shadcn-ui后,我们就可以开始编写主页的前端代码了:
在这里插入图片描述
在编写代码之前,先通过 shadcn-ui 安装一些组件:

npx shadcn-ui@latest add button input tooltip textarea skeleton

安装 react-simple-typewriter 打字机效果插件:

npm install react-simple-typewriter

修改layout.tsx,改变元数据和字体:

import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";

const inter = Inter({
  subsets: ["latin"],
  display: "swap",
  adjustFontFallback: false,
});

export const metadata: Metadata = {
  title: "LT2Mind",
  description:
    "Transform your text and links into beautiful mind maps with ease.",
  icons: {
    icon: '/favicon.ico'
  }
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
      <html lang="en">
        <body className={inter.className}>
        </body>
      </html>
  );
}

globals.css 里配置一些通用样式:

@tailwind base;
@tailwind components;
@tailwind utilities;

  @layer base {
    :root {
      --background: 0 0% 100%;
      --foreground: 222.2 84% 4.9%;

      --card: 0 0% 100%;
      --card-foreground: 222.2 84% 4.9%;

      --popover: 0 0% 100%;
      --popover-foreground: 222.2 84% 4.9%;

      --primary: 222.2 47.4% 11.2%;
      --primary-foreground: 210 40% 98%;

      --secondary: 210 40% 96.1%;
      --secondary-foreground: 222.2 47.4% 11.2%;

      --muted: 210 40% 96.1%;
      --muted-foreground: 215.4 16.3% 46.9%;

      --accent: 210 40% 96.1%;
      --accent-foreground: 222.2 47.4% 11.2%;

      --destructive: 0 84.2% 60.2%;
      --destructive-foreground: 210 40% 98%;

      --border: 214.3 31.8% 91.4%;
      --input: 214.3 31.8% 91.4%;
      --ring: 222.2 84% 4.9%;

      --radius: 0.5rem;
    }

    .dark {
      --background: 222.2 84% 4.9%;
      --foreground: 210 40% 98%;

      --card: 222.2 84% 4.9%;
      --card-foreground: 210 40% 98%;

      --popover: 222.2 84% 4.9%;
      --popover-foreground: 210 40% 98%;

      --primary: 210 40% 98%;
      --primary-foreground: 222.2 47.4% 11.2%;

      --secondary: 217.2 32.6% 17.5%;
      --secondary-foreground: 210 40% 98%;

      --muted: 217.2 32.6% 17.5%;
      --muted-foreground: 215 20.2% 65.1%;

      --accent: 217.2 32.6% 17.5%;
      --accent-foreground: 210 40% 98%;

      --destructive: 0 62.8% 30.6%;
      --destructive-foreground: 210 40% 98%;

      --border: 217.2 32.6% 17.5%;
      --input: 217.2 32.6% 17.5%;
      --ring: 212.7 26.8% 83.9%;
    }
  }

  @layer base {
    * {
      @apply border-border;
    }
    body {
      @apply bg-background text-foreground;
    }
  }

  .bg {
    @apply bg-gradient-to-r from-blue-100 via-purple-100 to-pink-100
  } 

在 components 文件夹下创建一个 hero 组件,作为应用的主页:
hero.tsx:

"use client";
import { useState } from "react";
import { Textarea } from "./ui/textarea";
import { Button } from "@/components/ui/button";
import Link from "next/link";
import { Typewriter } from "react-simple-typewriter";
import { Skeleton } from "@/components/ui/skeleton";
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "../components/ui/tooltip";

export default function Hero() {
  const { isSignedIn } = useUser();
  const [imgUrl, setImgUrl] = useState("");
  const [editUrl, setEditUrl] = useState("");
  const [loading, setLoading] = useState(false);

  const handleSubmit = async (event: any) => {
    event.preventDefault(); // Prevent the default form submission behavior
    if (!isSignedIn) {
      //router.push('/sign-in');
      return;
    }
    setLoading(true);
    const inputValue = event.target.elements.textOrLink.value; // Get the value from the textarea
    const result = await toMind(inputValue); // Call the toMind function with the input value
    if (result) {
      setImgUrl(result.imgUrl);
      setEditUrl(result.editUrl);
    }
    setLoading(false);
  };

  return (
    <div className="flex flex-col bg">
      <header className="text-blue-500">
        <section className="container max-w-5xl px-4 md:px-6 py-6 md:py-10">
          <div className="text-center space-y-4 sm:mt-4">
            <h1 className="text-4xl md:text-6xl font-bold tracking-widest">
              LT2MIND
            </h1>
            <p className="text-lg md:text-xl max-w-3xl mx-auto italic">
              <Typewriter
                words={[
                  "Transform your text and links into beautiful mind maps with ease.",
                ]}
                loop={1}
                cursor
                cursorStyle=""
                typeSpeed={20}
                deleteSpeed={50}
                delaySpeed={1000}
              />
            </p>
          </div>
        </section>
        <section className="py-12 md:py-20">
          <div className="container max-w-5xl px-4 md:px-6 grid grid-cols-1 md:grid-cols-2 gap-8">
            <div className="space-y-4">
              <h2 className="text-3xl font-bold text-purple-400">
                Convert to Mind Map
              </h2>
              <p className="text-muted-foreground">
                Enter your text or link and let LT2Mind do the rest. You may
                wait for one minute or more for the transition to complete.
              </p>
              <form className="flex gap-2" onSubmit={handleSubmit}>
                <div className="flex flex-col gap-2 h-[40vh] w-full">
                  <Textarea
                    name="textOrLink"
                    placeholder="Enter text or link..."
                    className="shadow-sm focus:border-none flex-1 resize-none bg"
                    style={{
                      outline: "none",
                      overflow: "auto",
                      scrollbarWidth: "none",
                      msOverflowStyle: "none",
                    }}
                  />

                  <style jsx>{`
                    textarea::-webkit-scrollbar {
                      display: none;
                    }
                  `}</style>
                  <TooltipProvider>
                    <Tooltip>
                      <TooltipTrigger asChild>
                        <div>
                          <Button
                            type="submit"
                            className="mt-2 w-full bg-pink-200 text-purple-500 hover:bg-pink-100"
                            disabled={!isSignedIn}
                          >
                            Convert
                          </Button>
                        </div>
                      </TooltipTrigger>
                      {!isSignedIn && (
                        <TooltipContent>
                          You need to sign in to convert
                        </TooltipContent>
                      )}
                    </Tooltip>
                  </TooltipProvider>
                </div>
              </form>
            </div>
            {loading ? (
              <div className="flex flex-col items-center justify-center gap-2">
                <div className="animate-spin rounded-full h-16 w-16 border-t-2 border-b-2 border-purple-500"></div>
                <p className="text-lg text-purple-400">converting...</p>
              </div>
            ) : imgUrl ? (
              <div className="flex flex-col items-center justify-center gap-2">
                <img
                  src={imgUrl}
                  alt="Image 1"
                  className="w-full h-full object-contain shadow-sm"
                />
                <div className="flex gap-x-4 w-full justify-center">
                  <Link href={editUrl} target="_blank" className="w-full">
                    <Button className="bg-pink-200 text-purple-500 w-full hover:bg-pink-100">
                      Edit in TreeMind
                    </Button>
                  </Link>
                  <a
                    href={imgUrl}
                    download="mindmap.jpeg"
                    target="_blank"
                    className="w-full"
                  >
                    <Button className="bg-pink-200 text-purple-500 w-full hover:bg-pink-100">
                      Download
                    </Button>
                  </a>
                </div>
              </div>
            ) : (
              <div className="flex flex-col items-center justify-center gap-2">
                <p className="text-lg text-purple-400">
                  Waiting For Conversion
                  <Typewriter
                    words={["..."]}
                    loop={true}
                    cursor
                    cursorStyle=""
                    typeSpeed={200}
                    deleteSpeed={50}
                    delaySpeed={2000}
                  />
                </p>
              </div>
            )}
          </div>
        </section>
      </header>
    </div>
  );
}

这时,你应该能得到这样一个页面,并且有了打字机的动画效果:
在这里插入图片描述

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值