瀏覽代碼

Initial commit

D8D 1 年之前
當前提交
add9be3277
共有 8 個文件被更改,包括 241 次插入0 次删除
  1. 21 0
      .gitignore
  2. 22 0
      package.json
  3. 26 0
      src/App.tsx
  4. 51 0
      src/components/AddProductForm.tsx
  5. 29 0
      src/components/ProductList.tsx
  6. 77 0
      src/index.css
  7. 10 0
      src/main.tsx
  8. 5 0
      src/types.ts

+ 21 - 0
.gitignore

@@ -0,0 +1,21 @@
+node_modules/
+.DS_Store
+*.log
+dist/
+build/
+coverage/
+.env
+.env.local
+.env.*.local
+.cache/
+.next/
+.nuxt/
+.vuepress/dist
+.serverless/
+.idea/
+.vscode/
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 22 - 0
package.json

@@ -0,0 +1,22 @@
+{
+  "name": "product-management-system",
+  "private": true,
+  "version": "0.0.0",
+  "type": "module",
+  "scripts": {
+    "dev": "vite",
+    "build": "tsc && vite build",
+    "preview": "vite preview"
+  },
+  "dependencies": {
+    "react": "^18.2.0",
+    "react-dom": "^18.2.0"
+  },
+  "devDependencies": {
+    "@types/react": "^18.0.28",
+    "@types/react-dom": "^18.0.11",
+    "@vitejs/plugin-react-swc": "^3.0.0",
+    "typescript": "^4.9.3",
+    "vite": "^4.2.0"
+  }
+}

+ 26 - 0
src/App.tsx

@@ -0,0 +1,26 @@
+import React, { useState } from 'react';
+import ProductList from './components/ProductList';
+import AddProductForm from './components/AddProductForm';
+import { Product } from './types';
+
+const App: React.FC = () => {
+  const [products, setProducts] = useState<Product[]>([]);
+
+  const addProduct = (product: Product) => {
+    setProducts([...products, { ...product, id: Date.now() }]);
+  };
+
+  const deleteProduct = (id: number) => {
+    setProducts(products.filter(product => product.id !== id));
+  };
+
+  return (
+    <div className="container">
+      <h1>Product Management System</h1>
+      <AddProductForm onAddProduct={addProduct} />
+      <ProductList products={products} onDeleteProduct={deleteProduct} />
+    </div>
+  );
+};
+
+export default App;

+ 51 - 0
src/components/AddProductForm.tsx

@@ -0,0 +1,51 @@
+import React, { useState } from 'react';
+import { Product } from '../types';
+
+interface AddProductFormProps {
+  onAddProduct: (product: Product) => void;
+}
+
+const AddProductForm: React.FC<AddProductFormProps> = ({ onAddProduct }) => {
+  const [name, setName] = useState('');
+  const [price, setPrice] = useState('');
+
+  const handleSubmit = (e: React.FormEvent) => {
+    e.preventDefault();
+    if (name && price) {
+      onAddProduct({ name, price: parseFloat(price), id: 0 });
+      setName('');
+      setPrice('');
+    }
+  };
+
+  return (
+    <form onSubmit={handleSubmit}>
+      <h2>Add New Product</h2>
+      <div>
+        <label htmlFor="name">Name:</label>
+        <input
+          type="text"
+          id="name"
+          value={name}
+          onChange={(e) => setName(e.target.value)}
+          required
+        />
+      </div>
+      <div>
+        <label htmlFor="price">Price:</label>
+        <input
+          type="number"
+          id="price"
+          value={price}
+          onChange={(e) => setPrice(e.target.value)}
+          min="0"
+          step="0.01"
+          required
+        />
+      </div>
+      <button type="submit">Add Product</button>
+    </form>
+  );
+};
+
+export default AddProductForm;

+ 29 - 0
src/components/ProductList.tsx

@@ -0,0 +1,29 @@
+import React from 'react';
+import { Product } from '../types';
+
+interface ProductListProps {
+  products: Product[];
+  onDeleteProduct: (id: number) => void;
+}
+
+const ProductList: React.FC<ProductListProps> = ({ products, onDeleteProduct }) => {
+  return (
+    <div className="product-list">
+      <h2>Product List</h2>
+      {products.length === 0 ? (
+        <p>No products available.</p>
+      ) : (
+        <ul>
+          {products.map((product) => (
+            <li key={product.id}>
+              {product.name} - ${product.price}
+              <button onClick={() => onDeleteProduct(product.id)}>Delete</button>
+            </li>
+          ))}
+        </ul>
+      )}
+    </div>
+  );
+};
+
+export default ProductList;

+ 77 - 0
src/index.css

@@ -0,0 +1,77 @@
+body {
+  font-family: Arial, sans-serif;
+  margin: 0;
+  padding: 0;
+  background-color: #f0f0f0;
+}
+
+.container {
+  max-width: 800px;
+  margin: 0 auto;
+  padding: 20px;
+}
+
+h1, h2 {
+  color: #333;
+}
+
+form {
+  background-color: #fff;
+  padding: 20px;
+  border-radius: 5px;
+  margin-bottom: 20px;
+}
+
+form div {
+  margin-bottom: 10px;
+}
+
+label {
+  display: inline-block;
+  width: 60px;
+}
+
+input {
+  width: 200px;
+  padding: 5px;
+}
+
+button {
+  background-color: #4CAF50;
+  color: white;
+  padding: 10px 15px;
+  border: none;
+  border-radius: 4px;
+  cursor: pointer;
+}
+
+button:hover {
+  background-color: #45a049;
+}
+
+.product-list {
+  background-color: #fff;
+  padding: 20px;
+  border-radius: 5px;
+}
+
+ul {
+  list-style-type: none;
+  padding: 0;
+}
+
+li {
+  margin-bottom: 10px;
+  padding: 10px;
+  background-color: #f9f9f9;
+  border-radius: 4px;
+}
+
+li button {
+  margin-left: 10px;
+  background-color: #f44336;
+}
+
+li button:hover {
+  background-color: #d32f2f;
+}

+ 10 - 0
src/main.tsx

@@ -0,0 +1,10 @@
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import App from './App'
+import './index.css'
+
+ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
+  <React.StrictMode>
+    <App />
+  </React.StrictMode>,
+)

+ 5 - 0
src/types.ts

@@ -0,0 +1,5 @@
+export interface Product {
+  id: number;
+  name: string;
+  price: number;
+}