当前位置: 首页 > article >正文

【Next.js 项目实战系列】05-删除 Issue

原文链接

CSDN 的排版/样式可能有问题,去我的博客查看原文系列吧,觉得有用的话,给我的库点个star,关注一下吧 

上一篇【Next.js 项目实战系列】04-修改 Issue

删除 Issue

添加删除 Button​

本节代码链接

这里我们主要关注布局的问题,我们调整 Grid 的 columns 与第一个 Box 的设置,使得在小设备上,两个 Box 上下排布,在中等及以上,左边 Box 占屏幕 80%

# /app/issues/[id]/page.tsx

  const IssueDeatilPage = async ({ params }: Props) => {
    ...
    return (
+     <Grid columns={{ initial: "1", sm: "5" }} gap="5">
+       <Box className="md:col-span-4">
          <IssueDetails issue={issue} />
        </Box>
        <Box>
          <Flex direction="column" gap="3">
            <EditIssueButton issueId={issue.id} />
+           <DeleteIssueButton issueId={issue.id} />
          </Flex>
        </Box>
      </Grid>
    );
  };
  export default IssueDeatilPage;

其次,在 layout.tsx 中将 <main > 中所有内容用 Radix UI 中的 Container 包起来,以实现居中,最终显示效果如下

Delete Page

添加确认框​

本节代码链接

# /app/issues/[id]/DeleteIssueButton.tsx

"use client";
import { AlertDialog, Button, Flex } from "@radix-ui/themes";
import { Cross2Icon } from "@radix-ui/react-icons";

const DeleteIssueButton = ({ issueId }: { issueId: number }) => {
  return (
    <AlertDialog.Root>
      <AlertDialog.Trigger>
        <Button color="red">
          <Cross2Icon />
          Delete Issue
        </Button>
      </AlertDialog.Trigger>
      <AlertDialog.Content>
        <AlertDialog.Title>Confirm Deletion</AlertDialog.Title>
        <AlertDialog.Description>
          Are you sure you want to delete this? This action cannot be undone.
        </AlertDialog.Description>
        <Flex mt="4" gap="4">
          <AlertDialog.Cancel>
            <Button variant="soft" color="gray">
              Cancel
            </Button>
          </AlertDialog.Cancel>
          <AlertDialog.Action>
            <Button color="red">Delete Issue</Button>
          </AlertDialog.Action>
        </Flex>
      </AlertDialog.Content>
    </AlertDialog.Root>
  );
};
export default DeleteIssueButton;

显示效果如下

Confirm Dialog

删除 Issue​

API​

本节代码链接

# /app/api/issues/[id]/route.tsx

export async function DELETE(
  request: NextRequest,
  { params }: { params: { id: string } }
) {
  const issue = await prisma.issue.findUnique({
    where: { id: parseInt(params.id) },
  });
  if (!issue)
    return NextResponse.json({ error: "Invalid Issue" }, { status: 404 });

  await prisma.issue.delete({
    where: { id: issue.id },
  });

  return NextResponse.json({ status: 200 });
}

连接​

本节代码链接

# /app/issues/[id]/DeleteIssueButton.tsx

  ...
+ import axios from "axios";
+ import { useRouter } from "next/navigation";

  const DeleteIssueButton = ({ issueId }: { issueId: number }) => {
+   const router = useRouter();
+   const handleDelete = async () => {
+     await axios.delete("/api/issues/" + issueId);
+     router.push("/issues");
+     router.refresh();
+   };

    return (
      ...
      <AlertDialog.Action>
+       <Button color="red" onClick={handleDelete}>
          Delete Issue
        </Button>
      </AlertDialog.Action>
      ...
    );
  };
  export default DeleteIssueButton;

处理 error​

本节代码链接

# /app/issues/[id]/DeleteIssueButton.tsx

  ...
+ import { useState } from "react";

  const DeleteIssueButton = ({ issueId }: { issueId: number }) => {
+   const [error, setError] = useState(false);

    const handleDeleteIssue = async () => {
      try {
        await axios.delete("/api/issues/" + issueId);
        router.push("/issues");
        router.refresh();
      } catch (error) {
+       setError(true);
      }
    };

    return (
      <>
        <AlertDialog.Root>
        ...
        </AlertDialog.Root>
+       <AlertDialog.Root open={error}>
+         <AlertDialog.Content>
+           <AlertDialog.Title>Error</AlertDialog.Title>
+           <AlertDialog.Description>
+             This issue could not be deleted
+           </AlertDialog.Description>
+           <Button
+             color="gray"
+             variant="soft"
+             mt="4"
+             onClick={() => setError(false)}
+           >
+             OK
+           </Button>
+         </AlertDialog.Content>
+       </AlertDialog.Root>
     </>
    );
  };
  export default DeleteIssueButton;

效果如下,在发生错误时会弹出这样一个框

Delete Error

优化用户体验​

本节代码链接

和Button 优化技巧一章相同,我们可以添加一个 Spinner 和 Disable 来优化用户体验

# /app/issues/[id]/DeleteIssueButton.tsx

+ import { Spinner } from "@/app/components";

  const DeleteIssueButton = ({ issueId }: { issueId: number }) => {
+   const [isDeleting, setDeleting] = useState(false);

    const handleDeleteIssue = async () => {
      try {
+       setDeleting(true);
        await axios.delete("/api/issues/" + issueId);
        router.push("/issues");
        router.refresh();
      } catch (error) {
+       setDeleting(false);
        setError(true);
      }
    };

    return (
      ...
      <AlertDialog.Trigger>
+       <Button color="red" disabled={isDeleting}>
          <Cross2Icon />
          Delete Issue
+         {isDeleting && <Spinner />}
        </Button>
      </AlertDialog.Trigger>
      ...
    );
  };
  export default DeleteIssueButton;

CSDN 的排版/样式可能有问题,去我的博客查看原文系列吧,觉得有用的话,给我的库点个star,关注一下吧  

 下一篇讲身份验证


http://www.kler.cn/news/350634.html

相关文章:

  • 【C语言】控制台学生成绩管理系统
  • 语音语言模型最新综述! 关于GPT-4o背后技术的尝试
  • Java Spring Boot 项目开发示例指南
  • mac nwjs程序签名公证(其他mac程序也一样适用)
  • Vue 项目中 Webpack 常见问题详解
  • 【前端】实操tips集合
  • Python--plt.errorbar学习笔记
  • 视频网站后端架构:Spring Boot的创新应用
  • 【代码随想录Day44】动态规划Part12
  • Python do while 实现案例
  • 使用CSS+SVG实现加载动画
  • SpringCloudAlibaba升级手册
  • Finops成本优化企业实践-可规划篇
  • linux线程 | 线程的控制(下)
  • linux下在线安装MySQL-华为云服务器
  • 【WebLogic】Oracle发布2024年第四季度中间件安全公告
  • Sharding-JDBC标准模式详解
  • Java基础:面向对象编程5
  • 恢复已删除文件的 10 种安卓数据恢复工具
  • IRP默认最小流程
  • 2023年“网络建设与运维”广西省赛试题复盘
  • yakit使用教程(四,信息收集)
  • WorkFlow GO-Task 源码分析
  • 简单说说mysql中一条读sql是如何执行的
  • 2023年12月中国电子学会青少年软件编程(Python)等级考试试卷(一级)答案 + 解析
  • PowerShell中conda activate指令无效的问题