首页 > web前端 > js教程 > 使用 Next.js、Vercel AI 和 Tolgee 构建看板

使用 Next.js、Vercel AI 和 Tolgee 构建看板

Patricia Arquette
发布: 2024-11-17 22:17:02
原创
604 人浏览过

长话短说

在本文中,我们将使用 WebSockets 在 Next.js 中构建实时看板,并提供数据库支持、通过 Vercel AI SDK 提供的 AI 支持以及通过 Tolgee 进行本地化。

您将学到什么:✨

  • 在没有 Express 的 Next.js 中设置 WebSocket 服务器。
  • 使用 NextAuth 在 Next.js 中实现基于凭据的身份验证。
  • 使用 Docker 或云提供商配置 PostgreSQL 数据库。
  • 将任务描述的 AI 支持与 Vercel AI SDK 集成。
  • 使用 Tolgee 添加实时翻译和本地化。

为 Tolgee 存储库加注星标 ⭐

您准备好构建具有人工智能和本地化支持的独特看板了吗? ?

Building a Kanban Board with Next.js,Vercel AI and Tolgee


设置项目?️

初始化 Next.js 应用程序

使用以下命令初始化一个新的 Next.js 应用程序:

ℹ️ 您可以使用您选择的任何包管理器。对于这个项目,我将使用 npm。

npx create-next-app@latest kanban-ai-realtime-localization --typescript --tailwind --eslint --app --src-dir --use-npm

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

接下来,导航到新创建的 Next.js 项目:

cd kanban-ai-realtime-localization

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

安装依赖项

我们需要几个依赖项。运行此命令来安装我们项目所需的所有依赖项:

npm install @ai-sdk/openai @tolgee/react @tolgee/web @tolgee/format-icu @tanstack/react-query @prisma/client ai socket.io socket.io-client prisma next-auth date-fns nodemon ts-node zod tsconfig-paths react-beautiful-dnd

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

设置 UI 组件

对于 UI 组件,我们将使用 shadcn/ui。使用以下命令将其初始化为默认设置:

npx shadcn@latest init -d

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

现在,让我们添加一些稍后将在应用程序中使用的 UI 组件。要从 shadcn/ui 添加可重用组件,请运行以下命令:

npx shadcn@latest add button card input label select textarea toast

登录后复制
登录后复制
登录后复制

在 app/components/ui 目录中,将为这些组件添加一些附加文件,我们将在为应用程序构建 UI 时使用这些文件。


设置数据库模型 ?

初始化 Prisma

使用以下命令初始化 Prisma:

npx prisma init

登录后复制
登录后复制
登录后复制

运行此命令后,应在项目根目录的 prisma 目录中创建一个新的 schema.prisma 文件。

定义 Prisma 架构

修改新创建的 schema.prisma 文件以使用 PostgreSQL 作为数据库并包含 User 和 Task 模型。

// ? prisma/schema.prisma

// This is your Prisma schema file,
// learn more about it in the docs: <https://pris.ly/d/prisma-schema>

// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: <https://pris.ly/cli/accelerate-init>

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
  id       String @id @default(cuid())
  email    String @unique
  password String

  tasks Task[] @relation("UserTasks")

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model Task {
  id          String  @id @default(cuid())
  title       String
  description String?
  userId      String

  column Int
  order  Int

  createdBy User @relation("UserTasks", fields: [userId], references: [id])

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

登录后复制
登录后复制
登录后复制

该模型很简单:每个用户可以有多个任务,每个任务都链接到一个特定的用户。任务有一个表示其状态的整数列值(0 表示正在进行,1 表示待处理,2 表示已完成)。顺序值决定每个任务在其指定列中的位置。

现在我们已经准备好了模型,我们需要将其推送到我们的数据库。为此,我们需要连接 URL。

如果您已经可以使用 Neon 或其他服务访问数据库,那就太好了。使用连接 URL 填充 .env 文件。您不需要使用 docker 在本地设置数据库。


使用 Docker 在本地设置数据库?

如果您正在跟进并且只想使用 Docker 尝试使用本地 PostgreSQL 数据库的项目,请将具有此连接字符串值的名为 DATABASE_URL 的新变量添加到 .env 文件中。

npx create-next-app@latest kanban-ai-realtime-localization --typescript --tailwind --eslint --app --src-dir --use-npm

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

要在本地运行数据库,请确保安装了 Docker。在项目根目录中创建一个名为scripts的新目录,并添加一个名为start-local-db-docker.sh的文件,其中包含以下代码行:

cd kanban-ai-realtime-localization

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

该脚本基本上读取 DATABASE_URL 变量的 .env 文件,并提取所有相关数据,如用户名、密码、数据库名称,并创建一个容器(如果不存在)。如果已经存在,它只会旋转现有容器。

运行此脚本来创建并运行一个 PostgreSQL 容器,该容器将托管我们应用程序的所有用户数据。

npm install @ai-sdk/openai @tolgee/react @tolgee/web @tolgee/format-icu @tanstack/react-query @prisma/client ai socket.io socket.io-client prisma next-auth date-fns nodemon ts-node zod tsconfig-paths react-beautiful-dnd

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

现在,我们应该有一个运行 PostgreSQL 的容器。您可以通过运行以下命令来检查是否是这种情况:

npx shadcn@latest init -d

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

现在,我们需要一种方法来实例化 Prisma 客户端以与数据库交互。

在 src/db 目录下创建一个新文件index.ts,并添加以下代码行:

npx shadcn@latest add button card input label select textarea toast

登录后复制
登录后复制
登录后复制

我们设置了 PrismaClient 的单例实例,以确保在您的应用程序中仅创建和重用一个实例,这在开发模式下特别有用。

我们现在可以使用导出的常量数据库与应用程序中的数据库进行交互。

运行以下命令将架构中的更改推送到数据库。

npx prisma init

登录后复制
登录后复制
登录后复制

现在,要让更新的类型在 IDE 中工作,请运行以下命令以根据我们更新的架构生成新类型。

// ? prisma/schema.prisma

// This is your Prisma schema file,
// learn more about it in the docs: <https://pris.ly/d/prisma-schema>

// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: <https://pris.ly/cli/accelerate-init>

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
  id       String @id @default(cuid())
  email    String @unique
  password String

  tasks Task[] @relation("UserTasks")

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model Task {
  id          String  @id @default(cuid())
  title       String
  description String?
  userId      String

  column Int
  order  Int

  createdBy User @relation("UserTasks", fields: [userId], references: [id])

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

登录后复制
登录后复制
登录后复制

这就是我们设置应用程序数据库所需的全部内容。 ?


设置 Tolgee 进行本地化?️

要使用 Tolgee 在 Next.js 应用程序中启用本地化,请按照以下步骤操作:

  1. 创建语言.ts

此文件处理语言检测和 cookie 管理。

// ? .env

# If you are using local DB with docker
DATABASE_URL=postgresql://postgres:password@localhost:5432/kanban-board

登录后复制

setLanguage 函数将所选语言(区域设置)保存为有效期为一年的 cookie,允许应用程序在会话中记住用户的语言首选项。

getLanguage 函数检查 cookie 中保存的语言。如果找到有效的语言,则返回该语言;否则,如果在浏览器中运行,它会尝试从浏览器标头中检测语言。如果检测失败或者环境不是浏览器,则默认为DEFAULT_LANGUAGE。

  1. 创建shared.ts

此文件包含用于处理本地化的共享常量和函数,包括获取用于翻译的静态数据

npx create-next-app@latest kanban-ai-realtime-localization --typescript --tailwind --eslint --app --src-dir --use-npm

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

getStaticData 函数负责加载特定语言和命名空间的翻译以预取本地化内容。它按语言和命名空间从消息目录中获取 JSON 文件,然后将所有内容捆绑到一个对象中并返回它。

对于我们应用程序中的语言选择,我们将为用户提供四种不同的语言选择(英语、捷克语、法语和德语)。如果您愿意,您可以添加对其他语言的支持。

在项目根目录的 messages 目录中,我们将为不同的单词和句子存储不同的静态数据。

ℹ️ 您可以在我的存储库中找到这些静态翻译文件的链接。该文件中没有什么需要解释的,因为它们是一堆不同其他语言的翻译句子。

TolgeeBase 函数为 Tolgee 设置了处理翻译的工具。它增加了对 ICU 消息格式化 (FormatIcu) 的支持,并包含用于调试的 DevTools。该函数使用环境变量中的 API 密钥和 URL,并将英语 (en) 设置为后备语言。

  1. 更新环境变量

我们使用两个不同的环境变量,使用这些 API 密钥填充 .env 文件。在 Tolgee 中注册一个帐户并访问 TOLGEE_API_KEYS,但对于此应用程序,不需要拥有该 API 密钥。

cd kanban-ai-realtime-localization

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
  1. 创建 server.ts

此文件配置 Tolgee 实例以进行服务器端渲染,设置翻译处理。

npm install @ai-sdk/openai @tolgee/react @tolgee/web @tolgee/format-icu @tanstack/react-query @prisma/client ai socket.io socket.io-client prisma next-auth date-fns nodemon ts-node zod tsconfig-paths react-beautiful-dnd

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

此代码创建一个用于服务器端翻译处理的 Tolgee 实例。首先将 getLocale 设置为使用 getLanguage 函数,该函数检索用户的首选语言。然后,在 createTolgee 中,它通过 getStaticData 使用所有支持的语言的翻译数据初始化 Tolgee。

它还设置 Tolgee 使用提供的语言(来自 getLanguage),并配置自定义获取函数以通过设置 revalidate: 0 始终加载新数据,从而防止缓存翻译请求。

  1. 创建 client.ts

这将为客户端渲染设置 Tolgee 提供程序。

npx shadcn@latest init -d

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

此代码设置了一个用于翻译的客户端 Tolgee 提供程序。 TolgeeProviderClient 将 language、staticData 和 Children 作为 props,并使用指定的语言和数据初始化 Tolgee。在 useEffect 内部,它通过 permanentChange 监听语言变化,每当语言更新时通过 router.refresh() 刷新页面。

最后,TolgeeProvider 渲染子项,使用 ssr 选项预加载翻译并在翻译未立即准备好时显示“正在加载...”。

  1. 在layout.tsx中使用TolgeeProviderClient包装应用程序

最后,用 包装您的应用程序组件以确保所有翻译均可访问。

npx create-next-app@latest kanban-ai-realtime-localization --typescript --tailwind --eslint --app --src-dir --use-npm

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

首先,我们根据标头或从函数设置的 cookie 来访问用户的区域设置。然后我们将该区域设置提供给

标签。

这就是我们在 Next.js 应用程序中设置 Tolgee 所需的全部内容。 ✨这将是您在任何 Next.js 应用程序中使用 Tolgee 实现位置所需的标准流程。


设置身份验证?️

我们将在我们的应用程序中使用 NextAuth 进行身份验证。首先,我们首先定义一个新的 Zod 模式,我们将使用它来验证用户传递的数据。

用于验证的 Zod 模式

定义 Zod 架构 (AuthSchema) 以验证用户在登录和注册期间输入的电子邮件和密码。这可以确保电子邮件格式正确并且密码满足指定的长度要求。

cd kanban-ai-realtime-localization

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

我们要求电子邮件字段是准确的电子邮件地址,而不是任何其他字符串,并且我们希望密码字段的最小长度为 8 个字符,最大长度为 20 个字符。我们将在多个地方使用此验证模式来验证登录/注册表单中用户传递的数据,以检查其是否符合条件。

NextAuth 配置

您在src/app/api/auth/[...nextauth]下的route.ts中设置NextAuth,使用CredentialsProvider进行身份验证。授权函数验证凭据、检查用户的存在并验证密码。

npm install @ai-sdk/openai @tolgee/react @tolgee/web @tolgee/format-icu @tanstack/react-query @prisma/client ai socket.io socket.io-client prisma next-auth date-fns nodemon ts-node zod tsconfig-paths react-beautiful-dnd

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

授权函数逻辑负责用户是否登录。此设置中的函数检查提供的电子邮件和密码是否与数据库中的现有用户匹配。

我们仅使用基于凭据的身份验证。首先,它使用 AuthSchema 进行字段验证来验证凭据。如果验证成功,它将通过电子邮件在数据库中查找用户。如果找到用户,则会将数据库中的散列密码与输入的密码进行比较。如果两项检查都通过,则返回用户的数据(不包括密码)。

正如您可能已经猜到的,这里我们需要在 .env 文件中定义 NEXTAUTH_SECRET 变量。使用这两个变量填充 .env 文件:

npx shadcn@latest init -d

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

用户注册接口

在 src/app/api/auth/register/route.ts 中,我们创建一个用于用户注册的端点,该端点对密码进行哈希处理并将用户数据存储在数据库中。然后,我们根据验证成功返回适当的响应。

npx create-next-app@latest kanban-ai-realtime-localization --typescript --tailwind --eslint --app --src-dir --use-npm

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

在这里,我们解析从客户端接收到的数据,并使用我们之前编写的 AuthSchema 对其进行验证。然后,我们创建一个旋转值为 12 的哈希值。这会生成一个加密文本,我们将其存储在数据库中,最后,我们返回用户。

现在,为了使我们的应用程序更加可靠,让我们添加一个中间件,在用户访问某个路由时检查 userSession,如果他们未经身份验证,则不允许他们访问该路由。

路由保护中间件

我们添加了一个中间件来限制未经身份验证的用户访问 /kanban 路由。

cd kanban-ai-realtime-localization

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

在这里,我们说的是,如果用户未经身份验证,则不应访问“/看板”路线。

我们已经完成了处理身份验证的后端逻辑。让我们研究一些客户端逻辑。


构建导航栏组件

我们的导航栏组件也将由一些较小的组件组​​成。我们将有一个用于登录、注册、注销的按钮和一个选择标签以允许用户切换语言。

让我们开始研究这些组件!

语言选择器组件

在 src/app/components 目录中创建一个新文件 lang-selector.tsx,其中包含以下代码行:

npm install @ai-sdk/openai @tolgee/react @tolgee/web @tolgee/format-icu @tanstack/react-query @prisma/client ai socket.io socket.io-client prisma next-auth date-fns nodemon ts-node zod tsconfig-paths react-beautiful-dnd

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

该组件应该是非常不言自明的。我们正在使用> shadcn/ui 提供的组件可以映射我们所有可用的语言选择。根据用户的选择,我们将语言设置为之前在 language.ts 文件中使用的 setLanguage 函数。

?注意:请注意我们没有对代码中的任何文本进行硬编码;相反,我们使用 Tolgee 的组件来渲染文本。这样,当用户切换语言时,文本也会相应改变。如果我们对文本进行硬编码,那么实现翻译将是无效的。我们将继续使用这种方法前进。

我们正在使用 >组件和我们从 Tolgee 的 useTranslate 钩子获得的 t 函数来应用翻译。要了解它们的差异,请访问此处。

LogoutBtn 组件

同样,在此组件目录中创建一个名为 logout-btn.tsx 的新文件,其中包含以下代码行:

npx shadcn@latest init -d

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

与之前类似,当用户单击按钮时,我们会触发handleLogout函数,然后该函数会尝试注销用户,如果发生任何错误,它会显示一条toast通知以及翻译后的错误消息。

我们使用加载状态在用户注销时显示加载程序图标。

导航栏组件

最后,现在我们需要的两个较小的组件都可用了,让我们来处理 > 。组件。

npx create-next-app@latest kanban-ai-realtime-localization --typescript --tailwind --eslint --app --src-dir --use-npm

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

这个导航栏组件为我们的应用程序创建一个导航栏。它使用 getServerSession 检查用户是否登录。如果用户通过身份验证,则会显示注销按钮。如果没有,它会显示用户登录和注册的链接。


构建身份验证页面

现在,我们已经完成了身份验证的后端逻辑的处理,也完成了在我们的应用程序中实现 Tolgee 的工作。让我们研究一些客户端逻辑并构建一些 UI。

登录组件

在 app/components 目录中,使用以下代码行创建一个新文件 login.tsx:

cd kanban-ai-realtime-localization

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

此登录组件显示电子邮件和密码的登录表单,两个输入字段都充当受控组件。提交表单后,它会从 next-auth 调用 SignIn 来处理身份验证。如果登录失败,则会通过 Toast 通知显示翻译后的错误消息。成功登录会将用户重定向至主页。

我们还有一个单独的加载状态变量,用于在用户登录到我们的应用程序时显示加载动画图标。

目前,这只是我们创建的一个组件;它尚未显示在我们的应用程序中。为此,我们需要在应用程序的 app 目录中渲染此组件。

登录页面路由

在 src/app/login 目录中,创建一个名为 page.tsx 的新文件,其中包含以下代码行:

npm install @ai-sdk/openai @tolgee/react @tolgee/web @tolgee/format-icu @tanstack/react-query @prisma/client ai socket.io socket.io-client prisma next-auth date-fns nodemon ts-node zod tsconfig-paths react-beautiful-dnd

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

在登录页面,我们首先检查用户是否有活动会话。如果用户有活动会话,我们只需将他们重定向到“/看板”路线(我们将很快实现)。如果用户没有活动会话,我们会显示之前的 我们构建的组件。

我们现在已经完成了登录页面的实现;同样,让我们​​构建注册页面。

注册组件

在 app/components 目录中,使用以下代码行创建一个新文件 register.tsx:

npx shadcn@latest init -d

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

此组件中输入的电子邮件和密码充当受控组件,与登录页面上的类似。在这里,我们使用 React Query 来简化发出 POST 请求的过程。这种方法消除了管理加载或错误处理的单独状态的需要。

当用户单击表单中的提交按钮时,系统会向我们的 API 路由发出 POST 请求,以便在我们之前使用的数据库中注册用户。如果注册成功,用户将被重定向到登录页面。如果没有,则会显示一条 Toast 消息以及翻译后的错误消息。

当用户单击提交按钮时,POST 请求将发送到我们的 API 路由,以在我们之前设置的数据库中注册用户。注册成功后,用户将被重定向到登录页面。如果注册失败,我们会使用相关按键显示一条 toast 消息以及翻译后的错误消息。

注册页面路由

在 src/app/register 目录中,创建一个名为 page.tsx 的新文件,其中包含以下代码行:

npx create-next-app@latest kanban-ai-realtime-localization --typescript --tailwind --eslint --app --src-dir --use-npm

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

设置此页面后,我们已经完成了应用程序的身份验证流程。您现在应该拥有一个可运行且支持身份验证且支持本地化的应用程序。


设置 WebSocket 和 QueryClient 提供程序

在本节中,我们将为我们的应用程序设置一个 WebSocket 服务器。我们首先创建一个函数来帮助我们访问套接字。

getSocket 函数

在 src/config 目录中,使用以下代码行创建一个新文件 socket.ts:

cd kanban-ai-realtime-localization

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

这段代码定义了一个函数 getSocket,它初始化一个 Socket.IO 客户端连接到环境变量 NEXT_PUBLIC_APP_URL 中指定的 URL,确保套接字只创建一次。如果套接字已经初始化,它只会返回现有的套接字实例。

套接字提供者

现在,我们需要管理我们的 socket.io 连接并为我们的组件提供一种访问套接字实例的方法。在 src/providers 目录中,使用以下代码行创建一个新文件 socket-provider.tsx:

npm install @ai-sdk/openai @tolgee/react @tolgee/web @tolgee/format-icu @tanstack/react-query @prisma/client ai socket.io socket.io-client prisma next-auth date-fns nodemon ts-node zod tsconfig-paths react-beautiful-dnd

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

此代码创建一个 React 上下文来管理 Socket.IO 连接,提供 useSocket 钩子来访问套接字实例。 SocketProviderClient 使用 getSocket 函数初始化套接字并连接它,然后将其子级包装在上下文提供程序中以在整个应用程序中共享套接字实例。

现在,我们需要使用此套接字提供程序包装我们的应用程序,以便能够使用 WebSocket 发送和接收数据。

QueryClient 和 SocketProvider

在同一目录中,创建一个新文件providers.tsx,我们将用它来用 @tanstack/react-query 中的 QueryClientProvider 和我们新创建的 SocketProviderClient 来包装我们的子组件。

将以下几行代码添加到文件中:

npx shadcn@latest init -d

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

现在,我们需要做的就是用这个 包装我们的应用程序。组件将允许访问我们的应用程序套接字和反应查询支持。

使用提供者包装应用程序布局

使用以下代码行修改项目根目录中的layout.tsx:

npx create-next-app@latest kanban-ai-realtime-localization --typescript --tailwind --eslint --app --src-dir --use-npm

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

使用 Socket.io 自定义 Web 服务器

现在,我们准备创建自己的 Socket.io 服务器。创建一个新文件 server.ts 并添加以下代码行:

cd kanban-ai-realtime-localization

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

现在,这个 server.ts 文件成为我们应用程序的入口点。我们可以使用带有像express.js这样的后端框架的socket.io服务器做几乎任何事情。

我们现在可以监听任何类似于监听“连接”和“断开连接”的事件。我们将来会修改这个文件来监听我们的自定义事件。

打字稿服务器配置

现在,创建一个新文件 tsconfig.server.json ,它将保存特定于我们服务器的设置。添加以下代码行:

npm install @ai-sdk/openai @tolgee/react @tolgee/web @tolgee/format-icu @tanstack/react-query @prisma/client ai socket.io socket.io-client prisma next-auth date-fns nodemon ts-node zod tsconfig-paths react-beautiful-dnd

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

此 tsconfig.server.json 文件扩展了 tsconfig.json 中的基本 TypeScript 配置,并为我们的项目指定了一些自定义设置。它使用 CommonJS 进行模块输出,并将编译后的文件定向到 dist 目录。 isolatedModules 选项设置为 false,允许可能不是独立的文件,而 noEmit 为 false,允许生成输出文件。最后,编译过程中只包含server.ts文件。

更新package.json

对于我们的开发服务器,我们将使用 nodemon,现在我们使用 server.ts 文件作为我们的服务器。因此,将 package.json 文件中的脚本修改为:

npx shadcn@latest init -d

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

此外,我们需要调整 nodemon 配置以观察 server.ts 文件中的变化并更改其执行命令。

Nodemon配置

在项目根目录创建一个新文件nodemon.json,配置如下:

npx shadcn@latest add button card input label select textarea toast

登录后复制
登录后复制
登录后复制

设置看板

最后,现在我们已经完成了电路板的所有前期工作。让我们为我们的看板显示和创建任务。

任务组件

在 src/components 目录中,使用以下代码行创建一个新文件 task.tsx:

npx prisma init

登录后复制
登录后复制
登录后复制

我们将使用它来显示应用程序中的任务。在这里,我们本质上接受一个任务对象作为道具,并使用 Card 组件以类似卡片的方式呈现任务内容。我们正在使用 date-fns 包以更易读的方式格式化日期。

添加任务组件

现在,让我们创建一个可用于向看板添加任务的组件。在 src/components 目录中,使用以下代码行创建一个新文件 add-task.tsx:

// ? prisma/schema.prisma

// This is your Prisma schema file,
// learn more about it in the docs: <https://pris.ly/d/prisma-schema>

// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: <https://pris.ly/cli/accelerate-init>

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
  id       String @id @default(cuid())
  email    String @unique
  password String

  tasks Task[] @relation("UserTasks")

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model Task {
  id          String  @id @default(cuid())
  title       String
  description String?
  userId      String

  column Int
  order  Int

  createdBy User @relation("UserTasks", fields: [userId], references: [id])

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

登录后复制
登录后复制
登录后复制

这个组件有很多事情要做。有两个输入字段,它们都是受控组件。然而,文本区域设置为只读,因为它是由人工智能而不是用户填充的。我们使用两个状态变量,标题和描述,来管理标题和描述字段。

当用户单击提交按钮时,会向我们的任务创建端点发出 API 请求,该端点会在数据库中为用户添加一个新任务并将其返回。如果发生任何错误,Toast 会显示翻译后的错误消息。成功后,我们重置输入字段并发出一个服务器将接收的事件,触发面板组件上的更新以显示所有任务。

从 Vercel 的 AI SDK 访问的 useChat 钩子在这里特别有趣。它提供对消息历史记录和当前输入消息等字段的访问,以及 isPending 变量,该变量跟踪 AI 的响应是否仍在加载。

当用户单击“生成”按钮时,我们将标题提交给 AI。收到响应后,我们使用 useEffect 挂钩检查 messages 字段。如果助理的消息更新,我们会为此新消息设置描述。

更新 server.ts 文件

现在,我们将更新 server.ts 文件以侦听任务创建的事件。使用以下代码行修改项目根目录中的 server.ts 文件:

npx create-next-app@latest kanban-ai-realtime-localization --typescript --tailwind --eslint --app --src-dir --use-npm

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

在这里,我们监听该事件,一旦接收到该事件,我们将其发送到所有连接的套接字。然后它被接收。组件,我们稍后将创建它。该组件将负责以看板格式显示所有任务并使用接收到的数据更新任务。


设置用于 AI 和任务创建的 API 路由

现在,在我们的 中组件中,当用户单击“生成”按钮时,handleAISubmit 函数会通过 POST 请求调用 /api/chat 端点。因此,我们需要创建 API 路由来处理流向描述字段的响应流。

用于消息验证的 Zod 架构

让我们创建一个模式文件来验证用户和人工智能的输入。在 src/lib/validators 目录中,使用以下代码行创建一个新文件 message.ts:

cd kanban-ai-realtime-localization

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

现在,我们可以使用这些模式来推断 AI 的响应类型,以在我们的 API 路由中进行类型验证。

OpenAI 的聊天路线

最后,在 src/api/chat 目录中,创建一个新文件route.ts,其中包含以下代码行:

npm install @ai-sdk/openai @tolgee/react @tolgee/web @tolgee/format-icu @tanstack/react-query @prisma/client ai socket.io socket.io-client prisma next-auth date-fns nodemon ts-node zod tsconfig-paths react-beautiful-dnd

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

在此 API 路线中,我们首先验证输入以确保它包含一个消息数组,其中每个对象都有一个角色和内容字段。接下来,我们从该数组中提取最新的用户消息(即最近向 AI 提出的问题或请求)。有了这条消息,我们将其传递给streamText函数,提示AI根据消息内容生成任务描述。

最后,我们将响应作为数据流返回,允许客户端实时更新消息数组。此流式响应会触发 useEffect 挂钩,该挂钩会更新描述字段,从而直接在文本区域中显示 AI 生成的描述。

用于添加任务验证的 Zod 架构

在 src/lib/validators 目录中,使用以下代码行创建一个新文件 create-task.ts:

npx create-next-app@latest kanban-ai-realtime-localization --typescript --tailwind --eslint --app --src-dir --use-npm

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

CreateTaskSchema 模式定义了创建任务的结构。它需要 1 到 50 个字符之间的标题,并包含可选的描述。

推断类型 TCreateTaskSchema 为该结构提供了类型安全性,允许我们使用它在客户端和服务器端代码中实现一致的类型。

用于创建任务的 API 端点

现在,让我们处理任务创建端点,即 /api/tasks/[userId]/create。

使用此路径创建一个新目录,并使用以下代码行在文件内创建一个route.ts:

cd kanban-ai-realtime-localization

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

此 API 路由创建一个新任务。它首先使用 getServerSession 检查有效的用户会话。如果没有活动会话(用户未登录),则返回 401 Unauthorized 错误。接下来,它使用 CreateTaskSchema 验证请求正文,如果验证失败,它会以 422 状态和错误详细信息进行响应。

如果输入有效,它将对默认列(0 - 正在进行)中的任务进行排序,然后使用提供的标题、可选描述、用户 ID、列和订单值在数据库中创建一个新任务,其中是数组的长度。成功则返回新任务;否则,它将返回内部服务器错误。


构建看板

?在这里,我们将构建主要的 UI 组件和一些用于更新板上任务的 API

板卡组件

现在,让我们创建一个>为我们的应用程序呈现多个不同任务的组件。

在 src/components 目录中,使用以下代码行创建一个新文件 board.tsx:

npm install @ai-sdk/openai @tolgee/react @tolgee/web @tolgee/format-icu @tanstack/react-query @prisma/client ai socket.io socket.io-client prisma next-auth date-fns nodemon ts-node zod tsconfig-paths react-beautiful-dnd

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

这是我们将利用看板主要功能的组件,即拖放项目。为此,我们将使用之前安装的软件包react-beautiful-dnd。该组件首先使用 getSession 获取用户会话并将其设置为状态。一旦会话可用,它就会调用 API 来为登录用户获取任务并将其存储在任务中。

它监听双套接字事件 —tasks-updated(更新任务列表)和 task-created(将新任务附加到当前任务列表)。

使用tasksByStatus 函数按列状态对任务进行分组(0 表示“正在进行”,1 表示“待处理”,2 表示“已完成”)。该组件映射这些状态以呈现具有相应任务的每一列。

DragDropContext 包装器支持拖放功能。当任务移动时,handleDragEnd 通过套接字事件将新的任务顺序发送到服务器进行同步。

每一列都是一个可放置区域,其中包含可拖动的任务组件,允许用户在列内和列之间重新排序任务。

用于获取用户任务的 API 路由

现在,让我们研究 /api/tasks 路由,它负责从数据库返回用户任务列表。

在 app/api/tasks 中,使用以下代码行创建一个route.ts 文件:

npx create-next-app@latest kanban-ai-realtime-localization --typescript --tailwind --eslint --app --src-dir --use-npm

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

此 API 路由中的 GET 函数获取用户的信息,包括他们的任务。首先使用 getServerSession 验证身份验证。如果会话缺席,则会返回 401 未授权状态。

路由从请求 URL 的查询参数中提取电子邮件和用户 ID。如果 userId 丢失或会话的用户电子邮件与提供的电子邮件不匹配,则会返回 403 Forbidden 状态。

接下来,它会在数据库中查询具有指定电子邮件和 ID 的用户,仅选择该用户的 ID 和任务。如果未找到用户,则返回 404 Not Found 状态。如果用户存在,他们的数据将在响应中发送。

现在,我们快完成了;我们只需要监听 中的任务拖动事件即可。 server.ts 文件中的组件并相应地处理它。

更新 server.ts 文件

修改项目根目录下的server.ts文件,代码如下:

cd kanban-ai-realtime-localization

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

任务拖动事件负责处理看板中任务的拖放功能。当任务从一个位置拖到另一个位置时,会触发此事件,从而允许服务器更新任务在数据库中的状态和位置。

当客户端发出“任务拖动”事件时,它会发送一个有效负载,其中包含被拖动任务的源位置和目标位置,以及用户的电子邮件地址。服务器监听此事件。

然后,服务器调用handleTaskDrag 函数,将用户的电子邮件、源和目标作为参数传递。此函数负责使用电子邮件地址从数据库中获取用户,确保任务更新与正确的用户关联。

在handleTaskDrag中,该函数从数据库中检索用户的任务,然后调用updateTasksInDB,它处理任务更新逻辑。该功能根据拖放操作更新任务的列和顺序,确保任务在数据库中正确重新排列。

如果任务更新成功,更新后的任务将使用 io.sockets.emit 发送回所有连接的客户端,广播更改,以便用户界面可以实时更新。

现在我们有了 >和<董事会>>组件准备就绪,是时候在我们的应用程序中使用它们了。

看板页面路由

在 src/app/kanban 目录中,使用以下代码行创建一个新文件 page.tsx:

npx create-next-app@latest kanban-ai-realtime-localization --typescript --tailwind --eslint --app --src-dir --use-npm

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

它首先使用 getServerSession 检查用户的会话,如果会话不存在,则重定向到登录页面。该语句可能永远不会执行,因为我们之前在 src 目录中构建了一个 middleware.ts 文件,该文件声明任何以 /kanban 开头的路由都无法被未经身份验证的用户访问。

但是,添加额外的验证层永远不会有坏处,因为 Next.js 会删除任何类似的重复请求。确认会话后,从数据库中检索用户的ID;如果未找到用户,则重定向至注册页面。

最后,它渲染 AddTask 和 Board 组件,并将用户的 ID 作为 prop 传递。

还剩下最后一件事:如果您注意到的话,在 在之前的组件中,我们有一种方法让用户可以通过 /kanban/[taskId] 的链接查看描述。

看板描述页面路由

在 src/app/kanban/[taskId] 目录中,使用以下代码行创建一个新文件 page.tsx:

cd kanban-ai-realtime-localization

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

这里也是如此:我们首先验证会话。如前所述,由于我们已经有了中间件,因此永远不应该执行此操作。

然后,我们只需使用我们收到的作为 prop 的 taskId 从数据库中获取任务。如果任务不存在,我们将用户重定向到 /kanban 页面。如果确实存在,我们会显示任务的标题和描述。

主页路线

最后,让我们处理应用程序的根主页(/路线)。使用以下代码行修改 src/app/page.tsx:

npm install @ai-sdk/openai @tolgee/react @tolgee/web @tolgee/format-icu @tanstack/react-query @prisma/client ai socket.io socket.io-client prisma next-auth date-fns nodemon ts-node zod tsconfig-paths react-beautiful-dnd

登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制

在这里,我们只是检查用户是否经过身份验证。如果是,则将它们发送到 /kanban 路线;如果没有,他们将被重定向到登录页面。

这实际上就是让我们的看板完美运行所需要做的全部事情。现在,您应该拥有一个功能齐全的看板,具有身份验证、本地化和实时支持。 ?

Building a Kanban Board with Next.js,Vercel AI and Tolgee


结论⚡

哇! ?‍?今天我们一起取得了很多成就。

如果您做到了这一步,那么您已经在博客文章的帮助下从头开始成功构建了一个由人工智能和本地化驱动的看板。给自己一个当之无愧的鼓励!

为 Tolgee 存储库加注星标 ⭐

关注Tolgee以获取更多此类内容。

Building a Kanban Board with Next.js,Vercel AI and Tolgee

托尔吉

Tolgee 是一个用于网络应用程序本地化的开源开发工具?

在下面的评论部分分享你的想法! ?

非常感谢您的阅读! ? ?

Building a Kanban Board with Next.js,Vercel AI and Tolgee


以上是使用 Next.js、Vercel AI 和 Tolgee 构建看板的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板