【前端】简易化看板

news2024/11/24 17:58:12

【前端】简易化看板

在这里插入图片描述
在这里插入图片描述

项目简介

看板分为三个模块,分别是待办,正在做,已做完三个部分。每个事件采取"卡片"式设计,支持任务间拖拽,删除等操作。

代码

import React, { useState } from 'react';
import { Card, CardContent } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';

const KanbanBoard = () => {
  const [tasks, setTasks] = useState({
    todo: [
      { id: '1', title: '设计新的登录页面' },
      { id: '2', title: '优化数据库查询' }
    ],
    doing: [
      { id: '3', title: '实现用户认证功能' },
      { id: '4', title: '编写单元测试' }
    ],
    done: [
      { id: '5', title: '更新API文档' },
      { id: '6', title: '修复登录bug' }
    ]
  });

  const [newTasks, setNewTasks] = useState({
    todo: '',
    doing: '',
    done: ''
  });

  const onDragStart = (e, id, sourceColumn) => {
    e.dataTransfer.setData('text/plain', JSON.stringify({ id, sourceColumn }));
  };

  const onDragOver = (e) => {
    e.preventDefault();
  };

  const onDrop = (e, targetColumn) => {
    e.preventDefault();
    const { id, sourceColumn } = JSON.parse(e.dataTransfer.getData('text'));
    if (sourceColumn === targetColumn) return;

    const updatedTasks = { ...tasks };
    const taskToMove = updatedTasks[sourceColumn].find(task => task.id === id);
    updatedTasks[sourceColumn] = updatedTasks[sourceColumn].filter(task => task.id !== id);
    updatedTasks[targetColumn].push(taskToMove);
    setTasks(updatedTasks);
  };

  const addTask = (column) => {
    if (newTasks[column].trim()) {
      const updatedTasks = { ...tasks };
      updatedTasks[column] = [...tasks[column], { 
        id: Date.now().toString(), 
        title: newTasks[column]
      }];
      setTasks(updatedTasks);
      setNewTasks({...newTasks, [column]: ''});
    }
  };

  const deleteTask = (columnId, taskId) => {
    const updatedTasks = { ...tasks };
    updatedTasks[columnId] = tasks[columnId].filter(task => task.id !== taskId);
    setTasks(updatedTasks);
  };

  const renderTask = (task, columnId) => (
    <Card 
      key={task.id}
      draggable
      onDragStart={(e) => onDragStart(e, task.id, columnId)}
      className="mb-2 shadow-sm hover:shadow-md transition-shadow duration-200"
    >
      <CardContent className="p-3 flex justify-between items-center">
        <p className="text-sm font-medium text-gray-700 truncate flex-grow mr-2">{task.title}</p>
        <Button 
          onClick={() => deleteTask(columnId, task.id)}
          className="text-gray-400 hover:text-red-500 transition-colors duration-200 flex-shrink-0"
          variant="ghost"
          size="sm"
        >
          ×
        </Button>
      </CardContent>
    </Card>
  );

  const renderColumn = (title, columnId) => (
    <div 
      className="flex-1 min-w-[250px] bg-gray-50 rounded-lg p-4 border border-gray-200"
      onDragOver={onDragOver}
      onDrop={(e) => onDrop(e, columnId)}
    >
      <h2 className="text-lg font-semibold mb-4 text-gray-700">{title}</h2>
      <div className="space-y-2">
        {tasks[columnId].map(task => renderTask(task, columnId))}
      </div>
      <div className="mt-4">
        <Input
          type="text"
          value={newTasks[columnId]}
          onChange={(e) => setNewTasks({...newTasks, [columnId]: e.target.value})}
          placeholder={`添加任务到 ${title}`}
          className="mb-2"
        />
        <Button onClick={() => addTask(columnId)} className="w-full bg-blue-500 hover:bg-blue-600 text-white">
          添加任务
        </Button>
      </div>
    </div>
  );

  return (
    <div className="container mx-auto p-6 bg-white">
      <header className="text-center mb-8">
        <h1 className="text-3xl font-bold text-gray-800">SeeBoard</h1>
      </header>
      <div className="flex flex-wrap gap-6">
        {renderColumn('待办', 'todo')}
        {renderColumn('进行中', 'doing')}
        {renderColumn('已完成', 'done')}
      </div>
    </div>
  );
};

export default KanbanBoard;

效果图

在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu多显示器设置不同缩放比例

Ubuntu多显示器设置不同缩放比例 设备问题解决方案 设备 笔记本屏幕分辨率为2560 \times 1600&#xff0c;外接显示器的分辨率为3840 \times 2160。 问题 Ubuntu默认的显示器设置中&#xff0c;缩放仅能选择100%&#xff0c;200%&#xff0c;300%&#xff0c;400%。假…

从我邮毕业啦!!!

引言 时间过的好快&#xff0c;转眼间就要从北邮毕业了&#xff0c;距离上一次月度总结又过去了两个月&#xff0c;故作本次总结。 PS: https://github.com/WeiXiao-Hyy/blog整理了后端开发的知识网络&#xff0c;欢迎Star&#xff01; 毕业&#x1f393; 6月1号完成了自己的…

开源模型应用落地-FastAPI-助力模型交互-WebSocket篇(三)

一、前言 使用 FastAPI 可以帮助我们更简单高效地部署 AI 交互业务。FastAPI 提供了快速构建 API 的能力,开发者可以轻松地定义模型需要的输入和输出格式,并编写好相应的业务逻辑。 FastAPI 的异步高性能架构,可以有效支持大量并发的预测请求,为用户提供流畅的交互体验。此外,F…

从零开始:Spring Boot 中使用 Drools 规则引擎的完整指南

规则引擎作用 规则引擎主要用于将业务逻辑从应用程序代码中分离出来&#xff0c;提高系统的灵活性和可维护性。规则引擎通过预定义的规则来处理输入数据并做出相应的决策&#xff0c;从而实现业务逻辑的自动化和动态调整。 例如 门店信息校验&#xff1a;美团点评在门店信息…

C语言分支和循环(上)

C语言分支和循环&#xff08;上&#xff09; 1. if语句1.1 if1.2 else1.3 分支中包含多条语句1.4 嵌套if1.5 悬空else问题 2. 关系操作符3. 条件操作符4. 逻辑操作符&#xff1a;&&,||,&#xff01;4.1 逻辑取反运算符4.2 与运算符4.3 或运算符4.4 练习&#xff1a;闰年…

日志可视化监控体系ElasticStack 8.X版本全链路实战

目录 一、SpringBoot3.X整合logback配置1.1 log4j、logback、self4j 之间关系 1.2 SpringBoot3.X整合logback配置 二、日志可视化分析ElasticStack 2.1为什么要有Elastic Stack 2.2 什么是Elastic Stack 三、ElasticSearch8.X源码部署 ​四、Kibana源码部署 五、LogSta…

昇思25天学习打卡营第3天|函数式自动微分

文章目录 昇思MindSpore快速入门基于MindSpore的函数式自动微分1、简介2、函数与计算图算例3、微分函数与梯度计算4、Stop Gradient&#xff08;停止梯度计算&#xff09;5、Auxiliary data6、神经网络梯度计算 Reference 昇思MindSpore快速入门 基于MindSpore的函数式自动微分…

Keil5中:出现:failed to execute ‘...\ARMCC\bin\ArmCC‘

点三个点&#xff0c;去自己的磁盘找自己的ARM\ARMCC\bin

vue-cil搭建项目

目录 一、使用 HbuilderX 快速搭建一个 vue-cli 项目 1.需要的环境——Node.js 2.搭建Vue-cil项目 二、组件路由 1.安装vue-router 2.创建router目录 3.使用路由 4.在main.js中配置路由 vue-cli 官方提供的一个脚手架&#xff0c;用于快速生成一个 vue 的项目模板&#xff1b;…

Windows/Linux/Mac 系统局域网服务发现协议及传输速度比较

简介 分析 / 验证对比常见局域网服务发现协议在 Windows/Linux/Mac 等不同系统下的支持和表现 在使用不同系统的智能硬件时&#xff0c;如常见的树莓派 / Openwrt 路由器 / Debian/Fedora/Windows/Mac 等系统是&#xff0c;系统间相互发现以及网络共享本应是系统的基础服务&a…

游戏AI的创造思路-技术基础-深度学习(3)

继续填坑&#xff0c;本篇介绍深度学习中的长短期记忆网络~~~~ 目录 3.3. 长短期记忆网络&#xff08;LSTM&#xff09; 3.3.1. 什么是长短期记忆网络 3.3.2. 形成过程与运行原理 3.3.2.1. 细胞状态与门结构 3.3.2.2. 遗忘门 3.3.2.3. 输入门 3.3.2.4. 细胞状态更新 3.…

vscode 生成项目目录结构 directory-tree 实用教程

1. 安装插件 directory-tree 有中文介绍&#xff0c;极其友好&#xff01; 2. 用 vscode 打开目标项目 3. 快捷键 Ctrl Shift p&#xff0c;输入 Directory Tree 后回车 会在 README.md 文件的底部生成项目目录&#xff08;若项目中没有 README.md 文件&#xff0c;则会自动创…

数据结构速成--图

由于是速成专题&#xff0c;因此内容不会十分全面&#xff0c;只会涵盖考试重点&#xff0c;各学校课程要求不同 &#xff0c;大家可以按照考纲复习&#xff0c;不全面的内容&#xff0c;可以看一下小编主页数据结构初阶的内容&#xff0c;找到对应专题详细学习一下。 目录 …

CO-DETR利用coco数据集训练和推理过程

CO-DETR利用coco数据集训练和推理过程&#xff0c;参考链接 Co-DETR训练自己的数据集 文章目录 前言训练过程推理过程总结 前言 环境&#xff1a;PyTorch 1.11.0 Python 3.8(ubuntu20.04) Cuda 11.3 先是在github上下载CO-DETR模型 !git clone https://github.com/Sense-X/Co…

JAVA设计模式-大集合数据拆分

背景 我们在做软件开发时&#xff0c;经常会遇到把大集合的数据&#xff0c;拆分成子集合处理。例如批量数据插入数据库时&#xff0c;一次大约插入5000条数据比较合理&#xff0c;但是有时候待插入的数据远远大于5000条。这时候就需要进行数据拆分。数据拆分基本逻辑并不复杂&…

复分析——第9章——椭圆函数导论(E.M. Stein R. Shakarchi)

第 9 章 椭圆函数导论 (An Introduction to Elliptic Functions) The form that Jacobi had given to the theory of elliptic functions was far from perfection; its flaws are obvious. At the base we find three fundamental functions sn, cn and dn. These functio…

一款轻量级的WPF UI库---Adonis UI

Adonis UI适用于 WPF 应用程序的轻型 UI 工具包,提供经典但增强的 Windows 视觉对象 组件内容 几乎所有 WPF 控件的模板的默认样式为方便起见,可根据需要使用两种配色方案(浅色和深色),也可用于自定义样式支持在运行时更改配色方案支持其他自定义配色方案提供水印等功能的…

华为BGP路由实验基础1------用物理口建立对等体

1.用物理口做BGP建立对等体建立BGP连接 实验拓扑&#xff1a; 实验步骤&#xff1a; 1.完成基本配置 sys [Huawei]sys AR1 [AR1]undo in e [AR1]int g0/0/0 [AR1-GigabitEthernet0/0/0]ip add 1.1.1.1 24 [AR1-GigabitEthernet0/0/0]q [AR1] sys [Huawei]sys AR2 [AR2]undo i…

2024年危化品安全员生产单位(生产管理人员)考试精选题库

31.《危险化学品安全管理条例》所称重大危险源,是指生产、储存、使用或者搬运危险化学品,且危险化学品的数量等于或者超过&#xff08;&#xff09;的单元(包括场所和设施)。 A.标准 B.一定量 C.临界量 答案&#xff1a;C 32.《危险化学品生产企业安全生产许可证实施办法》…

Sui创始团队在竞速环节中的快问快答

在Sui Basecamp活动期间&#xff0c;Sui区块链的最初贡献者在Oracle红牛赛车模拟器上展示了他们的技术能力&#xff0c;在驾驶圈时回答了有关Sui的问题。 Evan Cheng&#xff08;又名Revvin’ Evan&#xff09;在解释Mysticeti创下区块链最终性记录的同时保持着他的驾驶线路。…