-
Notifications
You must be signed in to change notification settings - Fork 350
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
21 changed files
with
710 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
# ⚡ vite-react-ts-tailwind-starter | ||
|
||
Starter using Vite + React + TypeScript + Tailwind with Firebase. | ||
|
||
## Motivation | ||
|
||
Improve building your faster **prototyping** by using Vite, TypeScript, React, TailwindCSS, Firebase. | ||
|
||
This starter uses following libraries: | ||
|
||
- Vite | ||
- React | ||
- React Router | ||
- TypeScript | ||
- Tailwind CSS | ||
- daisyUI | ||
- Firebase(v9, modular) | ||
- ESLint | ||
- Prettier | ||
|
||
## Set up | ||
|
||
```shell | ||
mv .env.local.example .env.local | ||
yarn | ||
yarn dev | ||
``` | ||
|
||
### Firebase | ||
|
||
If you **DO NOT** use Firebase, you should do: | ||
|
||
- Delete the Firebase-related code: you check Main.tsx, SignInButton.tsx, SignOutButton.tsx. | ||
- And then delete `src/lib/firebase.ts` | ||
- Run `yarn remove firebase` | ||
- Remove `VITE_FIREBASE_*` env values from `.env.local` | ||
|
||
If you want to use Firebase, you should do: | ||
|
||
- copy Firebase env values from Firebase Console, and paste them to `.env.local`. | ||
- enable Google Auth in Firebase Console. ref: https://firebase.google.com/docs/auth/web/google-signin#before_you_begin | ||
|
||
## Vite | ||
|
||
[Vite](https://github.com/vitejs/vite) is a fast frontend build tool. According to the [README](https://github.com/vitejs/vite/blob/main/README.md), it consists of two major parts: | ||
|
||
- A dev server that serves your source files over native ES modules, with rich built-in features and astonishingly fast Hot Module Replacement (HMR). | ||
- A build command that bundles your code with Rollup, pre-configured to output highly optimized static assets for production. | ||
|
||
## React | ||
|
||
[React](https://github.com/facebook/react) is a JavaScript library for building user interfaces. | ||
|
||
Due to its awesome renderer system, there are many [React Renderor](https://github.com/chentsulin/awesome-react-renderer). So React can be not used only Web, for example, used by [React Native](https://reactnative.dev/). | ||
|
||
Let's dive into React and Vite can use with React. | ||
|
||
## TypeScript | ||
|
||
[TypeScript](https://github.com/microsoft/TypeScript) is a superset of JavaScript. It is just one of NPM library, but it provides an original compiler. | ||
|
||
When you use TypeScript with React, you can write JSX with TypeScript, called TSX. Then you can develop views written by **Type-Safe** template. | ||
|
||
## Tailwind CSS | ||
|
||
[Tailwind CSS](https://tailwindcss.com/) is modern utility-first CSS framework. It provides many CSS rules, but these are purged when production builds. So developers do not worry about CSS asset size for performance optimization. | ||
|
||
In VSCode, I recommend to use [intellisense extension](https://tailwindcss.com/docs/intellisense). | ||
|
||
Frequently, React developers are worried about how to write CSS in TSX(JSX) template. You must choose from CSS Modules, [styled-components](https://styled-components.com/), [linaria](https://github.com/callstack/linaria), and so on. | ||
Additionally, CSS architecture is difficult about scoping, e.g. BEM, FLOCSS. | ||
|
||
When you decide to use Tailwind, you only write utility-first CSS classes, you don't have to worry about them! | ||
|
||
### daisyUI | ||
|
||
[daisyUI](https://daisyui.com/) is Tailwind CSS Components library. | ||
|
||
It prepares components CSS classes such as 'btn'. If you provide 'btn' class to `<button>` element, then there should be placed completely designed button. | ||
|
||
If you don't want to use it, just remove the package and remove config in `tailwind.config.js`. | ||
|
||
## Firebase | ||
|
||
[Firebase](https://firebase.google.com/) is a PaaS that makes us create hi-quality apps so easy and so fast. | ||
|
||
This library is not suitable for everyone, but I think it is one of the best libraries for prototyping. Therefore, I have added it to this repository. | ||
|
||
The Firebase js SDK has become very useful in version 9, with [optimizations that greatly reduce bundle size](https://firebase.google.com/docs/web/modular-upgrade). | ||
|
||
### How to Use | ||
|
||
Please look at [firebase.ts](https://github.com/TeXmeijin/vite-react-ts-tailwind-starter/blob/main/src/lib/firebase.ts). | ||
|
||
There you will find a set of utility functions to manipulate Firebase for the environment in which the Emulator is used. | ||
|
||
## Formatter and Linter | ||
|
||
Already set up [ESLint](https://eslint.org/) and [Prettier](https://prettier.io/). You can customize the rules. | ||
|
||
NOTICE: The template does not use [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) and [prettier-eslint](https://github.com/prettier/prettier-eslint). So I recommend that running commands individually. e.g. `prettier && eslint`. | ||
|
||
Please read: https://prettier.io/docs/en/integrating-with-linters.html. | ||
|
||
# ToDo | ||
|
||
- [x] install and set up [TailwindCSS/JIT](https://github.com/tailwindlabs/tailwindcss-jit) see this [PR](https://github.com/TeXmeijin/vite-react-ts-tailwind-starter/pull/1) | ||
|
||
--- | ||
|
||
### Support me! | ||
|
||
<a href="https://www.buymeacoffee.com/meijin" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<link rel="icon" type="image/svg+xml" href="src/favicon.svg" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Vite React TypeScript Tailwind Starter</title> | ||
</head> | ||
<body> | ||
<div id="root"></div> | ||
<script type="module" src="/src/main.tsx"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
{ | ||
"name": "Tast-1", | ||
"version": "1.0.0", | ||
"license": "MIT", | ||
"author": { | ||
"name": "TeXmeijin" | ||
}, | ||
"scripts": { | ||
"dev": "vite", | ||
"build": "tsc && vite build", | ||
"serve": "vite preview" | ||
}, | ||
"dependencies": { | ||
"@headlessui/react": "^1.7.18", | ||
"antd": "^5.19.3", | ||
"daisyui": "^4.6.1", | ||
"firebase": "^9.23.0", | ||
"react": "^18.2.0", | ||
"react-dom": "^18.2.0", | ||
"react-helmet-async": "^1.3.0", | ||
"react-router-dom": "^6.21.3", | ||
"store2": "^2.14.3" | ||
}, | ||
"devDependencies": { | ||
"@types/react": "18.2.50", | ||
"@types/react-dom": "18.2.18", | ||
"@types/react-router-dom": "^5.3.3", | ||
"@typescript-eslint/eslint-plugin": "^6.20.0", | ||
"@typescript-eslint/parser": "^6.20.0", | ||
"@vitejs/plugin-react": "^4.2.1", | ||
"autoprefixer": "^10.4.17", | ||
"eslint": "^8.56.0", | ||
"eslint-config-airbnb": "^19.0.4", | ||
"eslint-config-prettier": "^9.1.0", | ||
"eslint-config-standard": "^17.1.0", | ||
"eslint-plugin-import": "^2.29.1", | ||
"eslint-plugin-node": "^11.1.0", | ||
"eslint-plugin-promise": "6.1.1", | ||
"eslint-plugin-react": "^7.33.2", | ||
"postcss": "^8.4.33", | ||
"prettier": "^3.2.4", | ||
"tailwindcss": "^3.4.1", | ||
"typescript": "^5.3.3", | ||
"vite": "^4.4.9", | ||
"vite-tsconfig-paths": "^4.3.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// postcss.config.js | ||
module.exports = { | ||
plugins: { | ||
tailwindcss: {}, | ||
autoprefixer: {}, | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"extends": ["config:base"], | ||
"packageRules": [ | ||
{ | ||
"matchUpdateTypes": ["minor", "patch", "pin", "digest"], | ||
"automerge": true | ||
}, | ||
{ | ||
"matchDepTypes": ["devDependencies"], | ||
"automerge": true | ||
} | ||
], | ||
"rangeStrategy": "bump" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
function Header() { | ||
return ( | ||
<div className="font-semibold text-2xl"> | ||
待办列表 | ||
</div> | ||
); | ||
} | ||
|
||
export default Header; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/** 展示单个待办事项 */ | ||
function ToDoItem() { | ||
return ( | ||
<div className="font-semibold text-2xl"> | ||
展示单个待办事项 | ||
</div> | ||
); | ||
} | ||
|
||
export default ToDoItem; |
179 changes: 179 additions & 0 deletions
179
members/0xsuxin/task1/src/components/ToDoList/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
import type { TableProps } from 'antd'; | ||
import { | ||
Button, Form, Input, Modal, Table, | ||
} from 'antd'; | ||
import { useEffect, useState } from 'react'; | ||
import store2 from 'store2'; | ||
|
||
interface DataType { | ||
key?: string; | ||
name: string; | ||
states: number; | ||
} | ||
|
||
/** 展示所有待办事项 */ | ||
function ToDoList() { | ||
// 使用useState钩子来管理待办事项的数据状态 | ||
const [data, setData] = useState([]); | ||
// 使用useState钩子来管理模态框的打开状态 | ||
const [isModalOpen, setIsModalOpen] = useState(false); | ||
|
||
// 使用Form.useForm()来创建表单实例 | ||
const [form] = Form.useForm(); | ||
|
||
/** | ||
* 打开模态框 | ||
* 该函数用于触发模态框的显示,以便用户可以添加新的待办事项 | ||
*/ | ||
const showModal = () => { | ||
setIsModalOpen(true); | ||
}; | ||
|
||
/** | ||
* 处理确认按钮的点击事件 | ||
* 该函数用于提交表单,验证字段,并将新的待办事项添加到列表中 | ||
*/ | ||
const handleOk = async () => { | ||
form.submit(); | ||
// 等待表单验证并获取名称字段的值 | ||
const { name }: { name: string } = await form.validateFields(); | ||
// 如果名称字段为空,则不执行任何操作并返回 | ||
if (!name) return; | ||
// 获取当前的待办事项列表,如果不存在则初始化为空数组 | ||
const todoList = data; | ||
// 将新的待办事项添加到列表中 | ||
todoList.push({ name, states: false }); | ||
// 更新待办事项的数据状态 | ||
setData([...todoList]); | ||
// 重置表单字段 | ||
form.resetFields(); | ||
// 关闭模态框 | ||
setIsModalOpen(false); | ||
}; | ||
|
||
/** | ||
* 删除待办事项 | ||
* @param index 待删除待办事项的索引 | ||
* 该函数用于从列表中删除指定的待办事项 | ||
*/ | ||
const onDelete = (index: number) => { | ||
// 获取当前的待办事项列表,如果不存在则初始化为空数组 | ||
const todoList = data; | ||
// 从列表中移除指定索引的待办事项 | ||
todoList.splice(index, 1); | ||
// 更新待办事项的数据状态 | ||
setData([...todoList]); | ||
}; | ||
|
||
/** | ||
* 改变待办事项的状态 | ||
* @param index 待改变状态的待办事项的索引 | ||
* 该函数用于改变指定待办事项的状态(已完成或未完成) | ||
*/ | ||
const onCompleted = (index: number) => { | ||
// 获取当前的待办事项列表,如果不存在则初始化为空数组 | ||
const todoList = data; | ||
// 更新指定索引的待办事项的状态 | ||
todoList[index] = { | ||
...todoList[index], | ||
states: !todoList[index].states, | ||
}; | ||
// 更新待办事项的数据状态 | ||
setData([...todoList]); | ||
}; | ||
|
||
/** | ||
* 关闭模态框 | ||
* 该函数用于关闭模态框,通常在点击取消按钮时调用 | ||
*/ | ||
const handleCancel = () => { | ||
setIsModalOpen(false); | ||
}; | ||
|
||
// 定义表格的列配置 | ||
const columns: TableProps<DataType>['columns'] = [ | ||
{ | ||
title: '#', | ||
align: 'center', | ||
// 自定义列渲染,用于显示待办事项的序号 | ||
render: (a, b, i) => <p>{i + 1}</p>, | ||
}, | ||
{ | ||
title: '名称', | ||
dataIndex: 'name', | ||
align: 'center', | ||
}, | ||
{ | ||
title: '状态', | ||
dataIndex: 'states', | ||
align: 'center', | ||
// 自定义列渲染,用于显示待办事项的状态文本 | ||
render: (states: string) => (states ? '已完成' : '未完成'), | ||
}, | ||
{ | ||
title: '操作', | ||
align: 'center', | ||
// 自定义列渲染,用于显示删除和更改状态的操作按钮 | ||
render: (...row: any) => ( | ||
<> | ||
<Button type="link" onClick={() => onDelete(row[2])}> | ||
删除 | ||
</Button> | ||
<Button type="link" onClick={() => onCompleted(row[2])}> | ||
更改状态 | ||
</Button> | ||
</> | ||
), | ||
}, | ||
]; | ||
|
||
useEffect(() => { | ||
// 获取数据 | ||
const todoList = store2('todoList'); | ||
if (todoList?.length) { | ||
setData(todoList); | ||
} | ||
return () => { | ||
store2('todoList', todoList); | ||
}; | ||
}, []); | ||
|
||
return ( | ||
<> | ||
<div className=""> | ||
<Button type="primary" className="mb-2" onClick={showModal}> | ||
添加待办事项 | ||
</Button> | ||
</div> | ||
<Table columns={columns} dataSource={data} rowKey="name" /> | ||
|
||
<Modal title="添加待办事项" open={isModalOpen} onOk={handleOk} onCancel={handleCancel}> | ||
<Form name="basic" form={form}> | ||
<Form.Item | ||
label="待办事件" | ||
name="name" | ||
rules={[ | ||
{ | ||
required: true, | ||
validator: (rule, value) => { | ||
const todoList = data; | ||
if (todoList.some((v) => v.name === value)) { | ||
return Promise.reject(new Error('待办事件已存在')); | ||
} | ||
if (!value) { | ||
return Promise.reject(new Error('请输入待办事件名称')); | ||
} | ||
return Promise.resolve(); | ||
}, | ||
}, | ||
]} | ||
> | ||
<Input placeholder="请输入待办事件名称" /> | ||
</Form.Item> | ||
</Form> | ||
</Modal> | ||
</> | ||
); | ||
} | ||
|
||
export default ToDoList; |
Oops, something went wrong.