akarshanxyz 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/a1/array +3 -0
- package/a1/functions +5 -0
- package/a1/interfaceDatabase +19 -0
- package/a1/interfaceObject +18 -0
- package/a2/TypeSpeedApp +32 -0
- package/a2/showHidePass +18 -0
- package/a2/ticTacToe +77 -0
- package/a3/FoodRating +108 -0
- package/a3/ShopApp +73 -0
- package/a4/contextApi +59 -0
- package/a4/reactRouter +81 -0
- package/a4/useReducer +129 -0
- package/a5/E-commerce +148 -0
- package/a5/onlineFoodOrder +68 -0
- package/a6/ControlFormrealTimeVali&UIupdate +55 -0
- package/a6/UncontrolledForm(useRef)Avoidre-renderssimple data +35 -0
- package/a6/login+backendErrorHandling +79 -0
- package/a6/userRegisterForm(ReactHook+Typrescript) +103 -0
- package/akarshan2.0-1.0.0.tgz +0 -0
- package/package.json +4 -0
package/a1/array
ADDED
package/a1/functions
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
interface Database {
|
|
2
|
+
connect(): void;
|
|
3
|
+
disconnect(): void;
|
|
4
|
+
query(sql: string): any;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
class MyDatabase implements Database {
|
|
8
|
+
connect(): void {
|
|
9
|
+
console.log("Connected");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
disconnect(): void {
|
|
13
|
+
console.log("Disconnected");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
query(sql: string): any {
|
|
17
|
+
return `Executing: ${sql}`;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface Product {
|
|
2
|
+
id: number;
|
|
3
|
+
name: string;
|
|
4
|
+
price: number;
|
|
5
|
+
inStock: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function getInStockProducts(products: Product[]): Product[] {
|
|
9
|
+
return products.filter(p => p.inStock);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const products: Product[] = [
|
|
13
|
+
{ id: 1, name: "Laptop", price: 1000, inStock: true },
|
|
14
|
+
{ id: 2, name: "Phone", price: 500, inStock: false },
|
|
15
|
+
{ id: 3, name: "Tablet", price: 300, inStock: true }
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
console.log(getInStockProducts(products));
|
package/a2/TypeSpeedApp
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const input = document.createElement("input");
|
|
2
|
+
const timerDisplay = document.createElement("div");
|
|
3
|
+
const wpmDisplay = document.createElement("div");
|
|
4
|
+
const startButton = document.createElement("button");
|
|
5
|
+
|
|
6
|
+
input.type = "text";
|
|
7
|
+
input.placeholder = "Start typing...";
|
|
8
|
+
timerDisplay.textContent = "Time: 0";
|
|
9
|
+
wpmDisplay.textContent = "WPM: 0";
|
|
10
|
+
startButton.textContent = "Start";
|
|
11
|
+
|
|
12
|
+
let startTime = 0;
|
|
13
|
+
let timer: number;
|
|
14
|
+
|
|
15
|
+
startButton.addEventListener("click", () => {
|
|
16
|
+
input.value = "";
|
|
17
|
+
startTime = Date.now();
|
|
18
|
+
|
|
19
|
+
clearInterval(timer);
|
|
20
|
+
timer = setInterval(() => {
|
|
21
|
+
const elapsed = Math.floor((Date.now() - startTime) / 1000);
|
|
22
|
+
timerDisplay.textContent = `Time: ${elapsed}`;
|
|
23
|
+
|
|
24
|
+
const words = input.value.trim().split(/\s+/).filter(Boolean).length;
|
|
25
|
+
const minutes = elapsed / 60;
|
|
26
|
+
const wpm = minutes > 0 ? Math.round(words / minutes) : 0;
|
|
27
|
+
|
|
28
|
+
wpmDisplay.textContent = `WPM: ${wpm}`;
|
|
29
|
+
}, 1000);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
document.body.append(input, startButton, timerDisplay, wpmDisplay);
|
package/a2/showHidePass
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const passwordInput = document.createElement("input");
|
|
2
|
+
passwordInput.type = "password";
|
|
3
|
+
|
|
4
|
+
const toggleButton = document.createElement("button");
|
|
5
|
+
toggleButton.textContent = "Show";
|
|
6
|
+
|
|
7
|
+
toggleButton.addEventListener("click", () => {
|
|
8
|
+
if (passwordInput.type === "password") {
|
|
9
|
+
passwordInput.type = "text";
|
|
10
|
+
toggleButton.textContent = "Hide";
|
|
11
|
+
} else {
|
|
12
|
+
passwordInput.type = "password";
|
|
13
|
+
toggleButton.textContent = "Show";
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
document.body.appendChild(passwordInput);
|
|
18
|
+
document.body.appendChild(toggleButton);
|
package/a2/ticTacToe
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const board = document.createElement("div");
|
|
2
|
+
const result = document.createElement("div");
|
|
3
|
+
const resetBtn = document.createElement("button");
|
|
4
|
+
|
|
5
|
+
board.style.display = "grid";
|
|
6
|
+
board.style.gridTemplateColumns = "repeat(3, 100px)";
|
|
7
|
+
board.style.gap = "5px";
|
|
8
|
+
|
|
9
|
+
resetBtn.textContent = "Reset";
|
|
10
|
+
result.textContent = "Current Player: X";
|
|
11
|
+
|
|
12
|
+
let currentPlayer: "X" | "O" = "X";
|
|
13
|
+
let cells: HTMLButtonElement[] = [];
|
|
14
|
+
|
|
15
|
+
const winPatterns = [
|
|
16
|
+
[0,1,2],[3,4,5],[6,7,8],
|
|
17
|
+
[0,3,6],[1,4,7],[2,5,8],
|
|
18
|
+
[0,4,8],[2,4,6]
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
function checkWinner(): string | null {
|
|
22
|
+
for (const [a,b,c] of winPatterns) {
|
|
23
|
+
if (
|
|
24
|
+
cells[a].textContent &&
|
|
25
|
+
cells[a].textContent === cells[b].textContent &&
|
|
26
|
+
cells[a].textContent === cells[c].textContent
|
|
27
|
+
) {
|
|
28
|
+
return cells[a].textContent;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function handleClick(e: MouseEvent) {
|
|
35
|
+
const btn = e.target as HTMLButtonElement;
|
|
36
|
+
if (btn.textContent) return;
|
|
37
|
+
|
|
38
|
+
btn.textContent = currentPlayer;
|
|
39
|
+
const winner = checkWinner();
|
|
40
|
+
|
|
41
|
+
if (winner) {
|
|
42
|
+
result.textContent = `Winner: ${winner}`;
|
|
43
|
+
cells.forEach(c => c.disabled = true);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (cells.every(c => c.textContent)) {
|
|
48
|
+
result.textContent = "Draw";
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
currentPlayer = currentPlayer === "X" ? "O" : "X";
|
|
53
|
+
result.textContent = `Current Player: ${currentPlayer}`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function createBoard() {
|
|
57
|
+
board.innerHTML = "";
|
|
58
|
+
cells = [];
|
|
59
|
+
|
|
60
|
+
for (let i = 0; i < 9; i++) {
|
|
61
|
+
const btn = document.createElement("button");
|
|
62
|
+
btn.style.height = "100px";
|
|
63
|
+
btn.style.fontSize = "24px";
|
|
64
|
+
btn.addEventListener("click", handleClick);
|
|
65
|
+
cells.push(btn);
|
|
66
|
+
board.appendChild(btn);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
resetBtn.addEventListener("click", () => {
|
|
71
|
+
currentPlayer = "X";
|
|
72
|
+
result.textContent = "Current Player: X";
|
|
73
|
+
createBoard();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
createBoard();
|
|
77
|
+
document.body.append(board, result, resetBtn);
|
package/a3/FoodRating
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
|
|
3
|
+
interface FoodItem {
|
|
4
|
+
id: number;
|
|
5
|
+
name: string;
|
|
6
|
+
rating: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
type Filter = "all" | "high" | "low" | "unrated";
|
|
10
|
+
|
|
11
|
+
const App: React.FC = () => {
|
|
12
|
+
const [foods, setFoods] = useState<FoodItem[]>([
|
|
13
|
+
{ id: 1, name: "Pizza", rating: 0 },
|
|
14
|
+
{ id: 2, name: "Burger", rating: 0 },
|
|
15
|
+
{ id: 3, name: "Taco", rating: 0 },
|
|
16
|
+
{ id: 4, name: "Salad", rating: 0 }
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
const [filter, setFilter] = useState<Filter>("all");
|
|
20
|
+
|
|
21
|
+
const updateRating = (id: number, rating: number) => {
|
|
22
|
+
setFoods(prev =>
|
|
23
|
+
prev.map(f => (f.id === id ? { ...f, rating } : f))
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const filteredFoods = foods.filter(f => {
|
|
28
|
+
if (filter === "high") return f.rating >= 4;
|
|
29
|
+
if (filter === "low") return f.rating < 3;
|
|
30
|
+
if (filter === "unrated") return f.rating === 0;
|
|
31
|
+
return true;
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const ratings = foods.map(f => f.rating);
|
|
35
|
+
const hasRatings = ratings.some(r => r > 0);
|
|
36
|
+
|
|
37
|
+
const avg =
|
|
38
|
+
ratings.reduce((a, b) => a + b, 0) / foods.length || 0;
|
|
39
|
+
|
|
40
|
+
const highest = foods.reduce((a, b) =>
|
|
41
|
+
a.rating >= b.rating ? a : b
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const lowest = foods.reduce((a, b) =>
|
|
45
|
+
a.rating <= b.rating ? a : b
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const highCount = foods.filter(f => f.rating >= 4).length;
|
|
49
|
+
|
|
50
|
+
const resetRatings = () => {
|
|
51
|
+
setFoods(prev => prev.map(f => ({ ...f, rating: 0 })));
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<div style={{ padding: 20 }}>
|
|
56
|
+
<h2>Food Rating App</h2>
|
|
57
|
+
|
|
58
|
+
<div>
|
|
59
|
+
<button onClick={() => setFilter("all")}>Show All</button>
|
|
60
|
+
<button onClick={() => setFilter("high")}>
|
|
61
|
+
High Rated (4+)
|
|
62
|
+
</button>
|
|
63
|
+
<button onClick={() => setFilter("low")}>
|
|
64
|
+
Low Rated (< 3)
|
|
65
|
+
</button>
|
|
66
|
+
<button onClick={() => setFilter("unrated")}>
|
|
67
|
+
Unrated (0)
|
|
68
|
+
</button>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<div>
|
|
72
|
+
{filteredFoods.map(food => (
|
|
73
|
+
<div key={food.id} style={{ margin: "10px 0" }}>
|
|
74
|
+
<span>
|
|
75
|
+
{food.name} - {food.rating}
|
|
76
|
+
</span>
|
|
77
|
+
<div>
|
|
78
|
+
{[1, 2, 3, 4, 5].map(star => (
|
|
79
|
+
<button
|
|
80
|
+
key={star}
|
|
81
|
+
onClick={() => updateRating(food.id, star)}
|
|
82
|
+
>
|
|
83
|
+
{star}
|
|
84
|
+
</button>
|
|
85
|
+
))}
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
))}
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
<h3>Statistics</h3>
|
|
92
|
+
{!hasRatings ? (
|
|
93
|
+
<p>No ratings available</p>
|
|
94
|
+
) : (
|
|
95
|
+
<div>
|
|
96
|
+
<p>Average Rating: {avg.toFixed(2)}</p>
|
|
97
|
+
<p>Highest Rated: {highest.name}</p>
|
|
98
|
+
<p>Lowest Rated: {lowest.name}</p>
|
|
99
|
+
<p>Foods with rating >= 4: {highCount}</p>
|
|
100
|
+
</div>
|
|
101
|
+
)}
|
|
102
|
+
|
|
103
|
+
<button onClick={resetRatings}>Reset All Ratings</button>
|
|
104
|
+
</div>
|
|
105
|
+
);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export default App;
|
package/a3/ShopApp
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
|
|
3
|
+
interface Product {
|
|
4
|
+
id: number;
|
|
5
|
+
name: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface ProductItemProps {
|
|
9
|
+
product: Product;
|
|
10
|
+
onDelete: (id: number) => void;
|
|
11
|
+
onAddToCart: (product: Product) => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const ProductItem: React.FC<ProductItemProps> = ({
|
|
15
|
+
product,
|
|
16
|
+
onDelete,
|
|
17
|
+
onAddToCart
|
|
18
|
+
}) => {
|
|
19
|
+
const handleView = () => {
|
|
20
|
+
alert(product.name);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<div style={{ margin: "10px 0" }}>
|
|
25
|
+
<span>{product.name}</span>
|
|
26
|
+
<button onClick={handleView}>View</button>
|
|
27
|
+
<button onClick={() => onDelete(product.id)}>Delete</button>
|
|
28
|
+
<button onClick={() => onAddToCart(product)}>Add to Cart</button>
|
|
29
|
+
</div>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const App: React.FC = () => {
|
|
34
|
+
const [products, setProducts] = useState<Product[]>([
|
|
35
|
+
{ id: 1, name: "Phone" },
|
|
36
|
+
{ id: 2, name: "Laptop" },
|
|
37
|
+
{ id: 3, name: "Headphones" }
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
const [cart, setCart] = useState<Product[]>([]);
|
|
41
|
+
|
|
42
|
+
const handleDelete = (id: number) => {
|
|
43
|
+
setProducts(prev => prev.filter(p => p.id !== id));
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const handleAddToCart = (product: Product) => {
|
|
47
|
+
setCart(prev => [...prev, product]);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<div style={{ padding: 20 }}>
|
|
52
|
+
<h2>Products</h2>
|
|
53
|
+
|
|
54
|
+
{products.map(product => (
|
|
55
|
+
<ProductItem
|
|
56
|
+
key={product.id}
|
|
57
|
+
product={product}
|
|
58
|
+
onDelete={handleDelete}
|
|
59
|
+
onAddToCart={handleAddToCart}
|
|
60
|
+
/>
|
|
61
|
+
))}
|
|
62
|
+
|
|
63
|
+
<h2>Cart</h2>
|
|
64
|
+
{cart.length === 0 ? (
|
|
65
|
+
<p>No items in cart</p>
|
|
66
|
+
) : (
|
|
67
|
+
cart.map(item => <div key={item.id}>{item.name}</div>)
|
|
68
|
+
)}
|
|
69
|
+
</div>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default App;
|
package/a4/contextApi
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React, { createContext, useContext, useState } from "react";
|
|
2
|
+
|
|
3
|
+
interface CounterContextType {
|
|
4
|
+
count: number;
|
|
5
|
+
step: number;
|
|
6
|
+
increment: () => void;
|
|
7
|
+
decrement: () => void;
|
|
8
|
+
reset: () => void;
|
|
9
|
+
setStep: (value: number) => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const CounterContext = createContext<CounterContextType | null>(null);
|
|
13
|
+
|
|
14
|
+
const Controls: React.FC = () => {
|
|
15
|
+
const ctx = useContext(CounterContext)!;
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<div>
|
|
19
|
+
<button onClick={ctx.increment}>Increment</button>
|
|
20
|
+
<button onClick={ctx.decrement}>Decrement</button>
|
|
21
|
+
<button onClick={ctx.reset}>Reset</button>
|
|
22
|
+
<div>
|
|
23
|
+
<button onClick={() => ctx.setStep(1)}>Step +1</button>
|
|
24
|
+
<button onClick={() => ctx.setStep(5)}>Step +5</button>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const Display: React.FC = () => {
|
|
31
|
+
const ctx = useContext(CounterContext)!;
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<div>
|
|
35
|
+
<h2>Count: {ctx.count}</h2>
|
|
36
|
+
<h3>Current Step: {ctx.step}</h3>
|
|
37
|
+
<Controls />
|
|
38
|
+
</div>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const App: React.FC = () => {
|
|
43
|
+
const [count, setCount] = useState(0);
|
|
44
|
+
const [step, setStep] = useState(1);
|
|
45
|
+
|
|
46
|
+
const increment = () => setCount(c => c + step);
|
|
47
|
+
const decrement = () => setCount(c => c - step);
|
|
48
|
+
const reset = () => setCount(0);
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<CounterContext.Provider
|
|
52
|
+
value={{ count, step, increment, decrement, reset, setStep }}
|
|
53
|
+
>
|
|
54
|
+
<Display />
|
|
55
|
+
</CounterContext.Provider>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export default App;
|
package/a4/reactRouter
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
BrowserRouter,
|
|
4
|
+
Routes,
|
|
5
|
+
Route,
|
|
6
|
+
NavLink,
|
|
7
|
+
useNavigate
|
|
8
|
+
} from "react-router-dom";
|
|
9
|
+
|
|
10
|
+
const Navbar: React.FC = () => {
|
|
11
|
+
const activeStyle = ({ isActive }: { isActive: boolean }) => ({
|
|
12
|
+
marginRight: "10px",
|
|
13
|
+
fontWeight: isActive ? "bold" : "normal",
|
|
14
|
+
color: isActive ? "red" : "black"
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<nav>
|
|
19
|
+
<NavLink to="/" style={activeStyle}>Home</NavLink>
|
|
20
|
+
<NavLink to="/about" style={activeStyle}>About</NavLink>
|
|
21
|
+
<NavLink to="/contact" style={activeStyle}>Contact</NavLink>
|
|
22
|
+
</nav>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const Home: React.FC = () => {
|
|
27
|
+
const navigate = useNavigate();
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div>
|
|
31
|
+
<h2>Home</h2>
|
|
32
|
+
<button onClick={() => navigate("/contact")}>
|
|
33
|
+
Go to Contact
|
|
34
|
+
</button>
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const About: React.FC = () => {
|
|
40
|
+
return <h2>About</h2>;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const Contact: React.FC = () => {
|
|
44
|
+
const navigate = useNavigate();
|
|
45
|
+
const [name, setName] = React.useState("");
|
|
46
|
+
|
|
47
|
+
const handleSubmit = (e: React.FormEvent) => {
|
|
48
|
+
e.preventDefault();
|
|
49
|
+
alert("Form Submitted");
|
|
50
|
+
navigate("/");
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<div>
|
|
55
|
+
<h2>Contact</h2>
|
|
56
|
+
<form onSubmit={handleSubmit}>
|
|
57
|
+
<input
|
|
58
|
+
value={name}
|
|
59
|
+
onChange={e => setName(e.target.value)}
|
|
60
|
+
placeholder="Enter name"
|
|
61
|
+
/>
|
|
62
|
+
<button type="submit">Submit</button>
|
|
63
|
+
</form>
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const App: React.FC = () => {
|
|
69
|
+
return (
|
|
70
|
+
<BrowserRouter>
|
|
71
|
+
<Navbar />
|
|
72
|
+
<Routes>
|
|
73
|
+
<Route path="/" element={<Home />} />
|
|
74
|
+
<Route path="/about" element={<About />} />
|
|
75
|
+
<Route path="/contact" element={<Contact />} />
|
|
76
|
+
</Routes>
|
|
77
|
+
</BrowserRouter>
|
|
78
|
+
);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export default App;
|
package/a4/useReducer
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import React, { useReducer, useState } from "react";
|
|
2
|
+
|
|
3
|
+
interface Student {
|
|
4
|
+
id: number;
|
|
5
|
+
name: string;
|
|
6
|
+
score: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface State {
|
|
10
|
+
students: Student[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
type Action =
|
|
14
|
+
| { type: "ADD_STUDENT"; payload: string }
|
|
15
|
+
| { type: "INCREMENT_SCORE"; payload: number }
|
|
16
|
+
| { type: "DECREMENT_SCORE"; payload: number }
|
|
17
|
+
| { type: "RESET_SCORE"; payload: number };
|
|
18
|
+
|
|
19
|
+
const reducer = (state: State, action: Action): State => {
|
|
20
|
+
switch (action.type) {
|
|
21
|
+
case "ADD_STUDENT":
|
|
22
|
+
if (!action.payload.trim()) return state;
|
|
23
|
+
return {
|
|
24
|
+
students: [
|
|
25
|
+
...state.students,
|
|
26
|
+
{
|
|
27
|
+
id: Date.now(),
|
|
28
|
+
name: action.payload,
|
|
29
|
+
score: 0
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
case "INCREMENT_SCORE":
|
|
35
|
+
return {
|
|
36
|
+
students: state.students.map(s =>
|
|
37
|
+
s.id === action.payload ? { ...s, score: s.score + 1 } : s
|
|
38
|
+
)
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
case "DECREMENT_SCORE":
|
|
42
|
+
return {
|
|
43
|
+
students: state.students.map(s =>
|
|
44
|
+
s.id === action.payload ? { ...s, score: s.score - 1 } : s
|
|
45
|
+
)
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
case "RESET_SCORE":
|
|
49
|
+
return {
|
|
50
|
+
students: state.students.map(s =>
|
|
51
|
+
s.id === action.payload ? { ...s, score: 0 } : s
|
|
52
|
+
)
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
default:
|
|
56
|
+
return state;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const App: React.FC = () => {
|
|
61
|
+
const [state, dispatch] = useReducer(reducer, { students: [] });
|
|
62
|
+
const [name, setName] = useState("");
|
|
63
|
+
|
|
64
|
+
const topStudent =
|
|
65
|
+
state.students.length > 0
|
|
66
|
+
? state.students.reduce((a, b) => (a.score >= b.score ? a : b))
|
|
67
|
+
: null;
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<div style={{ padding: 20 }}>
|
|
71
|
+
<h2>Student Scores</h2>
|
|
72
|
+
|
|
73
|
+
<input
|
|
74
|
+
value={name}
|
|
75
|
+
onChange={e => setName(e.target.value)}
|
|
76
|
+
placeholder="Enter student name"
|
|
77
|
+
/>
|
|
78
|
+
<button
|
|
79
|
+
onClick={() => {
|
|
80
|
+
dispatch({ type: "ADD_STUDENT", payload: name });
|
|
81
|
+
setName("");
|
|
82
|
+
}}
|
|
83
|
+
>
|
|
84
|
+
Add Student
|
|
85
|
+
</button>
|
|
86
|
+
|
|
87
|
+
<div>
|
|
88
|
+
{state.students.map(student => (
|
|
89
|
+
<div key={student.id} style={{ margin: "10px 0" }}>
|
|
90
|
+
<span>
|
|
91
|
+
{student.name} - {student.score}
|
|
92
|
+
</span>
|
|
93
|
+
<div>
|
|
94
|
+
<button
|
|
95
|
+
onClick={() =>
|
|
96
|
+
dispatch({ type: "INCREMENT_SCORE", payload: student.id })
|
|
97
|
+
}
|
|
98
|
+
>
|
|
99
|
+
Increase
|
|
100
|
+
</button>
|
|
101
|
+
<button
|
|
102
|
+
onClick={() =>
|
|
103
|
+
dispatch({ type: "DECREMENT_SCORE", payload: student.id })
|
|
104
|
+
}
|
|
105
|
+
>
|
|
106
|
+
Decrease
|
|
107
|
+
</button>
|
|
108
|
+
<button
|
|
109
|
+
onClick={() =>
|
|
110
|
+
dispatch({ type: "RESET_SCORE", payload: student.id })
|
|
111
|
+
}
|
|
112
|
+
>
|
|
113
|
+
Reset
|
|
114
|
+
</button>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
))}
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
<h3>
|
|
121
|
+
{topStudent
|
|
122
|
+
? `Top Student: ${topStudent.name}`
|
|
123
|
+
: "No students available"}
|
|
124
|
+
</h3>
|
|
125
|
+
</div>
|
|
126
|
+
);
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export default App;
|
package/a5/E-commerce
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
interface Product<T = string> {
|
|
2
|
+
id: T;
|
|
3
|
+
name: string;
|
|
4
|
+
basePrice: number;
|
|
5
|
+
category: string;
|
|
6
|
+
getDiscountedPrice(discount: number): number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface PaymentMethod {
|
|
10
|
+
processPayment(amount: number): Promise<boolean>;
|
|
11
|
+
validatePayment(): boolean;
|
|
12
|
+
getTransactionId(): string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
class BaseProduct implements Product<string> {
|
|
16
|
+
constructor(
|
|
17
|
+
public id: string,
|
|
18
|
+
public name: string,
|
|
19
|
+
public basePrice: number,
|
|
20
|
+
public category: string
|
|
21
|
+
) {}
|
|
22
|
+
|
|
23
|
+
getDiscountedPrice(discount: number): number {
|
|
24
|
+
return this.basePrice - (this.basePrice * discount) / 100;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
class ElectronicsProduct extends BaseProduct {
|
|
29
|
+
getDiscountedPrice(discount: number): number {
|
|
30
|
+
const maxDiscount = Math.min(discount, 20);
|
|
31
|
+
const extra = this.basePrice > 1000 ? 5 : 0;
|
|
32
|
+
const finalDiscount = maxDiscount + extra;
|
|
33
|
+
return this.basePrice - (this.basePrice * finalDiscount) / 100;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
class ClothingProduct extends BaseProduct {
|
|
38
|
+
getDiscountedPrice(discount: number): number {
|
|
39
|
+
const maxDiscount = Math.min(discount, 30);
|
|
40
|
+
const extra = this.category === "premium" ? 10 : 0;
|
|
41
|
+
const finalDiscount = maxDiscount + extra;
|
|
42
|
+
return this.basePrice - (this.basePrice * finalDiscount) / 100;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
class Inventory<T extends { id: string }> {
|
|
47
|
+
private items: T[] = [];
|
|
48
|
+
|
|
49
|
+
addItem(item: T): void {
|
|
50
|
+
this.items.push(item);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
removeItem(id: string): boolean {
|
|
54
|
+
const index = this.items.findIndex(i => i.id === id);
|
|
55
|
+
if (index !== -1) {
|
|
56
|
+
this.items.splice(index, 1);
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
findById(id: string): T | undefined {
|
|
63
|
+
return this.items.find(i => i.id === id);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
getAllItems(): T[] {
|
|
67
|
+
return this.items;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
class CreditCardPayment implements PaymentMethod {
|
|
72
|
+
private transactionId: string = "";
|
|
73
|
+
|
|
74
|
+
validatePayment(): boolean {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async processPayment(amount: number): Promise<boolean> {
|
|
79
|
+
if (!this.validatePayment()) return false;
|
|
80
|
+
this.transactionId = "CC-" + Date.now();
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
getTransactionId(): string {
|
|
85
|
+
return this.transactionId;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
class PayPalPayment implements PaymentMethod {
|
|
90
|
+
private transactionId: string = "";
|
|
91
|
+
|
|
92
|
+
validatePayment(): boolean {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async processPayment(amount: number): Promise<boolean> {
|
|
97
|
+
if (!this.validatePayment()) return false;
|
|
98
|
+
this.transactionId = "PP-" + Date.now();
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
getTransactionId(): string {
|
|
103
|
+
return this.transactionId;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
class Order {
|
|
108
|
+
private items: { product: Product; quantity: number }[] = [];
|
|
109
|
+
|
|
110
|
+
constructor(private payment: PaymentMethod) {}
|
|
111
|
+
|
|
112
|
+
addProduct(product: Product, quantity: number): void {
|
|
113
|
+
this.items.push({ product, quantity });
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
calculateSubtotal(): number {
|
|
117
|
+
return this.items.reduce(
|
|
118
|
+
(sum, item) =>
|
|
119
|
+
sum + item.product.getDiscountedPrice(10) * item.quantity,
|
|
120
|
+
0
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async checkout(): Promise<{ success: boolean; transactionId: string }> {
|
|
125
|
+
const total = this.calculateSubtotal();
|
|
126
|
+
const success = await this.payment.processPayment(total);
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
success,
|
|
130
|
+
transactionId: success ? this.payment.getTransactionId() : ""
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const p1 = new ElectronicsProduct("1", "Laptop", 1200, "electronics");
|
|
136
|
+
const p2 = new ClothingProduct("2", "Jacket", 200, "premium");
|
|
137
|
+
|
|
138
|
+
const inventory = new Inventory<BaseProduct>();
|
|
139
|
+
inventory.addItem(p1);
|
|
140
|
+
inventory.addItem(p2);
|
|
141
|
+
|
|
142
|
+
const payment = new CreditCardPayment();
|
|
143
|
+
const order = new Order(payment);
|
|
144
|
+
|
|
145
|
+
order.addProduct(p1, 1);
|
|
146
|
+
order.addProduct(p2, 2);
|
|
147
|
+
|
|
148
|
+
order.checkout().then(res => console.log(res));
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
class Order {
|
|
2
|
+
public customerName: string;
|
|
3
|
+
private orderId: string;
|
|
4
|
+
private amount: number;
|
|
5
|
+
private isDelivered: boolean;
|
|
6
|
+
|
|
7
|
+
constructor(customerName: string, orderId: string, amount: number) {
|
|
8
|
+
this.customerName = customerName;
|
|
9
|
+
this.orderId = orderId;
|
|
10
|
+
this.amount = amount;
|
|
11
|
+
this.isDelivered = false;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
getOrderId(): string {
|
|
15
|
+
return this.orderId;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
getAmount(): number {
|
|
19
|
+
return this.amount;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getDeliveryStatus(): boolean {
|
|
23
|
+
return this.isDelivered;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
addAmount(value: number): void;
|
|
27
|
+
addAmount(value: number, note: string): void;
|
|
28
|
+
addAmount(value: number, note?: string): void {
|
|
29
|
+
this.amount += value;
|
|
30
|
+
if (note) console.log(note);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
markAsDelivered(): void {
|
|
34
|
+
this.isDelivered = true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
applyDiscount(percent: number): void {
|
|
38
|
+
this.amount -= (this.amount * percent) / 100;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
toString(): string {
|
|
42
|
+
return `Order[name=${this.customerName}, id=${this.orderId}, amount=${this.amount}, delivered=${this.isDelivered}]`;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const o1 = new Order("Riya", "101", 500);
|
|
47
|
+
const o2 = new Order("Aman", "102", 300);
|
|
48
|
+
const o3 = new Order("Neha", "103", 700);
|
|
49
|
+
|
|
50
|
+
o1.addAmount(100);
|
|
51
|
+
o2.addAmount(50, "Extra item added");
|
|
52
|
+
o3.addAmount(200);
|
|
53
|
+
|
|
54
|
+
o1.applyDiscount(10);
|
|
55
|
+
o2.markAsDelivered();
|
|
56
|
+
|
|
57
|
+
const orders = [o1, o2, o3];
|
|
58
|
+
|
|
59
|
+
orders.forEach(o => console.log(o.toString()));
|
|
60
|
+
|
|
61
|
+
const highest = orders.reduce((a, b) =>
|
|
62
|
+
a.getAmount() >= b.getAmount() ? a : b
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const deliveredCount = orders.filter(o => o.getDeliveryStatus()).length;
|
|
66
|
+
|
|
67
|
+
console.log("Highest Amount Order:", highest.toString());
|
|
68
|
+
console.log("Delivered Orders Count:", deliveredCount);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
|
|
3
|
+
const App: React.FC = () => {
|
|
4
|
+
const [name, setName] = useState("");
|
|
5
|
+
const [email, setEmail] = useState("");
|
|
6
|
+
const [password, setPassword] = useState("");
|
|
7
|
+
|
|
8
|
+
const emailError = email && !email.includes("@");
|
|
9
|
+
const passwordError = password && password.length < 6;
|
|
10
|
+
|
|
11
|
+
const isValid =
|
|
12
|
+
name.trim() !== "" && !emailError && !passwordError;
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<div style={{ padding: 20 }}>
|
|
16
|
+
<h2>Signup Form</h2>
|
|
17
|
+
|
|
18
|
+
<div>
|
|
19
|
+
<input
|
|
20
|
+
placeholder="Name"
|
|
21
|
+
value={name}
|
|
22
|
+
onChange={e => setName(e.target.value)}
|
|
23
|
+
/>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div>
|
|
27
|
+
<input
|
|
28
|
+
placeholder="Email"
|
|
29
|
+
value={email}
|
|
30
|
+
onChange={e => setEmail(e.target.value)}
|
|
31
|
+
/>
|
|
32
|
+
{emailError && <p>Email must contain @</p>}
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<div>
|
|
36
|
+
<input
|
|
37
|
+
type="password"
|
|
38
|
+
placeholder="Password"
|
|
39
|
+
value={password}
|
|
40
|
+
onChange={e => setPassword(e.target.value)}
|
|
41
|
+
/>
|
|
42
|
+
{passwordError && <p>Password must be at least 6 characters</p>}
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<button disabled={!isValid}>Submit</button>
|
|
46
|
+
|
|
47
|
+
<h3>Preview</h3>
|
|
48
|
+
<p>Name: {name}</p>
|
|
49
|
+
<p>Email: {email}</p>
|
|
50
|
+
<p>Password: {password}</p>
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default App;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React, { useRef } from "react";
|
|
2
|
+
|
|
3
|
+
const App: React.FC = () => {
|
|
4
|
+
const nameRef = useRef<HTMLInputElement>(null);
|
|
5
|
+
const feedbackRef = useRef<HTMLTextAreaElement>(null);
|
|
6
|
+
|
|
7
|
+
const handleSubmit = (e: React.FormEvent) => {
|
|
8
|
+
e.preventDefault();
|
|
9
|
+
|
|
10
|
+
const name = nameRef.current?.value || "";
|
|
11
|
+
const feedback = feedbackRef.current?.value || "";
|
|
12
|
+
|
|
13
|
+
console.log({ name, feedback });
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<div style={{ padding: 20 }}>
|
|
18
|
+
<h2>Feedback Form</h2>
|
|
19
|
+
|
|
20
|
+
<form onSubmit={handleSubmit}>
|
|
21
|
+
<div>
|
|
22
|
+
<input ref={nameRef} placeholder="Name" />
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<div>
|
|
26
|
+
<textarea ref={feedbackRef} placeholder="Feedback" />
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<button type="submit">Submit</button>
|
|
30
|
+
</form>
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default App;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useForm } from "react-hook-form";
|
|
3
|
+
|
|
4
|
+
interface LoginData {
|
|
5
|
+
email: string;
|
|
6
|
+
password: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const App: React.FC = () => {
|
|
10
|
+
const {
|
|
11
|
+
register,
|
|
12
|
+
handleSubmit,
|
|
13
|
+
setError,
|
|
14
|
+
formState: { errors, isSubmitting }
|
|
15
|
+
} = useForm<LoginData>();
|
|
16
|
+
|
|
17
|
+
const onSubmit = async (data: LoginData) => {
|
|
18
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
19
|
+
|
|
20
|
+
const isValid =
|
|
21
|
+
data.email === "test@example.com" &&
|
|
22
|
+
data.password === "123456";
|
|
23
|
+
|
|
24
|
+
if (!isValid) {
|
|
25
|
+
setError("root", {
|
|
26
|
+
type: "manual",
|
|
27
|
+
message: "Invalid email or password"
|
|
28
|
+
});
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
console.log("Login successful");
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<div style={{ padding: 20 }}>
|
|
37
|
+
<h2>Login</h2>
|
|
38
|
+
|
|
39
|
+
<form onSubmit={handleSubmit(onSubmit)}>
|
|
40
|
+
<div>
|
|
41
|
+
<input
|
|
42
|
+
placeholder="Email"
|
|
43
|
+
{...register("email", {
|
|
44
|
+
required: "Email is required",
|
|
45
|
+
pattern: {
|
|
46
|
+
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
|
|
47
|
+
message: "Invalid email format"
|
|
48
|
+
}
|
|
49
|
+
})}
|
|
50
|
+
/>
|
|
51
|
+
{errors.email && <p>{errors.email.message}</p>}
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<div>
|
|
55
|
+
<input
|
|
56
|
+
type="password"
|
|
57
|
+
placeholder="Password"
|
|
58
|
+
{...register("password", {
|
|
59
|
+
required: "Password is required",
|
|
60
|
+
minLength: {
|
|
61
|
+
value: 6,
|
|
62
|
+
message: "Minimum 6 characters"
|
|
63
|
+
}
|
|
64
|
+
})}
|
|
65
|
+
/>
|
|
66
|
+
{errors.password && <p>{errors.password.message}</p>}
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
{errors.root && <p>{errors.root.message}</p>}
|
|
70
|
+
|
|
71
|
+
<button type="submit" disabled={isSubmitting}>
|
|
72
|
+
{isSubmitting ? "Logging in..." : "Login"}
|
|
73
|
+
</button>
|
|
74
|
+
</form>
|
|
75
|
+
</div>
|
|
76
|
+
);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export default App;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useForm } from "react-hook-form";
|
|
3
|
+
|
|
4
|
+
interface FormData {
|
|
5
|
+
fullName: string;
|
|
6
|
+
email: string;
|
|
7
|
+
password: string;
|
|
8
|
+
age: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const App: React.FC = () => {
|
|
12
|
+
const {
|
|
13
|
+
register,
|
|
14
|
+
handleSubmit,
|
|
15
|
+
formState: { errors }
|
|
16
|
+
} = useForm<FormData>({
|
|
17
|
+
defaultValues: {
|
|
18
|
+
fullName: "Guest User",
|
|
19
|
+
age: 18
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const onSubmit = (data: FormData) => {
|
|
24
|
+
console.log(data);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div style={{ padding: 20 }}>
|
|
29
|
+
<h2>User Registration</h2>
|
|
30
|
+
|
|
31
|
+
<form onSubmit={handleSubmit(onSubmit)}>
|
|
32
|
+
<div>
|
|
33
|
+
<input
|
|
34
|
+
placeholder="Full Name"
|
|
35
|
+
{...register("fullName", {
|
|
36
|
+
required: "Full Name is required",
|
|
37
|
+
minLength: {
|
|
38
|
+
value: 3,
|
|
39
|
+
message: "Minimum 3 characters"
|
|
40
|
+
}
|
|
41
|
+
})}
|
|
42
|
+
/>
|
|
43
|
+
{errors.fullName && <p>{errors.fullName.message}</p>}
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<div>
|
|
47
|
+
<input
|
|
48
|
+
placeholder="Email"
|
|
49
|
+
{...register("email", {
|
|
50
|
+
required: "Email is required",
|
|
51
|
+
pattern: {
|
|
52
|
+
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
|
|
53
|
+
message: "Invalid email format"
|
|
54
|
+
}
|
|
55
|
+
})}
|
|
56
|
+
/>
|
|
57
|
+
{errors.email && <p>{errors.email.message}</p>}
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<div>
|
|
61
|
+
<input
|
|
62
|
+
type="password"
|
|
63
|
+
placeholder="Password"
|
|
64
|
+
{...register("password", {
|
|
65
|
+
required: "Password is required",
|
|
66
|
+
minLength: {
|
|
67
|
+
value: 6,
|
|
68
|
+
message: "Minimum 6 characters"
|
|
69
|
+
},
|
|
70
|
+
validate: value =>
|
|
71
|
+
/\d/.test(value) || "Must include a number"
|
|
72
|
+
})}
|
|
73
|
+
/>
|
|
74
|
+
{errors.password && <p>{errors.password.message}</p>}
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<div>
|
|
78
|
+
<input
|
|
79
|
+
type="number"
|
|
80
|
+
placeholder="Age"
|
|
81
|
+
{...register("age", {
|
|
82
|
+
required: "Age is required",
|
|
83
|
+
min: {
|
|
84
|
+
value: 18,
|
|
85
|
+
message: "Minimum age is 18"
|
|
86
|
+
},
|
|
87
|
+
max: {
|
|
88
|
+
value: 60,
|
|
89
|
+
message: "Maximum age is 60"
|
|
90
|
+
},
|
|
91
|
+
valueAsNumber: true
|
|
92
|
+
})}
|
|
93
|
+
/>
|
|
94
|
+
{errors.age && <p>{errors.age.message}</p>}
|
|
95
|
+
</div>
|
|
96
|
+
|
|
97
|
+
<button type="submit">Submit</button>
|
|
98
|
+
</form>
|
|
99
|
+
</div>
|
|
100
|
+
);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export default App;
|
|
Binary file
|
package/package.json
ADDED