From c5d0b98e1e007eb83a956fdcec56f59d58c0484a Mon Sep 17 00:00:00 2001 From: taojiang Date: Thu, 19 Dec 2024 12:32:55 +0800 Subject: [PATCH 1/3] task1:there is creating project at taojiang dir --- members/taojiangcb/task1/src/AddToDo.tsx | 25 +++++++ members/taojiangcb/task1/src/App.css | 42 ++++++++++++ members/taojiangcb/task1/src/App.tsx | 56 +++++++++++++++ members/taojiangcb/task1/src/Header.tsx | 14 ++++ members/taojiangcb/task1/src/ToDoList.tsx | 4 ++ members/taojiangcb/task1/src/assets/react.svg | 1 + members/taojiangcb/task1/src/constants.ts | 2 + .../taojiangcb/task1/src/defined-object.ts | 5 ++ members/taojiangcb/task1/src/index.css | 68 +++++++++++++++++++ members/taojiangcb/task1/src/main.tsx | 10 +++ members/taojiangcb/task1/src/store.ts | 19 ++++++ members/taojiangcb/task1/src/vite-env.d.ts | 1 + 12 files changed, 247 insertions(+) create mode 100644 members/taojiangcb/task1/src/AddToDo.tsx create mode 100644 members/taojiangcb/task1/src/App.css create mode 100644 members/taojiangcb/task1/src/App.tsx create mode 100644 members/taojiangcb/task1/src/Header.tsx create mode 100644 members/taojiangcb/task1/src/ToDoList.tsx create mode 100644 members/taojiangcb/task1/src/assets/react.svg create mode 100644 members/taojiangcb/task1/src/constants.ts create mode 100644 members/taojiangcb/task1/src/defined-object.ts create mode 100644 members/taojiangcb/task1/src/index.css create mode 100644 members/taojiangcb/task1/src/main.tsx create mode 100644 members/taojiangcb/task1/src/store.ts create mode 100644 members/taojiangcb/task1/src/vite-env.d.ts diff --git a/members/taojiangcb/task1/src/AddToDo.tsx b/members/taojiangcb/task1/src/AddToDo.tsx new file mode 100644 index 000000000..a2aba1ee1 --- /dev/null +++ b/members/taojiangcb/task1/src/AddToDo.tsx @@ -0,0 +1,25 @@ +import Paper from '@mui/material/Paper'; + +import { IconButton, InputBase } from '@mui/material'; +import { Search as SearchIcon } from '@mui/icons-material' +interface Props { +} + +const AddToDo: React.FC = (props) => { + return
+ + + + {/* */} + + + + +
+} + +export default AddToDo; \ No newline at end of file diff --git a/members/taojiangcb/task1/src/App.css b/members/taojiangcb/task1/src/App.css new file mode 100644 index 000000000..b9d355df2 --- /dev/null +++ b/members/taojiangcb/task1/src/App.css @@ -0,0 +1,42 @@ +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} diff --git a/members/taojiangcb/task1/src/App.tsx b/members/taojiangcb/task1/src/App.tsx new file mode 100644 index 000000000..f05d3db86 --- /dev/null +++ b/members/taojiangcb/task1/src/App.tsx @@ -0,0 +1,56 @@ +import { useState, useEffect, useMemo } from 'react' +import './App.css' +import Header from './Header' +import { Todo } from './defined-object' +import TodoStore from './store'; +import AddToDo from './AddToDo'; +import { LOCAL_STORE_KEY } from './constants'; + + +function App() { + const [todos, setTodos] = useState(() => { + const json_str = localStorage.getItem(LOCAL_STORE_KEY); + const todos = JSON.parse(json_str || '[]'); + return todos; + }); + + const initStore = useMemo(() => { + function toSave(todos: Todo[]) { + localStorage.setItem(LOCAL_STORE_KEY, JSON.stringify(todos || [])); + } + + function setStore(todos: Todo[]) { + setTodos(todos) + toSave(todos); + } + + const addTodo = (todo: Todo) => { + setStore([...todos, todo]); + }; + + const deleteTodo = (id: string) => { + setStore(todos.filter((todo) => todo.id !== id)); + }; + + const changeTodo = (id: string, text: string) => { + setStore(todos.map((todo) => todo.id === id ? { ...todo, text } : todo)); + } + return { + todos, + addTodo, + deleteTodo, + changeTodo + } + }, [todos]); + + return
+
+ + +
+
+
+
+} + +export default App; diff --git a/members/taojiangcb/task1/src/Header.tsx b/members/taojiangcb/task1/src/Header.tsx new file mode 100644 index 000000000..6490c2013 --- /dev/null +++ b/members/taojiangcb/task1/src/Header.tsx @@ -0,0 +1,14 @@ + +interface Props { + title: string; +} + +const Header = ({ title }: Props) => { + return ( +
+

{title}

+
+ ) +} + +export default Header; \ No newline at end of file diff --git a/members/taojiangcb/task1/src/ToDoList.tsx b/members/taojiangcb/task1/src/ToDoList.tsx new file mode 100644 index 000000000..85bb68b81 --- /dev/null +++ b/members/taojiangcb/task1/src/ToDoList.tsx @@ -0,0 +1,4 @@ + +interface Props { + children: React.ReactNode; +} diff --git a/members/taojiangcb/task1/src/assets/react.svg b/members/taojiangcb/task1/src/assets/react.svg new file mode 100644 index 000000000..6c87de9bb --- /dev/null +++ b/members/taojiangcb/task1/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/members/taojiangcb/task1/src/constants.ts b/members/taojiangcb/task1/src/constants.ts new file mode 100644 index 000000000..8c6012018 --- /dev/null +++ b/members/taojiangcb/task1/src/constants.ts @@ -0,0 +1,2 @@ +export const LOCAL_STORE_KEY = "tasks"; + diff --git a/members/taojiangcb/task1/src/defined-object.ts b/members/taojiangcb/task1/src/defined-object.ts new file mode 100644 index 000000000..369cb28b7 --- /dev/null +++ b/members/taojiangcb/task1/src/defined-object.ts @@ -0,0 +1,5 @@ +export interface Todo { + id: string; + text: string; + done: boolean; +} diff --git a/members/taojiangcb/task1/src/index.css b/members/taojiangcb/task1/src/index.css new file mode 100644 index 000000000..6119ad9a8 --- /dev/null +++ b/members/taojiangcb/task1/src/index.css @@ -0,0 +1,68 @@ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/members/taojiangcb/task1/src/main.tsx b/members/taojiangcb/task1/src/main.tsx new file mode 100644 index 000000000..bef5202a3 --- /dev/null +++ b/members/taojiangcb/task1/src/main.tsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import './index.css' +import App from './App.tsx' + +createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/members/taojiangcb/task1/src/store.ts b/members/taojiangcb/task1/src/store.ts new file mode 100644 index 000000000..7872d3cfd --- /dev/null +++ b/members/taojiangcb/task1/src/store.ts @@ -0,0 +1,19 @@ +import React from "react"; +import { Todo as Todo } from "./defined-object"; + + +interface ITodoStore { + todos: Todo[]; + addTodo: (task: Todo) => void; + changeTodo: (id: string, text: string) => void; + deleteTodo: (id: string) => void; +} + +const TodoStore = React.createContext({ + todos: [], + addTodo: () => { }, + changeTodo: () => { }, + deleteTodo: () => { } +}) + +export default TodoStore \ No newline at end of file diff --git a/members/taojiangcb/task1/src/vite-env.d.ts b/members/taojiangcb/task1/src/vite-env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/members/taojiangcb/task1/src/vite-env.d.ts @@ -0,0 +1 @@ +/// From 1171804e97a9393748b40d166135963e7f85928e Mon Sep 17 00:00:00 2001 From: taojiang Date: Thu, 19 Dec 2024 12:38:40 +0800 Subject: [PATCH 2/3] task1:there is creating project at taojiang dir --- members/taojiangcb/task1/.gitignore | 24 ++++++++++ members/taojiangcb/task1/README.md | 50 +++++++++++++++++++++ members/taojiangcb/task1/eslint.config.js | 28 ++++++++++++ members/taojiangcb/task1/index.html | 13 ++++++ members/taojiangcb/task1/package.json | 33 ++++++++++++++ members/taojiangcb/task1/public/vite.svg | 1 + members/taojiangcb/task1/tsconfig.app.json | 26 +++++++++++ members/taojiangcb/task1/tsconfig.json | 7 +++ members/taojiangcb/task1/tsconfig.node.json | 24 ++++++++++ members/taojiangcb/task1/vite.config.ts | 7 +++ 10 files changed, 213 insertions(+) create mode 100644 members/taojiangcb/task1/.gitignore create mode 100644 members/taojiangcb/task1/README.md create mode 100644 members/taojiangcb/task1/eslint.config.js create mode 100644 members/taojiangcb/task1/index.html create mode 100644 members/taojiangcb/task1/package.json create mode 100644 members/taojiangcb/task1/public/vite.svg create mode 100644 members/taojiangcb/task1/tsconfig.app.json create mode 100644 members/taojiangcb/task1/tsconfig.json create mode 100644 members/taojiangcb/task1/tsconfig.node.json create mode 100644 members/taojiangcb/task1/vite.config.ts diff --git a/members/taojiangcb/task1/.gitignore b/members/taojiangcb/task1/.gitignore new file mode 100644 index 000000000..a547bf36d --- /dev/null +++ b/members/taojiangcb/task1/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/members/taojiangcb/task1/README.md b/members/taojiangcb/task1/README.md new file mode 100644 index 000000000..74872fd4a --- /dev/null +++ b/members/taojiangcb/task1/README.md @@ -0,0 +1,50 @@ +# React + TypeScript + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: + +- Configure the top-level `parserOptions` property like this: + +```js +export default tseslint.config({ + languageOptions: { + // other options... + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + }, +}) +``` + +- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked` +- Optionally add `...tseslint.configs.stylisticTypeChecked` +- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config: + +```js +// eslint.config.js +import react from 'eslint-plugin-react' + +export default tseslint.config({ + // Set the react version + settings: { react: { version: '18.3' } }, + plugins: { + // Add the react plugin + react, + }, + rules: { + // other rules... + // Enable its recommended rules + ...react.configs.recommended.rules, + ...react.configs['jsx-runtime'].rules, + }, +}) +``` diff --git a/members/taojiangcb/task1/eslint.config.js b/members/taojiangcb/task1/eslint.config.js new file mode 100644 index 000000000..092408a9f --- /dev/null +++ b/members/taojiangcb/task1/eslint.config.js @@ -0,0 +1,28 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' + +export default tseslint.config( + { ignores: ['dist'] }, + { + extends: [js.configs.recommended, ...tseslint.configs.recommended], + files: ['**/*.{ts,tsx}'], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + plugins: { + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, + }, + rules: { + ...reactHooks.configs.recommended.rules, + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, + }, +) diff --git a/members/taojiangcb/task1/index.html b/members/taojiangcb/task1/index.html new file mode 100644 index 000000000..e4b78eae1 --- /dev/null +++ b/members/taojiangcb/task1/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + React + TS + + +
+ + + diff --git a/members/taojiangcb/task1/package.json b/members/taojiangcb/task1/package.json new file mode 100644 index 000000000..be0af2724 --- /dev/null +++ b/members/taojiangcb/task1/package.json @@ -0,0 +1,33 @@ +{ + "name": "task1", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.0", + "@mui/icons-material": "^5.15.19", + "@mui/material": "^5.15.19", + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@eslint/js": "^9.15.0", + "@types/react": "^18.3.12", + "@types/react-dom": "^18.3.1", + "@vitejs/plugin-react": "^4.3.4", + "eslint": "^9.15.0", + "eslint-plugin-react-hooks": "^5.0.0", + "eslint-plugin-react-refresh": "^0.4.14", + "globals": "^15.12.0", + "typescript": "~5.6.2", + "typescript-eslint": "^8.15.0", + "vite": "^6.0.1" + } +} diff --git a/members/taojiangcb/task1/public/vite.svg b/members/taojiangcb/task1/public/vite.svg new file mode 100644 index 000000000..e7b8dfb1b --- /dev/null +++ b/members/taojiangcb/task1/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/members/taojiangcb/task1/tsconfig.app.json b/members/taojiangcb/task1/tsconfig.app.json new file mode 100644 index 000000000..358ca9ba9 --- /dev/null +++ b/members/taojiangcb/task1/tsconfig.app.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["src"] +} diff --git a/members/taojiangcb/task1/tsconfig.json b/members/taojiangcb/task1/tsconfig.json new file mode 100644 index 000000000..1ffef600d --- /dev/null +++ b/members/taojiangcb/task1/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/members/taojiangcb/task1/tsconfig.node.json b/members/taojiangcb/task1/tsconfig.node.json new file mode 100644 index 000000000..db0becc8b --- /dev/null +++ b/members/taojiangcb/task1/tsconfig.node.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2022", + "lib": ["ES2023"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/members/taojiangcb/task1/vite.config.ts b/members/taojiangcb/task1/vite.config.ts new file mode 100644 index 000000000..8b0f57b91 --- /dev/null +++ b/members/taojiangcb/task1/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react()], +}) From 19b1c7880e01957122d7814fb811b2c596f3a5b1 Mon Sep 17 00:00:00 2001 From: taojiang Date: Thu, 19 Dec 2024 18:28:29 +0800 Subject: [PATCH 3/3] task1: had been done --- members/taojiangcb/task1/package.json | 1 + members/taojiangcb/task1/src/AddToDo.tsx | 58 ++++++++++++----- members/taojiangcb/task1/src/App.tsx | 61 +++++------------- members/taojiangcb/task1/src/Header.tsx | 6 +- members/taojiangcb/task1/src/ToDoItem.tsx | 43 +++++++++++++ members/taojiangcb/task1/src/ToDoList.tsx | 54 +++++++++++++++- members/taojiangcb/task1/src/constants.ts | 2 - .../taojiangcb/task1/src/defined-object.ts | 5 -- members/taojiangcb/task1/src/index.css | 2 +- members/taojiangcb/task1/src/store.ts | 63 +++++++++++++++---- 10 files changed, 208 insertions(+), 87 deletions(-) create mode 100644 members/taojiangcb/task1/src/ToDoItem.tsx delete mode 100644 members/taojiangcb/task1/src/constants.ts delete mode 100644 members/taojiangcb/task1/src/defined-object.ts diff --git a/members/taojiangcb/task1/package.json b/members/taojiangcb/task1/package.json index be0af2724..7892a14c4 100644 --- a/members/taojiangcb/task1/package.json +++ b/members/taojiangcb/task1/package.json @@ -14,6 +14,7 @@ "@emotion/styled": "^11.14.0", "@mui/icons-material": "^5.15.19", "@mui/material": "^5.15.19", + "@mui/styles": "^6.2.1", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/members/taojiangcb/task1/src/AddToDo.tsx b/members/taojiangcb/task1/src/AddToDo.tsx index a2aba1ee1..02f284306 100644 --- a/members/taojiangcb/task1/src/AddToDo.tsx +++ b/members/taojiangcb/task1/src/AddToDo.tsx @@ -1,25 +1,51 @@ -import Paper from '@mui/material/Paper'; +import React, { useCallback, useState } from 'react'; +import { withStore, WithStoreChildProps } from './store'; +import { IconButton, Input } from '@mui/material'; +import AddCircleIcon from '@mui/icons-material/AddCircle'; -import { IconButton, InputBase } from '@mui/material'; -import { Search as SearchIcon } from '@mui/icons-material' -interface Props { +interface Props extends WithStoreChildProps { + defaultValue?: string; } +const AddToDo: React.FC = (props: Props) => { + const { store, ...reset } = props; + const [relValue, setRelValue] = useState(''); + + const onTextChange = useCallback((e: React.ChangeEvent) => { + setRelValue(e.target.value); + }, []); -const AddToDo: React.FC = (props) => { - return
- + const onAddTodo = useCallback(() => { + if (!relValue) return alert('请输入待办事项'); + const newData = { + id: Date.now().toString(), + text: relValue, + done: false + } + setRelValue(''); + store.setData([newData, ...store.data]); + }, [relValue]); + const handleKeyPress = (event: React.KeyboardEvent) => { + if (event.key === 'Enter') { + // 处理 Enter 键提交表单 + onAddTodo(); + } + }; - {/* + */} - - - - -
+ onChange={onTextChange} + value={relValue} + onKeyDown={handleKeyPress} // 监听键盘按下事件 + {...reset} + /> + + + + } -export default AddToDo; \ No newline at end of file +export default withStore(AddToDo); \ No newline at end of file diff --git a/members/taojiangcb/task1/src/App.tsx b/members/taojiangcb/task1/src/App.tsx index f05d3db86..992b46647 100644 --- a/members/taojiangcb/task1/src/App.tsx +++ b/members/taojiangcb/task1/src/App.tsx @@ -1,54 +1,25 @@ -import { useState, useEffect, useMemo } from 'react' +import React from 'react' import './App.css' import Header from './Header' -import { Todo } from './defined-object' -import TodoStore from './store'; +import TodoStore, { useCreateStore } from './store'; import AddToDo from './AddToDo'; -import { LOCAL_STORE_KEY } from './constants'; - +import ToDoList from './ToDoList'; +import { Card, CardContent, CardHeader } from '@mui/material'; function App() { - const [todos, setTodos] = useState(() => { - const json_str = localStorage.getItem(LOCAL_STORE_KEY); - const todos = JSON.parse(json_str || '[]'); - return todos; - }); - - const initStore = useMemo(() => { - function toSave(todos: Todo[]) { - localStorage.setItem(LOCAL_STORE_KEY, JSON.stringify(todos || [])); - } - - function setStore(todos: Todo[]) { - setTodos(todos) - toSave(todos); - } - - const addTodo = (todo: Todo) => { - setStore([...todos, todo]); - }; - - const deleteTodo = (id: string) => { - setStore(todos.filter((todo) => todo.id !== id)); - }; - - const changeTodo = (id: string, text: string) => { - setStore(todos.map((todo) => todo.id === id ? { ...todo, text } : todo)); - } - return { - todos, - addTodo, - deleteTodo, - changeTodo - } - }, [todos]); - + // 轻 store 初始化 + const store = useCreateStore(); return
-
- - -
-
+ + + +
+ + } /> + + + +
} diff --git a/members/taojiangcb/task1/src/Header.tsx b/members/taojiangcb/task1/src/Header.tsx index 6490c2013..58ea970cf 100644 --- a/members/taojiangcb/task1/src/Header.tsx +++ b/members/taojiangcb/task1/src/Header.tsx @@ -4,11 +4,7 @@ interface Props { } const Header = ({ title }: Props) => { - return ( -
-

{title}

-
- ) + return

{title}

} export default Header; \ No newline at end of file diff --git a/members/taojiangcb/task1/src/ToDoItem.tsx b/members/taojiangcb/task1/src/ToDoItem.tsx new file mode 100644 index 000000000..42216b92e --- /dev/null +++ b/members/taojiangcb/task1/src/ToDoItem.tsx @@ -0,0 +1,43 @@ +import { Todo } from "./store" +import { Checkbox, IconButton, ListItem, ListItemButton, ListItemIcon, ListItemText } from '@mui/material'; +import { DeleteOutlineOutlined } from '@mui/icons-material'; + +interface Props { + data: Todo, + onCheckChange: (todo: Todo, check: boolean) => void, + onDelete: (todo: Todo) => void +} + +const TodoItem = (props: Props) => { + const { data, onCheckChange } = props; + const handleToggle = () => { + onCheckChange && onCheckChange(data, !data.done) + }; + + const ui_del_btn = props.onDelete(data)} aria-label="comments"> + + + + return
+ + + + + + + + +
+} + +export default TodoItem \ No newline at end of file diff --git a/members/taojiangcb/task1/src/ToDoList.tsx b/members/taojiangcb/task1/src/ToDoList.tsx index 85bb68b81..b0ab0280c 100644 --- a/members/taojiangcb/task1/src/ToDoList.tsx +++ b/members/taojiangcb/task1/src/ToDoList.tsx @@ -1,4 +1,54 @@ +import { FC, useMemo } from 'react'; +import { Todo, withStore, WithStoreChildProps } from './store'; +import TodoItem from './ToDoItem'; +import { List, Theme } from '@mui/material'; +import { makeStyles } from '@mui/styles'; -interface Props { - children: React.ReactNode; +interface Props extends WithStoreChildProps { } + +const useStyles = makeStyles((theme: Theme) => { + return { + scrollContent: { + overflow: 'hidden', + overflowY: 'auto', + maxHeight: '300px', + backgroundColor: '#fafafa', + marginBottom: 10, + } + } +}); + +const ToDoList: FC = (props: Props) => { + const styles = useStyles(); + const { store } = props; + + const ui_item_controller = useMemo(() => { + const onCheckChange = (todo: Todo, check: boolean) => { + /** 懒的写替换方法了,先直接修改对象 */ + todo.done = check; + store.setData([...store.data]) + } + + const onDelete = (todo: Todo) => { + const res = confirm('确定删除?'); + if (res) { + const datas = store.data.filter(item => item.id !== todo.id); + store.setData(datas); + } + } + + const ans = []; + for (let i = 0; i < store.data.length; i++) { + ans.push() + } + return ans; + }, [store.data]) + + return
+ + {ui_item_controller} + +
} + +export default withStore(ToDoList); \ No newline at end of file diff --git a/members/taojiangcb/task1/src/constants.ts b/members/taojiangcb/task1/src/constants.ts deleted file mode 100644 index 8c6012018..000000000 --- a/members/taojiangcb/task1/src/constants.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const LOCAL_STORE_KEY = "tasks"; - diff --git a/members/taojiangcb/task1/src/defined-object.ts b/members/taojiangcb/task1/src/defined-object.ts deleted file mode 100644 index 369cb28b7..000000000 --- a/members/taojiangcb/task1/src/defined-object.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface Todo { - id: string; - text: string; - done: boolean; -} diff --git a/members/taojiangcb/task1/src/index.css b/members/taojiangcb/task1/src/index.css index 6119ad9a8..3135cd52b 100644 --- a/members/taojiangcb/task1/src/index.css +++ b/members/taojiangcb/task1/src/index.css @@ -54,7 +54,7 @@ button:focus-visible { outline: 4px auto -webkit-focus-ring-color; } -@media (prefers-color-scheme: light) { +@media (prefers-color-scheme: dark) { :root { color: #213547; background-color: #ffffff; diff --git a/members/taojiangcb/task1/src/store.ts b/members/taojiangcb/task1/src/store.ts index 7872d3cfd..0151498db 100644 --- a/members/taojiangcb/task1/src/store.ts +++ b/members/taojiangcb/task1/src/store.ts @@ -1,19 +1,60 @@ -import React from "react"; -import { Todo as Todo } from "./defined-object"; +import React, { PropsWithChildren, useContext, useMemo } from "react"; +const LOCAL_STORE_KEY = "todo-list"; +export interface Todo { + id: string; + text: string; + done: boolean; +} + +export type WithStoreChildProps = PropsWithChildren & { + store: ITodoStore +} + +export interface ITodoStore { + data: readonly Todo[], + setData: (data: Todo[]) => void +} + +/** + * 构建一个基本的 store 包括 data 和 setData 能力 + * @returns a store object with data and setData + */ +export const useCreateStore = (/** initialData */) => { + const [todos, setTodos] = React.useState(() => { + const json_str = localStorage.getItem(LOCAL_STORE_KEY); + const todos = JSON.parse(json_str || '[]'); + return todos; + }); + + const store = useMemo(() => { + function toSaveLocal(todos: Todo[]) { + localStorage.setItem(LOCAL_STORE_KEY, JSON.stringify(todos || [])); + } + + function setData(todos: Todo[]) { + setTodos(todos) // 更新数据 + toSaveLocal(todos); // 保存到本地 + } + + return { + data: Object.freeze(todos), // 冻结数据,只能通过 setData 更新数据 + setData + } + }, [todos]); + return store; +} -interface ITodoStore { - todos: Todo[]; - addTodo: (task: Todo) => void; - changeTodo: (id: string, text: string) => void; - deleteTodo: (id: string) => void; +export function withStore(Component: React.ComponentType) { + return function WithStore(props: any) { + const store = useContext(TodoStore); + return React.createElement(Component, { ...props, store }); + } } const TodoStore = React.createContext({ - todos: [], - addTodo: () => { }, - changeTodo: () => { }, - deleteTodo: () => { } + data: [], + setData: () => { } }) export default TodoStore \ No newline at end of file