himanshu-toolkit 1.0.3 → 1.0.5

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/App2.jsx ADDED
@@ -0,0 +1,244 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import 'bootstrap/dist/css/bootstrap.min.css';
3
+
4
+ const API = 'http://localhost:5000/api/laptops';
5
+ const emptyLaptop = {
6
+ sellerName: '', laptopBrand: '', laptopModel: '', processorType: '',
7
+ laptopRam: '', storageType: '', laptopColor: '', sellingPrice: '',
8
+ contactNumber: '', Negotiable: false
9
+ };
10
+ const laptopOptions = {
11
+ HP: ['Pavilion', 'Omen', 'EliteBook', 'G16'],
12
+ Dell: ['Inspiron', 'Latitude', 'XPS', 'Gaming'],
13
+ Lenovo: ['LOQ', 'Legion', 'ThinkPad', 'IdeaPad'],
14
+ Apple: ['MacBook Air M1', 'MacBook Air M2', 'MacBook Pro', 'MacBook Neo']
15
+ };
16
+ const processorOptions = {
17
+ HP: ['i3', 'i5', 'i7', 'Ryzen 5', 'Ryzen 7'],
18
+ Dell: ['i3', 'i5', 'i7', 'Ryzen 5', 'Ryzen 7'],
19
+ Lenovo: ['i3', 'i5', 'i7', 'Ryzen 5', 'Ryzen 7'],
20
+ Apple: ['i3', 'i5', 'i7', 'Ryzen 5', 'Ryzen 7']
21
+ };
22
+ const ramOptions = ['4 GB', '8 GB', '16 GB', '32 GB'];
23
+ const storageOptions = ['HDD', 'SSD'];
24
+ const get = (item, camel, snake) => item[camel] ?? item[snake] ?? '';
25
+
26
+ export default function App() {
27
+ const [laptop, setLaptop] = useState({ ...emptyLaptop });
28
+ const [laptops, setLaptops] = useState([]);
29
+ const [editId, setEditId] = useState(null);
30
+ const [success, setSuccess] = useState('');
31
+ const [error, setError] = useState('');
32
+
33
+ const fetchLaptops = async () => {
34
+ try {
35
+ const res = await fetch(API);
36
+ if (!res.ok) throw new Error('Failed to fetch laptop records.');
37
+ setLaptops(await res.json());
38
+ } catch (err) {
39
+ console.error('Fetch error:', err);
40
+ setError('Could not load laptops. Check your backend server.');
41
+ }
42
+ };
43
+ useEffect(() => { fetchLaptops(); }, []);
44
+
45
+ const onTextChange = ({ target: { name, value, type, checked } }) => {
46
+ setLaptop(prev => ({
47
+ ...prev,
48
+ [name]: type === 'checkbox' ? checked : value,
49
+ ...(name === 'laptopBrand' ? { laptopModel: '', processorType: '' } : {})
50
+ }));
51
+ setSuccess('');
52
+ setError('');
53
+ };
54
+
55
+ const validateForm = () => {
56
+ if (!laptop.sellerName.trim() || !laptop.laptopBrand || !laptop.laptopModel ||
57
+ !laptop.processorType || !laptop.laptopRam || !laptop.storageType ||
58
+ !laptop.laptopColor.trim() || laptop.sellingPrice === '' || !laptop.contactNumber)
59
+ return 'Please fill in all required fields.';
60
+ if (laptop.sellerName.trim().length > 20)
61
+ return 'Seller name cannot exceed 20 characters.';
62
+ if (!laptopOptions[laptop.laptopBrand]?.includes(laptop.laptopModel))
63
+ return 'Please select a valid laptop model for the selected brand.';
64
+ if (!processorOptions[laptop.laptopBrand]?.includes(laptop.processorType))
65
+ return 'Please select a valid processor type for the selected brand.';
66
+ if (!ramOptions.includes(laptop.laptopRam))
67
+ return 'RAM must be 4 GB, 8 GB, 16 GB, or 32 GB.';
68
+ if (!storageOptions.includes(laptop.storageType))
69
+ return 'Please select HDD or SSD.';
70
+ if (!Number.isFinite(Number(laptop.sellingPrice)) || Number(laptop.sellingPrice) <= 0)
71
+ return 'Selling price must be a positive number.';
72
+ if (!/^[0-9]{10}$/.test(laptop.contactNumber.trim()))
73
+ return 'Contact number must contain exactly 10 digits.';
74
+ return '';
75
+ };
76
+
77
+ const resetForm = () => {
78
+ setLaptop({ ...emptyLaptop });
79
+ setEditId(null);
80
+ };
81
+
82
+ const handleSaveRecord = async e => {
83
+ e.preventDefault();
84
+ setSuccess('');
85
+ setError('');
86
+ const validationError = validateForm();
87
+ if (validationError) return setError(validationError);
88
+
89
+ const payload = {
90
+ ...laptop,
91
+ sellerName: laptop.sellerName.trim(),
92
+ laptopModel: laptop.laptopModel.trim(),
93
+ laptopColor: laptop.laptopColor.trim(),
94
+ sellingPrice: Number(laptop.sellingPrice)
95
+ };
96
+ try {
97
+ const res = await fetch(editId !== null ? `${API}/${editId}` : API, {
98
+ method: editId !== null ? 'PUT' : 'POST',
99
+ headers: { 'Content-Type': 'application/json' },
100
+ body: JSON.stringify(payload)
101
+ });
102
+ const result = await res.json();
103
+ if (!res.ok) throw new Error(result.error || 'Failed to save laptop details.');
104
+ setSuccess(editId !== null ? 'Laptop details updated successfully!' : 'Laptop listed successfully!');
105
+ resetForm();
106
+ await fetchLaptops();
107
+ } catch (err) {
108
+ console.error('Save error:', err);
109
+ setError(err.message || 'Failed to save laptop details.');
110
+ }
111
+ };
112
+
113
+ const handleEdit = item => {
114
+ setLaptop({
115
+ sellerName: get(item, 'sellerName', 'seller_name'),
116
+ laptopBrand: get(item, 'laptopBrand', 'laptop_brand'),
117
+ laptopModel: get(item, 'laptopModel', 'laptop_model'),
118
+ processorType: get(item, 'processorType', 'processor_type'),
119
+ laptopRam: get(item, 'laptopRam', 'laptop_ram'),
120
+ storageType: get(item, 'storageType', 'storage_type'),
121
+ laptopColor: get(item, 'laptopColor', 'laptop_color'),
122
+ sellingPrice: String(get(item, 'sellingPrice', 'selling_price')),
123
+ contactNumber: String(get(item, 'contactNumber', 'contact_number')),
124
+ Negotiable: Boolean(get(item, 'Negotiable', 'negotiable'))
125
+ });
126
+ setEditId(item.id ?? item.ID);
127
+ setSuccess(''); setError('');
128
+ window.scrollTo({ top: 0, behavior: 'smooth' });
129
+ };
130
+
131
+ const handleDelete = async id => {
132
+ if (!window.confirm('Are you sure you want to delete this laptop listing?')) return;
133
+ setSuccess(''); setError('');
134
+ try {
135
+ const res = await fetch(`${API}/${id}`, { method: 'DELETE' });
136
+ const result = await res.json();
137
+ if (!res.ok) throw new Error(result.error || 'Failed to delete laptop listing.');
138
+ if (String(editId) === String(id)) resetForm();
139
+ setSuccess('Laptop listing deleted successfully!');
140
+ await fetchLaptops();
141
+ } catch (err) {
142
+ console.error('Delete error:', err);
143
+ setError(err.message || 'Failed to delete laptop listing.');
144
+ }
145
+ };
146
+
147
+ const handleCancel = () => { resetForm(); setSuccess(''); setError(''); };
148
+ const fieldError = message => message && <small className="text-danger d-block">{message}</small>;
149
+
150
+ return (
151
+ <div className="container mt-5 mb-5">
152
+ <h2 className="text-center mb-2">Laptop Selling Management</h2>
153
+ <p className="text-center text-muted mb-4">Sell your laptop</p>
154
+ {success && <div className="alert alert-success" role="status">{success}</div>}
155
+ {error && <div className="alert alert-danger" role="alert">{error}</div>}
156
+
157
+ <div className="card shadow p-4 mb-5">
158
+ <h4 className="mb-3">{editId !== null ? 'Edit Laptop Listing' : 'List Your Laptop'}</h4>
159
+ <form onSubmit={handleSaveRecord}>
160
+ <div className="row">
161
+ <div className="col-md-6 mb-3">
162
+ <label className="form-label">Seller Name</label>
163
+ <input type="text" name="sellerName" className="form-control" value={laptop.sellerName} onChange={onTextChange} maxLength={20} placeholder="Enter seller name" required />
164
+ <small className="text-muted">Maximum 20 characters</small>
165
+ </div>
166
+ <div className="col-md-6 mb-3">
167
+ <label className="form-label">Laptop Brand</label>
168
+ <select name="laptopBrand" className="form-select" value={laptop.laptopBrand} onChange={onTextChange} required>
169
+ <option value="">Select laptop brand</option>
170
+ {Object.keys(laptopOptions).map(brand => <option key={brand} value={brand}>{brand}</option>)}
171
+ </select>
172
+ </div>
173
+ <div className="col-md-6 mb-3">
174
+ <label className="form-label">Laptop Model</label>
175
+ <select name="laptopModel" className="form-select" value={laptop.laptopModel} onChange={onTextChange} disabled={!laptop.laptopBrand} required>
176
+ <option value="">Select laptop model</option>
177
+ {(laptopOptions[laptop.laptopBrand] || []).map(model => <option key={model} value={model}>{model}</option>)}
178
+ </select>
179
+ </div>
180
+ <div className="col-md-6 mb-3">
181
+ <label className="form-label">Processor Type</label>
182
+ <select name="processorType" className="form-select" value={laptop.processorType} onChange={onTextChange} disabled={!laptop.laptopBrand} required>
183
+ <option value="">Select processor</option>
184
+ {(processorOptions[laptop.laptopBrand] || []).map(p => <option key={p} value={p}>{p}</option>)}
185
+ </select>
186
+ </div>
187
+ <div className="col-md-6 mb-3">
188
+ <label className="form-label">RAM Capacity</label>
189
+ <select name="laptopRam" className="form-select" value={laptop.laptopRam} onChange={onTextChange} required>
190
+ <option value="">Select RAM capacity</option>
191
+ {ramOptions.map(ram => <option key={ram} value={ram}>{ram}</option>)}
192
+ </select>
193
+ </div>
194
+ <div className="col-md-6 mb-3">
195
+ <label className="form-label">Storage Type</label>
196
+ <select name="storageType" className="form-select" value={laptop.storageType} onChange={onTextChange} required>
197
+ <option value="">Select storage type</option>
198
+ {storageOptions.map(type => <option key={type} value={type}>{type}</option>)}
199
+ </select>
200
+ </div>
201
+ <div className="col-md-6 mb-3">
202
+ <label className="form-label">Laptop Color</label>
203
+ <input type="text" name="laptopColor" className="form-control" value={laptop.laptopColor} onChange={onTextChange} placeholder="Enter laptop color" required />
204
+ </div>
205
+ <div className="col-md-6 mb-3">
206
+ <label className="form-label">Selling Price (₹)</label>
207
+ <input type="number" name="sellingPrice" className="form-control" value={laptop.sellingPrice} onChange={onTextChange} min="0.01" step="any" placeholder="Enter selling price" required />
208
+ </div>
209
+ <div className="col-md-6 mb-3">
210
+ <label className="form-label">Contact Number</label>
211
+ <input type="tel" inputMode="numeric" name="contactNumber" className="form-control" value={laptop.contactNumber} onChange={onTextChange} maxLength={10} pattern="[0-9]{10}" placeholder="Enter 10-digit contact number" required />
212
+ </div>
213
+ <div className="col-md-6 mb-3 d-flex align-items-center">
214
+ <div className="form-check mt-3">
215
+ <input type="checkbox" name="Negotiable" className="form-check-input" id="Negotiable" checked={laptop.Negotiable} onChange={onTextChange} />
216
+ <label className="form-check-label" htmlFor="Negotiable">Negotiable</label>
217
+ </div>
218
+ </div>
219
+ </div>
220
+ <button type="submit" className="btn btn-primary">{editId !== null ? 'Update Laptop' : 'List Laptop'}</button>
221
+ {editId !== null && <button type="button" className="btn btn-secondary ms-2" onClick={handleCancel}>Cancel</button>}
222
+ </form>
223
+ </div>
224
+
225
+ <h4 className="mb-3">Laptop Listings</h4>
226
+ <div className="table-responsive">
227
+ <table className="table table-bordered table-striped table-hover align-middle">
228
+ <thead className="table-dark"><tr>
229
+ <th>ID</th><th>Seller</th><th>Brand</th><th>Model</th><th>Processor</th><th>RAM</th><th>Storage</th><th>Color</th><th>Price</th><th>Contact</th><th>Negotiable</th><th>Actions</th>
230
+ </tr></thead>
231
+ <tbody>
232
+ {!laptops.length ? <tr><td colSpan="12" className="text-center">No laptop listings found</td></tr> : laptops.map(item => {
233
+ const id = item.id ?? item.ID;
234
+ return <tr key={id}>
235
+ <td>{id}</td><td>{get(item, 'sellerName', 'seller_name')}</td><td>{get(item, 'laptopBrand', 'laptop_brand')}</td><td>{get(item, 'laptopModel', 'laptop_model')}</td><td>{get(item, 'processorType', 'processor_type')}</td><td>{get(item, 'laptopRam', 'laptop_ram')}</td><td>{get(item, 'storageType', 'storage_type')}</td><td>{get(item, 'laptopColor', 'laptop_color')}</td><td>₹{Number(get(item, 'sellingPrice', 'selling_price')).toLocaleString('en-IN')}</td><td>{get(item, 'contactNumber', 'contact_number')}</td><td>{get(item, 'Negotiable', 'negotiable') ? 'Yes' : 'No'}</td>
236
+ <td><button type="button" className="btn btn-warning btn-sm me-2 mb-1" onClick={() => handleEdit(item)}>Edit</button><button type="button" className="btn btn-danger btn-sm mb-1" onClick={() => handleDelete(id)}>Delete</button></td>
237
+ </tr>;
238
+ })}
239
+ </tbody>
240
+ </table>
241
+ </div>
242
+ </div>
243
+ );
244
+ }
package/App3.jsx ADDED
@@ -0,0 +1,226 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import 'bootstrap/dist/css/bootstrap.min.css';
3
+
4
+ const API = 'http://localhost:5000/students';
5
+
6
+ export default function App() {
7
+ const [students, setStudents] = useState([]);
8
+ const [form, setForm] = useState({ sid: '', sname: '', course: '' });
9
+ const [editId, setEditId] = useState(null);
10
+ const [showForm, setShowForm] = useState(false);
11
+ const [message, setMessage] = useState('');
12
+ const [error, setError] = useState('');
13
+
14
+ const loadStudents = async () => {
15
+ try {
16
+ const res = await fetch(API);
17
+ const data = await res.json();
18
+ if (!res.ok) throw new Error(data.error || 'Failed to load students');
19
+ setStudents(data);
20
+ } catch (e) {
21
+ setError(e.message);
22
+ }
23
+ };
24
+
25
+ useEffect(() => {
26
+ loadStudents();
27
+ }, []);
28
+
29
+ const handleChange = e =>
30
+ setForm({ ...form, [e.target.name]: e.target.value });
31
+
32
+ const handleSubmit = async e => {
33
+ e.preventDefault();
34
+ setMessage('');
35
+ setError('');
36
+
37
+ try {
38
+ const res = await fetch(
39
+ editId ? `${API}/${editId}` : API,
40
+ {
41
+ method: editId ? 'PUT' : 'POST',
42
+ headers: { 'Content-Type': 'application/json' },
43
+ body: JSON.stringify({
44
+ ...form,
45
+ sid: Number(form.sid),
46
+ sname: form.sname.trim(),
47
+ course: form.course.trim()
48
+ })
49
+ }
50
+ );
51
+
52
+ const data = await res.json();
53
+ if (!res.ok) throw new Error(data.error || 'Operation failed');
54
+
55
+ setMessage(data.message);
56
+ setForm({ sid: '', sname: '', course: '' });
57
+ setEditId(null);
58
+ setShowForm(false);
59
+ await loadStudents();
60
+ } catch (e) {
61
+ setError(e.message);
62
+ }
63
+ };
64
+
65
+ const editStudent = student => {
66
+ setForm({
67
+ sid: student.sid,
68
+ sname: student.sname,
69
+ course: student.course
70
+ });
71
+ setEditId(student.sid);
72
+ setShowForm(true);
73
+ setMessage('');
74
+ setError('');
75
+ };
76
+
77
+ const deleteStudent = async sid => {
78
+ if (!window.confirm('Delete this student?')) return;
79
+
80
+ setMessage('');
81
+ setError('');
82
+
83
+ try {
84
+ const res = await fetch(`${API}/${sid}`, { method: 'DELETE' });
85
+ const data = await res.json();
86
+ if (!res.ok) throw new Error(data.error || 'Delete failed');
87
+
88
+ setMessage(data.message);
89
+ if (editId === sid) {
90
+ setEditId(null);
91
+ setShowForm(false);
92
+ setForm({ sid: '', sname: '', course: '' });
93
+ }
94
+ await loadStudents();
95
+ } catch (e) {
96
+ setError(e.message);
97
+ }
98
+ };
99
+
100
+ return (
101
+ <div className="container py-5">
102
+ <div className="card shadow">
103
+ <div className="card-header bg-primary text-white text-center">
104
+ <h2>Student Management System</h2>
105
+ </div>
106
+
107
+ <div className="card-body">
108
+ {message && <div className="alert alert-success">{message}</div>}
109
+ {error && <div className="alert alert-danger">{error}</div>}
110
+
111
+ <button
112
+ className="btn btn-success mb-3"
113
+ onClick={() => {
114
+ setForm({ sid: '', sname: '', course: '' });
115
+ setEditId(null);
116
+ setShowForm(true);
117
+ setMessage('');
118
+ setError('');
119
+ }}
120
+ >
121
+ Add New Student
122
+ </button>
123
+
124
+ {showForm && (
125
+ <form onSubmit={handleSubmit} className="border rounded p-3 mb-4">
126
+ <h5>{editId ? 'Edit Student' : 'Add Student'}</h5>
127
+
128
+ <input
129
+ className="form-control mb-3"
130
+ type="number"
131
+ name="sid"
132
+ placeholder="Student ID"
133
+ value={form.sid}
134
+ onChange={handleChange}
135
+ disabled={editId !== null}
136
+ min="1"
137
+ required
138
+ />
139
+
140
+ <input
141
+ className="form-control mb-3"
142
+ name="sname"
143
+ placeholder="Student Name"
144
+ value={form.sname}
145
+ onChange={handleChange}
146
+ required
147
+ />
148
+
149
+ <input
150
+ className="form-control mb-3"
151
+ name="course"
152
+ placeholder="Course"
153
+ value={form.course}
154
+ onChange={handleChange}
155
+ required
156
+ />
157
+
158
+ <button className="btn btn-primary me-2" type="submit">
159
+ {editId ? 'Update Student' : 'Submit Student'}
160
+ </button>
161
+
162
+ <button
163
+ className="btn btn-secondary"
164
+ type="button"
165
+ onClick={() => {
166
+ setShowForm(false);
167
+ setEditId(null);
168
+ }}
169
+ >
170
+ Cancel
171
+ </button>
172
+ </form>
173
+ )}
174
+
175
+ <h4>Student Records</h4>
176
+
177
+ <div className="table-responsive">
178
+ <table className="table table-bordered table-striped table-hover">
179
+ <thead className="table-dark">
180
+ <tr>
181
+ <th>Student ID</th>
182
+ <th>Student Name</th>
183
+ <th>Course</th>
184
+ <th>Actions</th>
185
+ </tr>
186
+ </thead>
187
+
188
+ <tbody>
189
+ {students.map(student => (
190
+ <tr key={student.sid}>
191
+ <td>{student.sid}</td>
192
+ <td>{student.sname}</td>
193
+ <td>{student.course}</td>
194
+ <td>
195
+ <button
196
+ className="btn btn-warning btn-sm me-2"
197
+ onClick={() => editStudent(student)}
198
+ >
199
+ Edit
200
+ </button>
201
+
202
+ <button
203
+ className="btn btn-danger btn-sm"
204
+ onClick={() => deleteStudent(student.sid)}
205
+ >
206
+ Delete
207
+ </button>
208
+ </td>
209
+ </tr>
210
+ ))}
211
+
212
+ {students.length === 0 && (
213
+ <tr>
214
+ <td colSpan="4" className="text-center">
215
+ No students found.
216
+ </td>
217
+ </tr>
218
+ )}
219
+ </tbody>
220
+ </table>
221
+ </div>
222
+ </div>
223
+ </div>
224
+ </div>
225
+ );
226
+ }
package/database2.sql ADDED
@@ -0,0 +1,18 @@
1
+ CREATE DATABASE IF NOT EXISTS laptop_seller;
2
+ USE laptop_seller;
3
+
4
+ CREATE TABLE IF NOT EXISTS laptops (
5
+ id INT AUTO_INCREMENT PRIMARY KEY,
6
+ seller_name VARCHAR(20) NOT NULL,
7
+ laptop_brand ENUM('HP', 'Dell', 'Lenovo', 'Apple') NOT NULL,
8
+ laptop_model VARCHAR(100) NOT NULL,
9
+ processor_type ENUM('i3', 'i5', 'i7', 'Ryzen 5', 'Ryzen 7') NOT NULL,
10
+ laptop_ram ENUM('4 GB', '8 GB', '16 GB', '32 GB') NOT NULL,
11
+ storage_type ENUM('HDD', 'SSD') NOT NULL,
12
+ laptop_color VARCHAR(30) NOT NULL,
13
+ selling_price DECIMAL(12,2) NOT NULL,
14
+ contact_number CHAR(10) NOT NULL,
15
+ negotiable BOOLEAN NOT NULL DEFAULT FALSE,
16
+ CHECK (selling_price > 0),
17
+ CHECK (contact_number REGEXP '^[0-9]{10}$')
18
+ );
package/database3.sql ADDED
@@ -0,0 +1,10 @@
1
+ CREATE DATABASE student_db;
2
+ USE student_db;
3
+
4
+ CREATE TABLE students (
5
+ sid INT PRIMARY KEY,
6
+ sname VARCHAR(100) NOT NULL,
7
+ course VARCHAR(100) NOT NULL
8
+ );
9
+
10
+ select*from students
package/package.json CHANGED
@@ -1,15 +1,21 @@
1
1
  {
2
2
  "name": "himanshu-toolkit",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "My reusable full-stack application toolkit",
5
5
  "main": "server.js",
6
6
  "files": [
7
7
  "App.jsx",
8
8
  "App1.jsx",
9
+ "App2.jsx",
10
+ "App3.jsx",
9
11
  "database.sql",
10
12
  "database1.sql",
13
+ "database2.sql",
14
+ "database3.sql",
11
15
  "server.js",
12
- "server1.js"
16
+ "server1.js",
17
+ "server3.js",
18
+ "server4.js"
13
19
  ],
14
20
  "keywords": [
15
21
  "react",
package/server3.js ADDED
@@ -0,0 +1,164 @@
1
+
2
+ const express = require('express');
3
+ const mysql = require('mysql2');
4
+ const cors = require('cors');
5
+
6
+ const app = express();
7
+ app.use(cors(), express.json());
8
+
9
+ const db = mysql.createConnection({
10
+ host: 'localhost',
11
+ user: 'root',
12
+ password: process.env.DB_PASSWORD || 'Himanshu@0334',
13
+ database: 'laptop_seller'
14
+ });
15
+
16
+ db.connect(err => {
17
+ if (err) return console.error('MySQL error:', err.message);
18
+ console.log('Connected to MySQL Database!');
19
+ });
20
+
21
+ const laptopOptions = {
22
+ HP: ['Pavilion', 'Omen', 'EliteBook', 'G16'],
23
+ Dell: ['Inspiron', 'Latitude', 'XPS', 'Gaming'],
24
+ Lenovo: ['LOQ', 'Legion', 'ThinkPad', 'IdeaPad'],
25
+ Apple: ['MacBook Air M1', 'MacBook Air M2', 'MacBook Pro', 'MacBook Neo']
26
+ };
27
+
28
+ const processorOptions = {
29
+ HP: ['i3', 'i5', 'i7', 'Ryzen 5', 'Ryzen 7'],
30
+ Dell: ['i3', 'i5', 'i7', 'Ryzen 5', 'Ryzen 7'],
31
+ Lenovo: ['i3', 'i5', 'i7', 'Ryzen 5', 'Ryzen 7'],
32
+ Apple: ['i3', 'i5', 'i7', 'Ryzen 5', 'Ryzen 7']
33
+ };
34
+
35
+ const ramOptions = ['4 GB', '8 GB', '16 GB', '32 GB'];
36
+ const storageOptions = ['HDD', 'SSD'];
37
+ const fail = (res, status, error) => res.status(status).json({ error });
38
+
39
+ function validateLaptop(l) {
40
+ if (typeof l.sellerName !== 'string' || !l.sellerName.trim())
41
+ return 'Seller name is required.';
42
+ if (l.sellerName.trim().length > 20)
43
+ return 'Seller name cannot exceed 20 characters.';
44
+ if (!laptopOptions[l.laptopBrand])
45
+ return 'Please select a valid laptop brand.';
46
+ if (!laptopOptions[l.laptopBrand].includes(l.laptopModel))
47
+ return 'Please select a valid laptop model.';
48
+ if (!processorOptions[l.laptopBrand].includes(l.processorType))
49
+ return 'Please select a valid processor.';
50
+ if (!ramOptions.includes(l.laptopRam))
51
+ return 'Please select a valid RAM capacity.';
52
+ if (!storageOptions.includes(l.storageType))
53
+ return 'Please select HDD or SSD.';
54
+ if (typeof l.laptopColor !== 'string' || !l.laptopColor.trim())
55
+ return 'Laptop color is required.';
56
+
57
+ const price = Number(l.sellingPrice);
58
+ if (l.sellingPrice === '' || l.sellingPrice == null ||
59
+ !Number.isFinite(price) || price <= 0)
60
+ return 'Selling price must be positive.';
61
+
62
+ if (typeof l.contactNumber !== 'string' ||
63
+ !/^[0-9]{10}$/.test(l.contactNumber))
64
+ return 'Contact number must contain exactly 10 digits.';
65
+
66
+ const negotiable = l.Negotiable ?? l.negotiable;
67
+ if (negotiable !== undefined && typeof negotiable !== 'boolean')
68
+ return 'Negotiable must be true or false.';
69
+
70
+ return null;
71
+ }
72
+
73
+ const getValues = l => [
74
+ l.sellerName.trim(), l.laptopBrand, l.laptopModel,
75
+ l.processorType, l.laptopRam, l.storageType,
76
+ l.laptopColor.trim(), Number(l.sellingPrice),
77
+ l.contactNumber, Boolean(l.Negotiable ?? l.negotiable)
78
+ ];
79
+
80
+ const selectSQL = `SELECT id, seller_name AS sellerName,
81
+ laptop_brand AS laptopBrand, laptop_model AS laptopModel,
82
+ processor_type AS processorType, laptop_ram AS laptopRam,
83
+ storage_type AS storageType, laptop_color AS laptopColor,
84
+ selling_price AS sellingPrice, contact_number AS contactNumber,
85
+ negotiable AS negotiable FROM laptops`;
86
+
87
+ app.get('/api/laptops', (req, res) => {
88
+ db.query(`${selectSQL} ORDER BY id DESC`, (err, rows) => {
89
+ if (err) return fail(res, 500, 'Failed to fetch laptops.');
90
+ res.json(rows);
91
+ });
92
+ });
93
+
94
+ app.post('/api/laptops', (req, res) => {
95
+ const error = validateLaptop(req.body);
96
+ if (error) return fail(res, 400, error);
97
+
98
+ const sql = `INSERT INTO laptops
99
+ (seller_name, laptop_brand, laptop_model, processor_type,
100
+ laptop_ram, storage_type, laptop_color, selling_price,
101
+ contact_number, negotiable)
102
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
103
+
104
+ db.query(sql, getValues(req.body), (err, result) => {
105
+ if (err) {
106
+ console.error(err.message);
107
+ return fail(res, 500, 'Failed to add laptop.');
108
+ }
109
+ res.status(201).json({
110
+ message: 'Laptop listed successfully!',
111
+ id: result.insertId
112
+ });
113
+ });
114
+ });
115
+
116
+ app.put('/api/laptops/:id', (req, res) => {
117
+ const id = Number(req.params.id);
118
+ if (!Number.isSafeInteger(id) || id <= 0)
119
+ return fail(res, 400, 'Invalid laptop ID.');
120
+
121
+ const error = validateLaptop(req.body);
122
+ if (error) return fail(res, 400, error);
123
+
124
+ const sql = `UPDATE laptops SET seller_name=?, laptop_brand=?,
125
+ laptop_model=?, processor_type=?, laptop_ram=?, storage_type=?,
126
+ laptop_color=?, selling_price=?, contact_number=?, negotiable=?
127
+ WHERE id=?`;
128
+
129
+ db.query(sql, [...getValues(req.body), id], (err, result) => {
130
+ if (err) return fail(res, 500, 'Failed to update laptop.');
131
+ if (result.affectedRows)
132
+ return res.json({ message: 'Laptop updated successfully!' });
133
+
134
+ db.query('SELECT id FROM laptops WHERE id=?', [id], (err, rows) => {
135
+ if (err) return fail(res, 500, 'Failed to verify laptop.');
136
+ if (!rows.length) return fail(res, 404, 'Laptop not found.');
137
+ res.json({ message: 'Laptop details are already up to date.' });
138
+ });
139
+ });
140
+ });
141
+
142
+ app.delete('/api/laptops/:id', (req, res) => {
143
+ const id = Number(req.params.id);
144
+ if (!Number.isSafeInteger(id) || id <= 0)
145
+ return fail(res, 400, 'Invalid laptop ID.');
146
+
147
+ db.query('DELETE FROM laptops WHERE id=?', [id], (err, result) => {
148
+ if (err) return fail(res, 500, 'Failed to delete laptop.');
149
+ if (!result.affectedRows)
150
+ return fail(res, 404, 'Laptop not found.');
151
+ res.json({ message: 'Laptop deleted successfully!' });
152
+ });
153
+ });
154
+
155
+ app.use((err, req, res, next) => {
156
+ if (err instanceof SyntaxError && err.status === 400)
157
+ return fail(res, 400, 'Invalid JSON request body.');
158
+ console.error(err);
159
+ res.status(500).json({ error: 'Internal server error.' });
160
+ });
161
+
162
+ app.listen(5000, () =>
163
+ console.log('Server running at http://localhost:5000')
164
+ );
package/server4.js ADDED
@@ -0,0 +1,107 @@
1
+
2
+ const express = require('express');
3
+ const mysql = require('mysql2/promise');
4
+ const cors = require('cors');
5
+
6
+ const app = express();
7
+ app.use(cors());
8
+ app.use(express.json());
9
+
10
+ const db = mysql.createPool({
11
+ host: 'localhost',
12
+ user: 'root',
13
+ password: process.env.DB_PASSWORD || 'Himanshu@0334',
14
+ database: 'student_db',
15
+ waitForConnections: true,
16
+ connectionLimit: 10
17
+ });
18
+
19
+ // GET: Display all students
20
+ app.get('/students', async (req, res) => {
21
+ try {
22
+ const [rows] = await db.query('SELECT * FROM students ORDER BY sid');
23
+ res.json(rows);
24
+ } catch (err) {
25
+ console.error(err);
26
+ res.status(500).json({ error: 'Failed to fetch students.' });
27
+ }
28
+ });
29
+
30
+ // POST: Add a student
31
+ app.post('/students', async (req, res) => {
32
+ const { sid, sname, course } = req.body;
33
+
34
+ if (!Number.isInteger(Number(sid)) || Number(sid) <= 0 ||
35
+ typeof sname !== 'string' || !sname.trim() ||
36
+ typeof course !== 'string' || !course.trim()) {
37
+ return res.status(400).json({ error: 'Enter a valid ID, name and course.' });
38
+ }
39
+
40
+ try {
41
+ await db.execute(
42
+ 'INSERT INTO students (sid, sname, course) VALUES (?, ?, ?)',
43
+ [Number(sid), sname.trim(), course.trim()]
44
+ );
45
+ res.status(201).json({ message: 'Student added successfully.' });
46
+ } catch (err) {
47
+ if (err.code === 'ER_DUP_ENTRY')
48
+ return res.status(409).json({ error: 'Student ID already exists.' });
49
+
50
+ console.error(err);
51
+ res.status(500).json({ error: 'Failed to add student.' });
52
+ }
53
+ });
54
+
55
+ // PUT: Update a student
56
+ app.put('/students/:sid', async (req, res) => {
57
+ const { sname, course } = req.body;
58
+ const sid = Number(req.params.sid);
59
+
60
+ if (!Number.isInteger(sid) || sid <= 0 ||
61
+ typeof sname !== 'string' || !sname.trim() ||
62
+ typeof course !== 'string' || !course.trim()) {
63
+ return res.status(400).json({ error: 'Enter a valid name and course.' });
64
+ }
65
+
66
+ try {
67
+ const [result] = await db.execute(
68
+ 'UPDATE students SET sname = ?, course = ? WHERE sid = ?',
69
+ [sname.trim(), course.trim(), sid]
70
+ );
71
+
72
+ if (!result.affectedRows) {
73
+ const [rows] = await db.execute(
74
+ 'SELECT sid FROM students WHERE sid = ?', [sid]
75
+ );
76
+ if (!rows.length)
77
+ return res.status(404).json({ error: 'Student not found.' });
78
+ }
79
+
80
+ res.json({ message: 'Student updated successfully.' });
81
+ } catch (err) {
82
+ console.error(err);
83
+ res.status(500).json({ error: 'Failed to update student.' });
84
+ }
85
+ });
86
+
87
+ // DELETE: Remove a student
88
+ app.delete('/students/:sid', async (req, res) => {
89
+ try {
90
+ const [result] = await db.execute(
91
+ 'DELETE FROM students WHERE sid = ?',
92
+ [Number(req.params.sid)]
93
+ );
94
+
95
+ if (!result.affectedRows)
96
+ return res.status(404).json({ error: 'Student not found.' });
97
+
98
+ res.json({ message: 'Student deleted successfully.' });
99
+ } catch (err) {
100
+ console.error(err);
101
+ res.status(500).json({ error: 'Failed to delete student.' });
102
+ }
103
+ });
104
+
105
+ app.listen(5000, () =>
106
+ console.log('Server running at http://localhost:5000')
107
+ );