【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,关注一下吧  

 下一篇讲身份验证

【Next.js 项目实战系列】06-身份验证

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/895796.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Win10 IDEA远程连接HBase

Win10 IDEA远程连接HBase Win10 IDEA连接虚拟机中的Hadoop&#xff08;HDFS&#xff09; 关闭Hadoop和Hbase 如果已经关闭不需要走这一步 cd /usr/local/hbase bin/stop-hbase.sh cd /usr/local/hadoop ./sbin/stop-dfs.sh获取虚拟机的ip 虚拟机终端输入 ip a关闭虚拟机…

VS Code开发qt项目

没整明白&#xff0c;尴尬 安装扩展 设置cmake路径 前提是已经安装了QT 报错 用msvc选windows启动&#xff0c;用mingw则选gdb启动

Vue3 新特性、Pinia

一、新特性 - defineOptions 背景说明 因为我们用了<script setup>语法&#xff0c;没办法给setup去提供一些平级的属性&#xff0c;官方就提供了一个叫做 defineOptions 的语法 所以在 Vue3.3 中引入了 defineOptions 宏&#xff0c;用来定义 Options API 的选项。可以…

[OpenCV] 数字图像处理 C++ 学习——17模板匹配详细讲解+附完整代码

文章目录 前言1.理论基础1.1模板匹配介绍1.2匹配算法介绍 2.代码实现2.1模块匹配(matchTemplate)2.2最佳匹配函数(minMaxLoc()) 3.完整代码 前言 模板匹配是图像处理和计算机视觉领域中的一种经典技术&#xff0c;它通过在大图像中搜索与小图像&#xff08;模板&#xff09;匹…

gewechat免费开源微信机器人开发

​聊天机器人&#xff0c;是一种通过自然语言模拟人类进行对话的程序。通常运行在特定的软件平台上&#xff0c;如PC平台或者移动终端设备平台。聊天机器人系统的主要功能是同用户进行基本沟通并自动回复用户有关产品或服务的问题&#xff0c;以实现降低企业客服运营成本、提升…

Tkinter 的布局pack() and grid()笔记

#encodingutf-8 import tkinter import re import tkinter.messagebox import tkinter.simpledialog import sys import os def get_resources_path(relative_path):if getattr(sys,frozen, False):base_pathsys._MEIPASS#获取临时文件else:base_pathos.path.dirname(".&q…

鸿蒙应用开发----西西购物商城(一)

目录 前言 一、项目介绍 二、项目结构 三、开发工具 四、样式展示 前言 harmonyos是华为推出的一款新一代操作系统&#xff0c;致力于打破设备间的边界&#xff0c;构建统一的智能生态。西西购物商城作为一款基于harmonyos开发的应用&#xff0c;能够利用鸿蒙的分布式技术…

R语言绘制Venn图(文氏图、温氏图、维恩图、范氏图、韦恩图)

Venn图&#xff0c;又称文氏图&#xff0c;标题中其他名字也是它的别称&#xff0c;由封闭圆形组成&#xff0c;代表不同集合。圆形重叠部分表示集合交集&#xff0c;非重叠处为独有元素。在生物学、统计学等领域广泛应用&#xff0c;可展示不同数据集相似性与差异&#xff0c;…

大数据新视界 --大数据大厂之大数据在智慧城市建设中的应用:打造智能生活的基石

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

【MR开发】在Pico设备上接入MRTK3(一)——在Unity工程中导入MRTK3依赖

写在前面的话 在Pico上接入MRTK3&#xff0c;目前已有大佬开源。 https://github.com/Phantomxm2021/PicoMRTK3 也有值得推荐的文章。 MRTK3在PICO4上的使用小结 但由于在MacOS上使用MRTK3&#xff0c;无法通过Mixed Reality Feature Tool工具管理MRTK3安装包。 故记录一下…

集合collection和泛型

collection可以直接打印内容&#xff0c;而不是地址&#xff0c;内部已经重写了。 List家族&#xff1a; package com.itheima.d6_collection_update_delete;import java.util.ArrayList; import java.util.Iterator; import java.util.List;/**目标&#xff1a;研究集合遍历并…

Fooocus模型部署指南

一、介绍 Fooocus是一款开源的AI绘画工具&#xff0c;由斯坦福大学博士生张吕敏&#xff08;Github上用户名lllyasviel&#xff09;开发。是一款结合StableDiffusion和Midjourney理念的图像生成工具&#xff0c;提供离线、开源且易于使用的界面。它简化安装步骤&#xff0c;用…

【软件测试】JUnit

Junit 是一个用于 Java 编程语言的单元测试框架&#xff0c;Selenium是自动化测试框架&#xff0c;专门用于Web测试 本篇博客介绍 Junit5 文章目录 Junit 使用语法注解参数执行顺序断言测试套件 Junit 使用 本篇博客使用 Idea集成开发环境 首先&#xff0c;创建新项目&#…

【深度学习】评价指标

https://zhuanlan.zhihu.com/p/479060683 https://blog.csdn.net/fyfugoyfa/article/details/136414958 Confusion Matrix&#xff0c;是一个用来衡量模型好坏的统计量&#xff0c;其中Accuracy&#xff0c;Precision&#xff0c;F1 score&#xff0c;Recall&#xff0c;ROC曲线…

[SAP ABAP] SE11定义数据类型(结构与表类型)

1.定义结构 使用事务码SE11创建数据类型(结构)&#xff0c;输入自定义的数据类型名称&#xff0c;点击创建按钮 勾选结构并点击确定按钮 填写简短描述&#xff0c;并在"组件"页签上添加相关字段信息&#xff0c;点击激活按钮即可生效该结构ZSPO_HEADER_437 2.定义表…

企业网站设计之网站结构设计

创意主题网站的结构设计更是需要更为精心的策划和执行&#xff0c;以确保吸引并保持用户的注意力。以下是创意主题网站结构设计的关键要素&#xff1a; 1. 目标明确的导航栏 导航栏是用户进入网站并浏览内容的入口。在创意主题网站中&#xff0c;导航栏的设计要突显网站的主…

【大数据算法】一文掌握大数据算法之:大数据算法分析技术。

大数据算法分析技术 1、引言2、 大数据分析技术2.1 时间/空间复杂度2.2 I/O 复杂度2.3 结果质量2.4 通信复杂度 3、总结 1、引言 小屌丝&#xff1a;鱼哥&#xff0c;最近更文有些不频繁了哈。 小鱼&#xff1a;这一个月不见&#xff0c;你这说话方式也变了。 小屌丝&#xff…

Electron-(一)创建桌面应用

一、概述 本文通过核心步骤介绍&#xff0c;形成使用Electron进行桌面应用创建的概述性内容。 在当今的软件开发领域&#xff0c;Electron 作为一款强大的工具&#xff0c;为开发者提供了一种便捷的方式来创建跨平台的桌面应用。本文将通过详细介绍核心步骤&#xff0c;带您领…

PPT自动化:掌握 python-pptx 的基础元素

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 PPT 📒📝 什么是 Slide?📝 了解 Shape📝 深入 Paragraph📝 探索 Run⚓️ 相关链接 ⚓️📖 介绍 📖 初学python-pptx,掌握 python-pptx 与 PPT 元素的对应关系是至关重要的一步。今天,我们一起来了解一下 PPT 中…

Python基于OpenCV的实时疲劳检测

2.检测方法 1&#xff09;方法 与用于计算眨眼的传统图像处理方法不同&#xff0c;该方法通常涉及以下几种组合&#xff1a; 1、眼睛定位。 2、阈值找到眼睛的白色。 3、确定眼睛的“白色”区域是否消失了一段时间&#xff08;表示眨眼&#xff09;。 相反&#xff0c;眼睛长…